| //+------------------------------------------------------------------+
|
| //| Moving Averages.mq5 |
|
| //| Copyright 2000-2025, MetaQuotes Ltd. |
|
| //| https://www.mql5.com |
|
| //+------------------------------------------------------------------+
|
| #property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
| #property link "https://www.mql5.com"
|
| #property version "1.00"
|
|
|
| #include <Trade\Trade.mqh>
|
|
|
| input double MaximumRisk = 0.02; // Maximum Risk in percentage
|
| input double DecreaseFactor = 3; // Descrease factor
|
| input int MovingPeriod = 12; // Moving Average period
|
| input int MovingShift = 6; // Moving Average shift
|
| //---
|
| int ExtHandle=0;
|
| bool ExtHedging=false;
|
| CTrade ExtTrade;
|
|
|
| #define MA_MAGIC 1234501
|
| //+------------------------------------------------------------------+
|
| //| Calculate optimal lot size |
|
| //+------------------------------------------------------------------+
|
| double TradeSizeOptimized(void)
|
| {
|
| double price=0.0;
|
| double margin=0.0;
|
| //--- select lot size
|
| if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,price))
|
| return(0.0);
|
| if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin))
|
| return(0.0);
|
| if(margin<=0.0)
|
| return(0.0);
|
|
|
| double lot=NormalizeDouble(AccountInfoDouble(ACCOUNT_MARGIN_FREE)*MaximumRisk/margin,2);
|
| //--- calculate number of losses orders without a break
|
| if(DecreaseFactor>0)
|
| {
|
| //--- select history for access
|
| HistorySelect(0,TimeCurrent());
|
| //---
|
| int orders=HistoryDealsTotal(); // total history deals
|
| int losses=0; // number of losses orders without a break
|
|
|
| for(int i=orders-1;i>=0;i--)
|
| {
|
| ulong ticket=HistoryDealGetTicket(i);
|
| if(ticket==0)
|
| {
|
| Print("HistoryDealGetTicket failed, no trade history");
|
| break;
|
| }
|
| //--- check symbol
|
| if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol)
|
| continue;
|
| //--- check Expert Magic number
|
| if(HistoryDealGetInteger(ticket,DEAL_MAGIC)!=MA_MAGIC)
|
| continue;
|
| //--- check profit
|
| double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);
|
| if(profit>0.0)
|
| break;
|
| if(profit<0.0)
|
| losses++;
|
| }
|
| //---
|
| if(losses>1)
|
| lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
|
| }
|
| //--- normalize and check limits
|
| double stepvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
|
| lot=stepvol*NormalizeDouble(lot/stepvol,0);
|
|
|
| double minvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
|
| if(lot<minvol)
|
| lot=minvol;
|
|
|
| double maxvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
|
| if(lot>maxvol)
|
| lot=maxvol;
|
| //--- return trading volume
|
| return(lot);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for open position conditions |
|
| //+------------------------------------------------------------------+
|
| void CheckForOpen(void)
|
| {
|
| MqlRates rt[2];
|
| //--- go trading only for first ticks of new bar
|
| if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
|
| {
|
| Print("CopyRates of ",_Symbol," failed, no history");
|
| return;
|
| }
|
| if(rt[1].tick_volume>1)
|
| return;
|
| //--- get current Moving Average
|
| double ma[1];
|
| if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
|
| {
|
| Print("CopyBuffer from iMA failed, no data");
|
| return;
|
| }
|
| //--- check signals
|
| ENUM_ORDER_TYPE signal=WRONG_VALUE;
|
|
|
| if(rt[0].open>ma[0] && rt[0].close<ma[0])
|
| signal=ORDER_TYPE_SELL; // sell conditions
|
| else
|
| {
|
| if(rt[0].open<ma[0] && rt[0].close>ma[0])
|
| signal=ORDER_TYPE_BUY; // buy conditions
|
| }
|
| //--- additional checking
|
| if(signal!=WRONG_VALUE)
|
| {
|
| if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && Bars(_Symbol,_Period)>100)
|
| ExtTrade.PositionOpen(_Symbol,signal,TradeSizeOptimized(),
|
| SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK),
|
| 0,0);
|
| }
|
| //---
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for close position conditions |
|
| //+------------------------------------------------------------------+
|
| void CheckForClose(void)
|
| {
|
| MqlRates rt[2];
|
| //--- go trading only for first ticks of new bar
|
| if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
|
| {
|
| Print("CopyRates of ",_Symbol," failed, no history");
|
| return;
|
| }
|
| if(rt[1].tick_volume>1)
|
| return;
|
| //--- get current Moving Average
|
| double ma[1];
|
| if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
|
| {
|
| Print("CopyBuffer from iMA failed, no data");
|
| return;
|
| }
|
| //--- positions already selected before
|
| bool signal=false;
|
| long type=PositionGetInteger(POSITION_TYPE);
|
|
|
| if(type==(long)POSITION_TYPE_BUY && rt[0].open>ma[0] && rt[0].close<ma[0])
|
| signal=true;
|
| if(type==(long)POSITION_TYPE_SELL && rt[0].open<ma[0] && rt[0].close>ma[0])
|
| signal=true;
|
| //--- additional checking
|
| if(signal)
|
| {
|
| if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && Bars(_Symbol,_Period)>100)
|
| ExtTrade.PositionClose(_Symbol,3);
|
| }
|
| //---
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Position select depending on netting or hedging |
|
| //+------------------------------------------------------------------+
|
| bool SelectPosition()
|
| {
|
| bool res=false;
|
| //--- check position in Hedging mode
|
| if(ExtHedging)
|
| {
|
| uint total=PositionsTotal();
|
| for(uint i=0; i<total; i++)
|
| {
|
| string position_symbol=PositionGetSymbol(i);
|
| if(_Symbol==position_symbol && MA_MAGIC==PositionGetInteger(POSITION_MAGIC))
|
| {
|
| res=true;
|
| break;
|
| }
|
| }
|
| }
|
| //--- check position in Netting mode
|
| else
|
| {
|
| if(!PositionSelect(_Symbol))
|
| return(false);
|
| else
|
| return(PositionGetInteger(POSITION_MAGIC)==MA_MAGIC); //---check Magic number
|
| }
|
| //--- result for Hedging mode
|
| return(res);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Expert initialization function |
|
| //+------------------------------------------------------------------+
|
| int OnInit(void)
|
| {
|
| //--- prepare trade class to control positions if hedging mode is active
|
| ExtHedging=((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
|
| ExtTrade.SetExpertMagicNumber(MA_MAGIC);
|
| ExtTrade.SetMarginMode();
|
| ExtTrade.SetTypeFillingBySymbol(Symbol());
|
| //--- Moving Average indicator
|
| ExtHandle=iMA(_Symbol,_Period,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE);
|
| if(ExtHandle==INVALID_HANDLE)
|
| {
|
| printf("Error creating MA indicator");
|
| return(INIT_FAILED);
|
| }
|
| //--- ok
|
| return(INIT_SUCCEEDED);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Expert tick function |
|
| //+------------------------------------------------------------------+
|
| void OnTick(void)
|
| {
|
| //---
|
| if(SelectPosition())
|
| CheckForClose();
|
| else
|
| CheckForOpen();
|
| //---
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Expert deinitialization function |
|
| //+------------------------------------------------------------------+
|
| void OnDeinit(const int reason)
|
| {
|
| }
|
| //+------------------------------------------------------------------+
|