1547 lines
116 KiB
MQL5
1547 lines
116 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Engine.mqh |
|
|
//| Copyright 2024 - Dev.Solve LTDA |
|
|
//+------------------------------------------------------------------+
|
|
//--- includes
|
|
#include "ExpertTakeProfit.mqh"
|
|
#include "ExpertStopLoss.mqh"
|
|
#include "ExpertStrategy.mqh"
|
|
#include "ExpertMoney.mqh"
|
|
#include "EngineBase.mqh"
|
|
//+------------------------------------------------------------------+
|
|
//| Class CEngine |
|
|
//| Appointment: Class CEngine - general class for trading robots. |
|
|
//+------------------------------------------------------------------+
|
|
class CEngine : public CEngineBase
|
|
{
|
|
protected:
|
|
//--- global variables
|
|
MqlTradeRequest m_request; // trade request
|
|
MqlTradeCheckResult m_check_result; // trade check result
|
|
MqlTradeResult m_result; // trade result
|
|
datetime m_expiration; // time expiration order
|
|
ENUM_ORDER_TYPE_FILLING m_typefilling; // preenchimento da ordem
|
|
ulong m_last_ticket; // number of the last ticket
|
|
//--- general configs
|
|
double m_shift_points_order; // [ordem pendente] deslocar entrada em pontos
|
|
bool m_flag_tick; // flag para checagem barra a barra ou tick a tick
|
|
bool m_flag_tick_in; // flag para abertura de posição barra a barra ou tick a tick
|
|
bool m_flag_error_params; // flag de erro de parâmetros de inicialização de otimização
|
|
//---position sizing defined in EngineBase
|
|
//--- trading hours
|
|
int m_horaInicioAbertura; // Hora de Inicio de Abertura de Posições
|
|
int m_minutoInicioAbertura; // Minuto de Inicio de Abertura de Pisoções
|
|
int m_horaFimAbertura; // Hora de Encerramento de Abertura de Posições
|
|
int m_minutoFimAbertura; // Minuto de Encerramento de Abertura de Posições
|
|
int m_horaFimOrdens; // Hora para o fim de emissão de ordens
|
|
int m_minFimOrdens; // Minutos para fim de emissão de ordens
|
|
bool m_expirationorders; // Remover ordens pendentes no término de envio de ordens
|
|
//--- simple type hour
|
|
bool m_simple_hour_flag; // Usar horário simpplificado
|
|
ENUM_SIMPLE_TYPE_HOURS m_simple_hour; // Tipo de intervalo escolhido
|
|
//--- config swing trade
|
|
bool m_is_swing; // Verificar se é operação de Swing Trade
|
|
ENUM_TYPE_TRADE_CLOSING m_trade_closing; // Período de encerramento do Trade
|
|
datetime m_init_swing; // Início da operação
|
|
datetime m_end_swing; // Término da operação
|
|
bool m_close_trade; // Encerrar operação
|
|
//--- global variables
|
|
string m_expertname; // Nome do EA
|
|
double m_lote; // Quantidade de Contratos
|
|
ulong m_deviation; // Desvio máximo em pontos
|
|
bool m_status_pos; // Flag do estado da posição
|
|
bool m_status_order; // Flag do estado da ordem
|
|
bool m_status_expiration; // FLag do estado da expiração de ordens
|
|
bool m_status_trading_hours; // Flag do estado do horário de negociação
|
|
int m_max_orders; // Número máximo de ordens pendentes
|
|
ulong m_ticket_buy; // Tikect da última ordem de compra
|
|
ulong m_ticket_sell; // Ticket da última ordem de venda
|
|
int m_num_orders_buy; // Número de ordens de compra
|
|
int m_num_orders_sell; // Número de ordens de venda
|
|
//--- used objects
|
|
CTrade *m_trade; // trade object
|
|
CPositionInfo m_position; // position info object
|
|
COrderInfo m_order; // order info object
|
|
CDealInfo m_deal; // deal info object
|
|
CExpertMoney *m_money; // money object
|
|
CExpertStrategy *m_strategy; // strategy object
|
|
CExpertStopLoss *m_stoploss; // stop loss object
|
|
CExpertTakeProfit *m_takeprofit; // take profit object
|
|
//--- linear regression
|
|
CLinearRegressionFilter *m_LRFilter_Buy; // linear regression filter buy
|
|
CLinearRegressionFilter *m_LRFilter_Sell; // linear regression filter sell
|
|
bool m_LRFilter_Is_Usage; // fag of the use
|
|
|
|
public:
|
|
CEngine();
|
|
~CEngine();
|
|
//--- initialization
|
|
bool Init(string expert_name,string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic=0,double lot=0);
|
|
//--- initialization objects
|
|
virtual bool InitTrade(ulong magic,CTrade *trade=NULL);
|
|
virtual bool InitMoney(CExpertMoney *money=NULL);
|
|
virtual bool InitStrategy(CExpertStrategy *strategy=NULL);
|
|
virtual bool InitStopLoss(CExpertStopLoss *stoploss=NULL);
|
|
virtual bool InitTakeProfit(CExpertTakeProfit *takeprofit=NULL);
|
|
//--- initioalize linear regresseion filter
|
|
virtual bool InitLinearRegressionFilter(bool is_usage, string symbol, ENUM_TIMEFRAMES LinearRegressionFilter_TF, int PeriodoLinearRegressionFilter_,
|
|
ENUM_FILTER_LINEAR_REGRESSION_DIRECTION LinearRegressionDirection_, bool LinearRegressionFilterUseLocation_,
|
|
ENUM_FILTER_LINEAR_REGRESSION_LOCATION LinearRegressionLocation_Buy_,
|
|
ENUM_FILTER_LINEAR_REGRESSION_LOCATION LinearRegressionLocation_Sell_);
|
|
//--- method of verification of settings
|
|
virtual bool ValidationSettings(void);
|
|
virtual void SetErrorParams(bool value) { m_flag_error_params=value; };
|
|
virtual bool GetErrorParams(void) { return m_flag_error_params; };
|
|
//--- method of creating the collection filters
|
|
virtual bool InitFilters(CExpertFilter *_filters=NULL);
|
|
//--- method of creating the indicator and timeseries
|
|
virtual bool InitIndicators(CIndicators *indicators=NULL);
|
|
//--- initialization trade hours and methods of hours
|
|
bool InitEngineHours(int h_ini,int min_ini,int h_end,int min_end);
|
|
bool GetHours(ENUM_TYPE_HOURS ini, ENUM_TYPE_HOURS orders, ENUM_TYPE_HOURS end);
|
|
void SetSimpleHour(bool value) { m_simple_hour_flag=value; };
|
|
void SetTypeSimpleHour(ENUM_SIMPLE_TYPE_HOURS value) { m_simple_hour=value; };
|
|
//--- manange close positions
|
|
void GetTypeClosing(ENUM_TYPE_TRADE_CLOSING value) { m_trade_closing=value; };
|
|
//--- get current lot
|
|
double GetCurrentLot(void) { return(m_lote); };
|
|
//--- deinitialization
|
|
virtual void Deinit(void);
|
|
//--- methods of setting adjustable parameters
|
|
int MaxOrders(void) const { return(m_max_orders); }
|
|
void MaxOrders(int value) { m_max_orders=value; }
|
|
ulong Deviation(void) const { return(m_deviation); }
|
|
void Deviation(ulong value) { m_deviation=value; }
|
|
bool ExpirationOrders(void) const { return(m_expirationorders); }
|
|
void ExpirationOrders(bool value) { m_expirationorders=value; }
|
|
double ShiftOrderPoints(void) const { return(m_shift_points_order); }
|
|
void ShiftOrderPoints(double value) { m_shift_points_order=value; }
|
|
void SetTickFlag(bool value) { m_flag_tick=value; }
|
|
void SetTickFlagIn(bool value) { m_flag_tick_in=value; }
|
|
//--- event handlers
|
|
virtual void OnTick(void);
|
|
virtual void OnTradeTransaction(const MqlTradeTransaction& trans,const MqlTradeRequest& request,const MqlTradeResult& result);
|
|
virtual double OnTester(void);
|
|
protected:
|
|
//--- deinitialization
|
|
virtual void DeinitTrade(void);
|
|
virtual void DeinitMoney(void);
|
|
virtual void DeinitStrategy(void);
|
|
virtual void DeinitStopLoss(void);
|
|
virtual void DeinitTakeProfit(void);
|
|
virtual void DeinitIndicators(void);
|
|
virtual void DeinitFilters(void);
|
|
//--- refreshing elements
|
|
virtual bool Refresh(void);
|
|
//--- trading hours
|
|
bool CheckTradingHours(void);
|
|
bool CheckExpirationOrders(void);
|
|
bool IsClosingTime(void);
|
|
bool IsCloseMarket(void);
|
|
bool CloseTrade(void);
|
|
//--- select elements trade
|
|
virtual bool SelectPosition(void);
|
|
virtual bool SelectOrder(void);
|
|
//--- initial checking
|
|
virtual bool InitChecking(void);
|
|
//--- main method
|
|
virtual bool Processing(void);
|
|
//--- check condition for open position
|
|
virtual bool IsEntryIn(bool flag);
|
|
virtual bool IsEntryOut(bool flag);
|
|
//--- trade open position check
|
|
virtual bool CheckOpen(void);
|
|
virtual bool CheckOpenLong(void);
|
|
virtual bool CheckOpenShort(void);
|
|
//--- order check
|
|
void ZeroRequest(void);
|
|
//--- trade open positions prcessing
|
|
virtual bool OpenLong(double price,double sl,double tp);
|
|
virtual bool OpenShort(double price,double sl,double tp);
|
|
//--- methos of stop loss
|
|
virtual bool CheckStopLoss(void);
|
|
virtual bool CheckStopLossLong(void);
|
|
virtual bool CheckStopLossShort(void);
|
|
virtual bool StopLoss(double sl,double tp);
|
|
//--- methos of take profit
|
|
virtual bool CheckTakeProfit(void);
|
|
virtual bool CheckTakeProfitLong(void);
|
|
virtual bool CheckTakeProfitShort(void);
|
|
virtual bool TakeProfit(double sl,double tp);
|
|
//--- methos of trailing orders
|
|
virtual bool CheckTrailingOrder(void) { return(false); };
|
|
virtual bool CheckTrailingOrderLong(void);
|
|
virtual bool CheckTrailingOrderShort(void);
|
|
virtual bool TrailingOrder(void);
|
|
virtual bool TrailingOrderLong(double price,datetime expiration);
|
|
virtual bool TrailingOrderShort(double price,datetime expiration);
|
|
//--- common protect functions
|
|
virtual void SetMarginMode(void) { m_margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); }
|
|
virtual bool IsHedging(void) const { return(m_margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING); }
|
|
//--- auxiliary functions
|
|
virtual int NumPendingOrdersBuy(void) { return(m_num_orders_buy); };
|
|
virtual int NumPendingOrdersSell(void) { return(m_num_orders_sell); };
|
|
virtual bool Close(void);
|
|
virtual bool CloseByTicket(ulong ticket);
|
|
virtual bool DeleteOrders(void);
|
|
virtual bool DeleteOrder(void);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CEngine::CEngine(): m_expiration(TimeCurrent()),
|
|
m_expirationorders(false),
|
|
m_trade(NULL),
|
|
m_deviation(10),
|
|
m_flag_error_params(false),
|
|
m_status_pos(false),
|
|
m_status_order(false),
|
|
m_status_expiration(false),
|
|
m_status_trading_hours(false),
|
|
m_shift_points_order(0),
|
|
m_ticket_buy(-1),
|
|
m_ticket_sell(-1),
|
|
m_last_ticket(-1),
|
|
m_num_orders_buy(0),
|
|
m_num_orders_sell(0)
|
|
{
|
|
m_adjusted_point = 10;
|
|
m_period = WRONG_VALUE;
|
|
m_typefilling = ORDER_FILLING_RETURN;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
CEngine::~CEngine()
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::Init(string expert_name,string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic=0,double lot=0.000000)
|
|
{
|
|
//---
|
|
if(period==PERIOD_CURRENT)
|
|
period=::Period();
|
|
//--- initialize common information
|
|
if(m_symbol==NULL)
|
|
{
|
|
if((m_symbol=new CSymbolInfo)==NULL)
|
|
return(false);
|
|
}
|
|
if(!m_symbol.Name(symbol))
|
|
return(false);
|
|
//---
|
|
m_expertname=expert_name;
|
|
m_period=period;
|
|
m_magic=magic;
|
|
m_every_tick=every_tick;
|
|
m_lote=(lot==0)?m_symbol.LotsMin():lot;
|
|
SetMarginMode();
|
|
MaxOrders(1);
|
|
//--- tuning for 3 or 5 digits
|
|
double digits_adjust=(m_symbol.Digits()==1 ||m_symbol.Digits()==3 || m_symbol.Digits()==5) ? 1/_Point : 1;
|
|
m_adjusted_point=m_symbol.Point()*digits_adjust;
|
|
//--- initializing objects expert
|
|
if(!InitTrade(magic))
|
|
{
|
|
printf(ERROR_SUFFIX+"error initialization trade object");
|
|
return(false);
|
|
}
|
|
//--- primary initialization is successful, pass to the phase of tuning
|
|
m_init_phase=INIT_PHASE_TUNING;
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init Trade |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitTrade(ulong magic,CTrade *trade=NULL)
|
|
{
|
|
//--- delete an existing object
|
|
if(m_trade!=NULL)
|
|
delete m_trade;
|
|
//--
|
|
if(trade==NULL)
|
|
{
|
|
if((m_trade=new CTrade)==NULL)
|
|
return(false);
|
|
}
|
|
else
|
|
m_trade=trade;
|
|
//--- tune trade object
|
|
m_trade.SetExpertMagicNumber(magic);
|
|
m_trade.SetMarginMode();
|
|
m_trade.SetTypeFilling(m_typefilling);
|
|
//--- set max deviation in points
|
|
m_trade.SetDeviationInPoints((ulong)(3*m_deviation*m_adjusted_point));
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init money |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitMoney(CExpertMoney *money)
|
|
{
|
|
if(m_money!=NULL)
|
|
delete m_money;
|
|
//---
|
|
if(money==NULL)
|
|
{
|
|
if((m_money=new CExpertMoney)==NULL)
|
|
return(false);
|
|
}
|
|
else
|
|
m_money=money;
|
|
|
|
//--- initializing trailing object
|
|
if(!m_money.Init(m_symbol.Name(),m_magic))
|
|
return(false);
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init Strategy |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitStrategy(CExpertStrategy *strategy)
|
|
{
|
|
if(m_strategy!=NULL)
|
|
delete m_strategy;
|
|
//--- no stop loss
|
|
if(strategy==NULL)
|
|
{
|
|
if((m_strategy=new CExpertStrategy)==NULL)
|
|
return(false);
|
|
}
|
|
else
|
|
m_strategy=strategy;
|
|
|
|
//--- initializing stop loss object
|
|
if(!m_strategy.Init(GetPointer(m_symbol),m_period,m_adjusted_point,m_magic,m_other_ticker,m_type_operation,m_direction))
|
|
return(false);
|
|
m_strategy.EveryTick(m_every_tick);
|
|
m_strategy.Magic(m_magic);
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init Stop Loss |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitStopLoss(CExpertStopLoss *stoploss)
|
|
{
|
|
if(m_stoploss!=NULL)
|
|
delete m_stoploss;
|
|
//--- no stop loss
|
|
if(stoploss==NULL)
|
|
{
|
|
if((m_stoploss=new CExpertStopLoss)==NULL)
|
|
return(false);
|
|
}
|
|
else
|
|
m_stoploss=stoploss;
|
|
|
|
//--- initializing stop loss object
|
|
if(!m_stoploss.Init(GetPointer(m_symbol),m_period,m_adjusted_point,m_magic,m_other_ticker,m_type_operation,m_direction))
|
|
return(false);
|
|
m_stoploss.EveryTick(m_every_tick);
|
|
m_stoploss.Magic(m_magic);
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init Take Profit |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitTakeProfit(CExpertTakeProfit *takeprofit)
|
|
{
|
|
if(m_takeprofit!=NULL)
|
|
delete m_takeprofit;
|
|
//--- no take profit
|
|
if(takeprofit==NULL)
|
|
{
|
|
if((m_takeprofit=new CExpertTakeProfit)==NULL)
|
|
return(false);
|
|
}
|
|
else
|
|
m_takeprofit=takeprofit;
|
|
|
|
//--- initializing take profit object
|
|
if(!m_takeprofit.Init(GetPointer(m_symbol),m_period,m_adjusted_point,m_magic,m_other_ticker,m_type_operation,m_direction))
|
|
return(false);
|
|
m_takeprofit.EveryTick(m_every_tick);
|
|
m_takeprofit.Magic(m_magic);
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Validation settings |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::ValidationSettings(void)
|
|
{
|
|
if(!CEngineBase::ValidationSettings())
|
|
return(false);
|
|
//--- Check strategy parameters
|
|
if(!m_money.ValidationSettings())
|
|
{
|
|
printf(ERROR_SUFFIX+"error money parameters.");
|
|
return(false);
|
|
}
|
|
//--- Check strategy parameters
|
|
if(!m_strategy.ValidationSettings())
|
|
{
|
|
|
|
printf(ERROR_SUFFIX+"error strategy parameters.");
|
|
return(false);
|
|
}
|
|
//--- Check stop loss parameters
|
|
if(!m_stoploss.ValidationSettings())
|
|
{
|
|
printf(ERROR_SUFFIX+"error stop loss parameters.");
|
|
return(false);
|
|
}
|
|
//--- Check take profit parameters
|
|
if(!m_takeprofit.ValidationSettings())
|
|
{
|
|
printf(ERROR_SUFFIX+"error take profit parameters.");
|
|
return(false);
|
|
}
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Initialization filters |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitFilters(CExpertFilter *_filters)
|
|
{
|
|
//--- create required filters
|
|
if(!CEngineBase::InitFilters(_filters))
|
|
{
|
|
printf(ERROR_SUFFIX+"error initialization filters of strategy.");
|
|
return(false);
|
|
}
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init Linear Regression Filter |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitLinearRegressionFilter(bool is_usage,
|
|
string symbol,
|
|
ENUM_TIMEFRAMES LinearRegressionFilter_TF,
|
|
int PeriodoLinearRegressionFilter_,
|
|
ENUM_FILTER_LINEAR_REGRESSION_DIRECTION LinearRegressionDirection_,
|
|
bool LinearRegressionFilterUseLocation_,
|
|
ENUM_FILTER_LINEAR_REGRESSION_LOCATION LinearRegressionLocation_Buy_,
|
|
ENUM_FILTER_LINEAR_REGRESSION_LOCATION LinearRegressionLocation_Sell_)
|
|
{
|
|
m_LRFilter_Is_Usage=is_usage;
|
|
//--- check if is usage
|
|
if(is_usage)
|
|
{
|
|
//--- init LR Buy
|
|
m_LRFilter_Buy=new CLinearRegressionFilter;
|
|
if(!m_LRFilter_Buy.Init(symbol,
|
|
LinearRegressionFilter_TF,
|
|
false,
|
|
PeriodoLinearRegressionFilter_,
|
|
LinearRegressionDirection_,
|
|
LinearRegressionFilterUseLocation_,
|
|
LinearRegressionLocation_Buy_))
|
|
{
|
|
return(false);
|
|
}
|
|
//--- check pointer
|
|
if(!CheckPointer(m_LRFilter_Buy))
|
|
return(false);
|
|
//--- init LR Sell
|
|
m_LRFilter_Sell=new CLinearRegressionFilter;
|
|
if(!m_LRFilter_Sell.Init(symbol,
|
|
LinearRegressionFilter_TF,
|
|
true,
|
|
PeriodoLinearRegressionFilter_,
|
|
LinearRegressionDirection_,
|
|
LinearRegressionFilterUseLocation_,
|
|
LinearRegressionLocation_Sell_))
|
|
{
|
|
return(false);
|
|
}
|
|
//--- check pointer
|
|
if(!CheckPointer(m_LRFilter_Sell))
|
|
return(false);
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
//--- delete pointer if is not null
|
|
if(m_LRFilter_Buy!=NULL)
|
|
delete m_LRFilter_Buy;
|
|
m_LRFilter_Buy=NULL;
|
|
//--- delete pointer if is not null
|
|
if(m_LRFilter_Sell!=NULL)
|
|
delete m_LRFilter_Sell;
|
|
m_LRFilter_Sell=NULL;
|
|
//---
|
|
return(true);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Initialization indicators |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitIndicators(CIndicators *indicators)
|
|
{
|
|
//--- NULL always comes as the parameter, but here it's not significant for us
|
|
CIndicators *indicators_ptr=GetPointer(m_indicators);
|
|
//--- create required timeseries
|
|
if(!CEngineBase::InitIndicators(indicators_ptr))
|
|
return(false);
|
|
//---
|
|
if(!m_strategy.InitIndicators(indicators_ptr))
|
|
{
|
|
printf(ERROR_SUFFIX+"error initialization indicators of strategy object.");
|
|
return(false);
|
|
}
|
|
//---
|
|
if(!m_stoploss.InitIndicators(indicators_ptr))
|
|
{
|
|
printf(ERROR_SUFFIX+"error initialization indicators of stop loss object.");
|
|
return(false);
|
|
}
|
|
//---
|
|
if(!m_takeprofit.InitIndicators(indicators_ptr))
|
|
{
|
|
printf(ERROR_SUFFIX+"error initialization indicators of take profit object.");
|
|
return(false);
|
|
}
|
|
//--- initialization complete
|
|
printf(ALERT_SUFIX+"%s completamente carregado. Ativo operante: %s. Time Frame: %s.",m_expertname,m_symbol.Name(),EnumToString(m_period));
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Get trading hours |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::GetHours(ENUM_TYPE_HOURS ini,ENUM_TYPE_HOURS orders,ENUM_TYPE_HOURS end)
|
|
{
|
|
//--- masks of the bits
|
|
int mask_min=63;
|
|
int mask_hour=31;
|
|
//--- hour init trades
|
|
m_minutoInicioAbertura=mask_min&int(ini);
|
|
m_horaInicioAbertura=mask_hour&int(ini)>>6;
|
|
//--- hour of end emition ordens
|
|
m_minFimOrdens=mask_min&int(orders);
|
|
m_horaFimOrdens=mask_hour&int(orders)>>6;
|
|
//--- hour of end trades
|
|
m_minutoFimAbertura=mask_min&int(end);
|
|
m_horaFimAbertura=mask_hour&int(end)>>6;
|
|
//--- if simple hour used
|
|
if(m_simple_hour_flag)
|
|
{
|
|
switch(m_simple_hour)
|
|
{
|
|
case HOUR_0905_1300:
|
|
m_horaInicioAbertura=9;
|
|
m_minutoInicioAbertura=5;
|
|
m_horaFimOrdens=13;
|
|
m_minFimOrdens=0;
|
|
m_horaFimAbertura=17;
|
|
m_minutoFimAbertura=45;
|
|
break;
|
|
case HOUR_0905_1730:
|
|
m_horaInicioAbertura=9;
|
|
m_minutoInicioAbertura=5;
|
|
m_horaFimOrdens=17;
|
|
m_minFimOrdens=30;
|
|
m_horaFimAbertura=17;
|
|
m_minutoFimAbertura=45;
|
|
break;
|
|
case HOUR_1300_1730:
|
|
m_horaInicioAbertura=13;
|
|
m_minutoInicioAbertura=0;
|
|
m_horaFimOrdens=17;
|
|
m_minFimOrdens=30;
|
|
m_horaFimAbertura=17;
|
|
m_minutoFimAbertura=45;
|
|
break;
|
|
}
|
|
}
|
|
//--- check input values
|
|
if(m_horaInicioAbertura>m_horaFimAbertura || m_horaInicioAbertura>m_horaFimOrdens)
|
|
{
|
|
printf(ERROR_SUFFIX+"error, Trading Hours Inconsistency! Check the inputs parametres.");
|
|
return(false);
|
|
}
|
|
if(m_horaInicioAbertura==m_horaFimOrdens && m_minutoInicioAbertura>=m_minFimOrdens)
|
|
{
|
|
printf(ERROR_SUFFIX+"error, Trading Hours Inconsistency! Check the inputs parametres.");
|
|
return(false);
|
|
}
|
|
if(m_horaInicioAbertura==m_horaFimAbertura && m_minutoInicioAbertura>=m_minutoFimAbertura)
|
|
{
|
|
printf(ERROR_SUFFIX+"error, Trading Hours Inconsistency! Check the inputs parametres.");
|
|
return(false);
|
|
}
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check Trading Hours |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckTradingHours(void)
|
|
{
|
|
//--- define the variable horaAtual
|
|
MqlDateTime horaAtual;
|
|
//---
|
|
TimeToStruct(TimeCurrent(), horaAtual);
|
|
if(horaAtual.hour>=m_horaInicioAbertura && horaAtual.hour<=m_horaFimAbertura)
|
|
{
|
|
if(horaAtual.hour==m_horaInicioAbertura)
|
|
{
|
|
if(horaAtual.min>=m_minutoInicioAbertura)
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
if(horaAtual.hour==m_horaFimAbertura)
|
|
{
|
|
if(horaAtual.min<=m_minutoFimAbertura)
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
return(true);
|
|
}
|
|
else
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Checking closing time |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::IsClosingTime()
|
|
{
|
|
MqlDateTime hora_atual;
|
|
TimeToStruct(TimeCurrent(), hora_atual);
|
|
if(hora_atual.hour>m_horaFimAbertura)
|
|
return(true);
|
|
if((hora_atual.hour==m_horaFimAbertura) && (hora_atual.min>=m_minutoFimAbertura))
|
|
return(true);
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Checking close market |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::IsCloseMarket()
|
|
{
|
|
MqlDateTime hora_atual;
|
|
TimeToStruct(TimeCurrent(), hora_atual);
|
|
if(hora_atual.hour<m_horaInicioAbertura)
|
|
return(true);
|
|
if((hora_atual.hour==m_horaInicioAbertura) && (hora_atual.min<=m_minutoInicioAbertura))
|
|
return(true);
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check expiration orders |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckExpirationOrders(void)
|
|
{
|
|
//--- define the variable horaAtual
|
|
MqlDateTime horaAtual;
|
|
//---
|
|
TimeToStruct(TimeCurrent(), horaAtual);
|
|
if(horaAtual.hour>=m_horaInicioAbertura && horaAtual.hour<=m_horaFimOrdens)
|
|
{
|
|
if(horaAtual.hour==m_horaInicioAbertura)
|
|
{
|
|
if(horaAtual.min>=m_minutoInicioAbertura)
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
if(horaAtual.hour==m_horaFimOrdens)
|
|
{
|
|
if(horaAtual.min<=m_minFimOrdens)
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
return(true);
|
|
}
|
|
else
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Manange Trade |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CloseTrade(void)
|
|
{
|
|
//---
|
|
m_close_trade=false;
|
|
//---
|
|
MqlDateTime dts_init,dts_end;
|
|
switch(m_trade_closing)
|
|
{
|
|
//--- closing three days
|
|
case TRADE_CLOSING_3DIAS:
|
|
TimeToStruct(m_init_swing,dts_init);
|
|
TimeToStruct(TimeCurrent(),dts_end);
|
|
if(dts_init.day_of_week==MONDAY && (dts_end.day_of_week==THURSDAY || dts_end.day_of_week==FRIDAY)) //closes the following day in case of public holidays
|
|
m_close_trade=true;
|
|
if(dts_init.day_of_week==TUESDAY && (dts_end.day_of_week==FRIDAY || dts_end.day_of_week==MONDAY)) //closes the following day in case of public holidays
|
|
m_close_trade=true;
|
|
if(dts_init.day_of_week==WEDNESDAY && (dts_end.day_of_week==MONDAY || dts_end.day_of_week==TUESDAY)) //closes the following day in case of public holidays
|
|
m_close_trade=true;
|
|
if(dts_init.day_of_week==THURSDAY && (dts_end.day_of_week==TUESDAY || dts_end.day_of_week==WEDNESDAY)) //closes the following day in case of public holidays
|
|
m_close_trade=true;
|
|
if(dts_init.day_of_week==FRIDAY && (dts_end.day_of_week==WEDNESDAY || dts_end.day_of_week==THURSDAY)) //closes the following day in case of public holidays
|
|
m_close_trade=true;
|
|
break;
|
|
//--- closing five days
|
|
case TRADE_CLOSING_5DIAS:
|
|
TimeToStruct(m_init_swing,dts_init);
|
|
TimeToStruct(TimeCurrent(),dts_end);
|
|
if(dts_init.day_of_week==dts_end.day_of_week)
|
|
{
|
|
if(dts_end.day>dts_init.day)
|
|
m_close_trade=true;
|
|
if(dts_end.mon!=dts_init.mon)
|
|
m_close_trade=true;
|
|
}
|
|
break;
|
|
//--- closeing in friday
|
|
case TRADE_CLOSING_SEXTA:
|
|
TimeToStruct(TimeCurrent(),dts_end);
|
|
if(dts_end.day_of_week==FRIDAY)
|
|
m_close_trade=true;
|
|
break;
|
|
//--- closeing daily
|
|
case TRADE_CLOSING_DIARIO:
|
|
m_close_trade=true;
|
|
break;
|
|
//--- not closing
|
|
default:
|
|
m_close_trade=false;
|
|
break;
|
|
}
|
|
return(m_close_trade);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization expert |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::Deinit(void)
|
|
{
|
|
//--- delete trade class
|
|
DeinitTrade();
|
|
//--- delete money class
|
|
DeinitMoney();
|
|
//--- delete strategy class
|
|
DeinitStrategy();
|
|
//--- delete stop loss class
|
|
DeinitStopLoss();
|
|
//--- delete take profit class
|
|
DeinitTakeProfit();
|
|
//--- delete indicators collection
|
|
DeinitIndicators();
|
|
//--- deinit base
|
|
CEngineBase::DeInit();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization trade object |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::DeinitTrade(void)
|
|
{
|
|
if(m_trade!=NULL)
|
|
{
|
|
delete m_trade;
|
|
m_trade=NULL;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization money object |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::DeinitMoney(void)
|
|
{
|
|
if(m_money!=NULL)
|
|
{
|
|
delete m_money;
|
|
m_money=NULL;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization strategy object |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::DeinitStrategy(void)
|
|
{
|
|
if(m_strategy!=NULL)
|
|
{
|
|
delete m_strategy;
|
|
m_strategy=NULL;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization stop loss object |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::DeinitStopLoss(void)
|
|
{
|
|
if(m_stoploss!=NULL)
|
|
{
|
|
delete m_stoploss;
|
|
m_stoploss=NULL;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization take profit object |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::DeinitTakeProfit(void)
|
|
{
|
|
if(m_takeprofit!=NULL)
|
|
{
|
|
delete m_takeprofit;
|
|
m_takeprofit=NULL;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Deinitialization indicators |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::DeinitIndicators(void)
|
|
{
|
|
//--- clear indicators
|
|
m_indicators.Clear();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| OnTick handler |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::OnTick(void)
|
|
{
|
|
//--- updated quotes and indicators
|
|
if(!Refresh())
|
|
return;
|
|
//--- OnTick metric process
|
|
//--- update status
|
|
m_status_expiration=CheckExpirationOrders();
|
|
m_status_trading_hours=CheckTradingHours();
|
|
m_status_pos=SelectPosition();
|
|
m_status_order=SelectOrder();
|
|
//--- expert processing
|
|
Processing();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Refreshing data for processing |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::Refresh(void)
|
|
{
|
|
//--- refresh rates
|
|
if(!m_symbol.RefreshRates())
|
|
return(false);
|
|
//--- refresh indicators
|
|
m_indicators.Refresh();
|
|
//--- refresh filters
|
|
m_filters.Refresh();
|
|
//--- ok
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Select position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::SelectPosition(void)
|
|
{
|
|
bool res=false;
|
|
//---
|
|
if(PositionSelectByTicket(m_last_ticket))
|
|
res|=m_position.SelectByTicket(m_last_ticket);
|
|
//---
|
|
return(res);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Select orders |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::SelectOrder(void)
|
|
{
|
|
//---
|
|
bool res=false;
|
|
if(OrderSelect(m_ticket_buy))
|
|
res|=m_order.Select(m_ticket_buy);
|
|
if(OrderSelect(m_ticket_sell))
|
|
res|=m_order.Select(m_ticket_sell);
|
|
//---
|
|
return(res);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Main Method (Processing) |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::Processing(void)
|
|
{
|
|
//--- init checking
|
|
if(!InitChecking())
|
|
return(false);
|
|
//--- if position open
|
|
if(m_status_pos)
|
|
{
|
|
//---
|
|
if(IsEntryOut(m_flag_tick))
|
|
{
|
|
//--- check stop loss
|
|
if(CheckStopLoss())
|
|
return(true);
|
|
//--- check take profit
|
|
if(CheckTakeProfit())
|
|
return(true);
|
|
}
|
|
}
|
|
//--- no position open
|
|
if(IsEntryIn(m_flag_tick_in))
|
|
{
|
|
//--- check order send
|
|
if(!m_status_pos)
|
|
{
|
|
//--- if pending order
|
|
if(m_status_order && m_status_expiration)
|
|
if(CheckTrailingOrder())
|
|
return(true);
|
|
//--- check expiration pending orders
|
|
if(m_status_expiration)
|
|
{
|
|
//--- check all filters
|
|
if(!m_filters[1])
|
|
return(false);
|
|
//--- check the possibility of opening a position/setting pending order
|
|
if(CheckOpen())
|
|
return(true);
|
|
}
|
|
}
|
|
}
|
|
//---
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Init Checking |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::InitChecking(void)
|
|
{
|
|
//--- check the expiration orders
|
|
if(!m_status_expiration)
|
|
{
|
|
if(m_status_order)
|
|
{
|
|
if(ExpirationOrders())
|
|
{
|
|
DeleteOrders();
|
|
printf(ALERT_SUFIX+"Ordens pendentes removidas - Término do envio de ordens pendentes.");
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
//--- check the trading hours
|
|
if(IsClosingTime())
|
|
{
|
|
if(CloseTrade())
|
|
{
|
|
if(m_status_pos)
|
|
{
|
|
Close();
|
|
printf(ALERT_SUFIX+"Posição de Ticket= %I64d foi fechada - Encerramento do Trade.",m_position.Ticket());
|
|
}
|
|
if(m_status_order)
|
|
{
|
|
DeleteOrders();
|
|
printf(ALERT_SUFIX+"Ordens pendentes removidas - Encerramento do Trade.");
|
|
}
|
|
return(false);
|
|
}
|
|
return(true);
|
|
}
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for position open or limit/stop order set |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckOpen(void)
|
|
{
|
|
//--- check possibility of open long
|
|
CheckOpenLong();
|
|
//--- check possibility of open short
|
|
CheckOpenShort();
|
|
//--- return without operations
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for long position open or limit/stop order set |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckOpenLong(void)
|
|
{
|
|
double price=EMPTY_VALUE;
|
|
double sl=0.0;
|
|
double tp=0.0;
|
|
datetime expiration=TimeCurrent();
|
|
//--- check type operation
|
|
if(GetTypeOperation()==TYPE_SELL_ONLY)
|
|
return(false);
|
|
//--- check max pending orders
|
|
if(MaxOrders()<=NumPendingOrdersBuy())
|
|
return(false);
|
|
//--- check linear regression filter
|
|
if(m_LRFilter_Is_Usage)
|
|
if(!m_LRFilter_Buy[1])
|
|
return(false);
|
|
//--- check the signal for long enter operations
|
|
if(m_strategy.CheckOpenLong(price,sl,tp,expiration))
|
|
{
|
|
//--- check shift points
|
|
double shift=ShiftOrderPoints();
|
|
//--- normalize price
|
|
price=m_symbol.NormalizePrice(price+shift);
|
|
//--- check stop loss
|
|
if(m_stoploss.CheckStopLossLong(price,sl,tp))
|
|
{
|
|
if((sl==-2 && tp==-2) || price==sl)
|
|
return(false);
|
|
}
|
|
else
|
|
return(false); //--- is proibited empty stop loss
|
|
sl=sl==0.0?sl:m_symbol.NormalizePrice(sl+shift);
|
|
//--- check take profit
|
|
if(m_takeprofit.CheckTakeProfitLong(price,sl,tp))
|
|
{
|
|
if((sl==-2 && tp==-2) || price==tp)
|
|
return(false);
|
|
}
|
|
tp=tp==0.0?tp:m_symbol.NormalizePrice(tp+shift);
|
|
//--- set expiration order
|
|
//--- create request
|
|
ZeroRequest();
|
|
//---
|
|
m_request.magic = m_magic;
|
|
m_request.symbol = m_symbol.Name();
|
|
//--- update lot
|
|
m_lote =m_money.Lot(price,sl);
|
|
//---
|
|
m_request.volume = m_lote;
|
|
m_request.price = price;
|
|
m_request.sl = sl;
|
|
m_request.tp = tp;
|
|
//--- set request type
|
|
m_request.action =TRADE_ACTION_DEAL;
|
|
m_request.type =ORDER_TYPE_BUY;
|
|
//---
|
|
m_request.type_filling = m_typefilling;
|
|
m_request.type_time = ORDER_TIME_DAY;
|
|
m_request.comment = "Order Buy";
|
|
//--- order check
|
|
if(!OrderCheck(m_request,m_check_result))
|
|
{
|
|
ResetLastError();
|
|
printf(ALERT_SUFIX+"ORDEM INVÁLIDA - Retcode: %d (Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_check_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
return(false);
|
|
}
|
|
//--- uptade ticket order buy
|
|
if(OrderSend(m_request,m_result))
|
|
{
|
|
m_ticket_buy=m_result.order;
|
|
if(m_result.retcode==10009)
|
|
{
|
|
printf(ALERT_SUFIX+"Ordem de compra enviada com sucesso - Retcode: %d \n(Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
printf(ALERT_SUFIX+"ORDEM INVÁLIDA - Retcode: %d (Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
return(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf(ALERT_SUFIX+"ORDEM NÃO ENVIADA - Retcode: %d (Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
//--- failure in open long position param
|
|
return(false);
|
|
}
|
|
}
|
|
//--- failure
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for short position open or limit/stop order set |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckOpenShort(void)
|
|
{
|
|
double price=EMPTY_VALUE;
|
|
double sl=0.0;
|
|
double tp=0.0;
|
|
datetime expiration=TimeCurrent();
|
|
//--- check type operation
|
|
if(GetTypeOperation()==TYPE_BUY_ONLY)
|
|
return(false);
|
|
//--- check max pending orders
|
|
if(MaxOrders()<=NumPendingOrdersSell())
|
|
return(false);
|
|
//--- check linear regression filter
|
|
if(m_LRFilter_Is_Usage)
|
|
if(!m_LRFilter_Sell[1])
|
|
return(false);
|
|
//--- check de signal for short enter operations
|
|
if(m_strategy.CheckOpenShort(price,sl,tp,expiration))
|
|
{
|
|
//--- check shift points
|
|
double shift=ShiftOrderPoints();
|
|
//--- normalize price
|
|
price=m_symbol.NormalizePrice(price-shift);
|
|
//--- check stop loss
|
|
if(m_stoploss.CheckStopLossShort(price,sl,tp))
|
|
{
|
|
if((sl==-2 && tp==-2) || price==sl)
|
|
return(false);
|
|
}
|
|
sl=sl==0.0?sl:m_symbol.NormalizePrice(sl-shift);
|
|
//--- check take profit
|
|
if(m_takeprofit.CheckTakeProfitShort(price,sl,tp))
|
|
{
|
|
if((sl==-2 && tp==-2) || price==tp)
|
|
return(false);
|
|
}
|
|
tp=tp==0.0?tp:m_symbol.NormalizePrice(tp-shift);
|
|
//--- set expiration order
|
|
//--- create request
|
|
ZeroRequest();
|
|
//---
|
|
m_request.magic = m_magic;
|
|
m_request.symbol = m_symbol.Name();
|
|
//--- update lot
|
|
m_lote =m_money.Lot(price,sl);
|
|
//---
|
|
m_request.volume = m_lote;
|
|
m_request.price = price;
|
|
m_request.sl = sl;
|
|
m_request.tp = tp;
|
|
//--- set request type
|
|
m_request.action =TRADE_ACTION_DEAL;
|
|
m_request.type =ORDER_TYPE_SELL;
|
|
//---
|
|
m_request.type_filling = m_typefilling;
|
|
m_request.type_time = ORDER_TIME_DAY;
|
|
m_request.comment = "Order Sell";
|
|
//--- order check
|
|
if(!OrderCheck(m_request,m_check_result))
|
|
{
|
|
ResetLastError();
|
|
printf(ALERT_SUFIX+"ORDEM INVÁLIDA - Retcode: %d (Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_check_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
return(false);
|
|
}
|
|
//--- uptade ticket order sell
|
|
if(OrderSend(m_request,m_result))
|
|
{
|
|
m_ticket_sell=m_result.order;
|
|
if(m_result.retcode==10009)
|
|
{
|
|
printf(ALERT_SUFIX+"Ordem de venda enviada com sucesso - Retcode: %d \n(Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
printf(ALERT_SUFIX+"ORDEM INVÁLIDA - Retcode: %d (Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
return(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf(ALERT_SUFIX+"ORDEM NÃO ENVIADA - Retcode: %d (Magic = %I64d Lot = %.2f Price = %.2f SL = %.2f TP = %.2f)",m_result.retcode,m_magic,m_lote,price,sl,tp);
|
|
//--- failure in open long position param
|
|
return(false);
|
|
}
|
|
}
|
|
//--- failure
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Zero Request |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::ZeroRequest(void)
|
|
{
|
|
//--- zero memory
|
|
ZeroMemory(m_request);
|
|
ZeroMemory(m_result);
|
|
ZeroMemory(m_check_result);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for stop loss position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckStopLoss(void)
|
|
{
|
|
//--- position must be selected before call
|
|
if(m_position.PositionType()==POSITION_TYPE_BUY)
|
|
{
|
|
//--- check the possibility of modifying the long position
|
|
if(CheckStopLossLong())
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
//--- check the possibility of modifying the short position
|
|
if(CheckStopLossShort())
|
|
return(true);
|
|
}
|
|
//--- return without operations
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for take profit long position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckStopLossLong(void)
|
|
{
|
|
double sl=EMPTY_VALUE;
|
|
double tp=EMPTY_VALUE;
|
|
//--- check for long stop loss operations
|
|
if(m_stoploss.CheckStopLossLong(GetPointer(m_position),sl,tp))
|
|
{
|
|
double position_sl=m_position.StopLoss();
|
|
double position_tp=m_position.TakeProfit();
|
|
if(sl==EMPTY_VALUE)
|
|
sl=position_sl;
|
|
else
|
|
sl=(sl<0)?sl:m_symbol.NormalizePrice(sl);
|
|
if(tp==EMPTY_VALUE)
|
|
tp=position_tp;
|
|
else
|
|
tp=(tp<0)?tp:m_symbol.NormalizePrice(tp);
|
|
if(sl==position_sl && tp==position_tp)
|
|
return(false);
|
|
//--- long stop loss operations
|
|
return(StopLoss(sl,tp));
|
|
}
|
|
//--- return without operations
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for stop loss short position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckStopLossShort(void)
|
|
{
|
|
double sl=EMPTY_VALUE;
|
|
double tp=EMPTY_VALUE;
|
|
//--- check for short stop loss operations
|
|
if(m_stoploss.CheckStopLossShort(GetPointer(m_position),sl,tp))
|
|
{
|
|
double position_sl=m_position.StopLoss();
|
|
double position_tp=m_position.TakeProfit();
|
|
if(sl==EMPTY_VALUE)
|
|
sl=position_sl;
|
|
else
|
|
sl=(sl<0)?sl:m_symbol.NormalizePrice(sl);
|
|
if(tp==EMPTY_VALUE)
|
|
tp=position_tp;
|
|
else
|
|
tp=(tp<0)?tp:m_symbol.NormalizePrice(tp);
|
|
if(sl==position_sl && tp==position_tp)
|
|
return(false);
|
|
//--- short stop loss operations
|
|
return(StopLoss(sl,tp));
|
|
}
|
|
//--- return without operations
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Stop Loss long position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::StopLoss(double sl,double tp)
|
|
{
|
|
if(sl<0)
|
|
return(m_trade.PositionClose(m_position.Ticket()));
|
|
else
|
|
return(m_trade.PositionModify(m_position.Ticket(),sl,tp));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for take profit position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckTakeProfit(void)
|
|
{
|
|
//--- position must be selected before call
|
|
if(m_position.PositionType()==POSITION_TYPE_BUY)
|
|
{
|
|
//--- check the possibility of modifying the long position
|
|
if(CheckTakeProfitLong())
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
//--- check the possibility of modifying the short position
|
|
if(CheckTakeProfitShort())
|
|
return(true);
|
|
}
|
|
//--- return without operations
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for take profit long position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckTakeProfitLong(void)
|
|
{
|
|
double sl=EMPTY_VALUE;
|
|
double tp=EMPTY_VALUE;
|
|
//--- check for long take profit operations
|
|
if(m_takeprofit.CheckTakeProfitLong(GetPointer(m_position),sl,tp))
|
|
{
|
|
double position_sl=m_position.StopLoss();
|
|
double position_tp=m_position.TakeProfit();
|
|
if(sl==EMPTY_VALUE)
|
|
sl=position_sl;
|
|
else
|
|
sl=(sl<0)?sl:m_symbol.NormalizePrice(sl);
|
|
if(tp==EMPTY_VALUE)
|
|
tp=position_tp;
|
|
else
|
|
tp=(tp<0)?tp:m_symbol.NormalizePrice(tp);
|
|
if(sl==position_sl && tp==position_tp)
|
|
return(false);
|
|
//--- long step stop operations
|
|
return(TakeProfit(sl,tp));
|
|
}
|
|
//--- return without operations
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check for take profit short position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CheckTakeProfitShort(void)
|
|
{
|
|
double sl=EMPTY_VALUE;
|
|
double tp=EMPTY_VALUE;
|
|
//--- check for short take profit operations
|
|
if(m_takeprofit.CheckTakeProfitShort(GetPointer(m_position),sl,tp))
|
|
{
|
|
double position_sl=m_position.StopLoss();
|
|
double position_tp=m_position.TakeProfit();
|
|
if(sl==EMPTY_VALUE)
|
|
sl=position_sl;
|
|
else
|
|
sl=(sl<0)?sl:m_symbol.NormalizePrice(sl);
|
|
if(tp==EMPTY_VALUE)
|
|
tp=position_tp;
|
|
else
|
|
tp=(tp<0)?tp:m_symbol.NormalizePrice(tp);
|
|
if(sl==position_sl && tp==position_tp)
|
|
return(false);
|
|
//--- short take profitp operations
|
|
return(TakeProfit(sl,tp));
|
|
}
|
|
//--- return without operations
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Take Profit long position |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::TakeProfit(double sl,double tp)
|
|
{
|
|
if(tp<0)
|
|
return(m_trade.PositionClose(m_position.Ticket()));
|
|
else
|
|
return(m_trade.PositionModify(m_position.Ticket(),sl,tp));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Close position open |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::Close(void)
|
|
{
|
|
//---
|
|
bool res=true;
|
|
ResetLastError();
|
|
//--- close all postitions
|
|
int total=PositionsTotal();
|
|
for(int i=0; i<total; i++)
|
|
{
|
|
if(m_position.SelectByIndex(i))
|
|
{
|
|
ulong ticket=m_position.Ticket();
|
|
res&=m_trade.PositionClose(ticket);
|
|
}
|
|
}
|
|
//--- ok
|
|
return(res);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Close position open by ticket |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::CloseByTicket(ulong ticket)
|
|
{
|
|
return(m_trade.PositionClose(ticket));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Delete all limit/stop orders |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::DeleteOrders(void)
|
|
{
|
|
bool res=true;
|
|
ResetLastError();
|
|
//--- delete all pending orders
|
|
int total=OrdersTotal();
|
|
for(int i=0; i<total; i++)
|
|
{
|
|
if(m_order.SelectByIndex(i))
|
|
{
|
|
//--- clear structs
|
|
ZeroRequest();
|
|
//--- setting request
|
|
m_request.action =TRADE_ACTION_REMOVE;
|
|
m_request.magic =m_magic;
|
|
m_request.order =m_order.Ticket();
|
|
//--- action and return the result
|
|
res&=OrderSend(m_request,m_result);
|
|
}
|
|
}
|
|
//---
|
|
return(res);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Delete limit/stop order |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::DeleteOrder(void)
|
|
{
|
|
return(m_trade.OrderDelete(m_order.Ticket()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| OnTradeTransaction Handler |
|
|
//+------------------------------------------------------------------+
|
|
void CEngine::OnTradeTransaction(const MqlTradeTransaction &trans,const MqlTradeRequest &request,const MqlTradeResult &result)
|
|
{
|
|
//---
|
|
switch(trans.type)
|
|
{
|
|
//--- working with adding orders
|
|
case TRADE_TRANSACTION_ORDER_ADD:
|
|
//--- order buy add
|
|
if((trans.order_type==ORDER_TYPE_BUY_LIMIT || trans.order_type==ORDER_TYPE_BUY_STOP) && (m_ticket_buy==trans.order))
|
|
{
|
|
m_num_orders_buy++;
|
|
}
|
|
//--- order sell add
|
|
if((trans.order_type==ORDER_TYPE_SELL_LIMIT || trans.order_type==ORDER_TYPE_SELL_STOP) && (m_ticket_sell==trans.order))
|
|
{
|
|
m_num_orders_sell++;
|
|
}
|
|
break;
|
|
//--- working with canceled orders
|
|
case TRADE_TRANSACTION_ORDER_DELETE:
|
|
if(trans.order==trans.position)
|
|
{
|
|
//--- from pending order to position buy open
|
|
if((trans.order_type==ORDER_TYPE_BUY_LIMIT || trans.order_type==ORDER_TYPE_BUY_STOP) && (m_ticket_buy==trans.order))
|
|
{
|
|
m_last_ticket=trans.position;
|
|
m_num_orders_buy--;
|
|
}
|
|
//--- from pending order to position sell open
|
|
if((trans.order_type==ORDER_TYPE_SELL_LIMIT || trans.order_type==ORDER_TYPE_SELL_STOP) && (m_ticket_sell==trans.order))
|
|
{
|
|
m_last_ticket=trans.position;
|
|
m_num_orders_sell--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//--- pending order to buy canceled
|
|
if((trans.order_type==ORDER_TYPE_BUY_LIMIT || trans.order_type==ORDER_TYPE_BUY_STOP) && (m_ticket_buy==trans.order))
|
|
{
|
|
//--- order that was deleted (not necessarily pending order)
|
|
m_num_orders_buy--;
|
|
}
|
|
else
|
|
if((trans.order_type==ORDER_TYPE_SELL_LIMIT || trans.order_type==ORDER_TYPE_SELL_STOP) && (m_ticket_sell==trans.order))
|
|
{
|
|
m_num_orders_sell--;
|
|
}
|
|
}
|
|
break;
|
|
//--- working with canceled orders
|
|
case TRADE_TRANSACTION_DEAL_ADD:
|
|
{
|
|
switch(trans.deal_type)
|
|
{
|
|
//--- buy
|
|
case DEAL_TYPE_BUY:
|
|
if(m_ticket_buy==trans.order)
|
|
{
|
|
//--- update ticket of new position
|
|
m_last_ticket=trans.order;
|
|
}
|
|
break;
|
|
//--- sell
|
|
case DEAL_TYPE_SELL:
|
|
if(m_ticket_sell==trans.order)
|
|
{
|
|
//--- update ticket of new position
|
|
m_last_ticket=trans.order;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Verify is New Bar by Flag |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::IsEntryIn(bool flag)
|
|
{
|
|
//--- if false, evaluate the outputs every minute
|
|
ENUM_TIMEFRAMES period=m_period;
|
|
if(flag)
|
|
period=PERIOD_M1;
|
|
//--- memorize the time of opening of the last bar in the static variable
|
|
static datetime last_time=0;
|
|
//--- current time
|
|
datetime lastbar_time=(datetime)SeriesInfoInteger(m_symbol.Name(),period,SERIES_LASTBAR_DATE);
|
|
//--- if it is the first call of the function
|
|
if(last_time==0)
|
|
{
|
|
//--- set the time and exit
|
|
last_time=lastbar_time;
|
|
return(true);
|
|
}
|
|
//--- if the time differs
|
|
if(last_time!=lastbar_time)
|
|
{
|
|
//--- memorize the time and return true
|
|
last_time=lastbar_time;
|
|
return(true);
|
|
}
|
|
//--- if we passed to this line, then the bar is not new; return false
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Verify is New Bar by Flag |
|
|
//+------------------------------------------------------------------+
|
|
bool CEngine::IsEntryOut(bool flag)
|
|
{
|
|
//--- if false, evaluate the outputs every minute
|
|
ENUM_TIMEFRAMES period=m_period;
|
|
if(flag)
|
|
period=PERIOD_M1;
|
|
//--- memorize the time of opening of the last bar in the static variable
|
|
static datetime last_time=0;
|
|
//--- current time
|
|
datetime lastbar_time=(datetime)SeriesInfoInteger(m_symbol.Name(),period,SERIES_LASTBAR_DATE);
|
|
//--- if it is the first call of the function
|
|
if(last_time==0)
|
|
{
|
|
//--- set the time and exit
|
|
last_time=lastbar_time;
|
|
return(true);
|
|
}
|
|
//--- if the time differs
|
|
if(last_time!=lastbar_time)
|
|
{
|
|
//--- memorize the time and return true
|
|
last_time=lastbar_time;
|
|
return(true);
|
|
}
|
|
//--- if we passed to this line, then the bar is not new; return false
|
|
return(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| On Tester Function |
|
|
//+------------------------------------------------------------------+
|
|
double CEngine::OnTester(void)
|
|
{
|
|
//---
|
|
double custom_metric=TesterStatistics(STAT_RECOVERY_FACTOR);
|
|
//---
|
|
return(custom_metric);
|
|
}
|
|
//+------------------------------------------------------------------+
|