ÿþ
#property copyright "Copyright © 2020, Vladimir Karputov"
#property link "https://www.mql5.com/ru/market/product/43516"
#property version "1.000"
#property tester_indicator "MA on ATR Color N bars"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Expert\Money\MoneyFixedMargin.mqh>
CPositionInfo m_position;
CTrade m_trade;
CSymbolInfo m_symbol;
CAccountInfo m_account;
CDealInfo m_deal;
COrderInfo m_order;
CMoneyFixedMargin *m_money;
enum ENUM_LOT_OR_RISK
{
lots_min=0,
lot=1,
risk=2,
};
enum ENUM_PIPS_OR_POINTS
{
pips=0,
points=1,
};
input group "Trading settings"
input ENUM_TIMEFRAMES InpWorkingPeriod=PERIOD_CURRENT;
input ENUM_PIPS_OR_POINTS InpPipsOrPoints=pips;
input uint InpStopLoss = 15;
input uint InpTakeProfit = 46;
input ushort InpTrailingFrequency = 10;
input ushort InpSignalsFrequency = 10;
input uint InpTrailingStop = 25;
input uint InpTrailingStep = 5;
input group "Position size management (lot calculation)"
input ENUM_LOT_OR_RISK InpLotOrRisk = risk;
input double InpVolumeLotOrRisk = 3.0;
input group "Time control"
input bool InpTimeControl = true;
input uchar InpStartHour = 10;
input uchar InpStartMinute = 01;
input uchar InpEndHour = 15;
input uchar InpEndMinute = 02;
input group "ATR"
input int Inp_ATR_ma_period = 14;
input group "MA"
input int Inp_MA_ma_period = 6;
input ENUM_MA_METHOD Inp_MA_ma_method = MODE_EMA;
input uchar Inp_MA_trend_n_bars = 3;
input group "Pending Order Parameters"
input ushort InpPendingExpiration = 600;
input uint InpPendingIndent = 5;
input uint InpPendingMaxSpread = 12;
input bool InpPendingOnlyOne = false;
input bool InpPendingReverse = false;
input bool InpPendingClosePrevious=true;
input group "Additional features"
input bool InpPrintLog = false;
input uchar InpFreezeCoefficient = 1;
input ulong InpDeviation = 10;
input ulong InpMagic = 200;
double m_stop_loss = 0.0;
double m_take_profit = 0.0;
double m_trailing_stop = 0.0;
double m_trailing_step = 0.0;
double m_pending_indent = 0.0;
double m_max_spread = 0.0;
int handle_iCustom;
double m_adjusted_point;
datetime m_last_trailing = 0;
datetime m_last_signal = 0;
datetime m_prev_bars = 0;
datetime m_last_deal_in = 0;
int m_bar_current = 0;
bool m_need_delete_all = false;
bool m_waiting_pending_order = false;
struct STRUCT_PENDING
{
ENUM_ORDER_TYPE pending_type;
double volume;
double price;
double stop_loss;
double take_profit;
double indent;
long expiration;
STRUCT_PENDING()
{
pending_type = WRONG_VALUE;
volume = 0.0;
price = 0.0;
stop_loss = 0.0;
take_profit = 0.0;
indent = 0.0;
expiration = 0;
}
};
STRUCT_PENDING SPending[];
int OnInit()
{
if(InpTrailingStop!=0 && InpTrailingStep==0)
{
string err_text=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")?
""@59;8=3 =52>7<>65=: ?0@0<5B@ \"Trailing Step\" @025= =C;N!":
"Trailing is not possible: parameter \"Trailing Step\" is zero!";
if(MQLInfoInteger(MQL_TESTER))
{
Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);
return(INIT_FAILED);
}
else
{
Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);
return(INIT_PARAMETERS_INCORRECT);
}
}
ResetLastError();
if(!m_symbol.Name(Symbol()))
{
Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");
return(INIT_FAILED);
}
RefreshRates();
if(InpPendingExpiration>0)
{
int exp_type=(int)SYMBOL_EXPIRATION_SPECIFIED;
int expiration=(int)m_symbol.TradeTimeFlags();
if((expiration&exp_type)!=exp_type)
{
string err_text=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")?
"0 A8<2>;5 "+m_symbol.Name()+" =5;L7O 7040BL !@>: 8AB5G5=8O 4;O >B;>65==>3> >@45@0!":
"On the symbol "+m_symbol.Name()+" you can not set the expiration date for a pending order!";
if(MQLInfoInteger(MQL_TESTER))
{
Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);
return(INIT_FAILED);
}
else
{
Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);
return(INIT_PARAMETERS_INCORRECT);
}
}
}
m_trade.SetExpertMagicNumber(InpMagic);
m_trade.SetMarginMode();
m_trade.SetTypeFillingBySymbol(m_symbol.Name());
m_trade.SetDeviationInPoints(InpDeviation);
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)
{
m_stop_loss = InpStopLoss * m_adjusted_point;
m_take_profit = InpTakeProfit * m_adjusted_point;
m_trailing_stop = InpTrailingStop * m_adjusted_point;
m_trailing_step = InpTrailingStep * m_adjusted_point;
m_pending_indent = InpPendingIndent * m_adjusted_point;
m_max_spread = InpPendingMaxSpread * m_adjusted_point;
}
else
{
m_stop_loss = InpStopLoss * m_symbol.Point();
m_take_profit = InpTakeProfit * m_symbol.Point();
m_trailing_stop = InpTrailingStop * m_symbol.Point();
m_trailing_step = InpTrailingStep * m_symbol.Point();
m_pending_indent = InpPendingIndent * m_symbol.Point();
m_max_spread = InpPendingMaxSpread * m_symbol.Point();
}
string err_text="";
if(InpLotOrRisk==lot)
{
if(!CheckVolumeValue(InpVolumeLotOrRisk,err_text))
{
if(MQLInfoInteger(MQL_TESTER))
{
Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);
return(INIT_FAILED);
}
else
{
Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);
return(INIT_PARAMETERS_INCORRECT);
}
}
}
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");
return(INIT_FAILED);
}
if(!m_money.Init(GetPointer(m_symbol),InpWorkingPeriod,m_symbol.Point()*digits_adjust))
{
Print(__FILE__," ",__FUNCTION__,", ERROR: CMoneyFixedMargin.Init");
return(INIT_FAILED);
}
m_money.Percent(InpVolumeLotOrRisk);
}
else
{
Print(__FILE__," ",__FUNCTION__,", ERROR: Object CMoneyFixedMargin is NULL");
return(INIT_FAILED);
}
}
handle_iCustom=iCustom(m_symbol.Name(),InpWorkingPeriod,"MA on ATR Color N bars",
"ATR",
Inp_ATR_ma_period,
"MA",
Inp_MA_ma_period,
Inp_MA_ma_method,
Inp_MA_trend_n_bars);
if(handle_iCustom==INVALID_HANDLE)
{
PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
m_symbol.Name(),
EnumToString(InpWorkingPeriod),
GetLastError());
return(INIT_FAILED);
}
m_bar_current=(InpSignalsFrequency<10)?1:0;
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
if(m_money!=NULL)
delete m_money;
}
void OnTick()
{
if(m_need_delete_all)
{
if(IsPendingOrdersExists())
{
DeleteAllPendingOrders();
return;
}
else
m_need_delete_all=false;
}
int size_need_pending=ArraySize(SPending);
if(size_need_pending>0)
{
if(!m_waiting_pending_order)
for(int i=size_need_pending-1; i>=0; i--)
{
m_waiting_pending_order=true;
PlaceOrders(i);
}
return;
}
if(InpTrailingFrequency>=10)
{
datetime time_current=TimeCurrent();
if(time_current-m_last_trailing>InpTrailingFrequency)
{
Trailing();
m_last_trailing=time_current;
}
}
if(InpSignalsFrequency>=10)
{
datetime time_current=TimeCurrent();
if(time_current-m_last_signal>InpSignalsFrequency)
{
if(!RefreshRates())
{
m_prev_bars=0;
return;
}
if(!SearchTradingSignals())
{
m_prev_bars=0;
return;
}
m_last_signal=time_current;
}
}
datetime time_0=iTime(m_symbol.Name(),InpWorkingPeriod,0);
if(time_0==m_prev_bars)
return;
m_prev_bars=time_0;
if(InpTrailingFrequency<10)
{
Trailing();
}
if(InpSignalsFrequency<10)
{
if(!RefreshRates())
{
m_prev_bars=0;
return;
}
if(!SearchTradingSignals())
{
m_prev_bars=0;
return;
}
}
}
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
}
bool RefreshRates()
{
if(!m_symbol.RefreshRates())
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","RefreshRates error");
return(false);
}
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","Ask == 0.0 OR Bid == 0.0");
return(false);
}
return(true);
}
bool CheckVolumeValue(double volume,string &error_description)
{
double min_volume=m_symbol.LotsMin();
if(volume<min_volume)
{
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
error_description=StringFormat("1J5< <5=LH5 <8=8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MIN=%.2f",min_volume);
else
error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
return(false);
}
double max_volume=m_symbol.LotsMax();
if(volume>max_volume)
{
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
error_description=StringFormat("1J5< 1>;LH5 <0:A8<0;L=> 4>?CAB8<>3> 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);
}
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)=="Russian")
error_description=StringFormat("1J5< =5 :@0B5= <8=8<0;L=><C H03C SYMBOL_VOLUME_STEP=%.2f, 1;8609H89 ?@028;L=K9 >1J5< %.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);
}
double LotCheck(double lots,CSymbolInfo &symbol)
{
double volume=NormalizeDouble(lots,2);
double stepvol=symbol.LotsStep();
if(stepvol>0.0)
volume=stepvol*MathFloor(volume/stepvol);
double minvol=symbol.LotsMin();
if(volume<minvol)
volume=0.0;
double maxvol=symbol.LotsMax();
if(volume>maxvol)
volume=maxvol;
return(volume);
}
void FreezeStopsLevels(double &freeze,double &stops)
{
double coeff=(double)InpFreezeCoefficient;
if(!RefreshRates() || !m_symbol.Refresh())
return;
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;
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;
}
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());
}
bool iGetArray(const int handle,const int buffer,const int start_pos,
const int count,double &arr_buffer[])
{
bool result=true;
if(!ArrayIsDynamic(arr_buffer))
{
if(InpPrintLog)
PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
return(false);
}
ArrayFree(arr_buffer);
ResetLastError();
int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
if(copied!=count)
{
if(InpPrintLog)
PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
__FILE__,__FUNCTION__,count,copied,GetLastError());
return(false);
}
return(result);
}
void Trailing()
{
if(InpTrailingStop==0)
return;
double freeze=0.0,stops=0.0;
FreezeStopsLevels(freeze,stops);
for(int i=PositionsTotal()-1; i>=0; i--)
if(m_position.SelectByIndex(i))
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
{
double price_current = m_position.PriceCurrent();
double price_open = m_position.PriceOpen();
double stop_loss = m_position.StopLoss();
double take_profit = m_position.TakeProfit();
double ask = m_symbol.Ask();
double bid = m_symbol.Bid();
if(m_position.PositionType()==POSITION_TYPE_BUY)
{
if(price_current-price_open>m_trailing_stop+m_trailing_step)
if(stop_loss<price_current-(m_trailing_stop+m_trailing_step))
if(m_trailing_stop>=freeze && (take_profit-bid>=freeze || take_profit==0.0))
{
if(!m_trade.PositionModify(m_position.Ticket(),
m_symbol.NormalizePrice(price_current-m_trailing_stop),
take_profit))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",m_position.Ticket(),
" Position -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
if(InpPrintLog)
{
RefreshRates();
m_position.SelectByIndex(i);
PrintResultModify(m_trade,m_symbol,m_position);
}
continue;
}
}
else
{
if(price_open-price_current>m_trailing_stop+m_trailing_step)
if((stop_loss>(price_current+(m_trailing_stop+m_trailing_step))) || (stop_loss==0))
if(m_trailing_stop>=freeze && ask-take_profit>=freeze)
{
if(!m_trade.PositionModify(m_position.Ticket(),
m_symbol.NormalizePrice(price_current+m_trailing_stop),
take_profit))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",m_position.Ticket(),
" Position -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
if(InpPrintLog)
{
RefreshRates();
m_position.SelectByIndex(i);
PrintResultModify(m_trade,m_symbol,m_position);
}
}
}
}
}
void PrintResultModify(CTrade &trade,CSymbolInfo &symbol,CPositionInfo &position)
{
Print("File: ",__FILE__,", symbol: ",symbol.Name());
Print("Code of request result: "+IntegerToString(trade.ResultRetcode()));
Print("code of request result as a string: "+trade.ResultRetcodeDescription());
Print("Deal ticket: "+IntegerToString(trade.ResultDeal()));
Print("Order ticket: "+IntegerToString(trade.ResultOrder()));
Print("Volume of deal or order: "+DoubleToString(trade.ResultVolume(),2));
Print("Price, confirmed by broker: "+DoubleToString(trade.ResultPrice(),symbol.Digits()));
Print("Current bid price: "+DoubleToString(symbol.Bid(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultBid(),symbol.Digits()));
Print("Current ask price: "+DoubleToString(symbol.Ask(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultAsk(),symbol.Digits()));
Print("Broker comment: "+trade.ResultComment());
Print("Freeze Level: "+DoubleToString(symbol.FreezeLevel(),0),", Stops Level: "+DoubleToString(symbol.StopsLevel(),0));
Print("Price of position opening: "+DoubleToString(position.PriceOpen(),symbol.Digits()));
Print("Price of position's Stop Loss: "+DoubleToString(position.StopLoss(),symbol.Digits()));
Print("Price of position's Take Profit: "+DoubleToString(position.TakeProfit(),symbol.Digits()));
Print("Current price by position: "+DoubleToString(position.PriceCurrent(),symbol.Digits()));
}
void ClosePositions(const ENUM_POSITION_TYPE pos_type)
{
double freeze=0.0,stops=0.0;
FreezeStopsLevels(freeze,stops);
for(int i=PositionsTotal()-1; i>=0; i--)
if(m_position.SelectByIndex(i))
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
if(m_position.PositionType()==pos_type)
{
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()))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CTrade.PositionClose ",m_position.Ticket());
}
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()))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CTrade.PositionClose ",m_position.Ticket());
}
}
}
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))
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();
}
}
}
bool SearchTradingSignals(void)
{
if(m_prev_bars==m_last_deal_in)
return(true);
if(!TimeControlHourMinute())
return(true);
if(InpPendingOnlyOne)
if(IsPendingOrdersExists())
return(true);
double ma_on_atr_colors[];
MqlRates rates[];
ArraySetAsSeries(ma_on_atr_colors,true);
ArraySetAsSeries(rates,true);
int start_pos=0,count=6;
if(!iGetArray(handle_iCustom,2,start_pos,count,ma_on_atr_colors) || CopyRates(m_symbol.Name(),InpWorkingPeriod,start_pos,count,rates)!=count)
return(false);
if(InpPendingClosePrevious)
m_need_delete_all=true;
int size_need_pending=ArraySize(SPending);
if(ma_on_atr_colors[m_bar_current]==0.0)
{
if(InpPendingClosePrevious)
m_need_delete_all=true;
ArrayResize(SPending,size_need_pending+1);
if(!InpPendingReverse)
{
SPending[size_need_pending].price=rates[m_bar_current].high;
SPending[size_need_pending].pending_type=ORDER_TYPE_BUY_STOP;
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY STOP ('Pending: Reverse pending type' -> false)");
}
else
{
SPending[size_need_pending].price=rates[m_bar_current].low;
SPending[size_need_pending].pending_type=ORDER_TYPE_SELL_STOP;
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY STOP ('Pending: Reverse pending type' -> true)");
}
SPending[size_need_pending].indent=m_pending_indent;
if(InpPendingExpiration>0)
SPending[size_need_pending].expiration=(long)(InpPendingExpiration*60);
}
if(ma_on_atr_colors[m_bar_current]==2.0)
{
if(InpPendingClosePrevious)
m_need_delete_all=true;
ArrayResize(SPending,size_need_pending+1);
if(!InpPendingReverse)
{
SPending[size_need_pending].price=rates[m_bar_current].low;
SPending[size_need_pending].pending_type=ORDER_TYPE_SELL_STOP;
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL STOP ('Pending: Reverse pending type' -> false)");
}
else
{
SPending[size_need_pending].price=rates[m_bar_current].high;
SPending[size_need_pending].pending_type=ORDER_TYPE_BUY_STOP;
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL STOP ('Pending: Reverse pending type' -> true)");
}
SPending[size_need_pending].indent=m_pending_indent;
if(InpPendingExpiration>0)
SPending[size_need_pending].expiration=(long)(InpPendingExpiration*60);
}
return(true);
}
void DeleteAllPendingOrders(void)
{
double freeze=0.0,stops=0.0;
FreezeStopsLevels(freeze,stops);
for(int i=OrdersTotal()-1; i>=0; i--)
if(m_order.SelectByIndex(i))
if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==InpMagic)
{
if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT)
{
if(m_symbol.Ask()-m_order.PriceOpen()>=freeze)
if(!m_trade.OrderDelete(m_order.Ticket()))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CTrade.OrderDelete ",m_order.Ticket());
continue;
}
if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)
{
if(m_order.PriceOpen()-m_symbol.Ask()>=freeze)
if(!m_trade.OrderDelete(m_order.Ticket()))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CTrade.OrderDelete ",m_order.Ticket());
continue;
}
if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT)
{
if(m_order.PriceOpen()-m_symbol.Bid()>=freeze)
if(!m_trade.OrderDelete(m_order.Ticket()))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CTrade.OrderDelete ",m_order.Ticket());
continue;
}
if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)
{
if(m_symbol.Bid()-m_order.PriceOpen()>=freeze)
if(!m_trade.OrderDelete(m_order.Ticket()))
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CTrade.OrderDelete ",m_order.Ticket());
continue;
}
}
}
bool IsPendingOrdersExists(void)
{
for(int i=OrdersTotal()-1; i>=0; i--)
if(m_order.SelectByIndex(i))
if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==InpMagic)
return(true);
return(false);
}
void PlaceOrders(const int index)
{
double freeze=0.0,stops=0.0;
FreezeStopsLevels(freeze,stops);
double spread=m_symbol.Ask()-m_symbol.Bid();
if(spread>m_max_spread)
{
m_waiting_pending_order=false;
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,
", ERROR: ","Spread Ask-Bid (",DoubleToString(spread,m_symbol.Digits()),")",
" > Maximum spread (",DoubleToString(m_max_spread,m_symbol.Digits()),")");
return;
}
if(SPending[index].pending_type==ORDER_TYPE_BUY_LIMIT)
{
if(SPending[index].price==0.0)
SPending[index].price=m_symbol.Ask()-m_pending_indent;
if(m_symbol.Ask()-SPending[index].price<stops)
SPending[index].price=m_symbol.Ask()-stops;
SPending[index].stop_loss=(m_stop_loss==0.0)?0.0:SPending[index].price-m_stop_loss;
SPending[index].take_profit=(m_take_profit==0.0)?0.0:SPending[index].price+m_take_profit;
double sl=SPending[index].stop_loss;
if(sl<=0.0)
sl=0.0;
else
if(SPending[index].price-sl<stops)
sl=SPending[index].price-stops;
double tp=SPending[index].take_profit;
if(tp<=0.0)
tp=0.0;
else
if(tp-SPending[index].price<stops)
tp=SPending[index].price+stops;
PendingOrder(index,sl,tp);
ArrayRemove(SPending,index,1);
m_waiting_pending_order=false;
return;
}
if(SPending[index].pending_type==ORDER_TYPE_SELL_LIMIT)
{
if(SPending[index].price==0.0)
SPending[index].price=m_symbol.Bid()+m_pending_indent;
if(SPending[index].price-m_symbol.Bid()<stops)
SPending[index].price=m_symbol.Bid()+stops;
SPending[index].stop_loss=(m_stop_loss==0.0)?0.0:SPending[index].price+m_stop_loss;
SPending[index].take_profit=(m_take_profit==0.0)?0.0:SPending[index].price-m_take_profit;
double sl=SPending[index].stop_loss;
if(sl<=0.0)
sl=0.0;
else
if(sl-SPending[index].price<stops)
sl=SPending[index].price+stops;
double tp=SPending[index].take_profit;
if(tp<=0.0)
tp=0.0;
else
if(SPending[index].price-tp<stops)
tp=SPending[index].price-stops;
PendingOrder(index,sl,tp);
ArrayRemove(SPending,index,1);
m_waiting_pending_order=false;
return;
}
if(SPending[index].pending_type==ORDER_TYPE_BUY_STOP)
{
if(SPending[index].price==0.0)
SPending[index].price=m_symbol.Ask()+m_pending_indent;
if(SPending[index].price-m_symbol.Ask()<stops)
SPending[index].price=m_symbol.Ask()+stops;
SPending[index].stop_loss=(m_stop_loss==0.0)?0.0:SPending[index].price-m_stop_loss;
SPending[index].take_profit=(m_take_profit==0.0)?0.0:SPending[index].price+m_take_profit;
double sl=SPending[index].stop_loss;
if(sl<=0.0)
sl=0.0;
else
if(SPending[index].price-sl<stops)
sl=SPending[index].price-stops;
double tp=SPending[index].take_profit;
if(tp<=0.0)
tp=0.0;
else
if(tp-SPending[index].price<stops)
tp=SPending[index].price+stops;
PendingOrder(index,sl,tp);
ArrayRemove(SPending,index,1);
m_waiting_pending_order=false;
return;
}
if(SPending[index].pending_type==ORDER_TYPE_SELL_STOP)
{
if(SPending[index].price==0.0)
SPending[index].price=m_symbol.Bid()-m_pending_indent;
if(m_symbol.Bid()-SPending[index].price<stops)
SPending[index].price=m_symbol.Bid()-stops;
SPending[index].stop_loss=(m_stop_loss==0.0)?0.0:SPending[index].price+m_stop_loss;
SPending[index].take_profit=(m_take_profit==0.0)?0.0:SPending[index].price-m_take_profit;
double sl=SPending[index].stop_loss;
if(sl<=0.0)
sl=0.0;
else
if(sl-SPending[index].price<stops)
sl=SPending[index].price+stops;
double tp=SPending[index].take_profit;
if(tp<=0.0)
tp=0.0;
else
if(SPending[index].price-tp<stops)
tp=SPending[index].price-stops;
PendingOrder(index,sl,tp);
ArrayRemove(SPending,index,1);
m_waiting_pending_order=false;
return;
}
}
bool PendingOrder(const int index,double sl,double tp)
{
sl=m_symbol.NormalizePrice(sl);
tp=m_symbol.NormalizePrice(tp);
m_last_deal_in=iTime(m_symbol.Name(),InpWorkingPeriod,0);
ENUM_ORDER_TYPE check_order_type=-1;
switch(SPending[index].pending_type)
{
case ORDER_TYPE_BUY:
check_order_type=ORDER_TYPE_BUY;
break;
case ORDER_TYPE_SELL:
check_order_type=ORDER_TYPE_SELL;
break;
case ORDER_TYPE_BUY_LIMIT:
check_order_type=ORDER_TYPE_BUY;
break;
case ORDER_TYPE_SELL_LIMIT:
check_order_type=ORDER_TYPE_SELL;
break;
case ORDER_TYPE_BUY_STOP:
check_order_type=ORDER_TYPE_BUY;
break;
case ORDER_TYPE_SELL_STOP:
check_order_type=ORDER_TYPE_SELL;
break;
default:
return(false);
break;
}
double long_lot=0.0;
double short_lot=0.0;
if(InpLotOrRisk==risk)
{
bool error=false;
long_lot=m_money.CheckOpenLong(m_symbol.Ask(),sl);
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", OK: ","sl=",DoubleToString(sl,m_symbol.Digits()),
", CheckOpenLong: ",DoubleToString(long_lot,2),
", Balance: ", DoubleToString(m_account.Balance(),2),
", Equity: ", DoubleToString(m_account.Equity(),2),
", FreeMargin: ", DoubleToString(m_account.FreeMargin(),2));
if(long_lot==0.0)
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CMoneyFixedMargin.CheckOpenLong returned the value of \"0.0\"");
error=true;
}
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)
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","CMoneyFixedMargin.CheckOpenShort returned the value of \"0.0\"");
error=true;
}
if(error)
return(false);
}
else
if(InpLotOrRisk==lot)
{
long_lot=InpVolumeLotOrRisk;
short_lot=InpVolumeLotOrRisk;
}
else
if(InpLotOrRisk==lots_min)
{
long_lot=m_symbol.LotsMin();
short_lot=m_symbol.LotsMin();
}
else
return(false);
double check_price=0;
double check_lot=0;
if(check_order_type==ORDER_TYPE_BUY)
{
check_price=m_symbol.Ask();
check_lot=long_lot;
}
else
{
check_price=m_symbol.Bid();
check_lot=short_lot;
}
if(m_symbol.LotsLimit()>0.0)
{
double volume_buys = 0.0;
double volume_sells = 0.0;
double volume_buy_limits = 0.0;
double volume_sell_limits = 0.0;
double volume_buy_stops = 0.0;
double volume_sell_stops = 0.0;
CalculateAllVolumes(volume_buys,volume_sells,
volume_buy_limits,volume_sell_limits,
volume_buy_stops,volume_sell_stops);
if(volume_buys+volume_sells+
volume_buy_limits+volume_sell_limits+
volume_buy_stops+volume_sell_stops+check_lot>m_symbol.LotsLimit())
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","#0 ,",EnumToString(SPending[index].pending_type),", ",
"Volume Buy's (",DoubleToString(volume_buys,2),")",
"Volume Sell's (",DoubleToString(volume_sells,2),")",
"Volume Buy limit's (",DoubleToString(volume_buy_limits,2),")",
"Volume Sell limit's (",DoubleToString(volume_sell_limits,2),")",
"Volume Buy stops's (",DoubleToString(volume_buy_stops,2),")",
"Volume Sell stops's (",DoubleToString(volume_sell_stops,2),")",
"Check lot (",DoubleToString(check_lot,2),")",
" > Lots Limit (",DoubleToString(m_symbol.LotsLimit(),2),")");
return(false);
}
}
int account_limit_orders=m_account.LimitOrders();
if(account_limit_orders>0)
{
int all_pending_orders=CalculateAllPendingOrders();
if(all_pending_orders+1>account_limit_orders)
return(false);
}
double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(),
check_order_type,check_lot,check_price);
double margin_check=m_account.MarginCheck(m_symbol.Name(),
check_order_type,check_lot,SPending[index].price);
if(free_margin_check>margin_check)
{
bool result=false;
if(SPending[index].expiration>0)
{
datetime time_expiration=TimeCurrent()+(datetime)SPending[index].expiration;
result=m_trade.OrderOpen(m_symbol.Name(),
SPending[index].pending_type,check_lot,0.0,
m_symbol.NormalizePrice(SPending[index].price),
m_symbol.NormalizePrice(sl),
m_symbol.NormalizePrice(tp),
ORDER_TIME_SPECIFIED,
time_expiration);
}
else
{
result=m_trade.OrderOpen(m_symbol.Name(),
SPending[index].pending_type,check_lot,0.0,
m_symbol.NormalizePrice(SPending[index].price),
m_symbol.NormalizePrice(sl),
m_symbol.NormalizePrice(tp));
}
if(result)
{
if(m_trade.ResultOrder()==0)
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","#1 ",EnumToString(SPending[index].pending_type)," -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
if(InpPrintLog)
PrintResultTrade(m_trade,m_symbol);
return(false);
}
else
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", OK: ","#2 ",EnumToString(SPending[index].pending_type)," -> true. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
if(InpPrintLog)
PrintResultTrade(m_trade,m_symbol);
return(true);
}
}
else
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: ","#3 ",EnumToString(SPending[index].pending_type)," -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
if(InpPrintLog)
PrintResultTrade(m_trade,m_symbol);
return(false);
}
}
else
{
if(InpPrintLog)
Print(__FILE__," ",__FUNCTION__,", ERROR: CAccountInfo.FreeMarginCheck returned the value ",DoubleToString(free_margin_check,2));
return(false);
}
return(false);
}
void CalculateAllVolumes(double &volumne_buys,double &volumne_sells,
double &volumne_buy_limits,double &volumne_sell_limits,
double &volumne_buy_stops,double &volumne_sell_stops)
{
volumne_buys = 0.0;
volumne_sells = 0.0;
volumne_buy_limits = 0.0;
volumne_sell_limits = 0.0;
volumne_buy_stops = 0.0;
volumne_sell_stops = 0.0;
for(int i=PositionsTotal()-1; i>=0; i--)
if(m_position.SelectByIndex(i))
if(m_position.Symbol()==m_symbol.Name())
{
if(m_position.PositionType()==POSITION_TYPE_BUY)
volumne_buys+=m_position.Volume();
else
if(m_position.PositionType()==POSITION_TYPE_SELL)
volumne_sells+=m_position.Volume();
}
for(int i=OrdersTotal()-1; i>=0; i--)
if(m_order.SelectByIndex(i))
if(m_order.Symbol()==m_symbol.Name())
{
if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT)
volumne_buy_limits+=m_order.VolumeInitial();
else
if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT)
volumne_sell_limits+=m_order.VolumeInitial();
else
if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)
volumne_buy_stops+=m_order.VolumeInitial();
else
if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)
volumne_sell_stops+=m_order.VolumeInitial();
}
}
int CalculateAllPendingOrders(void)
{
int count=0;
for(int i=OrdersTotal()-1; i>=0; i--)
if(m_order.SelectByIndex(i))
count++;
return(count);
}
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))
{
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))
return(true);
}
else
if((InpStartHour*60*60+InpStartMinute*60)>(InpEndHour*60*60+InpEndMinute*60))
{
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)
return(true);
}
else
return(false);
return(false);
}
Comments