1. پارامترهای ورودی
//Import External class #include <Trade\PositionInfo.mqh> #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\AccountInfo.mqh> #include <Trade\OrderInfo.mqh> //--- introduce predefined variables for code readability #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK) #define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID) //--- input parameters input string EASettings = "---------------------------------------------"; //-------- <EA Settings> -------- input int InpMagicNumber = 123456; //Magic Number input string InpBotName = "LazyBot_V1"; //Bot Name input string TradingSettings = "---------------------------------------------"; //-------- <Trading Settings> -------- input double Inpuser_lot = 0.01; //Lots input double Inpuser_SL = 5.0; //Stoploss (in Pips) input double InpAddPrice_pip = 0; //Dist from [H], [L] to OP_Price (in Pips) input int Inpuser_SLippage = 3; // Maximum slippage allow_Pips. input double InpMax_spread = 0; //Maximum allowed spread (in Pips) (0 = floating) input string TimeSettings = "---------------------------------------------"; //-------- <Trading Time Settings> -------- input bool isTradingTime = true; //Allow trading time input int InpStartHour = 7; //Start Hour input int InpEndHour = 22; //End Hour input string MoneyManagementSettings = "---------------------------------------------"; //-------- <Money Settings> -------- input bool isVolume_Percent = false; //Allow Volume Percent input double InpRisk = 1; //Risk Percentage of Balance (%)
2. مقداردهی اولیه متغیرهای محلی
//Local parameters datetime last; int totalBars; int Pips2Points; // slippage 3 pips 3=points 30=points double Pips2Double; // Stoploss 15 pips 0.015 0.0150 double slippage; double acSpread; string strComment = ""; CPositionInfo m_position; // trade position object CTrade m_trade; // trading object CSymbolInfo m_symbol; // symbol info object CAccountInfo m_account; // account info wrapper COrderInfo m_order; // pending orders object
3. کد اصلی
توضیح استراتژی: هر روز، ربات تمام سفارشهای قدیمی را حذف میکند و بیشترین و کمترین مقدار کندل روزانه قبلی را پیدا کرده و دو سفارش شرطی “BUY_STOP” و “SELL_STOP” ارسال میکند. (بدون TakeProfit)
a/ تابع مقداردهی اولیه اکسپرت
int OnInit()
{
//---
//3 or 5 digits detection
//Pip and point
if(_Digits % 2 == 1)
{
Pips2Double = _Point*10;
Pips2Points = 10;
slippage = 10* Inpuser_SLippage;
}
else
{
Pips2Double = _Point;
Pips2Points = 1;
slippage = Inpuser_SLippage;
}
if(!m_symbol.Name(Symbol())) // sets symbol name
return(INIT_FAILED);
RefreshRates();
//---
m_trade.SetExpertMagicNumber(InpMagicNumber);
m_trade.SetMarginMode();
m_trade.SetTypeFillingBySymbol(m_symbol.Name());
m_trade.SetDeviationInPoints(slippage);
//---
return(INIT_SUCCEEDED);
}
b/ تابع تیک اکسپرت
int OnInit()
{
//---
//3 or 5 digits detection
//Pip and point
if(_Digits % 2 == 1)
{
Pips2Double = _Point*10;
Pips2Points = 10;
slippage = 10* Inpuser_SLippage;
}
else
{
Pips2Double = _Point;
Pips2Points = 1;
slippage = Inpuser_SLippage;
}
if(!m_symbol.Name(Symbol())) // sets symbol name
return(INIT_FAILED);
RefreshRates();
//---
m_trade.SetExpertMagicNumber(InpMagicNumber);
m_trade.SetMarginMode();
m_trade.SetTypeFillingBySymbol(m_symbol.Name());
m_trade.SetDeviationInPoints(slippage);
//---
return(INIT_SUCCEEDED);
}
3.1 محاسبه سیگنال و ارسال سفارشها
//+------------------------------------------------------------------+
//| CALCULATE SIGNAL AND SEND ORDER |
//+------------------------------------------------------------------+
void OpenOrder()
{
double TP_Buy = 0, TP_Sell = 0;
double SL_Buy = 0, SL_Sell = 0;
//Check Maximum Spread
if(InpMax_spread != 0){
if(acSpread > InpMax_spread){
Print(__FUNCTION__," > current Spread is greater than user Spread!...");
return;
}
}
double Bar1High = m_symbol.NormalizePrice(iHigh(m_symbol.Name(), PERIOD_D1, 1));
double Bar1Low = m_symbol.NormalizePrice(iLow(m_symbol.Name(), PERIOD_D1, 1));
//Calculate Lots
double lot1 = CalculateVolume();
double OpenPrice = m_symbol.NormalizePrice(Bar1High + InpAddPrice_pip * Pips2Double);// + NormalizeDouble((acSpread/Pips2Points) * Pips2Double, Digits);
//For BUY_STOP --------------------------------
TP_Buy = 0;//Bar1High + NormalizeDouble(min_sl* Pips2Double, Digits);
SL_Buy = m_symbol.NormalizePrice(OpenPrice - Inpuser_SL * Pips2Double);
totalBars = iBars(m_symbol.Name(), PERIOD_D1);
string comment = InpBotName + ";" + m_symbol.Name() + ";" + totalBars;
if(CheckVolumeValue(lot1)
&& CheckOrderForFREEZE_LEVEL(ORDER_TYPE_BUY_STOP, OpenPrice)
&& CheckMoneyForTrade(m_symbol.Name(),lot1, ORDER_TYPE_BUY)
&& CheckStopLoss(OpenPrice, SL_Buy))
{
if(!m_trade.BuyStop(lot1, OpenPrice, m_symbol.Name(), SL_Buy, TP_Buy, ORDER_TIME_GTC, 0, comment))// use "ORDER_TIME_GTC" when expiration date = 0
Print(__FUNCTION__, "--> Buy Error");
}
//For SELL_STOP --------------------------------
OpenPrice = m_symbol.NormalizePrice(Bar1Low - InpAddPrice_pip * Pips2Double);// - NormalizeDouble((acSpread/Pips2Points) * Pips2Double, Digits);
TP_Sell = 0;//Bar1Low - NormalizeDouble(min_sl* Pips2Double, Digits);
SL_Sell = m_symbol.NormalizePrice(OpenPrice + Inpuser_SL * Pips2Double);
if(CheckVolumeValue(lot1)
&& CheckOrderForFREEZE_LEVEL(ORDER_TYPE_SELL_STOP, OpenPrice)
&& CheckMoneyForTrade(m_symbol.Name(),lot1, ORDER_TYPE_SELL)
&& CheckStopLoss(OpenPrice, SL_Sell))
{
if(!m_trade.SellStop(lot1, OpenPrice, m_symbol.Name(), SL_Sell, TP_Sell, ORDER_TIME_GTC, 0, comment))
Print(__FUNCTION__, "--> Sell Error");
}
}
3.2 روز جدید، حذف تمام سفارشهای قدیمی
//+------------------------------------------------------------------+
//| Delele Old Orders |
//+------------------------------------------------------------------+
void DeleteOldOrds()
{
string sep=";"; // A separator as a character
ushort u_sep; // The code of the separator character
string result[]; // An array to get strings
for(int i = OrdersTotal() - 1; i >= 0; i--) // returns the number of current orders
{
if(m_order.SelectByIndex(i)) // selects the pending order by index for further access to its properties
{
//--- Get the separator code
u_sep = StringGetCharacter(sep, 0);
string Ordcomment = m_order.Comment();
//Split OrderComment (EAName;Symbol;totalBar) to get Ordersymbol
int k = StringSplit(Ordcomment, u_sep, result);
if(k > 2)
{
string sym = m_symbol.Name();
if((m_order.Magic() == InpMagicNumber) && (sym == result[1]))
{
m_trade.OrderDelete(m_order.Ticket());
}
}
}
}
}
3.3 اکسپرت دارای تابع “Trailing StopLoss” است، SL هر بار که قیمت تغییر میکند، تغییر میکند و باعث افزایش سود میشود.
//+------------------------------------------------------------------+
//| TRAILING STOPLOSS |
//+------------------------------------------------------------------+
void TrailingSL()
{
double SL_in_Pip = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(m_position.SelectByIndex(i)) // selects the orders by index for further access to its properties
{
if((m_position.Magic() == InpMagicNumber) && (m_position.Symbol() == m_symbol.Name())) //m_symbol.Name()
{
double order_stoploss1 = m_position.StopLoss();
// For Buy oder
if(m_position.PositionType() == POSITION_TYPE_BUY)
{
//--Calculate SL when price changed
SL_in_Pip = NormalizeDouble((Bid - order_stoploss1), _Digits) / Pips2Double;
//Print(__FUNCTION__, "Modify Order Buy " + (string)SL_in_Pip);
if(SL_in_Pip > Inpuser_SL)
{
order_stoploss1 = NormalizeDouble(Bid - (Inpuser_SL * Pips2Double), _Digits);
m_trade.PositionModify(m_position.Ticket(), order_stoploss1, m_position.TakeProfit());
}
}
//For Sell Order
if(m_position.PositionType() == POSITION_TYPE_SELL)
{
//--Calculate SL when price changed
SL_in_Pip = NormalizeDouble((m_position.StopLoss() - Ask), _Digits) / Pips2Double;
if(SL_in_Pip > Inpuser_SL)
{
order_stoploss1 = NormalizeDouble(Ask + (Inpuser_SL * Pips2Double), _Digits);
m_trade.PositionModify(m_position.Ticket(), order_stoploss1, m_position.TakeProfit());
}
}
}
}
}
}
3.4 بررسی مقدار حجم (Volume)
//+------------------------------------------------------------------+
//| Check the correctness of the order volume |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume)
{
//--- minimal allowed volume for trade operations
double min_volume = m_symbol.LotsMin();
//--- maximal allowed volume of trade operations
double max_volume = m_symbol.LotsMax();
//--- get minimal step of volume changing
double volume_step = m_symbol.LotsStep();
if(volume < min_volume || volume>max_volume)
{
return(false);
}
int ratio = (int)MathRound(volume/volume_step);
if(MathAbs(ratio*volume_step-volume)>0.0000001)
{
return(false);
}
return(true);
}
3.5 بررسی سطح آزاد (FreeLevel)
//+------------------------------------------------------------------+
//| CHECK FREEZE LEVEL |
//+------------------------------------------------------------------+
bool CheckOrderForFREEZE_LEVEL(ENUM_ORDER_TYPE type, double price)//change name of this function
{
int freeze_level = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL);
bool check = false;
//--- check only two order types
switch(type)
{
//--- Buy operation
case ORDER_TYPE_BUY_STOP:
{
//--- check the distance from the opening price to the activation price
check = ((price-Ask) > freeze_level*_Point);
//--- return the result of checking
return(check);
}
//--- Sell operation
case ORDER_TYPE_SELL_STOP:
{
//--- check the distance from the opening price to the activation price
check = ((Bid-price)>freeze_level*_Point);
//--- return the result of checking
return(check);
}
break;
}
//--- a slightly different function is required for pending orders
return false;
}
3.6 بررسی موجودی حساب برای معامله (Money)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
{
//--- Getting the opening price
MqlTick mqltick;
SymbolInfoTick(symb,mqltick);
double price=mqltick.ask;
if(type==ORDER_TYPE_SELL)
price=mqltick.bid;
//--- values of the required and free margin
double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
if(!OrderCalcMargin(type,symb,lots,price,margin))
{
//--- something went wrong, report and return false
Print("Error in ",__FUNCTION__," code=",GetLastError());
return(false);
}
//--- if there are insufficient funds to perform the operation
if(margin>free_margin)
{
//--- report the error and return false
Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
return(false);
}
//--- checking successful
return(true);
}
3.7 بررسی حد ضرر (Stoploss)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
{
//--- Getting the opening price
MqlTick mqltick;
SymbolInfoTick(symb,mqltick);
double price=mqltick.ask;
if(type==ORDER_TYPE_SELL)
price=mqltick.bid;
//--- values of the required and free margin
double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
if(!OrderCalcMargin(type,symb,lots,price,margin))
{
//--- something went wrong, report and return false
Print("Error in ",__FUNCTION__," code=",GetLastError());
return(false);
}
//--- if there are insufficient funds to perform the operation
if(margin>free_margin)
{
//--- report the error and return false
Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
return(false);
}
//--- checking successful
return(true);
}





