#ifndef SETKA_MQH #define SETKA_MQH // Использование библиотеки CLog4mql #ifdef USE_LOG4MQL #include "..\Libs\log4mql.mqh" CLog4mql* log4 = CLog4mql::getInstance(); #else #define _TRACE(msg) ; #define _DEBUG(msg) ; #define _INFO(msg) ; #define _WARN(msg) ; #define _ERROR(msg) ; #define _CRIT(msg) ; #define _B2S(B) ((B)?"True":"False") #define _CHECK_TRACE(name,cache, val) ; #endif #ifdef TRACE #define adx m5t_adx #include #undef adx #else #define _IN(desc) ; #define _IN1(desc) ; #define _IN2(desc) ; #define _IN3(desc) ; #define _IN4(desc) ; #define _IN5(desc) ; #define _WATCH(w, v) ; #define _BRKUSES(u) ; #endif // TRACE #include "enum/enum.mqh" #include "defines.mqh" #include "logic_handler.mqh" #include "api.mqh" #ifndef FOR_OPTIMIZATION #include "..\Libs\CtrlPanel\CtrlPanel.mqh" CCtrlPanelBase* CtrlPanel=NULL; #endif //FOR_OPTIMIZATION #property version VER #define TOSTR(A) " " + #A + " = " + (string)Tick.A logic_handler *short_hd; logic_handler *long_hd; timer_t *life_timer; bool _init_failed = false; #ifdef FOR_OPTIMIZATION int _last_order_count; MqlDateTime _prev_date; //datetime _prev_date; #endif //FOR_OPTIMIZATION #ifdef USE_FILTERS #include "filters/entry_point.mqh" #endif #ifdef RSI_CCI #include "rsi_cci/calc_rc.mqh" #include "rsi_cci/entry_point.mqh" #endif #ifndef FOR_OPTIMIZATION #include "test/test.mqh" //#define B2S(B) B?"True":"False" void show_market_info() { _IN1(""); MqlTick Tick; SymbolInfoTick(CURRENT_SYMBOL,Tick); log_info ( StringFormat ( SRC_SETKA_MODE_LOW, dtos ( kernel_market::price_day_min ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_HIGH, dtos ( kernel_market::price_day_max ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_TIME, TimeToString ( kernel_market::tick_last_time ( ), TIME_DATE | TIME_MINUTES | TIME_SECONDS ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_BID, dtos ( layer_market::price_buy ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_ASK, dtos ( layer_market::price_sell ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_POINT, dtos ( layer_market::point ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_DIGITS, itos ( kernel_market::digits ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_SPREAD, itos ( layer_market::spread ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_STOPLEVEL, dtos ( layer_market::stop_level ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_LOTSIZE, dtos ( layer_market::lot_size ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_TICKVALUE, dtos ( layer_market::tick_value ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_TICKSIZE, dtos ( layer_market::tick_size ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_SWAPLONG, dtos ( kernel_market::swap_long ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_SWAPSHORT, dtos ( kernel_market::swap_short ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_STARTING, TimeToString ( kernel_market::starting ( ), TIME_DATE | TIME_MINUTES | TIME_SECONDS ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_EXPIRATION, TimeToString ( kernel_market::expiration ( ), TIME_DATE | TIME_MINUTES | TIME_SECONDS ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_TRADEALLOWED, kernel_market::trade_allowed ( ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MINLOT, dtos ( layer_market::lot_min ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_LOTSTEP, dtos ( layer_market::lot_step ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MAXLOT, dtos ( kernel_market::lot_max ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_SWAPTYPE, EnumToString ( kernel_market::swap_type ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_PROFITCALCMODE, EnumToString ( kernel_market::profit_calc_type ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MARGINCALCMODE, EnumToString ( kernel_market::margin_calc_type ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MARGININIT, dtos ( kernel_market::margin_init ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MARGINMAINTENANCE, dtos ( kernel_market::margin_maintenance ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MARGINHEDGED, dtos ( kernel_market::margin_hedged ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_MARGINREQUIRED, dtos ( layer_market::margin_required ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_MODE_FREEZELEVEL, dtos ( kernel_market::freeze_level ( ) ) ) ); log_info ( StringFormat ( SRC_SETKA_TERMINAL_VERSION_MSG, itos ( TerminalInfoInteger ( TERMINAL_BUILD ) ) ) ); log_info ( StringFormat ( SRC_SETKA_VERSION_MSG, VER, itos(BUILD), ttos(__DATETIME__),(" " + "time=" + TimeToString(Tick.time) + "." + ::IntegerToString(Tick.time_msc % 1000, 3, '0')) )); log_info ( StringFormat ( SRC_SETKA_ACCOUNT_COMPANY, kernel_account::company() ) ); log_info ( StringFormat ( SRC_SETKA_ACCOUNT_CURRENCY, layer_account::currency() ) ); log_info ( StringFormat ( SRC_SETKA_ACCOUNT_LEVERAGE, itos ( layer::account_leverage() ) ) ); log_info ( ext_string::get_hash ( itos ( kernel_account::number() ) ) ); log_info ( StringFormat ( SRC_SETKA_ACCOUNT_SERVER, kernel_account::server() ) ); log_info ( StringFormat ( SRC_SETKA_ACCOUNT_STOPOUT, itos ( (int)kernel_account::stopout_level() ) ) ); log_info ( StringFormat ( SRC_SETKA_ACCOUNT_STOPOUT_MODE, itos ( kernel_account::stopout_mode() ) ) ); } int OnInit() { _IN1(""); #ifdef TRACE //**************** ДОБАВЛЕНО TRACE m_traceview=new CTraceView; // создали отображение граф m_trace=new CTraceCtrl; // создали граф m_traceview.m_trace=m_trace; // подсоединили граф m_trace.m_traceview=m_traceview; // подсоединили отображение графа if(!kernel_account::is_testing()) m_traceview.Create(ChartID()); // создали чарт //**************** #endif //TRACE //--- //--- run timer if(!kernel_account::is_testing()) EventSetTimer(1); OnTimer(); //--- done _init_failed = false; gc::init(); tool_cache::update_instance_state(); if ( !layer_account::is_testing() ) { _IN2(""); life_timer = timer_t::create ( 60 ); gc::push ( gc_dispose_type_on_end_deinit, life_timer ); } show_market_info(); double lot_step = layer_market::lot_step (); int lot_exp = get_lot_exp_by_minlot ( lot_step ); log_info ( StringFormat ( SRC_SETKA_COUNT_SYMBOL_FOR_AVG, ( int ) lot_exp ) ); if ( lot_exp == -1 ) { _IN2(""); log_error ( StringFormat ( SRC_SETKA_NOT_GOOD_LOTSTEP, lot_step ) ); _init_failed = true; return INIT_FAILED; } if ( !defines_validate() ) { _IN2(""); log_error ( SRC_SETKA_VALID_NOT_GOOD ); _init_failed = true; return INIT_FAILED; } if ( !test::all() ) { _IN2(""); log_error ( SRC_SETKA_TEST_NOT_GOOD ); _init_failed = true; return INIT_FAILED; } log_info ( SRC_SETKA_TEST_GOOD ); setting_t *short_settings = defines_create ( false, lot_exp ); gc::push ( gc_dispose_type_on_end_deinit, short_settings ); setting_t *long_settings = defines_create ( true, lot_exp ); gc::push ( gc_dispose_type_on_end_deinit, long_settings ); layer_order::init(); short_hd = new logic_handler ( false, short_settings ); long_hd = new logic_handler ( true, long_settings ); int max_order_count = short_settings.max_open_orders + long_settings.max_open_orders; factory_c_order::init ( max_order_count ); factory_order_operation::init ( max_order_count ); if ( !layer_account::is_testing() ) { _IN2(""); api::set_short_handler ( short_hd ); api::set_long_handler ( long_hd ); api::set_times ( GlobalParamsUpdateTiming ); api::init(); } defines_init_scheduler(); #ifdef USE_FILTERS // Indicators intitialisation--- if( calc_adx::Init(short_settings) ){ _IN2(""); return(INIT_FAILED); }; if( calc_osc::Init(short_settings) ){ _IN2(""); return(INIT_FAILED); }; #endif #ifdef RSI_CCI if( calc_rc::Init(short_settings) ){ _IN2(""); return(INIT_FAILED); }; #endif //--- elavr 20201102 CtrlPanel CtrlPanel = CreateCtrlPanel(); if (CtrlPanel==NULL||!CtrlPanel.OnInitEvent()) { return(INIT_FAILED); } CtrlPanel.DrawPanelInfo(); log_info ( SRC_SETKA_INIT_COMPLETED ); return INIT_SUCCEEDED; } #else //FOR_OPTIMIZATION int OnInit() { _IN1(""); #ifdef TRACE //**************** ДОБАВЛЕНО TRACE m_traceview=new CTraceView; // создали отображение граф m_trace=new CTraceCtrl; // создали граф m_traceview.m_trace=m_trace; // подсоединили граф m_trace.m_traceview=m_traceview; // подсоединили отображение графа m_traceview.Create(ChartID()); // создали чарт //**************** #endif //TRACE //--- run timer if(!kernel_account::is_testing()) EventSetTimer(1); OnTimer(); //--- done ZeroMemory(_prev_date); _init_failed = false; if ( !layer_account::is_optimization() && !layer_account::is_testing() ) { _init_failed = true; Alert(StringFormat("%s", SRC_SETKA_ERROR_OPT_FOR_REAL) ); return INIT_FAILED; } gc::init(); tool_cache::update_instance_state(); double lot_step = layer_market::lot_step (); int lot_exp = get_lot_exp_by_minlot ( lot_step ); log_info ( StringFormat ( SRC_SETKA_COUNT_SYMBOL_FOR_AVG, ( int ) lot_exp ) ); if ( lot_exp == -1 ) { _IN2(""); log_error ( StringFormat ( SRC_SETKA_NOT_GOOD_LOTSTEP, lot_step ) ); _init_failed = true; return INIT_FAILED; } if ( !defines_validate() ) { _IN2(""); log_error ( SRC_SETKA_VALID_NOT_GOOD ); _init_failed = true; return INIT_PARAMETERS_INCORRECT; } setting_t *short_settings = defines_create ( false, lot_exp ); gc::push ( gc_dispose_type_on_end_deinit, short_settings ); setting_t *long_settings = defines_create ( true, lot_exp ); gc::push ( gc_dispose_type_on_end_deinit, long_settings ); layer_order::init(); short_hd = new logic_handler ( false, short_settings ); long_hd = new logic_handler ( true, long_settings ); int max_order_count = short_settings.max_open_orders + long_settings.max_open_orders; factory_c_order::init ( max_order_count ); factory_order_operation::init ( max_order_count ); defines_init_scheduler(); #ifdef RSI_CCI if( calc_rc::Init(short_settings) ){ _IN2(""); return(INIT_FAILED); }; #endif #ifdef USE_FILTERS // Indicators intitialisation--- if( calc_adx::Init(short_settings) ){ _IN2(""); return(INIT_FAILED); }; if( calc_osc::Init(short_settings) ){ _IN2(""); return(INIT_FAILED); }; #endif return INIT_SUCCEEDED; } #endif void OnDeinit ( const int reason ) { _IN1(""); string reason_str = error_deinit_reason ( reason ); if ( reason_str != NULL ) { _IN2(""); log_info ( StringFormat ( SRC_SETKA_DEINIT_REASON, reason_str ) ); } //--- elavr контрол панель #ifndef FOR_OPTIMIZATION if (CtrlPanel!=NULL) { CtrlPanel.OnDeinitEvent(reason); delete CtrlPanel; CtrlPanel=NULL; } #endif if ( short_hd != NULL ) { _IN2(""); delete short_hd; } if ( long_hd != NULL ) { _IN2(""); delete long_hd; } api::deinit(); gc::deinit(); #ifndef FOR_OPTIMIZATION //--- Log4MQL deinit // Использование библиотеки CLog4mql #ifdef USE_LOG4MQL log4.release(); #endif #endif #ifdef TRACE //**************** ДОБАВЛЕНО TRACE delete m_traceview; delete m_trace; //**************** #endif // TRACE //--- capteen 190422 #ifdef RSI_CCI calc_rc::Deinit(); #endif //--- capteen 190422 //--- capteen 190322 ---------------- #ifdef USE_FILTERS calc_adx::Deinit(); calc_osc::Deinit(); #endif Print ( StringFormat ( SRC_SETKA_DEINIT_REASON, BOT_NAME, VER, reason_str,TesterStatistics(STAT_GROSS_PROFIT),TesterStatistics(STAT_GROSS_LOSS),TesterStatistics(STAT_EQUITY_DD) ) ); } double get_recovery_factor() { _IN1(""); double rf = 0, tt = TesterStatistics( STAT_TRADES ), dd = TesterStatistics( STAT_EQUITY_DD ), ddp = TesterStatistics( STAT_EQUITYDD_PERCENT ), gp = TesterStatistics( STAT_GROSS_PROFIT ), gl = MathAbs(TesterStatistics( STAT_GROSS_LOSS )), ctl = TesterStatistics( STAT_MAX_CONLOSS_TRADES ); if (OnTester_Min_Trade!=0) { if (OnTester_Min_Trade>tt && tt>0) return -2; } if (OnTester_Max_DD_Percent!=0) { if (OnTester_Max_DD_Percent0) return -1; } rf= ( CP(dd) != 0.0) ? NormalizeDouble((gp - gl) / dd, 5) : TesterStatistics(STAT_RECOVERY_FACTOR); if (OnTester_Max_Conloss_Trades!=0) { if (ctl>OnTester_Max_Conloss_Trades) rf-=(ctl/100.0); } Print( StringFormat(SRC_SETKA_PROFIT_RECOVERY_FACTOR, TesterStatistics(STAT_PROFIT_FACTOR),rf)); return rf; } double OnTester( ) { _IN1(""); return get_recovery_factor(); } void OnTick() { _IN1(""); if ( _init_failed ) { _IN2(""); return; } pre_tick_handler(); tick_handler(); post_tick_handler(); //--- elavr контроль панель. #ifndef FOR_OPTIMIZATION if (CtrlPanel!=NULL && (CtrlPanel.IsEnableTickCalculateEvent())) { CtrlPanel.OnTickCalculateEvent(); if (CtrlPanel.IsReadyForUpdate()) CtrlPanel.DrawPanelInfo(); } #endif } //+------------------------------------------------------------------+ //| OnChartEvent | //+------------------------------------------------------------------+ void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { _IN1(""); //--- elavr контроль панель. #ifndef FOR_OPTIMIZATION if (CtrlPanel!=NULL) { CtrlPanel.OnEvent(id,lparam,dparam,sparam); } #endif #ifdef TRACE //**************** ДОБАВЛЕНО TRACE m_traceview.OnChartEvent(id, lparam, dparam, sparam); Sleep(50); //**************** #endif } //+------------------------------------------------------------------+ //| OnTimer | //+------------------------------------------------------------------+ void OnTimer(void) { _IN1(""); //--- elavr контроль панель. #ifndef FOR_OPTIMIZATION if (CtrlPanel!=NULL) { CtrlPanel.OnTimerEvent(); } #endif #ifdef TRACE //**************** ДОБАВЛЕНО TRACE if (!m_traceview.IsOpenView()) { m_traceview.Deinit(); m_traceview.Create(ChartID()); } // если окно было случайно закрыто else m_traceview.OnTimer(); //**************** #endif // TRACE } void pre_tick_handler() { _IN1(""); MqlTick Tick; SymbolInfoTick(Symbol(),Tick); OnTimer(); layer_error::reset(); tool_cache::update_tick_state(); if ( short_hd.is_strong_sleep() && long_hd.is_strong_sleep() ) { _IN2(""); return; } #ifndef FOR_OPTIMIZATION factory_c_order::reset(); factory_order_operation::reset(); layer_order::refresh_all(); #else // FOR_OPTIMIZATION MqlDateTime _current_date; TimeCurrent(_current_date); datetime _current_date_t = TimeCurrent(); static ushort tick_counter=0; if (_last_order_count != kernel_order::count() //||(_last_ticket != !GC_CHECK_PTR ( _last_order ) ? -1.0 : _last_order.ticket) || (_prev_date.day_of_year < _current_date.day_of_year && _current_date.min >= 0) || _current_date.day_of_year == 0 //|| _current_date_t - _prev_date > 300 //Отсчитываем 15 серкунд //|| _prev_date == 0 //|| tick_counter >= 10000 ) { _IN2(""); factory_c_order::reset(); factory_order_operation::reset(); layer_order::refresh_all(); _last_order_count = kernel_order::count(); _prev_date = _current_date; tick_counter = 0; } tick_counter++; #endif // FOR_OPTIMIZATION } void tick_handler() { #ifdef INFO_PANEL return; #endif _IN1(""); if ( short_hd.is_strong_sleep() && long_hd.is_strong_sleep() ) { _IN2(""); return; } if ( !layer_account::is_trade_allowed() ) { _IN2(""); log_info ( SRC_SETKA_TRADE_NOT_ALLOWED ); return; } enum_trade_mode_type trade_mode = layer_symbol::trade_mode ( CURRENT_SYMBOL ); if ( trade_mode != trade_mode_type_full ) { _IN2(""); switch ( trade_mode ) { case trade_mode_type_disabled: log_info ( SRC_SETKA_SYMBOL_TRADE_MODE_DISABLED ); return; case trade_mode_type_long_only: log_info ( SRC_SETKA_SYMBOL_TRADE_MODE_LONGONLY ); break; case trade_mode_type_short_only: log_info ( SRC_SETKA_SYMBOL_TRADE_MODE_SHORTONLY ); break; case trade_mode_type_close_only: log_info ( SRC_SETKA_SYMBOL_TRADE_MODE_CLOSEONLY ); break; } } double account_balance = kernel_account::balance(); if ( account_balance == 0.00 ) { _IN2(""); log_info ( SRC_SETKA_NO_MONEY ); return; } double account_drawdown_percent = ( 1 - ( kernel_account::equity() / account_balance ) ) * 100; short_hd.drawdown_changed_handler ( account_drawdown_percent ); long_hd.drawdown_changed_handler ( account_drawdown_percent ); short_hd.mark_block_work_by_stop_trade ( false ); long_hd.mark_block_work_by_stop_trade ( false ); bool is_close_by_profit_percent = (CloseAllOrders_ByProfitPercent > 0 ) && is_close_orders_profit_in_percent ( layer_account::profit_clear_percent()); bool is_close_by_profit_currency = CloseAllOrders_ByProfitMoney > 0 && is_close_orders_profit_in_money ( layer_account::profit_clear_currency() ); bool is_close_by_drawdown_percent = CloseAllOrders_ByDrawdownPercent > 0 && is_close_orders_drawdown_in_percent ( layer_account::drawdown_percent() ); bool is_close_by_drawdown_currency = CloseAllOrders_ByDrawdownMoney > 0 && is_close_orders_drawdown_in_money ( layer_account::drawdown_currency() ); bool is_close_by_dd_001lot_short = is_close_orders_drawdown_in_money_by_001lot ( short_hd ); bool is_close_by_dd_001lot_long = is_close_orders_drawdown_in_money_by_001lot ( long_hd ); bool is_close_by_dd_tpratio_short = is_close_orders_drawdown_tp_ratio ( short_hd ); bool is_close_by_dd_tpratio_long = is_close_orders_drawdown_tp_ratio ( long_hd ); bool is_close_by_profit = is_close_by_profit_currency || is_close_by_profit_percent; bool is_close_by_drawdown = is_close_by_drawdown_currency || is_close_by_drawdown_percent; bool is_need_close = is_close_by_profit || is_close_by_drawdown; bool is_close_by_percent = is_close_by_profit_percent || is_close_by_drawdown_percent; if ( (!short_hd.is_close_module_activated()&& short_hd.is_can_close()&& (is_close_by_dd_001lot_short||is_close_by_dd_tpratio_short )) ||(!long_hd.is_close_module_activated()&& long_hd.is_can_close()&&(is_close_by_dd_001lot_long||is_close_by_dd_tpratio_long ))) { if ( is_close_by_dd_001lot_short || is_close_by_dd_tpratio_short ) { log_alert ( StringFormat ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_BY_DRAWDOWN_MSG, DoubleToString ( (short_hd.get_profit()*-1), 2 ), DoubleToString ( is_close_by_dd_001lot_short ? short_hd.calc_drawdown_per_001lot() : short_hd.calc_drawdown_tp_ratio() , 2 ) ) ); short_hd.mark_close_all_orders ( 0, true, (is_close_by_dd_001lot_short || is_close_by_dd_tpratio_short) ); if ( short_hd._is_block_work ) { log_alert ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_STOP_TRADE_MSG ); } } if (is_close_by_dd_001lot_long || is_close_by_dd_tpratio_long) { log_alert ( StringFormat ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_BY_DRAWDOWN_MSG, DoubleToString ( (long_hd.get_profit()*-1), 2 ), DoubleToString ( is_close_by_dd_001lot_long ? long_hd.calc_drawdown_per_001lot() : long_hd.calc_drawdown_tp_ratio(), 2 ) ) ); long_hd.mark_close_all_orders ( 0, true, (is_close_by_dd_001lot_long || is_close_by_dd_tpratio_long) ); if ( long_hd._is_block_work ) { log_alert ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_STOP_TRADE_MSG ); } } } else if ( !short_hd.is_close_module_activated() && !long_hd.is_close_module_activated() && short_hd.is_can_close() && long_hd.is_can_close() && is_need_close ) { _IN2(""); if ( is_close_by_drawdown ) { _IN3(""); log_alert ( StringFormat ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_BY_DRAWDOWN_MSG, is_close_by_percent ? DoubleToString ( layer_account::drawdown_percent(), 2 ) + "%" : DoubleToString ( layer_account::drawdown_currency(), 2 ), is_close_by_percent ? DoubleToString ( CloseAllOrders_ByDrawdownPercent, 2 ) + "%" : DoubleToString ( CloseAllOrders_ByDrawdownMoney, 2 ) ) ); } else { _IN3(""); log_alert ( StringFormat ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_BY_PROFIT_MSG, is_close_by_percent ? DoubleToString ( layer_account::profit_clear_percent(), 2 ) + "%" : DoubleToString ( layer_account::profit_clear_currency(), 2 ), is_close_by_percent ? DoubleToString ( CloseAllOrders_ByProfitPercent, 2 ) + "%" : DoubleToString ( CloseAllOrders_ByProfitMoney, 2 ) ) ); } short_hd.mark_close_all_orders ( 0, true, is_close_by_drawdown ); long_hd.mark_close_all_orders ( 0, true, is_close_by_drawdown ); if ( short_hd._is_block_work ) { log_alert ( SRC_SETKA_DRAWDOWN_CLOSE_ALL_STOP_TRADE_MSG ); } } else if ( is_stop_trade_drawdown_in_percent ( layer_account::drawdown_percent() ) || is_stop_trade_drawdown_in_money ( layer_account::drawdown_currency() ) ) { _IN2(""); log_info ( StringFormat ( SRC_SETKA_DRAWDOWN_MSG, DoubleToString ( layer_account::drawdown_percent(), 0 ) + "%" ) ); if ( short_hd.get_profit() > long_hd.get_profit() ) { _IN3(""); long_hd.mark_block_work_by_stop_trade ( true ); } else { _IN3(""); short_hd.mark_block_work_by_stop_trade ( true ); } } if ( layer_market::is_closed() ) { _IN2(""); return; } short_hd.tick_handler(); long_hd.tick_handler(); } void post_tick_handler() { _IN1(""); if ( layer_market::is_closed() ) { _IN2(""); log_info ( SRC_SETKA_MARKET_CLOSE_ERROR ); short_hd.reset_states(); long_hd.reset_states(); } api::process(); gc::dispose(); if(kernel_account::is_testing()) { _IN2(""); OnTimer(); long lparam = 0; double dparam = 0; string sparam = ""; OnChartEvent(0,lparam,dparam,sparam); } if ( life_timer != NULL && life_timer.is_elapsed() ) { _IN2(""); life_timer.reset(); } } bool is_close_orders_drawdown_in_percent ( double drawdown_percent ) { _IN1(""); return CloseAllOrders_ByDrawdownPercent > 0 && drawdown_percent >= CloseAllOrders_ByDrawdownPercent; } bool is_close_orders_drawdown_in_money_by_001lot (logic_handler* hdl) { return hdl._settings.close_orders_by_drawdown_for_001lot > 0 && hdl.calc_drawdown_per_001lot()>0 && (hdl.get_profit()*-1) >= hdl.calc_drawdown_per_001lot(); } bool is_close_orders_drawdown_tp_ratio (logic_handler* hdl) { return hdl._settings.close_orders_by_drawdown_tp_ratio > 0 && hdl.calc_drawdown_tp_ratio()>0 && (hdl.get_profit()*-1) >= hdl.calc_drawdown_tp_ratio(); } bool is_close_orders_drawdown_in_money ( double drawdown_currency ) { _IN1(""); return CloseAllOrders_ByDrawdownMoney > 0 && drawdown_currency >= CloseAllOrders_ByDrawdownMoney; } bool is_close_orders_profit_in_percent ( double profit_percent ) { _IN1(""); return CloseAllOrders_ByProfitPercent > 0 && profit_percent >= CloseAllOrders_ByProfitPercent; } bool is_close_orders_profit_in_money ( double profit_currency ) { _IN1(""); return CloseAllOrders_ByProfitMoney > 0 && profit_currency >= CloseAllOrders_ByProfitMoney; } bool _stop_trade_by_drawdown_in_percent_enabled = false; bool is_stop_trade_drawdown_in_percent ( double drawdown_percent ) { _IN1(""); if ( StopTrade_ByDrawdownPercent == 0 ) { _IN2(""); return false; } if ( _stop_trade_by_drawdown_in_percent_enabled ) { _IN2(""); if ( drawdown_percent >= StopTrade_ByDrawdownPercent_Off ) { _IN3(""); return true; } log_alert ( StringFormat ( SRC_SETKA_STOP_DRAWDOWN_OFF, DoubleToString ( drawdown_percent, 2 ) + "%", DoubleToString ( StopTrade_ByDrawdownPercent_Off, 2 ) + "%" ) ); _stop_trade_by_drawdown_in_percent_enabled = false; return false; } bool result = drawdown_percent >= StopTrade_ByDrawdownPercent; if ( result && StopTrade_ByDrawdownPercent_Off != 0 ) { _IN2(""); log_alert ( StringFormat ( SRC_SETKA_STOP_DRAWDOWN_ON, DoubleToString ( drawdown_percent, 2 ) + "%", DoubleToString ( StopTrade_ByDrawdownPercent_Off, 2 ) + "%" ) ); _stop_trade_by_drawdown_in_percent_enabled = true; } return result; } bool _stop_trade_by_drawdown_in_money_enabled = false; bool is_stop_trade_drawdown_in_money ( double drawdown_currency ) { _IN1(""); if ( StopTrade_ByDrawdownMoney == 0 ) { _IN2(""); return false; } if ( _stop_trade_by_drawdown_in_money_enabled ) { _IN2(""); if ( drawdown_currency >= StopTrade_ByDrawdownMoney_Off ) { _IN3(""); return true; } log_alert ( StringFormat ( SRC_SETKA_STOP_DRAWDOWN_OFF, DoubleToString ( drawdown_currency, 2 ), DoubleToString ( StopTrade_ByDrawdownMoney_Off, 2 ) ) ); _stop_trade_by_drawdown_in_money_enabled = false; return false; } bool result = drawdown_currency >= StopTrade_ByDrawdownMoney; if ( result && StopTrade_ByDrawdownMoney_Off != 0 ) { _IN2(""); log_alert ( StringFormat ( SRC_SETKA_STOP_DRAWDOWN_ON, DoubleToString ( drawdown_currency, 2 ), DoubleToString ( StopTrade_ByDrawdownMoney_Off, 2 ) ) ); _stop_trade_by_drawdown_in_money_enabled = true; } return result; } int get_lot_exp_by_minlot ( double minlot ) { _IN1(""); int result = -1; if ( minlot >= 1.0 ) { _IN2(""); return result; } do { _IN2(""); result++; } while ( ( minlot *= 10 ) <= 1.0 ); return result; } #endif