| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- //+------------------------------------------------------------------+
- //| CribMarketEA.mq5 |
- //| Copyright 2025, MQL Development |
- //| https://www.mqldevelopment.com/ |
- //+------------------------------------------------------------------+
- #property copyright "Copyright 2025, MQL Development"
- #property link "https://www.mqldevelopment.com/"
- #property version "1.00"
- #include <Trade\Trade.mqh>
- CTrade trade;
- #define MaxOrders 10000
- struct new_trade_store
- {
- ulong buyTicket; // Buy Ticket
- ulong sellTicket; // Sell Ticket
- string buySymbol; // Buy Symbol Name
- string sellSymbol; // Sell Symbol Name
- new_trade_store()
- {
- buyTicket = -1;
- sellTicket = -1;
- }
- };
- new_trade_store newTradeStore[MaxOrders];
- input string Settings = " ------------- General Settings ------------- "; //_
- input int magicNo = 333; // Magic no
- input double lotSize = 0.01; // Lot Size
- input bool enableBasketTP = true; // Enable Basket TP
- input double basketTakeProfit = 1.0; // Basket Take Profit
- input int maxOpenPositions = 3; // Maximum number of Combinations
- input int miniHoldTimeSec = 120; // Mini time in (seconds) to hold trades closing before checking TP
- string goldPairs[];
- int totalGoldPairs = 0;
- int timer = 0;
- //+------------------------------------------------------------------+
- //| Expert initialization function |
- //+------------------------------------------------------------------+
- int OnInit()
- {
- //---
- trade.SetExpertMagicNumber(magicNo);
- trade.SetDeviationInPoints(10);
- trade.SetTypeFilling(ORDER_FILLING_IOC);
- trade.LogLevel(LOG_LEVEL_ALL);
- trade.SetAsyncMode(false);
- getSymbolsFromMarketWatch();
- // addToStructure(153718680, 153718681, "EURUSD", "XAUUSD.");
- //--- create timer
- EventSetMillisecondTimer(1000);
- //---
- return(INIT_SUCCEEDED);
- }
- //+------------------------------------------------------------------+
- //| Expert deinitialization function |
- //+------------------------------------------------------------------+
- void OnDeinit(const int reason)
- {
- //---
- EventKillTimer();
- }
- //+------------------------------------------------------------------+
- //| Expert tick function |
- //+------------------------------------------------------------------+
- void OnTick()
- {
- //---
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void OnTimer()
- {
- //---
- timer++;
- Print("<><><><><><><> Timer Start: ",timer," <><><><><><><>");
- removeFromStruct();
- if(enableBasketTP == true)
- {
- checkBasketTakeProfit();
- }
- string symbolToBuy = getSymbolWithLowestAsk();
- string symbolToSell = getSymbolWithHighestBid();
- int buyTickett = -1, sellTickett = -1;
- //Print(" Symbol to Buy is: ", symbolToBuy, " Symbol to Sell: ", symbolToSell);
- if(noOfActiveCombinations() < maxOpenPositions)
- {
- if(canTradeSymbol(symbolToBuy, symbolToSell, POSITION_TYPE_BUY, POSITION_TYPE_SELL))
- {
- if(symbolToBuy != symbolToSell)
- {
- if(symbolToBuy != NULL && symbolToBuy != "")
- {
- buyTickett = placeBuyTrade(symbolToBuy);
- }
- if(symbolToSell != NULL && symbolToSell != "")
- {
- sellTickett = placeSellTrade(symbolToSell);
- }
- }
- }
- }
- if(buyTickett != -1 && sellTickett != -1)
- {
- addToStructure(buyTickett, sellTickett, symbolToBuy, symbolToSell);
- }
- Print("<><><><><><><> Timer End: ",timer," <><><><><><><>");
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool newBar()
- {
- static datetime lastbar;
- datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0);
- if(lastbar != curbar)
- {
- lastbar = curbar;
- Print(" ---------------------- New Bar :: ---------------------- ",lastbar);
- return (true);
- }
- else
- {
- return (false);
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- int placeBuyTrade(string symbol)
- {
- double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
- double buySL = 0, buyTP = 0;
- int count=noOfActiveCombinations()+1;
- if(trade.PositionOpen(symbol, ORDER_TYPE_BUY, lotSize, ask, buySL, buyTP, "Buy Trade Placed # "+(string)timer))
- {
- Print("Buy Trade Placed on ", symbol, ": ", trade.ResultOrder());
- return (int)trade.ResultOrder();
- }
- else
- {
- Print("Error in placing Buy on ", symbol, ": ", GetLastError());
- }
- return 0;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- int placeSellTrade(string symbol)
- {
- double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
- double sellSL = 0, sellTP = 0;
- int count=noOfActiveCombinations()+1;
- if(trade.PositionOpen(symbol, ORDER_TYPE_SELL, lotSize, bid, sellSL, sellTP, "Sell Trade Placed # "+(string)timer))
- {
- Print("Sell Trade Placed on ", symbol, ": ", trade.ResultOrder());
- return (int)trade.ResultOrder();
- }
- else
- {
- Print("Error in placing Sell on ", symbol, ": ", GetLastError());
- }
- return 0;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void getSymbolsFromMarketWatch()
- {
- int totalSymbols = SymbolsTotal(true);
- ArrayResize(goldPairs, 0);
- totalGoldPairs = 0;
- for(int i = 0; i < totalSymbols; i++)
- {
- string symbolName = SymbolName(i, true);
- //if(StringFind(symbolName, "GOLD") != -1 || StringFind(symbolName, "XAU") != -1)
- if(symbolName!="XAUUSD#")
- {
- ArrayResize(goldPairs, totalGoldPairs + 1);
- if(totalGoldPairs < ArraySize(goldPairs))
- {
- goldPairs[totalGoldPairs] = symbolName;
- totalGoldPairs++;
- }
- else
- {
- Print("Error: Array resize failed for symbol ", symbolName);
- }
- }
- }
- Print("Found ", totalGoldPairs, " Symbol pairs in Market Watch");
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string getSymbolWithLowestAsk()
- {
- if(totalGoldPairs == 0)
- return NULL;
- string lowestSymbol = "";
- //double lowestAsk = INT_MAX; // SymbolInfoDouble(lowestSymbol, SYMBOL_ASK);
- double lowestAsk = DBL_MAX;
- for(int i = 0; i < totalGoldPairs; i++)
- {
- double currentAsk = SymbolInfoDouble(goldPairs[i], SYMBOL_ASK);
- Print(" Ask Price: ",currentAsk," || on Pair: ",goldPairs[i]);
- if(currentAsk < lowestAsk)
- {
- lowestAsk = currentAsk;
- lowestSymbol = goldPairs[i];
- }
- }
- Print("Lowest Ask Pair: ", lowestSymbol, " || Lowest Ask: ", lowestAsk);
- return lowestSymbol;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string getSymbolWithHighestBid()
- {
- if(totalGoldPairs == 0)
- return NULL;
- string highestSymbol = "";
- //double highestBid = INT_MIN; // SymbolInfoDouble(highestSymbol, SYMBOL_BID);
- double highestBid = 0;
- for(int i = 0; i < totalGoldPairs; i++)
- {
- double currentBid = SymbolInfoDouble(goldPairs[i], SYMBOL_BID);
- Print(" Bid Price: ",currentBid," || on Pair: ",goldPairs[i]);
- if(currentBid > highestBid)
- {
- highestBid = currentBid;
- highestSymbol = goldPairs[i];
- }
- }
- Print("Highest Bid Pair: ", highestSymbol, " || Highest Bid: ", highestBid);
- return highestSymbol;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- int noOfActiveCombinations()
- {
- int count = 0;
- for(int i = 0; i < MaxOrders; i++)
- {
- if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
- {
- count++;
- }
- }
- return count;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void checkBasketTakeProfit()
- {
- for(int i = 0; i < MaxOrders; i++)
- {
- if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
- {
- if(miniTimeBeforeClosing(newTradeStore[i].buyTicket, newTradeStore[i].sellTicket))
- {
- double combinationProfit = 0;
- if(PositionSelectByTicket(newTradeStore[i].buyTicket))
- {
- Print("Ticket:",newTradeStore[i].buyTicket);
- Print("Profit:",PositionGetDouble(POSITION_PROFIT), " Swap:",PositionGetDouble(POSITION_SWAP));
- combinationProfit += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP) ;
- }
- if(PositionSelectByTicket(newTradeStore[i].sellTicket))
- {
- Print("Ticket:",newTradeStore[i].sellTicket);
- Print("Profit:",PositionGetDouble(POSITION_PROFIT), " Swap:",PositionGetDouble(POSITION_SWAP));
- combinationProfit += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
- }
- if(combinationProfit >= basketTakeProfit)
- {
- Print("Combination TP hit: Closing trades. Profit = ", combinationProfit);
- if(!trade.PositionClose(newTradeStore[i].buyTicket))
- {
- Print(" Error Closing Buy Trade : ", newTradeStore[i].buyTicket," ",GetLastError());
- }
- else
- Print("Buy Trade Closed: ", newTradeStore[i].buyTicket);
- if(!trade.PositionClose(newTradeStore[i].sellTicket))
- {
- Print(" Error Closing Sell Trade : ", newTradeStore[i].sellTicket," ",GetLastError());
- }
- else
- Print("Sell Trade Closed: ", newTradeStore[i].sellTicket);
- }
- }
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool isGoldPair(string symbol)
- {
- for(int i = 0; i < totalGoldPairs; i++)
- {
- //Print("Total Gold pairs: ", totalGoldPairs, " Array: ", goldPairs[i], " Symbol: ", symbol);
- if(goldPairs[i] == symbol)
- return true;
- }
- return false;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void addToStructure(ulong r_buyTicket,ulong r_sellTicket, string r_buySymbol, string r_sellSymbol)
- {
- for(int i=0; i<MaxOrders; i++)
- {
- if(newTradeStore[i].buyTicket==-1 && newTradeStore[i].sellTicket==-1)
- {
- newTradeStore[i].buyTicket = r_buyTicket;
- newTradeStore[i].sellTicket = r_sellTicket;
- newTradeStore[i].buySymbol = r_buySymbol;
- newTradeStore[i].sellSymbol = r_sellSymbol;
- Print("Stored new ticket in structure. Buy Ticket: ", newTradeStore[i].buyTicket, " Sell Ticket: ", newTradeStore[i].sellTicket,
- " Buy Symbol: ", newTradeStore[i].buySymbol, " Sell Symbol: ", newTradeStore[i].sellSymbol);
- break;
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void removeFromStruct()
- {
- for(int i = 0 ; i < MaxOrders ; i++)
- {
- bool buyPresent = false;
- bool sellPresent = false;
- if(newTradeStore[i].buyTicket !=-1 && newTradeStore[i].sellTicket !=-1)
- {
- for(int j = PositionsTotal()-1; j>=0; j--)
- {
- ulong ticket = PositionGetTicket(j);
- if(PositionSelectByTicket(ticket))
- {
- if(ticket == newTradeStore[i].buyTicket)
- {
- buyPresent = true;
- }
- if(ticket == newTradeStore[i].sellTicket)
- {
- sellPresent = true;
- }
- }
- }
- if(!buyPresent && !sellPresent)
- {
- Print("Buy ticket closed so removed from struct: ", newTradeStore[i].buyTicket);
- newTradeStore[i].buyTicket = -1;
- newTradeStore[i].buySymbol = "";
- Print("Sell ticket closed so removed from struct: ", newTradeStore[i].sellTicket);
- newTradeStore[i].sellTicket = -1;
- newTradeStore[i].sellSymbol = "";
- }
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool canTradeSymbol(string symbol1, string symbol2, ENUM_POSITION_TYPE type1, ENUM_POSITION_TYPE type2)
- {
- for(int i = 0; i < MaxOrders; i++)
- {
- if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
- {
- if(newTradeStore[i].buySymbol == symbol1 && newTradeStore[i].sellSymbol == symbol2)
- {
- if(type1 == POSITION_TYPE_BUY && type2 == POSITION_TYPE_SELL)
- {
- Print("Already Have Buy and Sell on this Pair");
- Print("----------- Symbol Buy: ", symbol1, " Symbol Sell: ", symbol2, " Buy Ticket: ", newTradeStore[i].buyTicket,
- " Sell Ticket: ", newTradeStore[i].sellTicket," ---------------");
- return false;
- }
- }
- }
- }
- return true;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool miniTimeBeforeClosing(ulong buyTicket, ulong sellTicket)
- {
- datetime currentTime = TimeCurrent();
- datetime buyTime = 0;
- datetime sellTime = 0;
- if(PositionSelectByTicket(buyTicket))
- {
- buyTime = (datetime)PositionGetInteger(POSITION_TIME);
- }
- if(PositionSelectByTicket(sellTicket))
- {
- sellTime = (datetime)PositionGetInteger(POSITION_TIME);
- }
- datetime comboOpenTime = (buyTime > sellTime) ? buyTime : sellTime;
- int secondsHeld = (int)(currentTime - comboOpenTime);
- if(secondsHeld >= miniHoldTimeSec)
- {
- Print("Minimum time REACHED (", secondsHeld, "s) ");
- return true;
- }
- else
- {
- int secondsRemaining = miniHoldTimeSec - secondsHeld;
- Print("Minimum time NOT reached (", secondsHeld, "/", miniHoldTimeSec, "s) ",
- secondsRemaining, "s remaining");
- return false;
- }
- }
- //+------------------------------------------------------------------+
- //+------------------------------------------------------------------+
|