Files
2026-06-08 10:36:15 +02:00

1098 lines
66 KiB
Plaintext

//+------------------------------------------------------------------+
//| MA Crossover.mq4 |
//| Copyright © 2017, Matthew Kastor |
//| https://github.com/matthewkastor |
//+------------------------------------------------------------------+
#property copyright "Matthew Kastor"
#property link "https://github.com/matthewkastor"
#property description "Trading direction is biased by current moving average being above or below the previous moving average."
#property description "This will only buy, sell, or close at the beginning of a new bar."
#property version "1.00"
#property strict
#include <Schedule\Schedule.mqh>
//----
enum ENUM_ALLOWED_TRADE_DIRECTION
{
TRADE_LONG_ONLY=0,
TRADE_SHORT_ONLY=1,
TRADE_LONG_AND_SHORT=2
};
extern ENUM_ALLOWED_TRADE_DIRECTION Allowed_Trade_Direction=2;
extern bool HedgingAllowed=false;
extern bool Hidden_Tp_Sl=false;
extern double Leverage_Per_Position=10;
extern double StopLoss_Percent=0;
extern double Trailing_StopLoss_Percent=0;
extern double TakeProfit_Percent=0;
extern int Slippage=10;
extern int Minimum_Free_Equity_Percent=50;
extern bool Close_All_At_Minimum_Free_Equity_Reached=true;
extern bool Average_Up=false;
extern bool Average_Down=false;
extern double Averaging_Step_Size_Percent=0;
extern double Averaging_Down_Step_Multiplier=1;
extern bool Close_All_At_MA_Crossover=true;
extern ENUM_TIMEFRAMES MA_Timeframe_Previous=1440;
extern ENUM_TIMEFRAMES MA_Timeframe_Current=1440;
extern int MA_Period_Previous_Add=10;
extern int MA_Period_Current=42;
extern int MA_Shift_Previous=2;
extern int MA_Shift_Current=0;
extern ENUM_MA_METHOD MA_Method=0;
extern ENUM_APPLIED_PRICE MA_Applied_Price=1;
extern ENUM_DAY_OF_WEEK Start_Day=1;//Start Day
extern ENUM_DAY_OF_WEEK End_Day=5;//End Day
extern string Start_Time="00:00";//Start Time
extern string End_Time="24:00";//End Time
Schedule schedule(Start_Day,Start_Time,End_Day,End_Time);
bool Kill_Test_On_Validation_Error=true;
double effectiveLeverage=Leverage_Per_Position;
double Lots=0;
double StopLoss=0;
double TrailingStopLoss=0;
double TakeProfit=0;
double scaledSl=0;
double scaledTSl= 0;
double scaledTp = 0;
double sl=0;
double tsl= 0;
double tp = 0;
double freeEquityFactor=100;
double minMargin=0;
datetime lastBarTime=Time[0];
int MA_Period_Previous=1440;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void init()
{
MA_Period_Previous=MA_Period_Current+MA_Period_Previous_Add;
if(StopLoss_Percent>0)
{
StopLoss=StopLoss_Percent/100;
}
if(Trailing_StopLoss_Percent>0)
{
TrailingStopLoss=Trailing_StopLoss_Percent/100;
}
if(TakeProfit_Percent>0)
{
TakeProfit=TakeProfit_Percent/100;
}
if(Minimum_Free_Equity_Percent>0)
{
freeEquityFactor=NormalizeDouble(Minimum_Free_Equity_Percent,2)/100;
}
}
//+------------------------------------------------------------------+
//|Determines whether any of the settings is in an invalid state. |
//+------------------------------------------------------------------+
bool ValidateSettings()
{
bool out=true;
string message="";
if(Leverage_Per_Position<=0)
{
message=("Your Leverage_Per_Position is set to an invalid amount. It must be greater than 0.");
out=false;
}
else if(StopLoss_Percent<0)
{
message=("The StopLoss_Percent must be 0 or greater. Set it to 0 to disable the stop loss.");
out=false;
}
else if(Trailing_StopLoss_Percent<0)
{
message=("The Trailing_StopLoss_Percent must be 0 or greater. Set it to 0 to disable the trailing stop loss.");
out=false;
}
else if(TakeProfit_Percent<0)
{
message=("The TakeProfit_Percent must be 0 or greater. Set it to 0 to disable the take profit.");
out=false;
}
else if(Slippage<0)
{
message=("The Slippage must be 0 or greater.");
out=false;
}
else if(Minimum_Free_Equity_Percent<0)
{
message=("The Minimum_Free_Equity_Percent must be 0 or greater. Set it to zero to disable guards against excessive leverage and drawdown.");
out=false;
}
else if(Averaging_Step_Size_Percent<0)
{
message=("The Averaging_Step_Size_Percent must be 0 or greater. This only applies when using one of the averaging options.");
out=false;
}
else if(Averaging_Down_Step_Multiplier<=0)
{
message=("The Averaging_Down_Step_Multiplier must be greater than zero. This only applies when using one of the averaging options.");
out=false;
}
else if(MA_Timeframe_Previous<=0)
{
message=("The MA_Timeframe_Previous must be one of ENUM_TIMEFRAMES.");
out=false;
}
else if(MA_Timeframe_Current<=0)
{
message=("The MA_Timeframe_Current must be one of ENUM_TIMEFRAMES.");
out=false;
}
//else if(MA_Period_Previous_Add<0)
// {
// message=("The MA_Period_Previous_Add must be 0 or greater.");
// out=false;
// }
else if(MA_Period_Current<=0)
{
message=("The MA_Period_Current must be greater than zero.");
out=false;
}
else if(MA_Shift_Previous<0)
{
message=("The MA_Shift_Previous must be 0 or greater.");
out=false;
}
else if(MA_Shift_Current<0)
{
message=("The MA_Shift_Current must be 0 or greater.");
out=false;
}
else if(MA_Method<0)
{
message=("The MA_Method must be a valid value in ENUM_MA_METHOD.");
out=false;
}
else if(MA_Applied_Price<0)
{
message=("The MA_Applied_Price must be a valid value in ENUM_APPLIED_PRICE.");
out=false;
}
if(out==false)
{
Print("");
Print("!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~");
Print("");
Print("User Settings validation failed.");
Print(message);
Print("");
Print("!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~");
Print("");
ExpertRemove();
}
return out;
}
//+------------------------------------------------------------------+
//|Validates internally calculated settings. |
//+------------------------------------------------------------------+
bool ValidateCalculatedSettings()
{
bool out=true;
string message="";
if(effectiveLeverage<=0)
{
message=("The effectiveLeverage must be greater than zero.");
out=false;
}
else if(Lots<=0)
{
message=("The Lots must be greater than zero.");
out=false;
}
else if(StopLoss<0)
{
message=("The StopLoss must be 0 or greater.");
out=false;
}
else if(TrailingStopLoss<0)
{
message=("The TrailingStopLoss must be 0 or greater.");
out=false;
}
else if(TakeProfit<0)
{
message=("The TakeProfit must be 0 or greater.");
out=false;
}
else if(scaledSl<0)
{
message=("The scaledSl must be 0 or greater.");
out=false;
}
else if(scaledTp<0)
{
message=("The scaledTp must be 0 or greater.");
out=false;
}
else if(sl<0)
{
message=("The sl must be 0 or greater.");
out=false;
}
else if(tp<0)
{
message=("The tp must be 0 or greater.");
out=false;
}
else if(freeEquityFactor<0)
{
message=("The freeEquityFactor must be 0 or greater.");
out=false;
}
else if(minMargin<0)
{
message=("The minMargin must be 0 or greater.");
out=false;
}
else if(lastBarTime<=0)
{
message=("The lastBarTime must be greater than zero.");
out=false;
}
else if(MA_Period_Previous<=0)
{
message=("The MA_Period_Previous must be greater than zero.");
out=false;
}
if(out==false)
{
Print("");
Print("!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~");
Print("");
Print("Calculated Settings validation failed.");
Print(message);
Print("");
Print("!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~!~");
Print("");
if(Kill_Test_On_Validation_Error==true)
{
ExpertRemove();
}
}
return out;
}
//+------------------------------------------------------------------+
//|Rules to stop the bot from even trying to trade |
//+------------------------------------------------------------------+
bool CanTrade()
{
bool out=true;
string message="";
if(!IsTradeAllowed())
{
return false;
}
if(!IsNewBar())
{
return false;
}
if(!schedule.IsActive(Time[0]))
{
return false;
}
if(Bars<MA_Period_Current)
{
message=("bars less than MA_Period_Current. Waiting for more history.");
out=false;
}
else if(Bars<MA_Period_Previous)
{
message=("bars less than MA_Period_Previous. Waiting for more history.");
out=false;
}
if(out==false)
{
Print(message);
}
return out;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateMinMargin()
{
minMargin=AccountEquity()*freeEquityFactor;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void NormalizeExits(string symbol,ENUM_ORDER_TYPE orderType)
{
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(OrderStopLoss()!=sl || OrderTakeProfit()!=tp)
{
bool ret=OrderModify(OrderTicket(),OrderOpenPrice(),sl,tp,0);
if(!ret)
{
Print(GetLastError());
}
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateSlTp(string symbol,ENUM_ORDER_TYPE orderType,bool whatIfOrder)
{
double stopLevel=MarketInfo(symbol,MODE_STOPLEVEL)*Point;
double avgPrice=0;
if(whatIfOrder==true)
{
avgPrice=PairAveragePriceWithAdditonalOrder(symbol,orderType,Lots);
}
else
{
avgPrice=PairAveragePrice(symbol,orderType);
}
sl=0;
tsl=0;
tp=0;
scaledSl=0;
scaledTSl= 0;
scaledTp = 0;
CalculateEffectiveLeverage(symbol,orderType);
if(StopLoss>0)
{
scaledSl=(StopLoss/effectiveLeverage);
}
if(TrailingStopLoss>0)
{
scaledTSl=(TrailingStopLoss/effectiveLeverage);
}
if(TakeProfit>0)
{
scaledTp=(TakeProfit/effectiveLeverage);
}
if(orderType==OP_BUY)
{
sl=PairHighestStopLoss(symbol,orderType);
tsl=sl;
tp=PairHighestTakeProfit(symbol,orderType);
calculateSlBuy(symbol,avgPrice,stopLevel);
calculateTSlBuy(symbol,stopLevel);
if((tsl!=0) && (tsl>sl || sl==0))
{
sl=tsl;
}
calculateTpBuy(symbol,avgPrice,stopLevel);
}
if(orderType==OP_SELL)
{
sl=PairLowestStopLoss(symbol,orderType);
tsl=sl;
tp=PairLowestTakeProfit(symbol,orderType);
calculateSlSell(symbol,avgPrice,stopLevel);
calculateTSlSell(symbol,stopLevel);
if((tsl!=0) && (tsl<sl || sl==0))
{
sl=tsl;
}
calculateTpSell(symbol,avgPrice,stopLevel);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateSlBuy(string symbol,double avgPrice,double stopLevel)
{
double tmpDbl=0;
if(avgPrice==0)
{
avgPrice=Ask;
}
if(StopLoss>0 && (sl==0 || Average_Up || Average_Down))
{
tmpDbl=NormalizeDouble(Bid-(Bid*scaledSl),Digits);
if(tmpDbl>avgPrice)
{
tmpDbl=avgPrice;
}
else
{
tmpDbl=NormalizeDouble(avgPrice-(avgPrice*scaledSl),Digits);
}
if(tmpDbl>sl || sl==0)
{
sl=tmpDbl;
}
if((avgPrice*scaledSl)<stopLevel)
{
sl=NormalizeDouble(Bid-stopLevel,Digits);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateTSlBuy(string symbol,double stopLevel)
{
double tmpDbl=0;
if(TrailingStopLoss>0)
{
tmpDbl=NormalizeDouble(Bid-(Bid*scaledTSl),Digits);
if(tmpDbl>tsl || tsl==0)
{
tsl=tmpDbl;
}
if((Bid*scaledTSl)<stopLevel)
{
tsl=NormalizeDouble(Bid-stopLevel,Digits);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateSlSell(string symbol,double avgPrice,double stopLevel)
{
double tmpDbl=0;
if(avgPrice==0)
{
avgPrice=Bid;
}
if(StopLoss>0 && (sl==0 || Average_Up || Average_Down))
{
tmpDbl=NormalizeDouble(Ask+(Ask*scaledSl),Digits);
if(tmpDbl<avgPrice)
{
tmpDbl=avgPrice;
}
else
{
tmpDbl=NormalizeDouble(avgPrice+(avgPrice*scaledSl),Digits);
}
if(tmpDbl<sl || sl==0)
{
sl=tmpDbl;
}
if((avgPrice*scaledSl)<stopLevel)
{
sl=NormalizeDouble(Ask+stopLevel,Digits);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateTSlSell(string symbol,double stopLevel)
{
double tmpDbl=0;
if(TrailingStopLoss>0)
{
tmpDbl=NormalizeDouble(Ask+(Ask*scaledTSl),Digits);
if(tmpDbl<tsl || tsl==0)
{
tsl=tmpDbl;
}
if((Ask*scaledTSl)<stopLevel)
{
tsl=NormalizeDouble(Ask+stopLevel,Digits);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateTpBuy(string symbol,double avgPrice,double stopLevel)
{
double tmpDbl=0;
if(avgPrice==0)
{
avgPrice=Ask;
}
if(TakeProfit>0 && (tp==0 || Average_Up || Average_Down))
{
tmpDbl=NormalizeDouble(avgPrice+(avgPrice*scaledTp),Digits);
if(avgPrice<=tmpDbl && (tmpDbl<tp || tp==0))
{
tp=tmpDbl;
}
if((avgPrice*scaledTp)<stopLevel)
{
double x=NormalizeDouble(avgPrice+stopLevel,Digits);
if(avgPrice<x)
{
tp=x;
}
}
}
if(tp<0)
{
tp=0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateTpSell(string symbol,double avgPrice,double stopLevel)
{
double tmpDbl=0;
if(avgPrice==0)
{
avgPrice=Bid;
}
if(TakeProfit>0 && (tp==0 || Average_Up || Average_Down))
{
tmpDbl=NormalizeDouble(avgPrice-(avgPrice*scaledTp),Digits);
if(avgPrice>=tmpDbl && (tmpDbl>tp || tp==0))
{
tp=tmpDbl;
}
if((avgPrice*scaledTp)<stopLevel)
{
double x=NormalizeDouble(avgPrice-stopLevel,Digits);
if(avgPrice>x)
{
tp=x;
}
}
}
if(tp<0)
{
tp=0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseOrders(string symbol,ENUM_ORDER_TYPE orderType)
{
int ticket,i;
//----
while(PairHighestPricePaid(symbol,orderType)>0)
{
for(i=0;i<OrdersTotal();i++)
{
ticket=OrderSelect(i,SELECT_BY_POS);
if(OrderType()==OP_BUY && OrderSymbol()==symbol)
{
if(OrderClose(OrderTicket(),OrderLots(),Bid,Slippage)==false)
{
Print(GetLastError());
}
}
if(OrderType()==OP_SELL && OrderSymbol()==symbol)
{
if(OrderClose(OrderTicket(),OrderLots(),Ask,Slippage)==false)
{
Print(GetLastError());
}
}
}
}
}
//+------------------------------------------------------------------+
//|Returns true when there are no open positions or when all open |
//|positions are of the given orderType |
//+------------------------------------------------------------------+
bool CanMarketOrderForOp(string symbol,ENUM_ORDER_TYPE orderType)
{
bool result;
result=True;
if(HedgingAllowed==True)
{
return true;
}
if(orderType==OP_BUY && PairHighestPricePaid(symbol,OP_SELL)>0)
{
result=false;
}
if(orderType==OP_SELL && PairHighestPricePaid(symbol,OP_BUY)>0)
{
result=false;
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsNewBar()
{
bool output=false;
if(lastBarTime!=Time[0])
{
lastBarTime=Time[0];
output=true;
}
return output;
}
//+------------------------------------------------------------------+
//|Gets the highest stop loss for any order on the given pair. |
//+------------------------------------------------------------------+
double PairHighestStopLoss(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(num==0 || OrderStopLoss()>num)
{
num=OrderStopLoss();
}
}
}
return num;
}
//+------------------------------------------------------------------+
//|Gets the lowest stop loss for any order on the given pair. |
//+------------------------------------------------------------------+
double PairLowestStopLoss(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(num==0 || OrderStopLoss()<num)
{
num=OrderStopLoss();
}
}
}
return num;
}
//+------------------------------------------------------------------+
//|Gets the highest take profit for any order on the given pair. |
//+------------------------------------------------------------------+
double PairHighestTakeProfit(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(num==0 || OrderTakeProfit()>num)
{
num=OrderTakeProfit();
}
}
}
return num;
}
//+------------------------------------------------------------------+
//|Gets the lowest take profit for any order on the given pair. |
//+------------------------------------------------------------------+
double PairLowestTakeProfit(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(num==0 || OrderTakeProfit()<num)
{
num=OrderTakeProfit();
}
}
}
return num;
}
//+------------------------------------------------------------------+
//|Gets the highest price paid for any order on the given pair. |
//+------------------------------------------------------------------+
double PairHighestPricePaid(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(num==0 || OrderOpenPrice()>num)
{
num=OrderOpenPrice();
}
}
}
return num;
}
//+------------------------------------------------------------------+
//|Gets the lowest price paid for any order on the given pair. |
//+------------------------------------------------------------------+
double PairLowestPricePaid(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
if(num==0 || OrderOpenPrice()<num)
{
num=OrderOpenPrice();
}
}
}
return num;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double PairProfit(string symbol)
{
double output=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol)
{
output+=OrderProfit();
}
}
return output;
}
//+------------------------------------------------------------------+
//|Gets the current average price paid for the given currency pair. |
//+------------------------------------------------------------------+
double PairAveragePrice(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
double sum=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
sum=sum+OrderOpenPrice() * OrderLots();
num=num+OrderLots();
}
}
if(num>0 && sum>0)
{
return (sum / num);
}
else
{
return 0;
}
}
//+------------------------------------------------------------------+
//|Gets the current average price paid for the given currency pair. |
//+------------------------------------------------------------------+
double PairAveragePriceWithAdditonalOrder(string symbol,ENUM_ORDER_TYPE orderType,double size)
{
double num=0;
double sum=0;
if(orderType==OP_BUY)
{
num=size * 100000;
sum=Ask * size * 100000;
}
if(orderType==OP_SELL)
{
num=size * 100000;
sum=Bid * size * 100000;
}
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
sum=sum+OrderOpenPrice() * (OrderLots() * 100000);
num=num+(OrderLots() * 100000);
}
}
if(num>0 && sum>0)
{
return (sum / num);
}
else
{
return 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double GetHighStep(string symbol,double multiplier,ENUM_ORDER_TYPE orderType)
{
double highPrice=PairHighestPricePaid(symbol,orderType);
double highStep=highPrice;
if(Averaging_Step_Size_Percent>0)
{
highStep=highPrice+(((Averaging_Step_Size_Percent*multiplier)/100)*highPrice);
}
return highStep;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double GetLowStep(string symbol,double multiplier,ENUM_ORDER_TYPE orderType)
{
double lowPrice=PairLowestPricePaid(symbol,orderType);
double lowStep=lowPrice;
if(Averaging_Step_Size_Percent>0)
{
lowStep=lowPrice -(((Averaging_Step_Size_Percent*multiplier)/100)*lowPrice);
}
return lowStep;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateLots(string symbol)
{
double minLots = MarketInfo(symbol,MODE_MINLOT);
double maxLots = MarketInfo(symbol,MODE_MAXLOT);
double lotStep = MarketInfo(symbol,MODE_LOTSTEP);
Lots=NormalizeDouble(AccountBalance()/100000,2)*Leverage_Per_Position;
double modLots=NormalizeDouble(Lots-MathMod(Lots,lotStep),2);
if(modLots>0)
{
Lots=modLots;
}
if(Lots<minLots)
{
Lots=minLots;
//Print("Lot size is too small. Using broker specified minimum lot size ",minLots);
}
if(Lots>maxLots)
{
Lots=maxLots;
//Print("Lot size is too large. Using broker specified maximum lot size ",maxLots);
}
}
//+------------------------------------------------------------------+
//|Gets the total size on the given currency pair. |
//+------------------------------------------------------------------+
double PairLotsTotal(string symbol,ENUM_ORDER_TYPE orderType)
{
double num=0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==symbol && OrderType()==orderType)
{
num=num+OrderLots();
}
}
return num;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateEffectiveLeverage(string symbol,ENUM_ORDER_TYPE orderType)
{
double currentSize=NormalizeDouble((PairLotsTotal(symbol,orderType)*100000),0);
double num=0;
if(currentSize>0)
{
num=(currentSize/AccountBalance());
}
if(num>0)
{
effectiveLeverage=num;
}
else
{
effectiveLeverage=Leverage_Per_Position;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MarginGuard(string symbol)
{
CalculateMinMargin();
if(AccountFreeMargin()<=minMargin)
{
Print("Closing all open positons, minimum margin reached or exceeded.");
CloseOrders(symbol,OP_BUY);
CloseOrders(symbol,OP_SELL);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTick()
{
if(!ValidateSettings())
{
return;
}
if(!IsTradeAllowed())
{
return;
}
string symbol=Symbol();
if(Hidden_Tp_Sl==true)
{
if(TakeProfit>0 && (PairProfit(symbol)>=AccountBalance()*TakeProfit))
{
CloseOrders(symbol,OP_BUY);
CloseOrders(symbol,OP_SELL);
}
if(StopLoss>0 && ((PairProfit(symbol)*-1)>=AccountBalance()*StopLoss))
{
CloseOrders(symbol,OP_BUY);
CloseOrders(symbol,OP_SELL);
}
}
else
{
CalculateSlTp(symbol,OP_BUY,false);
CalculateEffectiveLeverage(symbol,OP_BUY);
NormalizeExits(symbol,OP_BUY);
CalculateSlTp(symbol,OP_SELL,false);
CalculateEffectiveLeverage(symbol,OP_SELL);
NormalizeExits(symbol,OP_SELL);
}
if(Close_All_At_Minimum_Free_Equity_Reached==true)
{
MarginGuard(symbol);
}
int ticket=0;
double MA=iMA(symbol,MA_Timeframe_Current,MA_Period_Current,MA_Shift_Current,MA_Method,MA_Applied_Price,0);
double MAPrev=iMA(symbol,MA_Timeframe_Previous,MA_Period_Previous,MA_Shift_Previous,MA_Method,MA_Applied_Price,0);
CalculateMinMargin();
CalculateLots(symbol);
Comment("MA Previous : ",MAPrev
,"\r\nMA : ",MA
,"\r\nLots : ",Lots
,"\r\nAccount Balance : ",AccountBalance()
,"\r\nAccount Equity : ",AccountEquity()
,"\r\nP&L : ",AccountEquity()-AccountBalance()
,"\r\nFree Margin : ",AccountFreeMargin()
,"\r\nStopLoss : ",StopLoss
,"\r\nTakeProfit : ",TakeProfit
,"\r\nMin Margin Allowed : ",minMargin
,"\r\nSchedule : ",schedule.ToString());
if(!CanTrade())
{
return;
}
// Check any open BUY orders
if(MAPrev<MA)
{
if(Close_All_At_MA_Crossover==true)
{
CloseOrders(symbol,OP_SELL);
}
if((Allowed_Trade_Direction==TRADE_LONG_ONLY || Allowed_Trade_Direction==TRADE_LONG_AND_SHORT) && (Average_Up || Average_Down || PairHighestPricePaid(symbol,OP_BUY)==0) && (CanMarketOrderForOp(symbol,OP_BUY)==true))
{
CalculateMinMargin();
CalculateLots(symbol);
if(AccountFreeMarginCheck(symbol,OP_BUY,Lots)<=minMargin || GetLastError()==134)
{
PrintFormat("Not Opening order, not enough free margin for %2.2f lots.",Lots);
}
else
{
if(
PairHighestPricePaid(symbol,OP_BUY)==0
|| (Ask>GetHighStep(symbol,1,OP_BUY) && Average_Up)
|| (Ask<GetLowStep(symbol,Averaging_Down_Step_Multiplier,OP_BUY) && Average_Down)
)
{
if(Hidden_Tp_Sl==false)
{
CalculateSlTp(symbol,OP_BUY,true);
}
if(ValidateCalculatedSettings())
{
ticket=OrderSend(symbol,OP_BUY,Lots,Ask,Slippage,sl,tp);
if(ticket<0)
{
Print(GetLastError());
}
if(Hidden_Tp_Sl==false)
{
CalculateSlTp(symbol,OP_BUY,false);
NormalizeExits(symbol,OP_BUY);
}
}
}
}
}
}
// Check any open SELL orders
if(MAPrev>MA)
{
if(Close_All_At_MA_Crossover==true)
{
CloseOrders(symbol,OP_BUY);
}
if((Allowed_Trade_Direction==TRADE_SHORT_ONLY || Allowed_Trade_Direction==TRADE_LONG_AND_SHORT) && (Average_Up || Average_Down || PairHighestPricePaid(symbol,OP_SELL)==0) && (CanMarketOrderForOp(symbol,OP_SELL)==true))
{
CalculateMinMargin();
CalculateLots(symbol);
if(AccountFreeMarginCheck(symbol,OP_SELL,Lots)<=minMargin || GetLastError()==134)
{
PrintFormat("Not Opening order, not enough free margin for %2.2f lots.",Lots);
}
else
{
if(
PairHighestPricePaid(symbol,OP_SELL)==0
|| (Bid<GetLowStep(symbol,1,OP_SELL) && Average_Up)
|| (Bid>GetHighStep(symbol,Averaging_Down_Step_Multiplier,OP_SELL) && Average_Down)
)
{
if(Hidden_Tp_Sl==false)
{
CalculateSlTp(symbol,OP_SELL,true);
}
if(ValidateCalculatedSettings())
{
ticket=OrderSend(symbol,OP_SELL,Lots,Bid,Slippage,sl,tp);
if(ticket<0)
{
Print(GetLastError());
}
if(Hidden_Tp_Sl==false)
{
CalculateSlTp(symbol,OP_SELL,false);
NormalizeExits(symbol,OP_SELL);
}
}
}
}
}
}
return;
}
//+------------------------------------------------------------------+