415 lines
35 KiB
Plaintext
415 lines
35 KiB
Plaintext
//| Copyright © 2019, Abu Saidu |
|
|
//| t.me/ask4abusaidu |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright © 2020, Abu Saidu"
|
|
#property link "https://www.mql5.com/en/users/ask4abusaidu"
|
|
""
|
|
#property description "For more information contact" // Description (line 1)
|
|
#property description ">>Telegram = t.me/ask4abusaidu<<"
|
|
#property description ">>whatsapp = +2347018717038<<"
|
|
#property version "1.0"
|
|
#property strict
|
|
|
|
#include <Trade\PositionInfo.mqh>
|
|
#include <Trade\Trade.mqh>
|
|
#include <Trade\SymbolInfo.mqh>
|
|
CPositionInfo m_position; // trade position object
|
|
CTrade m_trade; // trading object
|
|
CSymbolInfo m_symbol; // symbol info object
|
|
|
|
enum ENUM_TYPE_TRADE
|
|
{
|
|
buy=0, // Only BUY
|
|
sell=1, // Only SELL
|
|
buy_sell=2, // BUY and SELL
|
|
};
|
|
|
|
input int InpBandsPeriod=20; // Period
|
|
input int InpBandsShift=0; // Shift
|
|
input double InpBandsDeviations=2.0; // Deviation
|
|
extern int MagicNumber=15485;
|
|
input double InpLots = 1.0; // Lots
|
|
input ushort InpStopLoss = 1000; // Stop Loss (in pips) (do not use "0")
|
|
input ushort InpTakeProfit = 1000; // Take Profit (in pips) (do not use "0")
|
|
input ENUM_TYPE_TRADE InpTypeTrade = buy_sell; // Type trade:
|
|
|
|
|
|
bool crossed[2];
|
|
double Open[];
|
|
double upperbb[],midbb[],lowerbb[];
|
|
int bbhandle;
|
|
|
|
ulong m_slippage=10; // slippage
|
|
|
|
double ExtStopLoss=0.0;
|
|
double ExtTakeProfit=0.0;
|
|
double ExtStep=0.0;
|
|
|
|
datetime last_OUT_position_time=0; // последнее время закрытия позиции
|
|
int handle_iMA; // variable for storing the handle of the iMA indicator
|
|
|
|
double m_adjusted_point; // point value adjusted for 3 or 5 points
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
if(!m_symbol.Name(Symbol())) // sets symbol name
|
|
return(INIT_FAILED);
|
|
RefreshRates();
|
|
//---
|
|
m_trade.SetMarginMode();
|
|
m_trade.SetTypeFillingBySymbol(m_symbol.Name());
|
|
m_trade.SetDeviationInPoints(m_slippage);
|
|
//--- 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;
|
|
|
|
ExtStopLoss = InpStopLoss * m_adjusted_point;
|
|
ExtTakeProfit = InpTakeProfit * m_adjusted_point;
|
|
//---
|
|
ArraySetAsSeries(midbb, true);
|
|
ArraySetAsSeries(upperbb, true);
|
|
ArraySetAsSeries(lowerbb, true);
|
|
|
|
bbhandle = iBands(_Symbol,PERIOD_CURRENT,InpBandsPeriod,InpBandsShift,InpBandsDeviations,PRICE_CLOSE);
|
|
//---
|
|
for (int i = 0; i < ArraySize(crossed); i++)
|
|
crossed[i] = true;
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
|
|
IndicatorRelease(bbhandle);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
|
|
CopyBuffer(bbhandle, 0, 0, 2, midbb);
|
|
CopyBuffer(bbhandle, 1, 0, 2, upperbb);
|
|
CopyBuffer(bbhandle, 2, 0, 2, lowerbb);
|
|
if(CopyOpen(Symbol(), PERIOD_CURRENT, 0, 2, Open) <= 0) return;
|
|
ArraySetAsSeries(Open, true);
|
|
//---
|
|
ulong ordt = 0;
|
|
if(Cross(0,Open[0] > midbb[0]))
|
|
{
|
|
double sl=(InpStopLoss==0)?0.0:m_symbol.Ask()-ExtStopLoss;
|
|
double tp=(InpTakeProfit==0)?0.0:m_symbol.Ask()+ExtTakeProfit;
|
|
OpenBuy(sl,tp);
|
|
return;
|
|
}
|
|
if(Cross(1,Open[0] < midbb[0]))
|
|
{
|
|
double sl=(InpStopLoss==0)?0.0:m_symbol.Bid()+ExtStopLoss;
|
|
double tp=(InpTakeProfit==0)?0.0:m_symbol.Bid()-ExtTakeProfit;
|
|
OpenSell(sl,tp);
|
|
return;
|
|
|
|
}
|
|
}
|
|
bool Cross(int i, bool condition) //returns true if "condition" is true and was false in the previous call
|
|
{
|
|
bool ret = condition && !crossed[i];
|
|
crossed[i] = condition;
|
|
return(ret);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| TradeTransaction function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTradeTransaction(const MqlTradeTransaction &trans,
|
|
const MqlTradeRequest &request,
|
|
const MqlTradeResult &result)
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Open Buy position |
|
|
//+------------------------------------------------------------------+
|
|
void OpenBuy(double sl,double tp)
|
|
{
|
|
sl=m_symbol.NormalizePrice(sl);
|
|
tp=m_symbol.NormalizePrice(tp);
|
|
//--- check volume before OrderSend to avoid "not enough money" error (CTrade)
|
|
double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),InpLots,m_symbol.Ask(),ORDER_TYPE_BUY);
|
|
|
|
if(check_volume_lot!=0.0)
|
|
{
|
|
if(check_volume_lot>=InpLots)
|
|
{
|
|
if(m_trade.Buy(InpLots,m_symbol.Name(),m_symbol.Ask(),sl,tp))
|
|
{
|
|
if(m_trade.ResultDeal()==0)
|
|
{
|
|
Print(__FUNCTION__,", #1 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResult(m_trade,m_symbol);
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #2 Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResult(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #3 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResult(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume (",DoubleToString(check_volume_lot,2),") ",
|
|
"< Lots (",DoubleToString(InpLots,2),")");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume returned the value of \"0.0\"");
|
|
return;
|
|
}
|
|
//---
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Open Sell position |
|
|
//+------------------------------------------------------------------+
|
|
void OpenSell(double sl,double tp)
|
|
{
|
|
sl=m_symbol.NormalizePrice(sl);
|
|
tp=m_symbol.NormalizePrice(tp);
|
|
//--- check volume before OrderSend to avoid "not enough money" error (CTrade)
|
|
double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),InpLots,m_symbol.Bid(),ORDER_TYPE_SELL);
|
|
|
|
if(check_volume_lot!=0.0)
|
|
{
|
|
if(check_volume_lot>=InpLots)
|
|
{
|
|
if(m_trade.Sell(InpLots,m_symbol.Name(),m_symbol.Bid(),sl,tp))
|
|
{
|
|
if(m_trade.ResultDeal()==0)
|
|
{
|
|
Print(__FUNCTION__,", #1 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResult(m_trade,m_symbol);
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #2 Sell -> true. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResult(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #3 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResult(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume (",DoubleToString(check_volume_lot,2),") ",
|
|
"< Lots (",DoubleToString(InpLots,2),")");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume returned the value of \"0.0\"");
|
|
return;
|
|
}
|
|
//---
|
|
}
|
|
void PrintResult(CTrade &trade,CSymbolInfo &symbol)
|
|
{
|
|
Print("Code of request result: "+IntegerToString(trade.ResultRetcode()));
|
|
Print("code of request result: "+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(trade.ResultBid(),symbol.Digits()));
|
|
Print("current ask price: "+DoubleToString(trade.ResultAsk(),symbol.Digits()));
|
|
Print("broker comment: "+trade.ResultComment());
|
|
int d=0;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Refreshes the symbol quotes data |
|
|
//+------------------------------------------------------------------+
|
|
bool RefreshRates(void)
|
|
{
|
|
//--- refresh rates
|
|
if(!m_symbol.RefreshRates())
|
|
{
|
|
Print("RefreshRates error");
|
|
return(false);
|
|
}
|
|
//--- protection against the return value of "zero"
|
|
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check Freeze and Stops levels |
|
|
//+------------------------------------------------------------------+
|
|
bool FreezeStopsLevels(double &level)
|
|
{
|
|
//--- check Freeze and Stops levels
|
|
/*
|
|
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
|
|
|
|
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
|
|
*/
|
|
if(!RefreshRates() || !m_symbol.Refresh())
|
|
return(false);
|
|
//--- FreezeLevel -> for pending order and modification
|
|
double freeze_level=m_symbol.FreezeLevel()*m_symbol.Point();
|
|
if(freeze_level==0.0)
|
|
freeze_level=(m_symbol.Ask()-m_symbol.Bid())*3.0;
|
|
freeze_level*=1.1;
|
|
//--- StopsLevel -> for TakeProfit and StopLoss
|
|
double stop_level=m_symbol.StopsLevel()*m_symbol.Point();
|
|
if(stop_level==0.0)
|
|
stop_level=(m_symbol.Ask()-m_symbol.Bid())*3.0;
|
|
stop_level*=1.1;
|
|
|
|
if(freeze_level<=0.0 || stop_level<=0.0)
|
|
return(false);
|
|
|
|
level=(freeze_level>stop_level)?freeze_level:stop_level;
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Trailing |
|
|
//| InpTrailingStop: min distance from price to Stop Loss |
|
|
//+------------------------------------------------------------------+
|
|
bool Modification(const double level)
|
|
{
|
|
bool result=true;
|
|
int counter=0;
|
|
/*
|
|
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
|
|
*/
|
|
for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions
|
|
if(m_position.SelectByIndex(i))
|
|
if(m_position.Symbol()==m_symbol.Name())
|
|
{
|
|
if(m_position.PositionType()==POSITION_TYPE_BUY && (InpTypeTrade==buy || InpTypeTrade==buy_sell))
|
|
{
|
|
double price=m_symbol.Ask();
|
|
|
|
double sl=(InpStopLoss==0)?m_position.StopLoss():price-ExtStopLoss;
|
|
if(sl!=0.0 && ExtStopLoss<level) // check sl
|
|
sl=price-level;
|
|
|
|
double tp=(InpTakeProfit==0)?m_position.TakeProfit():price+ExtTakeProfit;
|
|
if(tp!=0.0 && ExtTakeProfit<level) // check price
|
|
tp=price+level;
|
|
|
|
if(!m_trade.PositionModify(m_position.Ticket(),
|
|
m_symbol.NormalizePrice(sl),
|
|
m_symbol.NormalizePrice(tp)))
|
|
{
|
|
result=false;
|
|
Print("Modify ",m_position.Ticket(),
|
|
" Position -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
}
|
|
counter++;
|
|
RefreshRates();
|
|
m_position.SelectByIndex(i);
|
|
PrintResultModify(m_trade,m_symbol,m_position);
|
|
continue;
|
|
}
|
|
if(m_position.PositionType()==POSITION_TYPE_SELL && (InpTypeTrade==sell || InpTypeTrade==buy_sell))
|
|
{
|
|
double price=m_symbol.Bid();
|
|
|
|
double sl=(InpStopLoss==0)?m_position.StopLoss():price+ExtStopLoss;
|
|
if(sl!=0.0 && ExtStopLoss<level) // check sl
|
|
sl=price+level;
|
|
|
|
double tp=(InpTakeProfit==0)?m_position.StopLoss():price-ExtTakeProfit;
|
|
if(tp!=0.0 && ExtTakeProfit<level) // check tp
|
|
tp=price-level;
|
|
|
|
if(!m_trade.PositionModify(m_position.Ticket(),
|
|
m_symbol.NormalizePrice(sl),
|
|
m_symbol.NormalizePrice(tp)))
|
|
{
|
|
result=false;
|
|
Print("Modify ",m_position.Ticket(),
|
|
" Position -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
}
|
|
counter++;
|
|
RefreshRates();
|
|
m_position.SelectByIndex(i);
|
|
PrintResultModify(m_trade,m_symbol,m_position);
|
|
continue;
|
|
}
|
|
}
|
|
//---
|
|
if(counter==0)
|
|
return(false);
|
|
return(result);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Print CTrade result |
|
|
//+------------------------------------------------------------------+
|
|
void PrintResultModify(CTrade &trade,CSymbolInfo &symbol,CPositionInfo &position)
|
|
{
|
|
Print("File: ",__FILE__,", symbol: ",m_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(m_symbol.FreezeLevel(),0),", Stops Level: "+DoubleToString(m_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()));
|
|
int d=0;
|
|
}
|
|
//+------------------------------------------------------------------+
|