//+------------------------------------------------------------------+ //| Rompimento do Candle Anterior.mq5 | //| Copyright © 2020, Christian Santana | //| GIVE ME MONEY | //+------------------------------------------------------------------+ #property copyright "Copyright © 2020, Christian Santana" #property link "GIVE ME MONEY" #property version "1.0" /* CONFIG RODOLFO 2.0 */ #include #include #include #include #include #include //--- CPositionInfo m_position; // object of CPositionInfo class CTrade m_trade; // object of CTrade class CSymbolInfo m_symbol; // object of CSymbolInfo class CAccountInfo m_account; // object of CAccountInfo class CDealInfo m_deal; // object of CDealInfo class CMoneyFixedMargin *m_money; // object of CMoneyFixedMargin class //+------------------------------------------------------------------+ //| Enum Lor or Risk | //+------------------------------------------------------------------+ enum ENUM_LOT_OR_RISK { lots_min=1, // Lots Min lot=5, // Constant lot risk=0, // Risk in percent for a deal }; //+------------------------------------------------------------------+ //| Enum Trade Mode | //+------------------------------------------------------------------+ enum ENUM_TRADE_MODE { buy=0, // Allowed only BUY positions sell=1, // Allowed only SELL positions buy_sell=2, // Allowed BUY and SELL positions }; //+------------------------------------------------------------------+ //| Enum Pips Or Points | //+------------------------------------------------------------------+ enum ENUM_PIPS_OR_POINTS { pips=0, // ticks (1.00045-1.00055=1 ticks) points=1, // Pontos (1.00045-1.00055=10 pontos) }; //+------------------------------------------------------------------+ //| Enum Price Calculation | //+------------------------------------------------------------------+ enum ENUM_PRICE_CALCULATION { high_low=0, // High - Low open_close=1, // Abs (Open - Close) }; //--- input parameters input group "Trading settings" input ENUM_TIMEFRAMES InpWorkingPeriod = PERIOD_CURRENT; // Timeframe input ENUM_PIPS_OR_POINTS InpPipsOrPoints = pips; // Pips Or Points: input uint InpTakeProfit = 12; // Take Profit input group "Position size management (lot calculation)" input ENUM_LOT_OR_RISK InpLotOrRisk = risk; // Gerenciamento de Risco: Lote ou Risco input double InpVolumeLotOrRisk = 3.0; // O Valor do "Gerenciamento de Risco" input group "Trade mode" input ENUM_TRADE_MODE InpTradeMode = buy_sell; // Modo de Trade: input group "Time control" input bool InpTimeControl = true; // Use time control input uchar InpStartHour = 10; // Start Hour input uchar InpStartMinute = 01; // Start Minute input uchar InpEndHour = 15; // End Hour input uchar InpEndMinute = 02; // End Minute input group "Previsious Bas" input ENUM_PRICE_CALCULATION InpPriceCalculation = open_close; // Previsious Bar: price calculation input uint InpMinSize = 8; // Previsious Bar: minimum size input group "Additional features" input bool InpReverse = false; // Positions: Reverse input bool InpPrintLog = false; // Print log input uchar InpFreezeCoefficient = 1; // Coefficient (if Freeze==0 Or StopsLevels==0) input ulong InpDeviation = 10; // Deviation input ulong InpMagic = 283301676; // Magic number //--- double m_take_profit = 0.0; // Take Profit -> double double m_min_size = 0.0; // Previsious Bas: minimum size -> double double m_adjusted_point; // point value adjusted for 3 or 5 points bool m_need_close_all = false; // close all positions datetime m_last_signal = 0; // "0" -> D'1970.01.01 00:00'; datetime m_prev_bars = 0; // "0" -> D'1970.01.01 00:00'; datetime m_last_deal_in = 0; // "0" -> D'1970.01.01 00:00'; bool m_init_error = false; // error on InInit //--- the tactic is this: for positions we strictly monitor the result *** //+------------------------------------------------------------------+ //| Structure Positions | //+------------------------------------------------------------------+ struct STRUCT_POSITION { ENUM_POSITION_TYPE pos_type; // position type bool waiting_transaction; // waiting transaction, "true" -> it's forbidden to trade, we expect a transaction ulong waiting_order_ticket; // waiting order ticket, ticket of the expected order bool transaction_confirmed; // transaction confirmed, "true" -> transaction confirmed //--- Constructor STRUCT_POSITION() { pos_type = WRONG_VALUE; waiting_transaction = false; waiting_order_ticket = 0; transaction_confirmed = false; } }; STRUCT_POSITION SPosition[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if(!m_symbol.Name(Symbol())) // sets symbol name { Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name"); return(INIT_FAILED); } RefreshRates(); //--- m_trade.SetExpertMagicNumber(InpMagic); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(m_symbol.Name()); m_trade.SetDeviationInPoints(InpDeviation); //--- tuning for 3 or 5 digits int digits_adjust=1; if(m_symbol.Digits()==3 || m_symbol.Digits()==5) digits_adjust=10; m_adjusted_point=m_symbol.Point()*digits_adjust; if(InpPipsOrPoints==pips) // Pips (1.00045-1.00055=1 pips) { m_take_profit = InpTakeProfit * m_adjusted_point; m_min_size = InpMinSize * m_adjusted_point; } else // Points (1.00045-1.00055=10 points) { m_take_profit = InpTakeProfit * m_symbol.Point(); m_min_size = InpMinSize * m_symbol.Point(); } //--- check the input parameter "Lots" string err_text=""; if(InpLotOrRisk==lot) { if(!CheckVolumeValue(InpVolumeLotOrRisk,err_text)) { if(MQLInfoInteger(MQL_TESTER)) // when testing, we will only output to the log about incorrect input parameters Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text); else // if the Expert Advisor is run on the chart, tell the user about the error Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text); //--- m_init_error=true; return(INIT_SUCCEEDED); } } else if(InpLotOrRisk==risk) { if(m_money!=NULL) delete m_money; m_money=new CMoneyFixedMargin; if(m_money!=NULL) { if(InpVolumeLotOrRisk<1 || InpVolumeLotOrRisk>100) { Print(__FILE__," ",__FUNCTION__,", ERROR: "); Print("The value for \"Money management\" (",DoubleToString(InpVolumeLotOrRisk,2),") -> invalid parameters"); Print(" parameter must be in the range: from 1.00 to 100.00"); //--- m_init_error=true; return(INIT_SUCCEEDED); } if(!m_money.Init(GetPointer(m_symbol),InpWorkingPeriod,m_symbol.Point()*digits_adjust)) { Print(__FILE__," ",__FUNCTION__,", ERROR: CMoneyFixedMargin.Init"); //--- m_init_error=true; return(INIT_SUCCEEDED); } m_money.Percent(InpVolumeLotOrRisk); } else { Print(__FILE__," ",__FUNCTION__,", ERROR: Object CMoneyFixedMargin is NULL"); return(INIT_FAILED); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- if(m_money!=NULL) delete m_money; } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(m_init_error) return; //--- if(m_need_close_all) { if(IsPositionExists()) { CloseAllPositions(); return; } else { m_need_close_all=false; ArrayFree(SPosition); } } //--- int size_need_position=ArraySize(SPosition); if(size_need_position>0) { for(int i=size_need_position-1; i>=0; i--) { if(SPosition[i].waiting_transaction) { if(!SPosition[i].transaction_confirmed) { if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","transaction_confirmed: ",SPosition[i].transaction_confirmed); return; } else if(SPosition[i].transaction_confirmed) { ArrayRemove(SPosition,i,1); return; } } if(SPosition[i].pos_type==POSITION_TYPE_BUY) { SPosition[i].waiting_transaction=true; OpenPosition(i); return; } if(SPosition[i].pos_type==POSITION_TYPE_SELL) { SPosition[i].waiting_transaction=true; OpenPosition(i); return; } } } //--- search for trading signals no more than once every 10 seconds datetime time_current=TimeCurrent(); if(time_current-m_last_signal>10) { //--- search for trading signals if(!RefreshRates()) { m_prev_bars=0; return; } if(!SearchTradingSignals()) { m_prev_bars=0; return; } m_last_signal=time_current; } //--- we work only at the time of the birth of new bar datetime time_0=iTime(m_symbol.Name(),InpWorkingPeriod,0); if(time_0==m_prev_bars) return; m_prev_bars=time_0; m_need_close_all=true; //--- } //+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result) { //--- get transaction type as enumeration value ENUM_TRADE_TRANSACTION_TYPE type=trans.type; //--- if transaction is result of addition of the transaction in history if(type==TRADE_TRANSACTION_DEAL_ADD) { ResetLastError(); if(HistoryDealSelect(trans.deal)) m_deal.Ticket(trans.deal); else { Print(__FILE__," ",__FUNCTION__,", ERROR: ","HistoryDealSelect(",trans.deal,") error: ",GetLastError()); return; } if(m_deal.Symbol()==m_symbol.Name() && m_deal.Magic()==InpMagic) { if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) { if(m_deal.Entry()==DEAL_ENTRY_IN || m_deal.Entry()==DEAL_ENTRY_INOUT) m_last_deal_in=iTime(m_symbol.Name(),InpWorkingPeriod,0); int size_need_position=ArraySize(SPosition); if(size_need_position>0) { for(int i=0; imax_volume) { if(TerminalInfoString(TERMINAL_LANGUAGE)=="English") error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume); else error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume); return(false); } //--- get minimal step of volume changing double volume_step=m_symbol.LotsStep(); int ratio=(int)MathRound(volume/volume_step); if(MathAbs(ratio*volume_step-volume)>0.0000001) { if(TerminalInfoString(TERMINAL_LANGUAGE)=="English") error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f", volume_step,ratio*volume_step); else error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f", volume_step,ratio*volume_step); return(false); } error_description="Correct volume value"; //--- return(true); } //+------------------------------------------------------------------+ //| Check Freeze and Stops levels | //+------------------------------------------------------------------+ void FreezeStopsLevels(double &freeze,double &stops) { //--- check Freeze and Stops levels /* SYMBOL_TRADE_FREEZE_LEVEL shows the distance of freezing the trade operations for pending orders and open positions in points ------------------------|--------------------|-------------------------------------------- Type of order/position | Activation price | Check ------------------------|--------------------|-------------------------------------------- Buy Limit order | Ask | Ask-OpenPrice >= SYMBOL_TRADE_FREEZE_LEVEL Buy Stop order | Ask | OpenPrice-Ask >= SYMBOL_TRADE_FREEZE_LEVEL Sell Limit order | Bid | OpenPrice-Bid >= SYMBOL_TRADE_FREEZE_LEVEL Sell Stop order | Bid | Bid-OpenPrice >= SYMBOL_TRADE_FREEZE_LEVEL Buy position | Bid | TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL | | Bid-StopLoss >= SYMBOL_TRADE_FREEZE_LEVEL Sell position | Ask | Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL | | StopLoss-Ask >= SYMBOL_TRADE_FREEZE_LEVEL ------------------------------------------------------------------------------------------ SYMBOL_TRADE_STOPS_LEVEL determines the number of points for minimum indentation of the StopLoss and TakeProfit levels from the current closing price of the open position ------------------------------------------------|------------------------------------------ Buying is done at the Ask price | Selling is done at the Bid price ------------------------------------------------|------------------------------------------ TakeProfit >= Bid | TakeProfit <= Ask StopLoss <= Bid | StopLoss >= Ask TakeProfit - Bid >= SYMBOL_TRADE_STOPS_LEVEL | Ask - TakeProfit >= SYMBOL_TRADE_STOPS_LEVEL Bid - StopLoss >= SYMBOL_TRADE_STOPS_LEVEL | StopLoss - Ask >= SYMBOL_TRADE_STOPS_LEVEL ------------------------------------------------------------------------------------------ */ double coeff=(double)InpFreezeCoefficient; if(!RefreshRates() || !m_symbol.Refresh()) return; //--- FreezeLevel -> for pending order and modification double freeze_level=m_symbol.FreezeLevel()*m_symbol.Point(); if(freeze_level==0.0) if(InpFreezeCoefficient>0) freeze_level=(m_symbol.Ask()-m_symbol.Bid())*coeff; //--- StopsLevel -> for TakeProfit and StopLoss double stop_level=m_symbol.StopsLevel()*m_symbol.Point(); if(stop_level==0.0) if(InpFreezeCoefficient>0) stop_level=(m_symbol.Ask()-m_symbol.Bid())*coeff; //--- freeze=freeze_level; stops=stop_level; //--- return; } //+------------------------------------------------------------------+ //| Open position | //| double stop_loss | //| -> pips * m_adjusted_point (if "0.0" -> the m_stop_loss) | //| double take_profit | //| -> pips * m_adjusted_point (if "0.0" -> the m_take_profit) | //+------------------------------------------------------------------+ void OpenPosition(const int index) { double freeze=0.0,stops=0.0; FreezeStopsLevels(freeze,stops); /* SYMBOL_TRADE_STOPS_LEVEL determines the number of points for minimum indentation of the StopLoss and TakeProfit levels from the current closing price of the open position ------------------------------------------------|------------------------------------------ Buying is done at the Ask price | Selling is done at the Bid price ------------------------------------------------|------------------------------------------ TakeProfit >= Bid | TakeProfit <= Ask StopLoss <= Bid | StopLoss >= Ask TakeProfit - Bid >= SYMBOL_TRADE_STOPS_LEVEL | Ask - TakeProfit >= SYMBOL_TRADE_STOPS_LEVEL Bid - StopLoss >= SYMBOL_TRADE_STOPS_LEVEL | StopLoss - Ask >= SYMBOL_TRADE_STOPS_LEVEL ------------------------------------------------------------------------------------------ */ //--- buy if(SPosition[index].pos_type==POSITION_TYPE_BUY) { double tp=(m_take_profit==0.0)?0.0:m_symbol.Ask()+m_take_profit; if(tp>0.0) if(tp-m_symbol.Ask()0.0) if(m_symbol.Bid()-tp0.0) { int count_buys = 0; double volume_buys = 0.0; double volume_biggest_buys = 0.0; int count_sells = 0; double volume_sells = 0.0; double volume_biggest_sells = 0.0; CalculateAllPositions(count_buys,volume_buys,volume_biggest_buys, count_sells,volume_sells,volume_biggest_sells); if(volume_buys+volume_sells+long_lot>m_symbol.LotsLimit()) { ArrayRemove(SPosition,index,1); if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","#0 Buy, Volume Buy (",DoubleToString(volume_buys,2), ") + Volume Sell (",DoubleToString(volume_sells,2), ") + Volume long (",DoubleToString(long_lot,2), ") > Lots Limit (",DoubleToString(m_symbol.LotsLimit(),2),")"); return; } } //--- check volume before OrderSend to avoid "not enough money" error (CTrade) double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(), ORDER_TYPE_BUY, long_lot, m_symbol.Ask()); double margin_check=m_account.MarginCheck(m_symbol.Name(), ORDER_TYPE_BUY, long_lot, m_symbol.Ask()); if(free_margin_check>margin_check) { if(m_trade.Buy(long_lot,m_symbol.Name(), m_symbol.Ask(),sl,tp)) // CTrade::Buy -> "true" { if(m_trade.ResultDeal()==0) { if(m_trade.ResultRetcode()==10009) // trade order went to the exchange { SPosition[index].waiting_transaction=true; SPosition[index].waiting_order_ticket=m_trade.ResultOrder(); } else { SPosition[index].waiting_transaction=false; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","#1 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); } if(InpPrintLog) PrintResultTrade(m_trade,m_symbol); } else { if(m_trade.ResultRetcode()==10009) { SPosition[index].waiting_transaction=true; SPosition[index].waiting_order_ticket=m_trade.ResultOrder(); } else { SPosition[index].waiting_transaction=false; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","#2 Buy -> true. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); } if(InpPrintLog) PrintResultTrade(m_trade,m_symbol); } } else { SPosition[index].waiting_transaction=false; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","#3 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); if(InpPrintLog) PrintResultTrade(m_trade,m_symbol); } } else { ArrayRemove(SPosition,index,1); if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","CAccountInfo.FreeMarginCheck returned the value ",DoubleToString(free_margin_check,2)); return; } //--- } //+------------------------------------------------------------------+ //| Open Sell position | //+------------------------------------------------------------------+ void OpenSell(const int index,double tp) { double sl=0.0; tp=m_symbol.NormalizePrice(tp); double short_lot=0.0; if(InpLotOrRisk==risk) { short_lot=m_money.CheckOpenShort(m_symbol.Bid(),sl); if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","sl=",DoubleToString(sl,m_symbol.Digits()), ", CheckOpenLong: ",DoubleToString(short_lot,2), ", Balance: ", DoubleToString(m_account.Balance(),2), ", Equity: ", DoubleToString(m_account.Equity(),2), ", FreeMargin: ", DoubleToString(m_account.FreeMargin(),2)); if(short_lot==0.0) { ArrayRemove(SPosition,index,1); if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","CMoneyFixedMargin.CheckOpenShort returned the value of \"0.0\""); return; } } else if(InpLotOrRisk==lot) short_lot=InpVolumeLotOrRisk; else if(InpLotOrRisk==lots_min) short_lot=m_symbol.LotsMin(); else { ArrayRemove(SPosition,index,1); return; } //--- if(m_symbol.LotsLimit()>0.0) { int count_buys = 0; double volume_buys = 0.0; double volume_biggest_buys = 0.0; int count_sells = 0; double volume_sells = 0.0; double volume_biggest_sells = 0.0; CalculateAllPositions(count_buys,volume_buys,volume_biggest_buys, count_sells,volume_sells,volume_biggest_sells); if(volume_buys+volume_sells+short_lot>m_symbol.LotsLimit()) { ArrayRemove(SPosition,index,1); if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","#0 Buy, Volume Buy (",DoubleToString(volume_buys,2), ") + Volume Sell (",DoubleToString(volume_sells,2), ") + Volume short (",DoubleToString(short_lot,2), ") > Lots Limit (",DoubleToString(m_symbol.LotsLimit(),2),")"); return; } } //--- check volume before OrderSend to avoid "not enough money" error (CTrade) double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(), ORDER_TYPE_SELL, short_lot, m_symbol.Bid()); double margin_check=m_account.MarginCheck(m_symbol.Name(), ORDER_TYPE_SELL, short_lot, m_symbol.Bid()); if(free_margin_check>margin_check) { if(m_trade.Sell(short_lot,m_symbol.Name(), m_symbol.Bid(),sl,tp)) // CTrade::Sell -> "true" { if(m_trade.ResultDeal()==0) { if(m_trade.ResultRetcode()==10009) // trade order went to the exchange { SPosition[index].waiting_transaction=true; SPosition[index].waiting_order_ticket=m_trade.ResultOrder(); } else { SPosition[index].waiting_transaction=false; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","#1 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); } if(InpPrintLog) PrintResultTrade(m_trade,m_symbol); } else { if(m_trade.ResultRetcode()==10009) { SPosition[index].waiting_transaction=true; SPosition[index].waiting_order_ticket=m_trade.ResultOrder(); } else { SPosition[index].waiting_transaction=false; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","#2 Sell -> true. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); } if(InpPrintLog) PrintResultTrade(m_trade,m_symbol); } } else { SPosition[index].waiting_transaction=false; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","#3 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); if(InpPrintLog) PrintResultTrade(m_trade,m_symbol); } } else { ArrayRemove(SPosition,index,1); if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","CAccountInfo.FreeMarginCheck returned the value ",DoubleToString(free_margin_check,2)); return; } //--- } //+------------------------------------------------------------------+ //| Print CTrade result | //+------------------------------------------------------------------+ void PrintResultTrade(CTrade &trade,CSymbolInfo &symbol) { Print(__FILE__," ",__FUNCTION__,", Symbol: ",symbol.Name()+", "+ "Code of request result: "+IntegerToString(trade.ResultRetcode())+", "+ "Code of request result as a string: "+trade.ResultRetcodeDescription(), "Trade execution mode: "+symbol.TradeExecutionDescription()); Print("Deal ticket: "+IntegerToString(trade.ResultDeal())+", "+ "Order ticket: "+IntegerToString(trade.ResultOrder())+", "+ "Order retcode external: "+IntegerToString(trade.ResultRetcodeExternal())+", "+ "Volume of deal or order: "+DoubleToString(trade.ResultVolume(),2)); Print("Price, confirmed by broker: "+DoubleToString(trade.ResultPrice(),symbol.Digits())+", "+ "Current bid price: "+DoubleToString(symbol.Bid(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultBid(),symbol.Digits())+", "+ "Current ask price: "+DoubleToString(symbol.Ask(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultAsk(),symbol.Digits())); Print("Broker comment: "+trade.ResultComment()); } //+------------------------------------------------------------------+ //| Calculate all positions | //+------------------------------------------------------------------+ void CalculateAllPositions(int &count_buys,double &volume_buys,double &volume_biggest_buys, int &count_sells,double &volume_sells,double &volume_biggest_sells) { count_buys = 0; volume_buys = 0.0; volume_biggest_buys = 0.0; count_sells = 0; volume_sells = 0.0; volume_biggest_sells = 0.0; for(int i=PositionsTotal()-1; i>=0; i--) if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties if(m_position.Symbol()==m_symbol.Name()) { if(m_position.PositionType()==POSITION_TYPE_BUY) { count_buys++; volume_buys+=m_position.Volume(); if(m_position.Volume()>volume_biggest_buys) volume_biggest_buys=m_position.Volume(); continue; } else if(m_position.PositionType()==POSITION_TYPE_SELL) { count_sells++; volume_sells+=m_position.Volume(); if(m_position.Volume()>volume_biggest_sells) volume_biggest_sells=m_position.Volume(); } } } //+------------------------------------------------------------------+ //| Search trading signals | //+------------------------------------------------------------------+ bool SearchTradingSignals(void) { if(iTime(m_symbol.Name(),InpWorkingPeriod,0)==m_last_deal_in) // on one bar - only one deal return(true); if(!TimeControlHourMinute()) return(true); MqlRates rates[]; ArraySetAsSeries(rates,true); int start_pos=0,count=3; if(CopyRates(m_symbol.Name(),InpWorkingPeriod,start_pos,count,rates)!=count) return(false); int size_need_position=ArraySize(SPosition); double bar_size=(InpPriceCalculation==high_low)?rates[1].high-rates[1].low:MathAbs(rates[1].open-rates[1].close); if(rates[1].open>rates[1].close && rates[0].close>rates[1].close && bar_size>=m_min_size) { bool breakdown=false; if(InpPriceCalculation==high_low) breakdown=(rates[0].close-rates[1].low>=m_min_size/2.0); else breakdown=(rates[0].close-rates[1].close>=m_min_size/2.0); if(breakdown) { if(!InpReverse) { if(InpTradeMode!=sell) { ArrayResize(SPosition,size_need_position+1); SPosition[size_need_position].pos_type=POSITION_TYPE_BUY; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY"); return(true); } } else { if(InpTradeMode!=buy) { ArrayResize(SPosition,size_need_position+1); SPosition[size_need_position].pos_type=POSITION_TYPE_SELL; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL"); return(true); } } } } if(rates[1].open=m_min_size) { bool breakdown=false; if(InpPriceCalculation==high_low) breakdown=(rates[1].high-rates[0].close>=m_min_size/2.0); else breakdown=(rates[1].close-rates[0].close>=m_min_size/2.0); if(breakdown) { if(!InpReverse) { if(InpTradeMode!=buy) { ArrayResize(SPosition,size_need_position+1); SPosition[size_need_position].pos_type=POSITION_TYPE_SELL; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL"); return(true); } } else { if(InpTradeMode!=sell) { ArrayResize(SPosition,size_need_position+1); SPosition[size_need_position].pos_type=POSITION_TYPE_BUY; if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY"); return(true); } } } } //--- return(true); } //+------------------------------------------------------------------+ //| Is position exists | //+------------------------------------------------------------------+ bool IsPositionExists(void) { for(int i=PositionsTotal()-1; i>=0; i--) if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic) return(true); //--- return(false); } //+------------------------------------------------------------------+ //| Close all positions | //+------------------------------------------------------------------+ void CloseAllPositions(void) { double freeze=0.0,stops=0.0; FreezeStopsLevels(freeze,stops); /* SYMBOL_TRADE_FREEZE_LEVEL shows the distance of freezing the trade operations for pending orders and open positions in points ------------------------|--------------------|-------------------------------------------- Type of order/position | Activation price | Check ------------------------|--------------------|-------------------------------------------- Buy Limit order | Ask | Ask-OpenPrice >= SYMBOL_TRADE_FREEZE_LEVEL Buy Stop order | Ask | OpenPrice-Ask >= SYMBOL_TRADE_FREEZE_LEVEL Sell Limit order | Bid | OpenPrice-Bid >= SYMBOL_TRADE_FREEZE_LEVEL Sell Stop order | Bid | Bid-OpenPrice >= SYMBOL_TRADE_FREEZE_LEVEL Buy position | Bid | TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL | | Bid-StopLoss >= SYMBOL_TRADE_FREEZE_LEVEL Sell position | Ask | Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL | | StopLoss-Ask >= SYMBOL_TRADE_FREEZE_LEVEL ------------------------------------------------------------------------------------------ */ for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic) { if(m_position.PositionType()==POSITION_TYPE_BUY) { bool take_profit_level=(m_position.TakeProfit()!=0.0 && m_position.TakeProfit()-m_position.PriceCurrent()>=freeze) || m_position.TakeProfit()==0.0; bool stop_loss_level=(m_position.StopLoss()!=0.0 && m_position.PriceCurrent()-m_position.StopLoss()>=freeze) || m_position.StopLoss()==0.0; if(take_profit_level && stop_loss_level) if(!m_trade.PositionClose(m_position.Ticket())) // close a position by the specified m_symbol if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","BUY PositionClose ",m_position.Ticket(),", ",m_trade.ResultRetcodeDescription()); } if(m_position.PositionType()==POSITION_TYPE_SELL) { bool take_profit_level=(m_position.TakeProfit()!=0.0 && m_position.PriceCurrent()-m_position.TakeProfit()>=freeze) || m_position.TakeProfit()==0.0; bool stop_loss_level=(m_position.StopLoss()!=0.0 && m_position.StopLoss()-m_position.PriceCurrent()>=freeze) || m_position.StopLoss()==0.0; if(take_profit_level && stop_loss_level) if(!m_trade.PositionClose(m_position.Ticket())) // close a position by the specified m_symbol if(InpPrintLog) Print(__FILE__," ",__FUNCTION__,", ERROR: ","SELL PositionClose ",m_position.Ticket(),", ",m_trade.ResultRetcodeDescription()); } } } //+------------------------------------------------------------------+ //| TimeControl | //+------------------------------------------------------------------+ bool TimeControlHourMinute(void) { if(!InpTimeControl) return(true); MqlDateTime STimeCurrent; datetime time_current=TimeCurrent(); if(time_current==D'1970.01.01 00:00') return(false); TimeToStruct(time_current,STimeCurrent); if((InpStartHour*60*60+InpStartMinute*60)<(InpEndHour*60*60+InpEndMinute*60)) // intraday time interval { /* Example: input uchar InpStartHour = 5; // Start hour input uchar InpEndHour = 10; // End hour 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 _ _ _ _ _ + + + + + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + + + + _ _ _ _ _ _ */ if((STimeCurrent.hour*60*60+STimeCurrent.min*60>=InpStartHour*60*60+InpStartMinute*60) && (STimeCurrent.hour*60*60+STimeCurrent.min*60(InpEndHour*60*60+InpEndMinute*60)) // time interval with the transition in a day { /* Example: input uchar InpStartHour = 10; // Start hour input uchar InpEndHour = 5; // End hour 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 _ _ _ _ _ _ _ _ _ _ + + + + + + + + + + + + + + + + + + + _ _ _ _ _ + + + + + + */ if(STimeCurrent.hour*60*60+STimeCurrent.min*60>=InpStartHour*60*60+InpStartMinute*60 || STimeCurrent.hour*60*60+STimeCurrent.min*60