#ifndef SCHEDULER_MQH #define SCHEDULER_MQH #define MIN_DATE D'1970.01.01 00:00:00' enum day_of_week_t { day_of_week_t_sunday = 0, day_of_week_t_monday = 1, day_of_week_t_tuesday = 2, day_of_week_t_wednesday = 3, day_of_week_t_thursday = 4, day_of_week_t_friday = 5, day_of_week_t_saturday = 6 }; //TODO: почему-то нельзя сделать внутри класса ... блядский mql bool scheduler_is_trade_enabled; day_of_week_t scheduler_trade_start_day; int scheduler_start_hour; int scheduler_start_minutes; int scheduler_start_total_minutes; day_of_week_t scheduler_trade_end_day; int scheduler_end_hour; int scheduler_end_minutes; int scheduler_end_total_minutes; bool scheduler_new_position_pause_enabled; datetime scheduler_new_position_pause_start[]; datetime scheduler_new_position_pause_end[]; char scheduler_new_position_pause_newyear_day_start; char scheduler_new_position_pause_newyear_day_end; bool scheduler_is_trade_pause_enabled; datetime scheduler_start_pause[]; datetime scheduler_end_pause[]; bool scheduler_is_intraday_enabled; int scheduler_start_intraday_hour[]; int scheduler_start_intraday_minutes[]; int scheduler_start_intraday_total_minutes[]; int scheduler_end_intraday_hour[]; int scheduler_end_intraday_minutes[]; int scheduler_end_intraday_total_minutes[]; bool scheduler_is_intraday_stop_trade_enabled; int scheduler_start_intraday_stop_trade_hour[]; int scheduler_start_intraday_stop_trade_minutes[]; int scheduler_start_intraday_stop_trade_total_minutes[]; int scheduler_end_intraday_stop_trade_hour[]; int scheduler_end_intraday_stop_trade_minutes[]; int scheduler_end_intraday_stop_trade_total_minutes[]; bool scheduler_close_all_orders_enabled; int scheduler_close_all_orders_hour; int scheduler_close_all_orders_minute; int scheduler_close_all_orders_total_minute; int scheduler_close_all_orders_total_minute_with_wait; class scheduler_close_all_orders_locker { public: layer_order_setting *settings; bool lock; }; list *scheduler_close_all_orders_lockers; class scheduler { private: static int get_current_total_minutes() { _IN1(""); TOOL_CACHED_TICK ( int, _current_total_minutes, _current_total_minutes = 60 * kernel_time::get_hour ( layer::time_current() ) + kernel_time::get_minute ( layer::time_current() ) ); } public: static void set_trade ( day_of_week_t start_day, int start_hour, int start_minute, day_of_week_t end_day, int end_hour, int end_minute ) { _IN1(""); scheduler_trade_start_day = start_day; scheduler_start_hour = start_hour; scheduler_start_minutes = start_minute; scheduler_start_total_minutes = ( 60 * start_hour ) + start_minute; scheduler_trade_end_day = end_day; scheduler_end_hour = end_hour; scheduler_end_minutes = end_minute; scheduler_end_total_minutes = ( 60 * end_hour ) + end_minute; scheduler_is_trade_enabled = true; } static void reset_trade () { _IN1(""); scheduler_is_trade_enabled = false; } #define declare_new_position_pause( number ) \ datetime start##number, datetime end##number #define declare_set_new_position_pause( number ) \ scheduler_new_position_pause_start[number] = start##number; \ scheduler_new_position_pause_end[number] = end##number; static void set_new_position_pause ( declare_new_position_pause ( 0 ), declare_new_position_pause ( 1 ), declare_new_position_pause ( 2 ), declare_new_position_pause ( 3 ), declare_new_position_pause ( 4 ), declare_new_position_pause ( 5 ), declare_new_position_pause ( 6 ), declare_new_position_pause ( 7 ), declare_new_position_pause ( 8 ), declare_new_position_pause ( 9 ), char new_position_pause_newyear_day_start, char new_position_pause_newyear_day_end ) { _IN1(""); ArrayResize ( scheduler_new_position_pause_start, 10 ); ArrayInitialize ( scheduler_new_position_pause_start, MIN_DATE ); ArrayResize ( scheduler_new_position_pause_end, 10 ); ArrayInitialize ( scheduler_new_position_pause_end, MIN_DATE ); declare_set_new_position_pause ( 0 ); declare_set_new_position_pause ( 1 ); declare_set_new_position_pause ( 2 ); declare_set_new_position_pause ( 3 ); declare_set_new_position_pause ( 4 ); declare_set_new_position_pause ( 5 ); declare_set_new_position_pause ( 6 ); declare_set_new_position_pause ( 7 ); declare_set_new_position_pause ( 8 ); declare_set_new_position_pause ( 9 ); scheduler_new_position_pause_newyear_day_start=new_position_pause_newyear_day_start; scheduler_new_position_pause_newyear_day_end=new_position_pause_newyear_day_end; scheduler_new_position_pause_enabled = true; } static void reset_new_position_pause () { _IN1(""); scheduler_new_position_pause_enabled = false; } #define declare_intraday_range( number ) \ int start_hour_##number, \ int start_minute_##number, \ int end_hour_##number, \ int end_minute_##number #define set_intraday_range( number ) \ scheduler_start_intraday_hour[number] = start_hour_##number; \ scheduler_start_intraday_minutes[number] = start_minute_##number; \ scheduler_start_intraday_total_minutes[number] = ( 60 * start_hour_##number ) + start_minute_##number; \ scheduler_end_intraday_hour[number] = end_hour_##number; \ scheduler_end_intraday_minutes[number] = end_minute_##number; \ scheduler_end_intraday_total_minutes[number] = ( 60 * end_hour_##number ) + end_minute_##number; static void set_intraday ( declare_intraday_range ( 0 ), declare_intraday_range ( 1 ), declare_intraday_range ( 2 ), declare_intraday_range ( 3 ), declare_intraday_range ( 4 ), declare_intraday_range ( 5 ), declare_intraday_range ( 6 ), declare_intraday_range ( 7 ), declare_intraday_range ( 8 ), declare_intraday_range ( 9 ) ) { _IN1(""); ArrayResize ( scheduler_start_intraday_hour, 10 ); ArrayInitialize ( scheduler_start_intraday_hour, 0 ); ArrayResize ( scheduler_start_intraday_minutes, 10 ); ArrayInitialize ( scheduler_start_intraday_minutes, 0 ); ArrayResize ( scheduler_start_intraday_total_minutes, 10 ); ArrayInitialize ( scheduler_start_intraday_total_minutes, 0 ); ArrayResize ( scheduler_end_intraday_hour, 10 ); ArrayInitialize ( scheduler_end_intraday_hour, 0 ); ArrayResize ( scheduler_end_intraday_minutes, 10 ); ArrayInitialize ( scheduler_end_intraday_minutes, 0 ); ArrayResize ( scheduler_end_intraday_total_minutes, 10 ); ArrayInitialize ( scheduler_end_intraday_total_minutes, 0 ); set_intraday_range ( 0 ); set_intraday_range ( 1 ); set_intraday_range ( 2 ); set_intraday_range ( 3 ); set_intraday_range ( 4 ); set_intraday_range ( 5 ); set_intraday_range ( 6 ); set_intraday_range ( 7 ); set_intraday_range ( 8 ); set_intraday_range ( 9 ); scheduler_is_intraday_enabled = true; } static void reset_intraday_stop_trade() { _IN1(""); scheduler_is_intraday_stop_trade_enabled = false; } #define declare_trade_pause( number ) \ datetime start##number, datetime end##number #define set_pause( number ) \ scheduler_start_pause[number] = start##number; \ scheduler_end_pause[number] = end##number; static void set_trade_pause ( declare_trade_pause ( 0 ), declare_trade_pause ( 1 ), declare_trade_pause ( 2 ), declare_trade_pause ( 3 ), declare_trade_pause ( 4 ), declare_trade_pause ( 5 ), declare_trade_pause ( 6 ), declare_trade_pause ( 7 ), declare_trade_pause ( 8 ), declare_trade_pause ( 9 ) ) { _IN1(""); ArrayResize ( scheduler_start_pause, 10 ); ArrayInitialize ( scheduler_start_pause, MIN_DATE ); ArrayResize ( scheduler_end_pause, 10 ); ArrayInitialize ( scheduler_end_pause, MIN_DATE ); set_pause ( 0 ); set_pause ( 1 ); set_pause ( 2 ); set_pause ( 3 ); set_pause ( 4 ); set_pause ( 5 ); set_pause ( 6 ); set_pause ( 7 ); set_pause ( 8 ); set_pause ( 9 ); scheduler_is_trade_pause_enabled = true; } static void reset_trade_pause () { _IN1(""); scheduler_is_trade_pause_enabled = false; } #define declare_intraday_stop_trade_range( number ) \ int start_hour_##number, \ int start_minute_##number, \ int end_hour_##number, \ int end_minute_##number #define set_intraday_stop_trade_range( number ) \ scheduler_start_intraday_stop_trade_hour[number] = start_hour_##number; \ scheduler_start_intraday_stop_trade_minutes[number] = start_minute_##number; \ scheduler_start_intraday_stop_trade_total_minutes[number] = ( 60 * start_hour_##number ) + start_minute_##number; \ scheduler_end_intraday_stop_trade_hour[number] = end_hour_##number; \ scheduler_end_intraday_stop_trade_minutes[number] = end_minute_##number; \ scheduler_end_intraday_stop_trade_total_minutes[number] = ( 60 * end_hour_##number ) + end_minute_##number; static void set_intraday_stop_trade ( declare_intraday_stop_trade_range ( 0 ), declare_intraday_stop_trade_range ( 1 ), declare_intraday_stop_trade_range ( 2 ), declare_intraday_stop_trade_range ( 3 ), declare_intraday_stop_trade_range ( 4 ), declare_intraday_stop_trade_range ( 5 ), declare_intraday_stop_trade_range ( 6 ), declare_intraday_stop_trade_range ( 7 ), declare_intraday_stop_trade_range ( 8 ), declare_intraday_stop_trade_range ( 9 ) ) { _IN1(""); ArrayResize ( scheduler_start_intraday_stop_trade_hour, 10 ); ArrayInitialize ( scheduler_start_intraday_stop_trade_hour, 0 ); ArrayResize ( scheduler_start_intraday_stop_trade_minutes, 10 ); ArrayInitialize ( scheduler_start_intraday_stop_trade_minutes, 0 ); ArrayResize ( scheduler_start_intraday_stop_trade_total_minutes, 10 ); ArrayInitialize ( scheduler_start_intraday_stop_trade_total_minutes, 0 ); ArrayResize ( scheduler_end_intraday_stop_trade_hour, 10 ); ArrayInitialize ( scheduler_end_intraday_stop_trade_hour, 0 ); ArrayResize ( scheduler_end_intraday_stop_trade_minutes, 10 ); ArrayInitialize ( scheduler_end_intraday_stop_trade_minutes, 0 ); ArrayResize ( scheduler_end_intraday_stop_trade_total_minutes, 10 ); ArrayInitialize ( scheduler_end_intraday_stop_trade_total_minutes, 0 ); set_intraday_stop_trade_range ( 0 ); set_intraday_stop_trade_range ( 1 ); set_intraday_stop_trade_range ( 2 ); set_intraday_stop_trade_range ( 3 ); set_intraday_stop_trade_range ( 4 ); set_intraday_stop_trade_range ( 5 ); set_intraday_stop_trade_range ( 6 ); set_intraday_stop_trade_range ( 7 ); set_intraday_stop_trade_range ( 8 ); set_intraday_stop_trade_range ( 9 ); scheduler_is_intraday_stop_trade_enabled = true; } static void reset_intraday () { _IN1(""); scheduler_is_intraday_enabled = false; } static void set_close_all_orders ( int hour, int minute ) { _IN1(""); scheduler_close_all_orders_hour = hour; scheduler_close_all_orders_minute = minute; scheduler_close_all_orders_total_minute = ( 60 * hour ) + minute; scheduler_close_all_orders_total_minute_with_wait = scheduler_close_all_orders_total_minute + 3; scheduler_close_all_orders_enabled = true; scheduler_close_all_orders_lockers = new list(); gc::push ( gc_dispose_type_on_end_deinit, scheduler_close_all_orders_lockers ); } static void reset_close_all_orders() { _IN1(""); scheduler_close_all_orders_enabled = false; } static bool is_trade_time() { _IN1(""); return pre_check_trade_pause(); } static bool is_trade_time_for_first_order() { _IN1(""); return pre_check_new_position_pause() && pre_check_trade_on_week() && pre_check_intraday(); } static bool is_stop_trade_time() { _IN1(""); return pre_check_intraday_stop_trade(); } static bool is_close_all_orders ( layer_order_setting *settings_ptr ) { _IN1(""); return pre_check_close_all_orders ( settings_ptr ); } private: static bool pre_check_trade_on_week() { _IN1(""); if ( check_trade_on_week() ) { _IN2(""); return true; } log_info ( StringFormat ( SRC_SCHEDULER_IS_NOT_TRADE_TIME_ON_WEEK, get_day_of_week_str ( scheduler_trade_start_day ), scheduler_start_hour, scheduler_start_minutes, get_day_of_week_str ( scheduler_trade_end_day ), scheduler_end_hour, scheduler_end_minutes ) ); return false; } static bool check_trade_on_week() { _IN1(""); if ( !scheduler_is_trade_enabled ) { _IN2(""); return true; } int day = kernel_time::get_day_of_week(); if ( scheduler_trade_start_day > day || scheduler_trade_end_day < day ) { _IN2(""); return false; } int total_minutes = get_current_total_minutes(); if ( ( scheduler_trade_start_day == day && scheduler_start_total_minutes >= total_minutes ) || ( scheduler_trade_end_day == day && scheduler_end_total_minutes < total_minutes ) ) { _IN2(""); return false; } return true; } static bool pre_check_new_position_pause() { _IN1(""); int new_position_pause_index = get_new_position_pause_index(); if ( new_position_pause_index == -1 ) { _IN2(""); return true; } string from_time,to_time; if ( new_position_pause_index == -2 ) { datetime current_time = layer::time_current(); MqlDateTime dt; int year_s=MIN_DATE,year_e=MIN_DATE; if (TimeToStruct(current_time,dt)){ year_s=(dt.mon==12)?dt.year:(dt.year-1); year_e=(dt.mon==1)?dt.year:(dt.year+1); } from_time = StringFormat("%d.12.%d 00:00:00",scheduler_new_position_pause_newyear_day_start,year_s); to_time = StringFormat("%d.01.%d 00:00:00",scheduler_new_position_pause_newyear_day_end,year_e); } else { from_time = TimeToString ( scheduler_new_position_pause_start[new_position_pause_index], TIME_DATE | TIME_MINUTES ); to_time = TimeToString ( scheduler_new_position_pause_end[new_position_pause_index], TIME_DATE | TIME_MINUTES ); } log_info ( StringFormat ( SRC_SCHEDULER_NEW_POSITION_PAUSE, from_time, to_time ) ); return false; } /* Проверяет не установлена ли пауза в открытии новой позиции Возвращает индекс элементов массива для которого установлена пауза либо -1 если шедулер не активен, -2 если установлена пауза в обход нового года */ static int get_new_position_pause_index() { _IN1(""); if ( !scheduler_new_position_pause_enabled ) { _IN2(""); return -1; } datetime current_time = layer::time_current(); int size = ArraySize ( scheduler_new_position_pause_start ); if (scheduler_new_position_pause_newyear_day_start||scheduler_new_position_pause_newyear_day_end){ MqlDateTime dt; if (TimeToStruct(current_time,dt)){ if (scheduler_new_position_pause_newyear_day_start && dt.mon==12 && dt.day>=scheduler_new_position_pause_newyear_day_start) return -2; if (scheduler_new_position_pause_newyear_day_end && dt.mon==1 && dt.day < scheduler_new_position_pause_newyear_day_end) return -2; } } for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_new_position_pause_start[i] != MIN_DATE && scheduler_new_position_pause_end[i] != MIN_DATE && current_time >= scheduler_new_position_pause_start[i] && current_time < scheduler_new_position_pause_end[i] ) { _IN3(""); return i; } } return -1; } static bool pre_check_trade_pause() { _IN1(""); int trade_pause_index = get_trade_pause_index(); if ( trade_pause_index == -1 ) { _IN2(""); return true; } string from_time = TimeToString ( scheduler_start_pause[trade_pause_index], TIME_DATE | TIME_MINUTES ); string to_time = TimeToString ( scheduler_end_pause[trade_pause_index], TIME_DATE | TIME_MINUTES ); log_info ( StringFormat ( SRC_SCHEDULER_IS_TRADE_PAUSE, from_time, to_time ) ); return false; } static int get_trade_pause_index() { _IN1(""); if ( !scheduler_is_trade_pause_enabled ) { _IN2(""); return -1; } datetime current_time = layer::time_current(); int size = ArraySize ( scheduler_start_pause ); for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_pause[i] != MIN_DATE && scheduler_end_pause[i] != MIN_DATE && current_time >= scheduler_start_pause[i] && current_time < scheduler_end_pause[i] ) { _IN3(""); return i; } } return -1; } static bool pre_check_intraday() { _IN1(""); if ( check_intraday() ) { _IN2(""); return true; } int near_intraday_index = get_near_intraday_index(); log_info ( StringFormat ( SRC_SCHEDULER_IS_NOR_INTRADAY, scheduler_start_intraday_hour[near_intraday_index], scheduler_start_intraday_minutes[near_intraday_index], scheduler_end_intraday_hour[near_intraday_index], scheduler_end_intraday_minutes[near_intraday_index] ) ); return false; } static bool check_intraday() { _IN1(""); if ( !scheduler_is_intraday_enabled ) { _IN2(""); return true; } int total_minutes = get_current_total_minutes(); bool is_all_same = true; int size = ArraySize ( scheduler_start_intraday_total_minutes ); for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_intraday_total_minutes[i] == scheduler_end_intraday_total_minutes[i] ) { _IN3(""); continue; } is_all_same = false; if ( check_total_minutes_range ( scheduler_start_intraday_total_minutes[i], total_minutes, scheduler_end_intraday_total_minutes[i] ) ) { _IN3(""); return true; } } return is_all_same; } static int get_near_intraday_index() { _IN1(""); int result = -1; int distance = 1440; int total_minutes = get_current_total_minutes(); // Ищем ближайшее время внутри дня текущего дня int size = ArraySize ( scheduler_start_intraday_total_minutes ); for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_intraday_total_minutes[i] == scheduler_end_intraday_total_minutes[i] ) { _IN3(""); continue; } int tmp_distance = scheduler_start_intraday_total_minutes[i] - total_minutes; if ( tmp_distance < 0 ) { _IN3(""); continue; } if (distance > tmp_distance){ distance = tmp_distance; result = i; } } if ( result != -1 ) { _IN2(""); return result; } // Ищем ближайшее время внутри дня следующего дня for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_intraday_total_minutes[i] == scheduler_end_intraday_total_minutes[i] ) { _IN3(""); continue; } if ( distance > scheduler_start_intraday_total_minutes[i] ) { _IN3(""); distance = scheduler_start_intraday_total_minutes[i]; result = i; } } return result; } static bool pre_check_intraday_stop_trade() { _IN1(""); if ( !check_intraday_stop_trade() ) { _IN2(""); return false; } int near_intraday_index = get_near_intraday_stop_trade_index(); log_info ( StringFormat ( SRC_SCHEDULER_IS_NOR_INTRADAY_STOP_TRADE, scheduler_start_intraday_stop_trade_hour[near_intraday_index], scheduler_start_intraday_stop_trade_minutes[near_intraday_index], scheduler_end_intraday_stop_trade_hour[near_intraday_index], scheduler_end_intraday_stop_trade_minutes[near_intraday_index] ) ); return true; } static bool check_intraday_stop_trade() { _IN1(""); if ( !scheduler_is_intraday_stop_trade_enabled ) { _IN2(""); return false; } int total_minutes = get_current_total_minutes(); int size = ArraySize ( scheduler_start_intraday_stop_trade_total_minutes ); for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_intraday_stop_trade_total_minutes[i] != scheduler_end_intraday_stop_trade_total_minutes[i] && check_total_minutes_range ( scheduler_start_intraday_stop_trade_total_minutes[i], total_minutes, scheduler_end_intraday_stop_trade_total_minutes[i] ) ) { _IN3(""); return true; } } return false; } static int get_near_intraday_stop_trade_index() { _IN1(""); int result = -1; int distance = 1440; int total_minutes = get_current_total_minutes(); // Ищем ближайшее время внутри дня текущего дня int size = ArraySize ( scheduler_start_intraday_stop_trade_total_minutes ); for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_intraday_stop_trade_total_minutes[i] == scheduler_end_intraday_stop_trade_total_minutes[i] ) { _IN3(""); continue; } int tmp_distance = scheduler_start_intraday_stop_trade_total_minutes[i] - total_minutes; if ( tmp_distance < 0 || tmp_distance < distance ) { _IN3(""); continue; } distance = tmp_distance; result = i; } if ( result != -1 ) { _IN2(""); return result; } // Ищем ближайшее время внутри дня следующего дня for ( int i = 0; i < size; i++ ) { _IN2(""); if ( scheduler_start_intraday_stop_trade_total_minutes[i] == scheduler_end_intraday_stop_trade_total_minutes[i] ) { _IN3(""); continue; } if ( distance > scheduler_start_intraday_stop_trade_total_minutes[i] ) { _IN3(""); distance = scheduler_start_intraday_stop_trade_total_minutes[i]; result = i; } } return result; } static bool pre_check_close_all_orders ( layer_order_setting *settings_ptr ) { _IN1(""); if ( !check_close_all_orders ( settings_ptr ) ) { _IN2(""); return false; } log_info_k ( StringFormat ( SRC_SCHEDULER_CLOSE_ALLORDERS_EVERYDAY, scheduler_close_all_orders_hour, scheduler_close_all_orders_minute ) ); return true; } static bool check_close_all_orders ( layer_order_setting *settings_ptr ) { _IN1(""); if ( !scheduler_close_all_orders_enabled ) { _IN2(""); return false; } LIST_FIRST_OR_DEFAULT ( scheduler_close_all_orders_lockers, locker, scheduler_close_all_orders_locker *, item, item.settings == settings_ptr ); ACTION_ON_NONVALUE_OR_DEFAULT ( locker, { _IN3(""); locker = new scheduler_close_all_orders_locker(); locker.settings = settings_ptr; locker.lock = false; scheduler_close_all_orders_lockers.add ( locker ); } ); bool result = check_total_minutes_range ( scheduler_close_all_orders_total_minute, get_current_total_minutes(), scheduler_close_all_orders_total_minute_with_wait ); if ( !result ) { _IN2(""); locker.lock = false; return false; } if ( locker.lock ) { _IN2(""); return false; } locker.lock = true; return true; } static bool check_total_minutes_range ( int start_range, int value, int end_range ) { _IN1(""); return start_range <= value && value < end_range; } static string get_day_of_week_str ( int day_of_week ) { _IN1(""); switch ( day_of_week ) { case 0: return SRC_SCHEDULER_SUNDAY; case 1: return SRC_SCHEDULER_MONDAY; case 2: return SRC_SCHEDULER_TUESDAY; case 3: return SRC_SCHEDULER_WEDNESDAY; case 4: return SRC_SCHEDULER_THURSDAY; case 5: return SRC_SCHEDULER_FRIDAY; case 6: return SRC_SCHEDULER_SATURDAY; default: return ""; } } }; #endif