Untitled
unknown
plain_text
15 days ago
26 kB
4
Indexable
//+------------------------------------------------------------------+ //| Determine trade direction based on indicators | //+------------------------------------------------------------------+ int GetTradeDirection() { if(UseRandomDirection) { // Randomly choose direction return MathRand() % 2; } // Use indicators for direction decision // MACD double macdMain = iMACD(Symbol(), 0, MACDFast, MACDSlow, MACDSignal, PRICE_CLOSE, MODE_MAIN, 0); double macdSignal = iMACD(Symbol(), 0, MACDFast, MACDSlow, MACDSignal, PRICE_CLOSE, MODE_SIGNAL, 0); double macdMain1 = iMACD(Symbol(), 0, MACDFast, MACDSlow, MACDSignal, PRICE_CLOSE, MODE_MAIN, 1); double macdSignal1 = iMACD(Symbol(), 0, MACDFast, MACDSlow, MACDSignal, PRICE_CLOSE, MODE_SIGNAL, 1); // EMA double fastEMA = iMA(Symbol(), 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 0); double slowEMA = iMA(Symbol(), 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 0); // RSI double rsi = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 0); // Calculate trend score int trendScore = 0; // MACD crossing up if(macdMain > macdSignal && macdMain1 <= macdSignal1) trendScore++; // MACD above zero if(macdMain > 0) trendScore++; // MACD above signal if(macdMain > macdSignal) trendScore++; // EMA trend if(fastEMA > slowEMA) trendScore++; // RSI trend if(rsi < RSIOversold) trendScore++; if(rsi > 50) trendScore++; // Determine direction based on trend score (0-6) // 0-2: Bearish, 3: Neutral, 4-6: Bullish if(trendScore >= 4) return 0; // Buy else if(trendScore <= 2) return 1; // Sell else return MathRand() % 2; // Neutral, random direction }//+------------------------------------------------------------------+ //| XAUUSD Rebate Harvester | //| Copyright 2025 | //+------------------------------------------------------------------+ // Input Parameters extern string RebateInfo = "--- Rebate Settings ---"; extern double RebatePerLot = 20.0; // USD Rebate per lot extern bool IsSwapFree = true; // Set to true for swap-free accounts extern bool CloseOnlyAtBreakeven = true; // Only close trades at breakeven or profit extern bool UseRealTimeSpread = true; // Monitor spread in real-time for information extern string TradingSettings = "--- Trading Settings ---"; extern double BaseLotSize = 0.01; // Starting lot size per trade extern bool UseMaringale = true; // Use martingale strategy for losing trades extern double MartingaleMultiplier = 2.0;// Multiplier for martingale strategy extern int MaxMartingaleLevels = 5; // Maximum martingale levels allowed extern int MinutesBetweenTrades = 1; // Wait time between trades extern double MaxDailyLoss = 100.0; // Maximum daily loss in USD extern bool UseRandomDirection = false; // Set to false to use trend indicator direction extern bool CloseTradesEndOfDay = false; // No need to close at end of day for swap-free accounts extern int MaxLossPips = 20; // Maximum loss in pips before martingale kicks in extern string TimeFrameInfo = "EA optimized for M1 or M5 timeframes"; extern string DashboardSettings = "--- Dashboard Settings ---"; extern int DashboardCorner = 1; // Corner to display dashboard (0-3) extern int DashboardXOffset = 10; // X offset from corner extern int DashboardYOffset = 10; // Y offset from corner extern color TextColor = clrWhite; // Dashboard text color extern color ProfitColor = clrLimeGreen; // Profit color extern color LossColor = clrRed; // Loss color extern int FontSize = 9; // Dashboard font size extern int MalaysiaGMTOffset = 8; // Malaysia time is GMT+8 extern int DailyResetHour = 7; // Hour to reset daily tracking (7am Malaysia time) // Global Variables datetime lastTradeTime = 0; double dailyLoss = 0.0; double dailyRebateTotal = 0.0; double totalRebateCollected = 0.0; int totalTradesTaken = 0; int winningTrades = 0; int losingTrades = 0; int breakEvenTrades = 0; double currentLotSize = 0.0; int martingaleLevel = 0; int lastTradeTicket = 0; bool inMaringaleSequence = false; datetime lastDayChecked = 0; int magicNumber = 8675309; string currentStatus = "Initializing..."; // Objects for dashboard string objPrefix = "RebateEA_"; string dashboardLabels[10]; string dashboardValues[10]; int dashboardCount = 0; //+------------------------------------------------------------------+ //| Calculate required number of lots to break even | //+------------------------------------------------------------------+ double CalculateBreakEvenLots() { // If BrokerSpread is $0.50 and RebatePerLot is $20 // We need to trade at least BrokerSpread/RebatePerLot = 0.025 lots to break even if(RebatePerLot <= 0) return 0; // For XAUUSD, we need to convert the spread from points to USD value double spreadInUSD = BrokerSpread * 0.01; // Rough approximation: 1 point ≈ $0.01 for XAUUSD return spreadInUSD / RebatePerLot; } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Get current spread double currentSpread = GetCurrentSpread(); // Display information Print("Rebate EA initialized for XAUUSD"); Print("Rebate per lot: $", RebatePerLot); Print("Current spread: ", currentSpread, " points"); Print("Every trade will earn $", RebatePerLot * BaseLotSize, " in rebate for ", BaseLotSize, " lot"); // Verify symbol is XAUUSD if(Symbol() != "XAUUSD") { Print("WARNING: This EA is designed for XAUUSD. Current symbol: ", Symbol()); } // Verify timeframe is M1 or M5 if(Period() != PERIOD_M1 && Period() != PERIOD_M5) { Print("WARNING: This EA is optimized for M1 or M5 timeframes. Current timeframe: ", PeriodToString(Period())); } // Initialize dashboard currentStatus = "Trading for rebate"; CreateDashboard(); // Reset daily tracking lastDayChecked = TimeCurrent(); dailyLoss = 0.0; dailyRebateTotal = 0.0; // Reset martingale settings inMaringaleSequence = false; martingaleLevel = 0; currentLotSize = BaseLotSize; return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Convert period constant to string | //+------------------------------------------------------------------+ string PeriodToString(int period) { switch(period) { case PERIOD_M1: return "M1"; case PERIOD_M5: return "M5"; case PERIOD_M15: return "M15"; case PERIOD_M30: return "M30"; case PERIOD_H1: return "H1"; case PERIOD_H4: return "H4"; case PERIOD_D1: return "D1"; case PERIOD_W1: return "W1"; case PERIOD_MN1: return "MN1"; default: return "Unknown"; } } //+------------------------------------------------------------------+ //| Convert server time to Malaysia time | //+------------------------------------------------------------------+ datetime ServerToMalaysiaTime(datetime serverTime) { // Get GMT time first int serverGMTOffset = TimeGMTOffset() / 3600; // Convert seconds to hours datetime gmtTime = serverTime - serverGMTOffset * 3600; // Convert GMT to Malaysia time (GMT+8) datetime malaysiaTime = gmtTime + MalaysiaGMTOffset * 3600; return malaysiaTime; } //+------------------------------------------------------------------+ //| Check for day reset | //+------------------------------------------------------------------+ void CheckDayReset() { datetime currentServerTime = TimeCurrent(); datetime malaysiaTime = ServerToMalaysiaTime(currentServerTime); // Extract hour in Malaysia time int malaysiaHour = TimeHour(malaysiaTime); int malaysiaDay = TimeDay(malaysiaTime); int lastCheckedMalaysiaDay = TimeDay(ServerToMalaysiaTime(lastDayChecked)); // Reset at specified hour (7am Malaysia time) if(malaysiaDay != lastCheckedMalaysiaDay && malaysiaHour >= DailyResetHour) { // Calculate yesterday's rebate double yesterdayRebate = dailyRebateTotal; totalRebateCollected += yesterdayRebate; // Reset daily tracking dailyLoss = 0.0; dailyRebateTotal = 0.0; lastDayChecked = currentServerTime; Print("New day - Reset daily tracking at ", TimeHour(malaysiaTime), ":", TimeMinute(malaysiaTime), " Malaysia time. ", "Yesterday's rebate: $", yesterdayRebate); } } //+------------------------------------------------------------------+ //| Create and update dashboard | //+------------------------------------------------------------------+ void CreateDashboard() { // Clear any existing dashboard for(int i = 0; i < dashboardCount; i++) { ObjectDelete(dashboardLabels[i]); ObjectDelete(dashboardValues[i]); } dashboardCount = 0; // Font and colors defined in settings // Start positions int x = DashboardXOffset; int y = DashboardYOffset; int lineHeight = FontSize + 4; // Get current spread double currentSpread = GetCurrentSpread(); // Get Malaysia time datetime malaysiaTime = ServerToMalaysiaTime(TimeCurrent()); string timeStr = TimeHour(malaysiaTime) + ":" + (TimeMinute(malaysiaTime) < 10 ? "0" + TimeMinute(malaysiaTime) : IntegerToString(TimeMinute(malaysiaTime))) + " MYT"; // Add current status at the top AddDashboardRow("Status:", currentStatus, x, y, currentStatus == "Trading for rebate" ? ProfitColor : StringFind(currentStatus, "Martingale") >= 0 ? clrOrange : TextColor); y += lineHeight; // Add Malaysia time AddDashboardRow("Malaysia Time:", timeStr, x, y); y += lineHeight; // Add current spread AddDashboardRow("Current Spread:", DoubleToString(currentSpread, 1) + " points", x, y); y += lineHeight; // Add rebate per trade AddDashboardRow("Rebate per Trade:", "$" + DoubleToString(RebatePerLot * currentLotSize, 2), x, y, ProfitColor); y += lineHeight; // Add labels to dashboard AddDashboardRow("Total Rebate:", DoubleToString(totalRebateCollected, 2) + " USD", x, y); y += lineHeight; AddDashboardRow("Today's Rebate:", DoubleToString(dailyRebateTotal, 2) + " USD", x, y); y += lineHeight; AddDashboardRow("Total Trades:", IntegerToString(totalTradesTaken), x, y); y += lineHeight; AddDashboardRow("Win/Loss/BE:", IntegerToString(winningTrades) + "/" + IntegerToString(losingTrades) + "/" + IntegerToString(breakEvenTrades), x, y); y += lineHeight; if(inMaringaleSequence) { AddDashboardRow("Martingale Level:", IntegerToString(martingaleLevel) + " of " + IntegerToString(MaxMartingaleLevels), x, y, clrOrange); y += lineHeight; AddDashboardRow("Current Lot Size:", DoubleToString(currentLotSize, 2), x, y); y += lineHeight; } // Add rebate calculation double estimatedDailyRebate = RebatePerLot * totalTradesTaken * BaseLotSize / (MathMax(1, TimeDiffDays(TimeCurrent(), GetAccountOpenTime()))); AddDashboardRow("Est. Daily Rebate:", DoubleToString(estimatedDailyRebate, 2) + " USD", x, y); } //+------------------------------------------------------------------+ //| Add a row to the dashboard | //+------------------------------------------------------------------+ void AddDashboardRow(string label, string value, int x, int y, color valueColor = CLR_NONE) { string labelName = objPrefix + "Label" + IntegerToString(dashboardCount); string valueName = objPrefix + "Value" + IntegerToString(dashboardCount); // Default color handling if(valueColor == CLR_NONE) { valueColor = StringFind(value, "-") >= 0 ? LossColor : ProfitColor; } // Save names for later deletion dashboardLabels[dashboardCount] = labelName; dashboardValues[dashboardCount] = valueName; // Create label object ObjectCreate(labelName, OBJ_LABEL, 0, 0, 0); ObjectSetText(labelName, label, FontSize, "Arial", TextColor); ObjectSet(labelName, OBJPROP_CORNER, DashboardCorner); ObjectSet(labelName, OBJPROP_XDISTANCE, x); ObjectSet(labelName, OBJPROP_YDISTANCE, y); // Create value object ObjectCreate(valueName, OBJ_LABEL, 0, 0, 0); ObjectSetText(valueName, value, FontSize, "Arial", valueColor); ObjectSet(valueName, OBJPROP_CORNER, DashboardCorner); ObjectSet(valueName, OBJPROP_XDISTANCE, x + 150); ObjectSet(valueName, OBJPROP_YDISTANCE, y); dashboardCount++; } //+------------------------------------------------------------------+ //| Update the dashboard | //+------------------------------------------------------------------+ void UpdateDashboard() { // Just recreate the dashboard CreateDashboard(); } //+------------------------------------------------------------------+ //| Get account open time (or use a default if not available) | //+------------------------------------------------------------------+ datetime GetAccountOpenTime() { // MT4 doesn't have a direct way to get account open time // Using a fallback of 30 days if not explicitly tracked datetime fallbackTime = TimeCurrent() - 30 * 24 * 60 * 60; // 30 days ago return fallbackTime; } //+------------------------------------------------------------------+ //| Calculate difference in days between two dates | //+------------------------------------------------------------------+ int TimeDiffDays(datetime time1, datetime time2) { return (int)((time1 - time2) / (24 * 60 * 60)); } //+------------------------------------------------------------------+ //| Check if we should close all trades (end of day) | //+------------------------------------------------------------------+ void CheckEndOfDayClose() { if(!CloseTradesEndOfDay) return; datetime currentTime = TimeCurrent(); int currentHour = TimeHour(currentTime); // Close all trades at the end of trading day (adjust times as needed) if(currentHour == 23 && TimeMinute(currentTime) >= 45) { CloseAllTrades(); Print("End of day - Closed all trades"); } } //+------------------------------------------------------------------+ //| Close all open trades | //+------------------------------------------------------------------+ void CloseAllTrades() { for(int i = OrdersTotal() - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == Symbol() && OrderMagicNumber() == magicNumber) { bool result = false; if(OrderType() == OP_BUY) { result = OrderClose(OrderTicket(), OrderLots(), Bid, MaxSlippage, clrRed); } else if(OrderType() == OP_SELL) { result = OrderClose(OrderTicket(), OrderLots(), Ask, MaxSlippage, clrRed); } if(!result) { Print("Error closing order: ", GetLastError()); } else { // Calculate rebate earned double rebateEarned = RebatePerLot * OrderLots(); dailyRebateTotal += rebateEarned; Print("Earned rebate from closed trade: $", rebateEarned); } } } } // Reset martingale sequence inMaringaleSequence = false; martingaleLevel = 0; currentLotSize = BaseLotSize; // Update dashboard UpdateDashboard(); } //+------------------------------------------------------------------+ //| Update trailing stops for open trades | //+------------------------------------------------------------------+ void UpdateTrailingStops() { if(!UseTrailingStop) return; for(int i = 0; i < OrdersTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == Symbol() && OrderMagicNumber() == magicNumber) { double currentStop = OrderStopLoss(); // For buy orders if(OrderType() == OP_BUY) { // Move to breakeven first if enough profit if(BreakevenAfterPips > 0 && Bid - OrderOpenPrice() >= Point * BreakevenAfterPips * 10 && (currentStop < OrderOpenPrice() || currentStop == 0)) { bool moved = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, clrBlue); if(moved) { Print("Moved stop to breakeven for order #", OrderTicket()); } } // Then apply trailing stop else if(Bid - OrderOpenPrice() > Point * TrailingStop * 10) { double newStop = Bid - Point * TrailingStop * 10; if(currentStop < newStop - Point) { // Only modify if significant difference bool trailed = OrderModify(OrderTicket(), OrderOpenPrice(), newStop, OrderTakeProfit(), 0, clrBlue); if(trailed) { Print("Updated trailing stop for order #", OrderTicket()); } } } } // For sell orders else if(OrderType() == OP_SELL) { // Move to breakeven first if enough profit if(BreakevenAfterPips > 0 && OrderOpenPrice() - Ask >= Point * BreakevenAfterPips * 10 && (currentStop > OrderOpenPrice() || currentStop == 0)) { bool moved = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, clrRed); if(moved) { Print("Moved stop to breakeven for order #", OrderTicket()); } } // Then apply trailing stop else if(OrderOpenPrice() - Ask > Point * TrailingStop * 10) { double newStop = Ask + Point * TrailingStop * 10; if(currentStop > newStop + Point || currentStop == 0) { // Only modify if significant difference bool trailed = OrderModify(OrderTicket(), OrderOpenPrice(), newStop, OrderTakeProfit(), 0, clrRed); if(trailed) { Print("Updated trailing stop for order #", OrderTicket()); } } } } } } } } //+------------------------------------------------------------------+ //| Check for trades that should be closed | //+------------------------------------------------------------------+ void CheckAndCloseHeldTrades() { for(int i = OrdersTotal() - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == Symbol() && OrderMagicNumber() == magicNumber) { // Check for maximum hold time (prevent trades staying open forever) if(TimeCurrent() - OrderOpenTime() >= MaxTradeHoldTimeHours * 3600) { // Only close if at breakeven or profit when CloseOnlyAtBreakeven is true if(!CloseOnlyAtBreakeven || OrderProfit() >= 0) { bool result = false; if(OrderType() == OP_BUY) { result = OrderClose(OrderTicket(), OrderLots(), Bid, MaxSlippage, clrRed); } else if(OrderType() == OP_SELL) { result = OrderClose(OrderTicket(), OrderLots(), Ask, MaxSlippage, clrRed); } if(result) { Print("Closed trade #", OrderTicket(), " after maximum hold time with profit: ", OrderProfit()); } else { Print("Error closing order after hold time: ", GetLastError()); } } } } } } } //+------------------------------------------------------------------+ //| Update daily profit/loss tracking | //+------------------------------------------------------------------+ void UpdateDailyPnL() { static double lastAccountBalance = AccountBalance(); double currentBalance = AccountBalance(); // If balance decreased, update daily loss if(currentBalance < lastAccountBalance) { dailyLoss += (lastAccountBalance - currentBalance); } lastAccountBalance = currentBalance; // Check if we hit maximum daily loss if(dailyLoss >= MaxDailyLoss) { Print("Maximum daily loss reached. Stopping trading for today."); CloseAllTrades(); } // Update dashboard UpdateDashboard(); } //+------------------------------------------------------------------+ //| Open a new trade | //+------------------------------------------------------------------+ void OpenNewTrade() { // If we're already in a martingale sequence, don't open a new trade if(inMaringaleSequence) return; // If we already have an open trade, don't open another one if(CountOpenTrades() > 0) return; // Determine trade direction based on indicators int direction = GetTradeDirection(); // Use base lot size for new trades currentLotSize = BaseLotSize; // Open the trade and store its ticket number lastTradeTicket = OpenSpecificTrade(direction, currentLotSize); } direction (based on indicators or random) int direction = GetTradeDirection(); int ticket = -1; if(direction == 0) { // Buy order ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, MaxSlippage, StopLoss > 0 ? Ask - Point * StopLoss * 10 : 0, TakeProfit > 0 ? Ask + Point * TakeProfit * 10 : 0, "RebateHarvester", magicNumber, 0, clrBlue); } else { // Sell order ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, MaxSlippage, StopLoss > 0 ? Bid + Point * StopLoss * 10 : 0, TakeProfit > 0 ? Bid - Point * TakeProfit * 10 : 0, "RebateHarvester", magicNumber, 0, clrRed); } if(ticket < 0) { Print("Error opening trade: ", GetLastError()); } else { lastTradeTime = TimeCurrent(); Print("Opened trade #", ticket, " Direction: ", (direction == 0 ? "Buy" : "Sell")); } } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check for day reset (based on Malaysia time) CheckDayReset(); // Update trailing stops UpdateTrailingStops(); // Update daily P&L UpdateDailyPnL(); // Update current status if not in special mode if(!inMaringaleSequence && CountOpenTrades() > 0) { currentStatus = "Trading for rebate"; } else if(CountOpenTrades() == 0 && !inMaringaleSequence) { currentStatus = "Waiting to open trade"; } // Check trades that need to be closed or martingaled CheckAndCloseHeldTrades(); // Check for end of day closing (if enabled) if(!IsSwapFree) { CheckEndOfDayClose(); } // If we've hit maximum daily loss, don't open new trades if(dailyLoss >= MaxDailyLoss) { currentStatus = "Daily loss limit reached"; UpdateDashboard(); return; } // Check for time between trades if(TimeCurrent() - lastTradeTime < MinutesBetweenTrades * 60) return; // Open a new trade if we don't have any open if(CountOpenTrades() == 0) { currentStatus = "Opening new trade"; UpdateDashboard(); OpenNewTrade(); } } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Clean up dashboard objects for(int i = 0; i < dashboardCount; i++) { ObjectDelete(dashboardLabels[i]); ObjectDelete(dashboardValues[i]); } Print("Rebate Harvester EA stopped"); Print("Total rebate collected: $", totalRebateCollected + dailyRebateTotal); Print("Total trades taken: ", totalTradesTaken); Print("Winning/Losing/Breakeven trades: ", winningTrades, "/", losingTrades, "/", breakEvenTrades); } //+------------------------------------------------------------------+
Editor is loading...
Leave a Comment