//+------------------------------------------------------------------+ //| 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 && 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