Complete .mq5 source code

Bitcoin MT5 Expert Advisor: BTCUSD MQL5 Example and Test Plan

Inspect an educational BTCUSD EA using H4 EMA, RSI and ATR values. The example includes a broker-server-time weekday filter and initial stop/target distances. It is not a verified backtest or a recommendation to trade; confirm the broker instrument, sessions, contract size, costs and execution rules before testing.

Strategy logic

Entry conditions

On a new H4 bar, the example considers a buy when the previous close is above its 200-period EMA and RSI is between 50 and 70, or a sell below the EMA with RSI between 30 and 50. This is a level condition, not a crossover. The lot calculation estimates balance risk using tick value and the ATR stop distance; it skips volumes below the broker minimum rather than rounding risk upward.

Exit conditions

The example submits initial stops at 2 times ATR and targets at 4 times ATR. It does not implement a trailing stop. On received ticks at or after Friday 20:00 broker-server time, it requests closure of matching positions and blocks weekend entries. This configurable research convention does not guarantee a fill or avoid gaps; the market session and tick availability depend on the broker.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//| Bitcoin Trend EA - BTCUSD H4                                    |
//| Pineify.app                                                      |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property version   "1.00"

input int    MagicNumber  = 890123;
input double RiskPercent  = 0.5;   // Lower risk for crypto
input int    EMA_Period   = 200;
input int    RSI_Period   = 14;
input int    ATR_Period   = 14;
input double ATR_SL_Mult  = 2.0;
input double ATR_TP_Mult  = 4.0;

int emaH, rsiH, atrH;
double emaBuf[], rsiBuf[], atrBuf[];

int OnInit() {
   emaH = iMA(_Symbol, PERIOD_H4, EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
   rsiH = iRSI(_Symbol, PERIOD_H4, RSI_Period, PRICE_CLOSE);
   atrH = iATR(_Symbol, PERIOD_H4, ATR_Period);
   ArraySetAsSeries(emaBuf, true); ArraySetAsSeries(rsiBuf, true);
   ArraySetAsSeries(atrBuf, true);
   if(emaH==INVALID_HANDLE || rsiH==INVALID_HANDLE || atrH==INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason) {
   IndicatorRelease(emaH); IndicatorRelease(rsiH); IndicatorRelease(atrH);
}

void OnTick() {
   // Weekend close: Friday 20:00
   MqlDateTime dt; TimeToStruct(TimeCurrent(), dt);
   if (dt.day_of_week == 5 && dt.hour >= 20) { CloseAll(); return; }
   if (dt.day_of_week == 6 || dt.day_of_week == 0) return;
   if (!IsNewBar(PERIOD_H4)) return;

   if(CopyBuffer(emaH, 0, 0, 3, emaBuf)!=3) return;
   if(CopyBuffer(rsiH, 0, 0, 3, rsiBuf)!=3) return;
   if(CopyBuffer(atrH, 0, 0, 3, atrBuf)!=3) return;

   if (CountPositions(MagicNumber) > 0) return;

   double close1 = iClose(_Symbol, PERIOD_H4, 1);
   double ema    = emaBuf[1];
   double rsi    = rsiBuf[1];
   double atr    = atrBuf[1];
   double lots   = CalcLots(atr * ATR_SL_Mult);
   if(lots<=0) return;

   bool longSignal  = close1 > ema && rsi > 50 && rsi < 70;
   bool shortSignal = close1 < ema && rsi < 50 && rsi > 30;

   if (longSignal)  OpenTrade(ORDER_TYPE_BUY,  lots, atr*ATR_SL_Mult, atr*ATR_TP_Mult, MagicNumber);
   if (shortSignal) OpenTrade(ORDER_TYPE_SELL, lots, atr*ATR_SL_Mult, atr*ATR_TP_Mult, MagicNumber);
}

bool IsNewBar(ENUM_TIMEFRAMES tf) {
   static datetime last=0; datetime cur=iTime(_Symbol,tf,0);
   if (cur!=last){last=cur;return true;} return false;
}

double CalcLots(double slPts) {
   double tv=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   double ts=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   double bal=AccountInfoDouble(ACCOUNT_BALANCE);
   if(ts<=0 || tv<=0 || slPts<=0 || RiskPercent<=0) return 0;
   double lot=(bal*RiskPercent/100.0)/(slPts/ts*tv);
   double stp=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   double minLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   double maxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   if(stp<=0 || minLot<=0 || maxLot<minLot) return 0;
   lot=MathFloor(MathMin(lot,maxLot)/stp)*stp;
   return lot<minLot ? 0 : lot;
}

int CountPositions(int magic) {
   int n=0;
   for (int i=PositionsTotal()-1;i>=0;i--) {
      ulong t=PositionGetTicket(i);
      if (PositionSelectByTicket(t)&&PositionGetString(POSITION_SYMBOL)==_Symbol&&(int)PositionGetInteger(POSITION_MAGIC)==magic) n++;
   } return n;
}

void CloseAll() {
   for (int i=PositionsTotal()-1;i>=0;i--) {
      ulong t=PositionGetTicket(i);
      if (!PositionSelectByTicket(t)||PositionGetString(POSITION_SYMBOL)!=_Symbol||(int)PositionGetInteger(POSITION_MAGIC)!=MagicNumber) continue;
      MqlTradeRequest req={}; MqlTradeResult res={};
      req.action=TRADE_ACTION_DEAL; req.position=t; req.symbol=_Symbol;
      req.volume=PositionGetDouble(POSITION_VOLUME);
      req.type=(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)?ORDER_TYPE_SELL:ORDER_TYPE_BUY;
      req.price=(req.type==ORDER_TYPE_SELL)?SymbolInfoDouble(_Symbol,SYMBOL_BID):SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      req.type_filling=ORDER_FILLING_IOC;
      if(!OrderSend(req,res) || res.retcode!=TRADE_RETCODE_DONE)
         Print("Close result: ",res.retcode," ",res.comment);
   }
}

void OpenTrade(ENUM_ORDER_TYPE type,double lots,double sl,double tp,int magic) {
   MqlTradeRequest req={}; MqlTradeResult res={};
   req.action=TRADE_ACTION_DEAL; req.symbol=_Symbol; req.volume=lots; req.type=type;
   req.price=(type==ORDER_TYPE_BUY)?SymbolInfoDouble(_Symbol,SYMBOL_ASK):SymbolInfoDouble(_Symbol,SYMBOL_BID);
   req.sl=(type==ORDER_TYPE_BUY)?req.price-sl:req.price+sl;
   req.tp=(type==ORDER_TYPE_BUY)?req.price+tp:req.price-tp;
   req.magic=magic; req.comment="Pineify BTC"; req.type_filling=ORDER_FILLING_IOC;
   if(!OrderSend(req,res) || res.retcode!=TRADE_RETCODE_DONE)
      Print("Open result: ",res.retcode," ",res.comment);
}

Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.

Generate a custom BTCUSD trend-following EA

Describe the entry, exit, position, order, and risk rules you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessStrategy orders are simulated; live automation needs a separate integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.