TrendPullbackEA.mq5

Specification


#property strict
#property version   "1.00"
#property description "EMA Trend + Pullback + Engulfing EA"

// Include the standard MT5 trade library.
#include <Trade/Trade.mqh>

CTrade trade;

//==============================================================
// INPUT SETTINGS
//==============================================================

// Trend indicators
input int FastEMA = 20;
input int SlowEMA = 50;

// Pullback settings
input int PullbackBars = 5;

// Stop-loss settings
// 0 = recent swing high/low
// 1 = ATR-based stop loss
input int    SL_Mode = 0;
input int    ATR_Period = 14;
input double ATR_Multiplier = 1.5;

// Take-profit setting
input double RiskReward = 2.0;

// Money management
input bool   UseFixedLot = true;
input double FixedlotSize = 0.10;
input double RiskPercent = 1.0;

// Trading controls
input ulong MagicNumber = 20261029;
input int   TradeStartHour = 8;
input int   TradeEndHour = 17;

// Debug messages in the Experts tab
input bool DebugMode = true;

//==============================================================
// GLOBAL VARIABLES
//==============================================================

// Indicator handles are created once and reused.
int fastEMAHandle = INVALID_HANDLE;
int slowEMAHandle = INVALID_HANDLE;
int atrHandle     = INVALID_HANDLE;

// Remember the opening time of the current candle.
// This ensures that signals are checked only once per candle.
datetime lastBarTime = 0;

//==============================================================
// DEBUGGING HELPER
//==============================================================
void DebugPrint(string message)
{
   if(DebugMode)
      Print("[TrendPullbackEA] ", message);
}

//==============================================================
// INITIALIZATION
//==============================================================
int OnInit()
{
   // Validate settings before starting.
   if(FastEMA <= 0 || SlowEMA <= 0 ||
      FastEMA >= SlowEMA ||
      PullbackBars < 1 ||
      ATR_Period <= 0 ||
      ATR_Multiplier <= 0 ||
      RiskReward <= 0 ||
      SL_Mode < 0 || SL_Mode > 1 ||
      FixedlotSize <= 0 ||
      RiskPercent <= 0 ||
      TradeStartHour < 0 || TradeStartHour > 23 ||
      TradeEndHour < 0 || TradeEndHour > 23)
   {
      Print("Invalid EA input settings. Check the Inputs tab.");
      return INIT_PARAMETERS_INCORRECT;
   }

   // Create the EMA indicator handles for the chart timeframe.
   fastEMAHandle = iMA(_Symbol, _Period, FastEMA,
                       0, MODE_EMA, PRICE_CLOSE);

   slowEMAHandle = iMA(_Symbol, _Period, SlowEMA,
                       0, MODE_EMA, PRICE_CLOSE);

   // Create the ATR handle, used when SL_Mode = 1.
   atrHandle = iATR(_Symbol, _Period, ATR_Period);

   // Stop if any indicator could not be initialized.
   if(fastEMAHandle == INVALID_HANDLE ||
      slowEMAHandle == INVALID_HANDLE ||
      atrHandle == INVALID_HANDLE)
   {
      Print("Failed to create indicator handles. Error: ",
            GetLastError());
      return INIT_FAILED;
   }

   // Configure the trade object.
   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetTypeFillingBySymbol(_Symbol);
   trade.SetAsyncMode(false);

   // Initialize the current candle time.
   lastBarTime = iTime(_Symbol, _Period, 0);

   DebugPrint("EA initialized successfully.");

   return INIT_SUCCEEDED;
}

//==============================================================
// SHUTDOWN
//==============================================================
void OnDeinit(const int reason)
{
   // Release indicator resources when the EA is removed.
   if(fastEMAHandle != INVALID_HANDLE)
      IndicatorRelease(fastEMAHandle);

   if(slowEMAHandle != INVALID_HANDLE)
      IndicatorRelease(slowEMAHandle);

   if(atrHandle != INVALID_HANDLE)
      IndicatorRelease(atrHandle);

   DebugPrint("EA stopped.");
}

//==============================================================
// NEW CANDLE DETECTION
//==============================================================
bool IsNewBar()
{
   datetime currentBarTime = iTime(_Symbol, _Period, 0);

   if(currentBarTime == 0)
      return false;

   if(currentBarTime != lastBarTime)
   {
      lastBarTime = currentBarTime;
      return true;
   }

   return false;
}

//==============================================================
// TRADING HOURS
//==============================================================
bool IsTradingTime()
{
   // Uses broker/server time, not your computer's local time.
   MqlDateTime currentTime;
   TimeToStruct(TimeTradeServer(), currentTime);

   int hour = currentTime.hour;

   // Equal start and end hours means trading all day.
   if(TradeStartHour == TradeEndHour)
      return true;

   // Normal session, for example 08:00 to 17:00.
   if(TradeStartHour < TradeEndHour)
   {
      return (hour >= TradeStartHour &&
              hour < TradeEndHour);
   }

   // Overnight session, for example 22:00 to 06:00.
   return (hour >= TradeStartHour ||
           hour < TradeEndHour);
}

//==============================================================
// CHECK FOR AN EXISTING POSITION ON THIS SYMBOL
//==============================================================
bool HasOpenPosition()
{
   // Check all open positions.
   // This prevents another trade on the symbol, even if another
   // EA or a manual trade opened the existing position.
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);

      if(ticket == 0)
         continue;

      if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         return true;
   }

   return false;
}

//==============================================================
// LOAD INDICATOR VALUES
//==============================================================
bool GetIndicatorValue(int handle, int shift, double &value)
{
   double buffer[1];

   // Copy one indicator value from the requested candle.
   if(CopyBuffer(handle, 0, shift, 1, buffer) != 1)
      return false;

   value = buffer[0];

   return (value != EMPTY_VALUE);
}

//==============================================================
// PULLBACK DETECTION
//==============================================================
bool HasPullback()
{
   // Search completed candles BEFORE the engulfing candle.
   // Shift 1 is the signal candle, so start from shift 2.
   for(int shift = 2; shift <= PullbackBars + 1; shift++)
   {
      double fastEMA, slowEMA;

      if(!GetIndicatorValue(fastEMAHandle, shift, fastEMA) ||
         !GetIndicatorValue(slowEMAHandle, shift, slowEMA))
      {
         return false;
      }

      double candleHigh = iHigh(_Symbol, _Period, shift);
      double candleLow  = iLow(_Symbol, _Period, shift);

      // The area between the two EMAs.
      double zoneHigh = MathMax(fastEMA, slowEMA);
      double zoneLow  = MathMin(fastEMA, slowEMA);

      // The candle range overlaps the EMA zone.
      if(candleLow <= zoneHigh && candleHigh >= zoneLow)
         return true;
   }

   return false;
}

//==============================================================
// BULLISH ENGULFING PATTERN
//==============================================================
bool IsBullishEngulfing()
{
   // Candle 1 is the most recently completed candle.
   // Candle 2 is the completed candle immediately before it.
   double open1  = iOpen(_Symbol, _Period, 1);
   double close1 = iClose(_Symbol, _Period, 1);
   double open2  = iOpen(_Symbol, _Period, 2);
   double close2 = iClose(_Symbol, _Period, 2);

   // Previous candle must be bearish.
   // Signal candle must be bullish and engulf the previous body.
   return (close2 < open2 &&
           close1 > open1 &&
           open1 <= close2 &&
           close1 >= open2);
}

//==============================================================
// BEARISH ENGULFING PATTERN
//==============================================================
bool IsBearishEngulfing()
{
   double open1  = iOpen(_Symbol, _Period, 1);
   double close1 = iClose(_Symbol, _Period, 1);
   double open2  = iOpen(_Symbol, _Period, 2);
   double close2 = iClose(_Symbol, _Period, 2);

   // Previous candle must be bullish.
   // Signal candle must be bearish and engulf the previous body.
   return (close2 > open2 &&
           close1 < open1 &&
           open1 >= close2 &&
           close1 <= open2);
}

//==============================================================
// FIND RECENT SWING STOP-LOSS PRICE
//==============================================================
double GetSwingStopLoss(bool isBuy)
{
   // Include the signal candle and recent candles before it.
   // This is a simple rolling swing approximation, not a
   // specialized market-structure swing-point detector.
   int lookback = PullbackBars + 1;

   double swingPrice = isBuy
                       ? iLow(_Symbol, _Period, 1)
                       : iHigh(_Symbol, _Period, 1);

   for(int shift = 2; shift <= lookback + 1; shift++)
   {
      if(isBuy)
      {
         double candleLow = iLow(_Symbol, _Period, shift);

         if(candleLow < swingPrice)
            swingPrice = candleLow;
      }
      else
      {
         double candleHigh = iHigh(_Symbol, _Period, shift);

         if(candleHigh > swingPrice)
            swingPrice = candleHigh;
      }
   }

   return swingPrice;
}

//==============================================================
// NORMALIZE LOT SIZE TO BROKER REQUIREMENTS
//==============================================================
double NormalizeVolume(double volume)
{
   double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double step   = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   if(step <= 0 || minLot <= 0 || maxLot <= 0)
      return 0.0;

   // Do not increase an undersized risk-based lot to the broker's
   // minimum, because that could exceed the intended risk.
   if(volume < minLot)
      return 0.0;

   volume = MathMin(volume, maxLot);

   // Round DOWN to a valid volume step.
   volume = MathFloor(volume / step + 1e-9) * step;

   if(volume < minLot)
      return 0.0;

   // Derive the number of decimal places from the volume step.
   int digits = 0;
   double checkStep = step;

   while(digits < 8 &&
         MathAbs(checkStep - MathRound(checkStep)) > 1e-8)
   {
      checkStep *= 10.0;
      digits++;
   }

   return NormalizeDouble(volume, digits);
}

//==============================================================
// CALCULATE LOT SIZE
//==============================================================
double CalculateLotSize(bool isBuy, double entryPrice,
                        double stopLoss)
{
   // Fixed-lot mode: use the user-defined lot size.
   if(UseFixedLot)
      return NormalizeVolume(FixedlotSize);

   // Risk-based mode: calculate risk as a percentage of equity.
   double equity = AccountInfoDouble(ACCOUNT_EQUITY);
   double riskMoney = equity * RiskPercent / 100.0;

   if(equity <= 0 || riskMoney <= 0)
      return 0.0;

   // Ask MT5 to estimate the monetary result for one lot
   // if the stop-loss price is reached.
   double profitAtSL = 0.0;

   ENUM_ORDER_TYPE orderType = isBuy ? ORDER_TYPE_BUY
                                     : ORDER_TYPE_SELL;

   if(!OrderCalcProfit(orderType, _Symbol, 1.0,
                       entryPrice, stopLoss, profitAtSL))
   {
      DebugPrint("OrderCalcProfit failed. Error: " +
                 IntegerToString(GetLastError()));
      return 0.0;
   }

   double lossPerLot = MathAbs(profitAtSL);

   if(lossPerLot <= 0)
      return 0.0;

   double rawLots = riskMoney / lossPerLot;

   return NormalizeVolume(rawLots);
}

//==============================================================
// VALIDATE STOP LOSS AND TAKE PROFIT DISTANCES
//==============================================================
bool ValidateStops(bool isBuy, double entryPrice,
                   double stopLoss, double takeProfit)
{
   // Check that prices are on the correct sides of entry.
   if(isBuy && (stopLoss >= entryPrice ||
                takeProfit <= entryPrice))
      return false;

   if(!isBuy && (stopLoss <= entryPrice ||
                 takeProfit >= entryPrice))
      return false;

   // Respect the broker's minimum stop distance.
   long stopsLevel = SymbolInfoInteger(_Symbol,
                                       SYMBOL_TRADE_STOPS_LEVEL);

   double minimumDistance = stopsLevel * _Point;

   if(isBuy)
   {
      if(entryPrice - stopLoss < minimumDistance ||
         takeProfit - entryPrice < minimumDistance)
         return false;
   }
   else
   {
      if(stopLoss - entryPrice < minimumDistance ||
         entryPrice - takeProfit < minimumDistance)
         return false;
   }

   return true;
}

//==============================================================
// OPEN A TRADE
//==============================================================
void OpenTrade(bool isBuy)
{
   MqlTick tick;

   if(!SymbolInfoTick(_Symbol, tick))
   {
      DebugPrint("Unable to obtain current market prices.");
      return;
   }

   // A market order fills at the current ask for a buy
   // and at the current bid for a sell.
   double entryPrice = isBuy ? tick.ask : tick.bid;

   double stopLoss = 0.0;

   // Select the requested stop-loss method.
   if(SL_Mode == 0)
   {
      stopLoss = GetSwingStopLoss(isBuy);
   }
   else
   {
      double atrValue;

      if(!GetIndicatorValue(atrHandle, 1, atrValue) ||
         atrValue <= 0)
      {
         DebugPrint("ATR value unavailable.");
         return;
      }

      double distance = atrValue * ATR_Multiplier;

      stopLoss = isBuy ? entryPrice - distance
                       : entryPrice + distance;
   }

   // Normalize SL to the symbol's price precision.
   stopLoss = NormalizeDouble(stopLoss, _Digits);

   // Check that the stop-loss is valid before sizing the trade.
   if((isBuy && stopLoss >= entryPrice) ||
      (!isBuy && stopLoss <= entryPrice))
   {
      DebugPrint("Invalid stop-loss price.");
      return;
   }

   // The target is based on the distance from entry to SL.
   double riskDistance = MathAbs(entryPrice - stopLoss);

   double takeProfit = isBuy
                       ? entryPrice + riskDistance * RiskReward
                       : entryPrice - riskDistance * RiskReward;

   takeProfit = NormalizeDouble(takeProfit, _Digits);

   // Do not send orders that violate broker stop-distance rules.
   if(!ValidateStops(isBuy, entryPrice, stopLoss, takeProfit))
   {
      DebugPrint("Trade skipped: stop distances are invalid "
                 "or too close to market price.");
      return;
   }

   // Calculate volume only after the final stop-loss is known.
   double lots = CalculateLotSize(isBuy, entryPrice, stopLoss);

   if(lots <= 0)
   {
      DebugPrint("Trade skipped: calculated lot size is invalid "
                 "or below the broker minimum.");
      return;
   }

   // Send the market order with SL and TP attached.
   bool sent = false;

   if(isBuy)
   {
      sent = trade.Buy(lots, _Symbol, 0.0,
                       stopLoss, takeProfit,
                       "EMA Pullback Buy");
   }
   else
   {
      sent = trade.Sell(lots, _Symbol, 0.0,
                        stopLoss, takeProfit,
                        "EMA Pullback Sell");
   }

   // A successful method call does not always mean the broker
   // executed the order, so inspect the trade result retcode.
   uint retcode = trade.ResultRetcode();

   if(sent &&
      (retcode == TRADE_RETCODE_DONE ||
       retcode == TRADE_RETCODE_DONE_PARTIAL ||
       retcode == TRADE_RETCODE_PLACED))
   {
      DebugPrint(string(isBuy ? "BUY" : "SELL") +
                 " request accepted. Lots=" +
                 DoubleToString(lots, 4) +
                 ", SL=" + DoubleToString(stopLoss, _Digits) +
                 ", TP=" + DoubleToString(takeProfit, _Digits));
   }
   else
   {
      DebugPrint("Trade failed. Retcode=" +
                 IntegerToString((int)retcode) +
                 ", description=" + trade.ResultRetcodeDescription());
   }
}

//==============================================================
// MAIN EA LOGIC
//==============================================================
void OnTick()
{
   // Check signals once per new candle, not on every tick.
   if(!IsNewBar())
      return;

   // Ensure enough chart history is available.
   int requiredBars = MathMax(SlowEMA, ATR_Period)
                      + PullbackBars + 5;

   if(Bars(_Symbol, _Period) < requiredBars)
   {
      DebugPrint("Waiting for more candle history.");
      return;
   }

   // Do not open another position on this symbol.
   if(HasOpenPosition())
   {
      DebugPrint("Position already exists on this symbol.");
      return;
   }

   // Restrict new entries to the selected trading hours.
   if(!IsTradingTime())
   {
      DebugPrint("Outside trading hours.");
      return;
   }

   // Read EMA values from the most recently closed candle.
   double fastEMA, slowEMA;

   if(!GetIndicatorValue(fastEMAHandle, 1, fastEMA) ||
      !GetIndicatorValue(slowEMAHandle, 1, slowEMA))
   {
      DebugPrint("Unable to read EMA values.");
      return;
   }

   // Determine trend direction.
   bool uptrend   = (fastEMA > slowEMA);
   bool downtrend = (fastEMA < slowEMA);

   // Confirm that a pullback occurred before the signal candle.
   bool pullback = HasPullback();

   if(!pullback)
   {
      DebugPrint("No pullback into the EMA zone.");
      return;
   }

   // Evaluate the completed signal candle.
   if(uptrend && IsBullishEngulfing())
   {
      DebugPrint("Bullish engulfing after pullback. Buy signal.");
      OpenTrade(true);
   }
   else if(downtrend && IsBearishEngulfing())
   {
      DebugPrint("Bearish engulfing after pullback. Sell signal.");
      OpenTrade(false);
   }
   else
   {
      DebugPrint("No valid engulfing signal.");
   }
}

Responded

1
Developer 1
Rating
(111)
Projects
184
25%
Arbitration
25
16% / 76%
Overdue
16
9%
Free
2
Developer 2
Rating
(402)
Projects
521
24%
Arbitration
61
57% / 25%
Overdue
60
12%
Loaded
3
Developer 3
Rating
(1)
Projects
2
0%
Arbitration
0
Overdue
0
Free
Published: 15 codes
4
Developer 4
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
5
Developer 5
Rating
(62)
Projects
90
29%
Arbitration
24
13% / 58%
Overdue
7
8%
Working
6
Developer 6
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
7
Developer 7
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
8
Developer 8
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
9
Developer 9
Rating
(29)
Projects
36
39%
Arbitration
0
Overdue
2
6%
Free
10
Developer 10
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Published: 1 code
11
Developer 11
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
12
Developer 12
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
13
Developer 13
Rating
(1)
Projects
1
0%
Arbitration
0
Overdue
0
Free
Published: 4 codes
14
Developer 14
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
15
Developer 15
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
16
Developer 16
Rating
(2)
Projects
2
0%
Arbitration
1
0% / 100%
Overdue
0
Free
17
Developer 17
Rating
(319)
Projects
574
35%
Arbitration
83
31% / 45%
Overdue
207
36%
Free
18
Developer 18
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Published: 10 codes
19
Developer 19
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
20
Developer 20
Rating
(5)
Projects
6
83%
Arbitration
0
Overdue
0
Free
Published: 2 codes
21
Developer 21
Rating
(8)
Projects
8
0%
Arbitration
2
50% / 0%
Overdue
1
13%
Working
22
Developer 22
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Published: 4 codes
23
Developer 23
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
24
Developer 24
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
25
Developer 25
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Published: 1 code
26
Developer 26
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
27
Developer 27
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
28
Developer 28
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
29
Developer 29
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
30
Developer 30
Rating
(13)
Projects
21
38%
Arbitration
0
Overdue
1
5%
Working
31
Developer 31
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
32
Developer 32
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Published: 1 code
33
Developer 33
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
34
Developer 34
Rating
(6)
Projects
8
38%
Arbitration
1
0% / 100%
Overdue
0
Free
35
Developer 35
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Published: 1 code
36
Developer 36
Rating
Projects
0
0%
Arbitration
0
Overdue
0
Free
Similar orders
Platform: MT5 only (no MT4 needed). Deliverable: an MT5 Expert Advisor with full source code (.mq5) that replicates the attached TradingView strategy (Pine Script v6, based on LuxAlgo's "ICT Killzones Toolkit" order blocks) as exactly as possible. Pasting the code into TradingView shows how it operates. I normally trade GBPUSD on the 5-minute chart Expected behavior: - Order block detection must match the Pine code
I have an existing compiled MetaTrader 5 Expert Advisor (EX5) designed for automated XAUUSD scalping. I want an experienced developer to assess and implement a solution to execute the EA’s original trading strategy through my broker’s FIX API. Requirements: Confirm the technical feasibility of connecting an existing MT5 EA to a broker FIX API. Explain how to obtain FIX API access and credentials from the broker
I have an existing compiled MT5 Expert Advisor (.ex5) for XAUUSD scalping. I need a developer to build a bridge that connects my existing EA to a broker’s FIX API, allowing its trading signals to execute orders directly through FIX instead of the standard MT5 trade server. I do not need a new trading strategy or a new EA. Please confirm whether this is technically possible without the EA source code, and explain your
The purpose of this order is ONLY to test and implement my H1 POI (Point of Interest) identification logic correctly. I am not requesting the complete EA at this stage. I will provide the exact rules for identifying the H1 POI after selecting the developer. The developer must convert those rules into clear, deterministic MQL5 logic. Requirements: Analyze H1 candles according to the rules I provide. Identify and mark
فيما يخص المتداولين من سلطان التداول وحتى المبتدى والضائع في أكبر سوق عالمي في التداول ااوكد لكم ان الاستشاره البسيطه من من يملك الاستراتيجيه المثلى في التداول والخبره الطويله في مجال التداول قد تغير مستقبلك
Hi, I need NinjaTrader 8 Strategy Analyzer backtests on two of my strategies, each over 1 year AND 3 years of data. Please quote the full job. Common settings: NT8 Strategy Analyzer, MCL (Micro WTI Crude Oil) continuous front-month contract (MCL ##-##), 5-minute bars, 1yr + 3yr of the most recent data, $2.50 round-turn commission per contract. Deliverables per run: full Strategy Analyzer summary (net profit, profit
Scalping bort 30+ USD
GOLD SCALPING BOT STRATEGY Symbol: XAUUSD (Gold vs USD) Broker: Exness Account: Standard Starting Balance: $20 1. TIMEFRAME - Trend analysis: M15. - Entry timeframe: M5. - Trade only when the market has a clear direction. 2. INDICATORS - EMA 50 - EMA 200 - RSI 14 - Support and Resistance 3. BUY RULES The bot must open a BUY trade only when all these conditions are met: 1. EMA 50 is above EMA 200 on M15. 2. Price is
Request for an Existing Automated Trading System (Expert Advisor) I am looking to acquire an existing, fully functional Expert Advisor (EA) that trades Forex CFDs, with the option of trading other CFDs if the strategy supports them safely. Performance objectives Target average net monthly return: 1.5%. A consistent 1.0% monthly return may be considered if the system demonstrates strong risk control and credible
Are you able to build one bot for stock and one for ninja trader and tell me the win rate on it. I need ninja trader bot that enter buy and exit according the move to do not stay long in the market in each entry . That can follow the smart money concept or other if you have a good one
Trading bot ea 30+ USD
yoo i want to make a trading bot i have my strategy in videos and also the rules to if anyone can work it out for me i will be glad welcome your bid and it urget let connect here on mgl5 And if you know you can not do the project without getting paid first please don't bid thanks

Project information

Budget
30+ USD

Customer

Placed orders1
Arbitrage count0