427 lines
No EOL
14 KiB
MQL5
427 lines
No EOL
14 KiB
MQL5
#ifndef FRAMEWORK_LAYER_ORDER_MQH
|
|
#define FRAMEWORK_LAYER_ORDER_MQH
|
|
|
|
#include "order.mqh"
|
|
#include "order_count.mqh"
|
|
#include "order_operation.mqh"
|
|
#include "order_symbol.mqh"
|
|
#include "layer_order_setting.mqh"
|
|
#include "layer_order_data.mqh"
|
|
|
|
list<layer_order_data *> *order_layer_orders;
|
|
list<order_symbol *> *order_layer_symbols;
|
|
|
|
#ifdef FOR_OPTIMIZATION
|
|
#define LAYER_ORDER_CHECK_SYMBOL(sym) true
|
|
#define LAYER_ORDER_CHECK_MAGIC(mag) true
|
|
#else
|
|
#define LAYER_ORDER_CHECK_SYMBOL(sym) (kernel_order::symbol() == sym)
|
|
#define LAYER_ORDER_CHECK_MAGIC(mag) (kernel_order::magic_number() == mag)
|
|
#endif
|
|
|
|
#define LAYER_ORDER_CHECK_TYPE(order_type, order_stop_type) (kernel_order::type() == order_type || kernel_order::type() == order_stop_type)
|
|
|
|
class layer_order {
|
|
public:
|
|
static void init() {
|
|
if (!GC_CHECK_PTR(order_layer_orders))
|
|
order_layer_orders=NULL;
|
|
if (!GC_CHECK_PTR(order_layer_symbols))
|
|
order_layer_symbols=NULL;
|
|
|
|
order_layer_orders = new list<layer_order_data *> ( 2 );
|
|
order_layer_orders.add ( new layer_order_data() );
|
|
order_layer_orders.add ( new layer_order_data() );
|
|
gc::push ( gc_dispose_type_on_end_deinit, order_layer_orders );
|
|
}
|
|
|
|
static order_symbol *get_order_layer_symbol_current_symbol() {
|
|
TOOL_CACHED ( order_symbol *,
|
|
_order_layer_symbol_current_symbol, {
|
|
_order_layer_symbol_current_symbol = order_symbol::create ( Symbol() );
|
|
gc::push ( gc_dispose_type_on_end_deinit, _order_layer_symbol_current_symbol );
|
|
} );
|
|
}
|
|
|
|
static void push_settings ( layer_order_setting *settings_ptr ) {
|
|
get_by_setting ( settings_ptr ).set ( settings_ptr );
|
|
|
|
if ( settings_ptr.max_trade_pairs != 0
|
|
|| settings_ptr.currency_block != 0 ) {
|
|
ACTION_ON_NONVALUE_OR_DEFAULT ( order_layer_symbols, {
|
|
order_layer_symbols = new list<order_symbol *>();
|
|
gc::push ( gc_dispose_type_on_end_deinit, order_layer_symbols );
|
|
});
|
|
}
|
|
}
|
|
|
|
static void refresh_all() {
|
|
get_order_layer_symbol_current_symbol().reset_direction();
|
|
ACTION_ON_VALUE_OR_DEFAULT ( order_layer_symbols, order_layer_symbols.clear() );
|
|
LIST_FOREACH ( order_layer_orders, layer_order_data *, item, item.reset() );
|
|
|
|
int magic_number = order_layer_orders.items[0].settings.magic_number;
|
|
//#ifdef MQL4
|
|
int ordersCount = kernel_order::count();
|
|
//#endif
|
|
//#ifdef MQL5
|
|
// int ordersCount = kernel_order::positions_count();
|
|
//#endif
|
|
for ( int i = 0; i < ordersCount; i++ ) {
|
|
if ( !kernel_order::select_by_index ( i ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( !LAYER_ORDER_CHECK_SYMBOL ( CURRENT_SYMBOL ) ) {
|
|
if ( GC_CHECK_PTR ( order_layer_symbols ) ) {
|
|
string symbol = kernel_order::symbol();
|
|
LIST_FIRST_OR_DEFAULT ( order_layer_symbols, found_symbol, order_symbol *, item, item.full == symbol );
|
|
|
|
if ( !GC_CHECK_PTR ( found_symbol ) ) {
|
|
found_symbol = order_symbol::create ( symbol );
|
|
order_layer_symbols.add ( found_symbol );
|
|
}
|
|
|
|
found_symbol.set_contains_direction ( c_order::is_buy_direction ( kernel_order::type() ) );
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ( !LAYER_ORDER_CHECK_MAGIC ( magic_number ) ) {
|
|
continue;
|
|
}
|
|
|
|
LIST_FOREACH ( order_layer_orders, layer_order_data *, item, {
|
|
if ( !LAYER_ORDER_CHECK_TYPE ( item.settings.order_type, item.settings.order_stop_type ) ) {
|
|
continue;
|
|
}
|
|
|
|
c_order *for_add = factory_c_order::get();
|
|
refresh_order ( for_add );
|
|
|
|
if ( !GC_CHECK_PTR ( item.min_order )
|
|
|| ( !item.is_buy_direction && for_add.open_price < item.min_order.open_price )
|
|
|| ( item.is_buy_direction && for_add.open_price > item.min_order.open_price ) ) {
|
|
item.min_order = for_add;
|
|
}
|
|
|
|
if ( !GC_CHECK_PTR ( item.max_order )
|
|
|| ( !item.is_buy_direction && for_add.open_price > item.max_order.open_price )
|
|
|| ( item.is_buy_direction && for_add.open_price < item.max_order.open_price ) ) {
|
|
item.max_order = for_add;
|
|
}
|
|
|
|
item.orders.add ( for_add );
|
|
item.count.inc_by_type ( for_add.order_type );
|
|
|
|
ACTION_ON_VALUE_OR_DEFAULT ( order_layer_symbols, get_order_layer_symbol_current_symbol().set_contains_direction ( item.is_buy_direction ) );
|
|
break;
|
|
} );
|
|
}
|
|
//#ifdef MQL5
|
|
// ordersCount = kernel_order::orders_count();
|
|
// for ( int i = 0; i < ordersCount; i++ ) {
|
|
// if ( !kernel_order::select_order_by_index ( i ) ) {
|
|
// continue;
|
|
// }
|
|
//
|
|
// if ( !LAYER_ORDER_CHECK_SYMBOL ( CURRENT_SYMBOL ) ) {
|
|
// if ( GC_CHECK_PTR ( order_layer_symbols ) ) {
|
|
// string symbol = kernel_order::symbol();
|
|
// LIST_FIRST_OR_DEFAULT ( order_layer_symbols, found_symbol, order_symbol *, item, item.full == symbol );
|
|
//
|
|
// if ( !GC_CHECK_PTR ( found_symbol ) ) {
|
|
// found_symbol = order_symbol::create ( symbol );
|
|
// order_layer_symbols.add ( found_symbol );
|
|
// }
|
|
//
|
|
// found_symbol.set_contains_direction ( c_order::is_buy_direction ( kernel_order::type() ) );
|
|
// }
|
|
//
|
|
// continue;
|
|
// }
|
|
//
|
|
// if ( !LAYER_ORDER_CHECK_MAGIC ( magic_number ) ) {
|
|
// continue;
|
|
// }
|
|
//
|
|
// LIST_FOREACH ( order_layer_orders, layer_order_data *, item, {
|
|
// if ( !LAYER_ORDER_CHECK_TYPE ( item.settings.order_type, item.settings.order_stop_type ) ) {
|
|
// continue;
|
|
// }
|
|
//
|
|
// c_order *for_add = factory_c_order::get();
|
|
// refresh_order ( for_add );
|
|
//
|
|
// if ( !GC_CHECK_PTR ( item.min_order )
|
|
// || ( !item.is_buy_direction && for_add.open_price < item.min_order.open_price )
|
|
// || ( item.is_buy_direction && for_add.open_price > item.min_order.open_price ) ) {
|
|
// item.min_order = for_add;
|
|
// }
|
|
//
|
|
// if ( !GC_CHECK_PTR ( item.max_order )
|
|
// || ( !item.is_buy_direction && for_add.open_price > item.max_order.open_price )
|
|
// || ( item.is_buy_direction && for_add.open_price < item.max_order.open_price ) ) {
|
|
// item.max_order = for_add;
|
|
// }
|
|
//
|
|
// item.orders.add ( for_add );
|
|
// item.count.inc_by_type ( for_add.order_type );
|
|
//
|
|
// ACTION_ON_VALUE_OR_DEFAULT ( order_layer_symbols, get_order_layer_symbol_current_symbol().set_contains_direction ( item.is_buy_direction ) );
|
|
// break;
|
|
// } );
|
|
// }
|
|
//#endif
|
|
}
|
|
|
|
// Вызывает после удаление ордеров надо бы как то это обыграть
|
|
static void refresh ( layer_order_setting *settings_ptr ) {
|
|
layer_order_data *pair = get_by_setting ( settings_ptr );
|
|
|
|
pair.orders.clear_without_dispoce();
|
|
pair.count.clear();
|
|
|
|
int ordersCount = kernel_order::count();
|
|
|
|
for ( int i = 0; i < ordersCount; i++ ) {
|
|
if ( !kernel_order::select_by_index ( i )
|
|
|| !LAYER_ORDER_CHECK_SYMBOL ( CURRENT_SYMBOL )
|
|
|| !LAYER_ORDER_CHECK_MAGIC ( pair.settings.magic_number )
|
|
|| !LAYER_ORDER_CHECK_TYPE ( pair.settings.order_type, pair.settings.order_stop_type ) ) {
|
|
continue;
|
|
}
|
|
|
|
|
|
c_order *for_add = factory_c_order::get();
|
|
refresh_order ( for_add );
|
|
pair.orders.add ( for_add );
|
|
pair.count.inc_by_type ( for_add.order_type );
|
|
}
|
|
}
|
|
|
|
static void push ( layer_order_setting *settings_ptr, TICKET_TYPE ticket ) {
|
|
bool t = !kernel_order::select_by_ticket ( ticket );
|
|
if ( /*!kernel_order::select_by_ticket ( ticket )*/ t ) {
|
|
return;
|
|
}
|
|
|
|
layer_order_data *collection = get_by_setting ( settings_ptr );
|
|
|
|
c_order *for_add = factory_c_order::get();
|
|
refresh_order ( for_add );
|
|
for_add.lvl = collection.orders.count + 1;
|
|
|
|
collection.orders.add ( for_add );
|
|
collection.max_order = for_add;
|
|
}
|
|
|
|
static void refresh ( layer_order_setting *settings_ptr, TICKET_TYPE ticket ) {
|
|
if ( !kernel_order::select_by_ticket ( ticket ) ) {
|
|
return;
|
|
}
|
|
|
|
list<c_order *> *orders = get ( settings_ptr );
|
|
LIST_FIRST_OR_DEFAULT ( orders, result, c_order *, item, item.ticket == ticket );
|
|
ACTION_ON_VALUE_OR_DEFAULT ( result, refresh_order ( result ) );
|
|
}
|
|
|
|
static list<c_order *> *get ( layer_order_setting *settings_ptr ) {
|
|
layer_order_data *collection = get_by_setting ( settings_ptr );
|
|
|
|
if ( !collection.is_sorted ) {
|
|
collection.is_sorted = true;
|
|
|
|
LIST_SORT_BUBBLE ( collection.orders,
|
|
open_price,
|
|
!collection.is_buy_direction );
|
|
LIST_FOREACH2 ( collection.orders,
|
|
c_order *,
|
|
item,
|
|
item.lvl = i_kdaskdgfgf + 1 );
|
|
}
|
|
|
|
return GET_VALUE_OR_DEFAULT ( collection, collection.orders );
|
|
}
|
|
|
|
static order_count_t *get_count ( layer_order_setting *settings_ptr ) {
|
|
layer_order_data *collection = get_by_setting ( settings_ptr );
|
|
return GET_VALUE_OR_DEFAULT ( collection, collection.count );
|
|
}
|
|
|
|
static c_order *get_min ( layer_order_setting *settings_ptr ) {
|
|
layer_order_data *collection = get_by_setting ( settings_ptr );
|
|
return GET_VALUE_OR_DEFAULT ( collection, collection.min_order );
|
|
}
|
|
|
|
static c_order *get_max ( layer_order_setting *settings_ptr ) {
|
|
layer_order_data *collection = get_by_setting ( settings_ptr );
|
|
return GET_VALUE_OR_DEFAULT ( collection, collection.max_order );
|
|
}
|
|
|
|
static int get_pair_count() {
|
|
return GET_VALUE_OR_MANUAL ( order_layer_symbols, order_layer_symbols.count, 0 );
|
|
}
|
|
|
|
static int get_base_count ( bool is_buy_direction ) {
|
|
if ( !GC_CHECK_PTR ( order_layer_symbols ) ) {
|
|
return 0;
|
|
}
|
|
|
|
order_symbol *check_symbol = get_order_layer_symbol_current_symbol();
|
|
LIST_COUNT ( order_layer_symbols,
|
|
result,
|
|
order_symbol *,
|
|
item,
|
|
item.check_base ( is_buy_direction, check_symbol ) );
|
|
return result;
|
|
}
|
|
|
|
static int get_profit_count ( bool is_buy_direction ) {
|
|
if ( !GC_CHECK_PTR ( order_layer_symbols ) ) {
|
|
return 0;
|
|
}
|
|
|
|
order_symbol *check_symbol = get_order_layer_symbol_current_symbol();
|
|
LIST_COUNT ( order_layer_symbols,
|
|
result,
|
|
order_symbol *,
|
|
item,
|
|
item.check_profit ( is_buy_direction, check_symbol ) );
|
|
return result;
|
|
}
|
|
|
|
static c_order *get_history_last_order ( layer_order_setting *settings_ptr ) {
|
|
layer_order_data *pair = get_by_setting ( settings_ptr );
|
|
|
|
for ( int i = kernel_order::count_history() - 1; i >= 0; i-- ) {
|
|
if ( !kernel_order::select_by_index_history ( i )
|
|
|| !LAYER_ORDER_CHECK_SYMBOL ( CURRENT_SYMBOL )
|
|
|| !LAYER_ORDER_CHECK_MAGIC ( pair.settings.magic_number )
|
|
|| !LAYER_ORDER_CHECK_TYPE ( pair.settings.order_type, pair.settings.order_stop_type ) ) {
|
|
continue;
|
|
}
|
|
|
|
c_order *result = factory_c_order::get();
|
|
refresh_order ( result );
|
|
return result;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static bool close_all ( int magic_number,
|
|
enum_order_operation_type order_type,
|
|
enum_order_operation_type order_stop_type,
|
|
int slippage ) {
|
|
bool result = false;
|
|
color order_color = c_order::get_order_color ( order_type );
|
|
|
|
for ( int i = 0; i < 3 && !result; i++ ) {
|
|
result = close_by_market ( magic_number,
|
|
order_type,
|
|
order_stop_type,
|
|
slippage,
|
|
order_color );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool close_by_market ( int magic_number,
|
|
enum_order_operation_type order_type,
|
|
enum_order_operation_type order_stop_type,
|
|
int slippage,
|
|
color order_color ) {
|
|
//#ifdef MQL4
|
|
for ( int i = kernel_order::count() - 1; i >= 0; i-- ) {
|
|
//#endif
|
|
//#ifdef MQL5
|
|
// for ( int i = kernel_order::positions_count() - 1; i >= 0; i-- ) {
|
|
//#endif
|
|
if ( !kernel_order::select_by_index ( i ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( !LAYER_ORDER_CHECK_SYMBOL ( CURRENT_SYMBOL )
|
|
|| !LAYER_ORDER_CHECK_MAGIC ( magic_number )
|
|
|| !LAYER_ORDER_CHECK_TYPE ( order_type, order_stop_type ) ) {
|
|
continue;
|
|
}
|
|
|
|
log_info_k ( StringFormat ( SRC_ORDER_TRY_CLOSE_ORDER, IntegerToString ( kernel_order::ticket() ) ) );
|
|
|
|
bool is_close = c_order::is_order_stop ( kernel_order::type() ) ?
|
|
kernel_order::delete_stop ( kernel_order::ticket(), order_color ) :
|
|
kernel_order::close ( kernel_order::ticket(),
|
|
kernel_order::lots(),
|
|
layer_market::price_close ( kernel_order::type() ),
|
|
slippage,
|
|
order_color );
|
|
|
|
if ( !is_close ) {
|
|
log_info_k ( SRC_ORDER_FAIL_CLOSE_ORDER );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//#ifdef MQL5
|
|
// for ( int i = kernel_order::orders_count() - 1; i >= 0; i-- ) {
|
|
// if ( !kernel_order::select_order_by_index ( i ) ) {
|
|
// return false;
|
|
// }
|
|
//
|
|
// if ( !LAYER_ORDER_CHECK_SYMBOL ( CURRENT_SYMBOL )
|
|
// || !LAYER_ORDER_CHECK_MAGIC ( magic_number )
|
|
// || !LAYER_ORDER_CHECK_TYPE ( order_type, order_stop_type ) ) {
|
|
// continue;
|
|
// }
|
|
//
|
|
// log_info_k ( StringFormat ( SRC_ORDER_TRY_CLOSE_ORDER, IntegerToString ( kernel_order::ticket() ) ) );
|
|
//
|
|
//// bool is_close = kernel_order::delete_stop ( kernel_order::ticket(), order_color );
|
|
// bool is_close = c_order::is_order_stop ( kernel_order::type() ) ?
|
|
// kernel_order::delete_stop ( kernel_order::ticket(), order_color ) :
|
|
// kernel_order::close ( kernel_order::ticket(),
|
|
// kernel_order::lots(),
|
|
// layer_market::price_close ( kernel_order::type() ),
|
|
// slippage,
|
|
// order_color );
|
|
//
|
|
// if ( !is_close ) {
|
|
// log_info_k ( SRC_ORDER_FAIL_CLOSE_ORDER );
|
|
// return false;
|
|
// }
|
|
// }
|
|
//#endif
|
|
return true;
|
|
}
|
|
|
|
static list<layer_order_data *> *get_all() {
|
|
return order_layer_orders;
|
|
}
|
|
|
|
static layer_order_data *get_by_setting ( layer_order_setting *settings_ptr ) {
|
|
return order_layer_orders.items[settings_ptr.order_type == order_operation_buy ? 0 : 1];
|
|
}
|
|
|
|
//private:
|
|
|
|
static void refresh_order ( c_order *value ) {
|
|
value.symbol = kernel_order::symbol();
|
|
value.magic_number = kernel_order::magic_number();
|
|
value.order_type = kernel_order::type();
|
|
value.ticket = kernel_order::ticket();
|
|
value.lot = kernel_order::lots();
|
|
value.open_price = kernel_order::open_price();
|
|
value.stop_loss = kernel_order::stop_loss();
|
|
value.take_profit = kernel_order::take_profit();
|
|
value.commission = kernel_order::commission();
|
|
value.swap = kernel_order::swap();
|
|
value.open_time = kernel_order::open_time();
|
|
value.close_time = kernel_order::close_time();
|
|
}
|
|
};
|
|
|
|
#endif |