881 lines
No EOL
52 KiB
MQL5
881 lines
No EOL
52 KiB
MQL5
#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 <MQL5Trace\View\TraceView.mqh>
|
|
#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_Percent<ddp && ddp>0)
|
|
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 |