Ingen beskrivning

CribMarketEAV2.mq5 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. //+------------------------------------------------------------------+
  2. //| CribMarketEA.mq5 |
  3. //| Copyright 2025, MQL Development |
  4. //| https://www.mqldevelopment.com/ |
  5. //+------------------------------------------------------------------+
  6. #property copyright "Copyright 2025, MQL Development"
  7. #property link "https://www.mqldevelopment.com/"
  8. #property version "1.00"
  9. #include <Trade\Trade.mqh>
  10. CTrade trade;
  11. #define MaxOrders 10000
  12. struct new_trade_store
  13. {
  14. ulong buyTicket; // Buy Ticket
  15. ulong sellTicket; // Sell Ticket
  16. string buySymbol; // Buy Symbol Name
  17. string sellSymbol; // Sell Symbol Name
  18. new_trade_store()
  19. {
  20. buyTicket = -1;
  21. sellTicket = -1;
  22. }
  23. };
  24. new_trade_store newTradeStore[MaxOrders];
  25. input string Settings = " ------------- General Settings ------------- "; //_
  26. input int magicNo = 333; // Magic no
  27. input double lotSize = 0.01; // Lot Size
  28. input bool enableBasketTP = true; // Enable Basket TP
  29. input double basketTakeProfit = 1.0; // Basket Take Profit
  30. input int maxOpenPositions = 3; // Maximum number of Combinations
  31. input int miniHoldTimeSec = 120; // Mini time in (seconds) to hold trades closing before checking TP
  32. string goldPairs[];
  33. int totalGoldPairs = 0;
  34. int timer = 0;
  35. //+------------------------------------------------------------------+
  36. //| Expert initialization function |
  37. //+------------------------------------------------------------------+
  38. int OnInit()
  39. {
  40. //---
  41. trade.SetExpertMagicNumber(magicNo);
  42. trade.SetDeviationInPoints(10);
  43. trade.SetTypeFilling(ORDER_FILLING_IOC);
  44. trade.LogLevel(LOG_LEVEL_ALL);
  45. trade.SetAsyncMode(false);
  46. getSymbolsFromMarketWatch();
  47. // addToStructure(153718680, 153718681, "EURUSD", "XAUUSD.");
  48. //--- create timer
  49. EventSetMillisecondTimer(1000);
  50. //---
  51. return(INIT_SUCCEEDED);
  52. }
  53. //+------------------------------------------------------------------+
  54. //| Expert deinitialization function |
  55. //+------------------------------------------------------------------+
  56. void OnDeinit(const int reason)
  57. {
  58. //---
  59. EventKillTimer();
  60. }
  61. //+------------------------------------------------------------------+
  62. //| Expert tick function |
  63. //+------------------------------------------------------------------+
  64. void OnTick()
  65. {
  66. //---
  67. }
  68. //+------------------------------------------------------------------+
  69. //| |
  70. //+------------------------------------------------------------------+
  71. void OnTimer()
  72. {
  73. //---
  74. timer++;
  75. Print("<><><><><><><> Timer Start: ",timer," <><><><><><><>");
  76. removeFromStruct();
  77. if(enableBasketTP == true)
  78. {
  79. checkBasketTakeProfit();
  80. }
  81. string symbolToBuy = getSymbolWithLowestAsk();
  82. string symbolToSell = getSymbolWithHighestBid();
  83. int buyTickett = -1, sellTickett = -1;
  84. //Print(" Symbol to Buy is: ", symbolToBuy, " Symbol to Sell: ", symbolToSell);
  85. if(noOfActiveCombinations() < maxOpenPositions)
  86. {
  87. if(canTradeSymbol(symbolToBuy, symbolToSell, POSITION_TYPE_BUY, POSITION_TYPE_SELL))
  88. {
  89. if(symbolToBuy != symbolToSell)
  90. {
  91. if(symbolToBuy != NULL && symbolToBuy != "")
  92. {
  93. buyTickett = placeBuyTrade(symbolToBuy);
  94. }
  95. if(symbolToSell != NULL && symbolToSell != "")
  96. {
  97. sellTickett = placeSellTrade(symbolToSell);
  98. }
  99. }
  100. }
  101. }
  102. if(buyTickett != -1 && sellTickett != -1)
  103. {
  104. addToStructure(buyTickett, sellTickett, symbolToBuy, symbolToSell);
  105. }
  106. Print("<><><><><><><> Timer End: ",timer," <><><><><><><>");
  107. }
  108. //+------------------------------------------------------------------+
  109. //| |
  110. //+------------------------------------------------------------------+
  111. bool newBar()
  112. {
  113. static datetime lastbar;
  114. datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0);
  115. if(lastbar != curbar)
  116. {
  117. lastbar = curbar;
  118. Print(" ---------------------- New Bar :: ---------------------- ",lastbar);
  119. return (true);
  120. }
  121. else
  122. {
  123. return (false);
  124. }
  125. }
  126. //+------------------------------------------------------------------+
  127. //| |
  128. //+------------------------------------------------------------------+
  129. int placeBuyTrade(string symbol)
  130. {
  131. double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
  132. double buySL = 0, buyTP = 0;
  133. int count=noOfActiveCombinations()+1;
  134. if(trade.PositionOpen(symbol, ORDER_TYPE_BUY, lotSize, ask, buySL, buyTP, "Buy Trade Placed # "+(string)timer))
  135. {
  136. Print("Buy Trade Placed on ", symbol, ": ", trade.ResultOrder());
  137. return (int)trade.ResultOrder();
  138. }
  139. else
  140. {
  141. Print("Error in placing Buy on ", symbol, ": ", GetLastError());
  142. }
  143. return 0;
  144. }
  145. //+------------------------------------------------------------------+
  146. //| |
  147. //+------------------------------------------------------------------+
  148. int placeSellTrade(string symbol)
  149. {
  150. double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
  151. double sellSL = 0, sellTP = 0;
  152. int count=noOfActiveCombinations()+1;
  153. if(trade.PositionOpen(symbol, ORDER_TYPE_SELL, lotSize, bid, sellSL, sellTP, "Sell Trade Placed # "+(string)timer))
  154. {
  155. Print("Sell Trade Placed on ", symbol, ": ", trade.ResultOrder());
  156. return (int)trade.ResultOrder();
  157. }
  158. else
  159. {
  160. Print("Error in placing Sell on ", symbol, ": ", GetLastError());
  161. }
  162. return 0;
  163. }
  164. //+------------------------------------------------------------------+
  165. //| |
  166. //+------------------------------------------------------------------+
  167. void getSymbolsFromMarketWatch()
  168. {
  169. int totalSymbols = SymbolsTotal(true);
  170. ArrayResize(goldPairs, 0);
  171. totalGoldPairs = 0;
  172. for(int i = 0; i < totalSymbols; i++)
  173. {
  174. string symbolName = SymbolName(i, true);
  175. //if(StringFind(symbolName, "GOLD") != -1 || StringFind(symbolName, "XAU") != -1)
  176. if(symbolName!="XAUUSD#")
  177. {
  178. ArrayResize(goldPairs, totalGoldPairs + 1);
  179. if(totalGoldPairs < ArraySize(goldPairs))
  180. {
  181. goldPairs[totalGoldPairs] = symbolName;
  182. totalGoldPairs++;
  183. }
  184. else
  185. {
  186. Print("Error: Array resize failed for symbol ", symbolName);
  187. }
  188. }
  189. }
  190. Print("Found ", totalGoldPairs, " Symbol pairs in Market Watch");
  191. }
  192. //+------------------------------------------------------------------+
  193. //| |
  194. //+------------------------------------------------------------------+
  195. string getSymbolWithLowestAsk()
  196. {
  197. if(totalGoldPairs == 0)
  198. return NULL;
  199. string lowestSymbol = "";
  200. //double lowestAsk = INT_MAX; // SymbolInfoDouble(lowestSymbol, SYMBOL_ASK);
  201. double lowestAsk = DBL_MAX;
  202. for(int i = 0; i < totalGoldPairs; i++)
  203. {
  204. double currentAsk = SymbolInfoDouble(goldPairs[i], SYMBOL_ASK);
  205. Print(" Ask Price: ",currentAsk," || on Pair: ",goldPairs[i]);
  206. if(currentAsk < lowestAsk)
  207. {
  208. lowestAsk = currentAsk;
  209. lowestSymbol = goldPairs[i];
  210. }
  211. }
  212. Print("Lowest Ask Pair: ", lowestSymbol, " || Lowest Ask: ", lowestAsk);
  213. return lowestSymbol;
  214. }
  215. //+------------------------------------------------------------------+
  216. //| |
  217. //+------------------------------------------------------------------+
  218. string getSymbolWithHighestBid()
  219. {
  220. if(totalGoldPairs == 0)
  221. return NULL;
  222. string highestSymbol = "";
  223. //double highestBid = INT_MIN; // SymbolInfoDouble(highestSymbol, SYMBOL_BID);
  224. double highestBid = 0;
  225. for(int i = 0; i < totalGoldPairs; i++)
  226. {
  227. double currentBid = SymbolInfoDouble(goldPairs[i], SYMBOL_BID);
  228. Print(" Bid Price: ",currentBid," || on Pair: ",goldPairs[i]);
  229. if(currentBid > highestBid)
  230. {
  231. highestBid = currentBid;
  232. highestSymbol = goldPairs[i];
  233. }
  234. }
  235. Print("Highest Bid Pair: ", highestSymbol, " || Highest Bid: ", highestBid);
  236. return highestSymbol;
  237. }
  238. //+------------------------------------------------------------------+
  239. //| |
  240. //+------------------------------------------------------------------+
  241. int noOfActiveCombinations()
  242. {
  243. int count = 0;
  244. for(int i = 0; i < MaxOrders; i++)
  245. {
  246. if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
  247. {
  248. count++;
  249. }
  250. }
  251. return count;
  252. }
  253. //+------------------------------------------------------------------+
  254. //| |
  255. //+------------------------------------------------------------------+
  256. void checkBasketTakeProfit()
  257. {
  258. for(int i = 0; i < MaxOrders; i++)
  259. {
  260. if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
  261. {
  262. if(miniTimeBeforeClosing(newTradeStore[i].buyTicket, newTradeStore[i].sellTicket))
  263. {
  264. double combinationProfit = 0;
  265. if(PositionSelectByTicket(newTradeStore[i].buyTicket))
  266. {
  267. Print("Ticket:",newTradeStore[i].buyTicket);
  268. Print("Profit:",PositionGetDouble(POSITION_PROFIT), " Swap:",PositionGetDouble(POSITION_SWAP));
  269. combinationProfit += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP) ;
  270. }
  271. if(PositionSelectByTicket(newTradeStore[i].sellTicket))
  272. {
  273. Print("Ticket:",newTradeStore[i].sellTicket);
  274. Print("Profit:",PositionGetDouble(POSITION_PROFIT), " Swap:",PositionGetDouble(POSITION_SWAP));
  275. combinationProfit += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
  276. }
  277. if(combinationProfit >= basketTakeProfit)
  278. {
  279. Print("Combination TP hit: Closing trades. Profit = ", combinationProfit);
  280. if(!trade.PositionClose(newTradeStore[i].buyTicket))
  281. {
  282. Print(" Error Closing Buy Trade : ", newTradeStore[i].buyTicket," ",GetLastError());
  283. }
  284. else
  285. Print("Buy Trade Closed: ", newTradeStore[i].buyTicket);
  286. if(!trade.PositionClose(newTradeStore[i].sellTicket))
  287. {
  288. Print(" Error Closing Sell Trade : ", newTradeStore[i].sellTicket," ",GetLastError());
  289. }
  290. else
  291. Print("Sell Trade Closed: ", newTradeStore[i].sellTicket);
  292. }
  293. }
  294. }
  295. }
  296. }
  297. //+------------------------------------------------------------------+
  298. //| |
  299. //+------------------------------------------------------------------+
  300. bool isGoldPair(string symbol)
  301. {
  302. for(int i = 0; i < totalGoldPairs; i++)
  303. {
  304. //Print("Total Gold pairs: ", totalGoldPairs, " Array: ", goldPairs[i], " Symbol: ", symbol);
  305. if(goldPairs[i] == symbol)
  306. return true;
  307. }
  308. return false;
  309. }
  310. //+------------------------------------------------------------------+
  311. //| |
  312. //+------------------------------------------------------------------+
  313. void addToStructure(ulong r_buyTicket,ulong r_sellTicket, string r_buySymbol, string r_sellSymbol)
  314. {
  315. for(int i=0; i<MaxOrders; i++)
  316. {
  317. if(newTradeStore[i].buyTicket==-1 && newTradeStore[i].sellTicket==-1)
  318. {
  319. newTradeStore[i].buyTicket = r_buyTicket;
  320. newTradeStore[i].sellTicket = r_sellTicket;
  321. newTradeStore[i].buySymbol = r_buySymbol;
  322. newTradeStore[i].sellSymbol = r_sellSymbol;
  323. Print("Stored new ticket in structure. Buy Ticket: ", newTradeStore[i].buyTicket, " Sell Ticket: ", newTradeStore[i].sellTicket,
  324. " Buy Symbol: ", newTradeStore[i].buySymbol, " Sell Symbol: ", newTradeStore[i].sellSymbol);
  325. break;
  326. }
  327. }
  328. }
  329. //+------------------------------------------------------------------+
  330. //| |
  331. //+------------------------------------------------------------------+
  332. void removeFromStruct()
  333. {
  334. for(int i = 0 ; i < MaxOrders ; i++)
  335. {
  336. bool buyPresent = false;
  337. bool sellPresent = false;
  338. if(newTradeStore[i].buyTicket !=-1 && newTradeStore[i].sellTicket !=-1)
  339. {
  340. for(int j = PositionsTotal()-1; j>=0; j--)
  341. {
  342. ulong ticket = PositionGetTicket(j);
  343. if(PositionSelectByTicket(ticket))
  344. {
  345. if(ticket == newTradeStore[i].buyTicket)
  346. {
  347. buyPresent = true;
  348. }
  349. if(ticket == newTradeStore[i].sellTicket)
  350. {
  351. sellPresent = true;
  352. }
  353. }
  354. }
  355. if(!buyPresent && !sellPresent)
  356. {
  357. Print("Buy ticket closed so removed from struct: ", newTradeStore[i].buyTicket);
  358. newTradeStore[i].buyTicket = -1;
  359. newTradeStore[i].buySymbol = "";
  360. Print("Sell ticket closed so removed from struct: ", newTradeStore[i].sellTicket);
  361. newTradeStore[i].sellTicket = -1;
  362. newTradeStore[i].sellSymbol = "";
  363. }
  364. }
  365. }
  366. }
  367. //+------------------------------------------------------------------+
  368. //| |
  369. //+------------------------------------------------------------------+
  370. bool canTradeSymbol(string symbol1, string symbol2, ENUM_POSITION_TYPE type1, ENUM_POSITION_TYPE type2)
  371. {
  372. for(int i = 0; i < MaxOrders; i++)
  373. {
  374. if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
  375. {
  376. if(newTradeStore[i].buySymbol == symbol1 && newTradeStore[i].sellSymbol == symbol2)
  377. {
  378. if(type1 == POSITION_TYPE_BUY && type2 == POSITION_TYPE_SELL)
  379. {
  380. Print("Already Have Buy and Sell on this Pair");
  381. Print("----------- Symbol Buy: ", symbol1, " Symbol Sell: ", symbol2, " Buy Ticket: ", newTradeStore[i].buyTicket,
  382. " Sell Ticket: ", newTradeStore[i].sellTicket," ---------------");
  383. return false;
  384. }
  385. }
  386. }
  387. }
  388. return true;
  389. }
  390. //+------------------------------------------------------------------+
  391. //| |
  392. //+------------------------------------------------------------------+
  393. bool miniTimeBeforeClosing(ulong buyTicket, ulong sellTicket)
  394. {
  395. datetime currentTime = TimeCurrent();
  396. datetime buyTime = 0;
  397. datetime sellTime = 0;
  398. if(PositionSelectByTicket(buyTicket))
  399. {
  400. buyTime = (datetime)PositionGetInteger(POSITION_TIME);
  401. }
  402. if(PositionSelectByTicket(sellTicket))
  403. {
  404. sellTime = (datetime)PositionGetInteger(POSITION_TIME);
  405. }
  406. datetime comboOpenTime = (buyTime > sellTime) ? buyTime : sellTime;
  407. int secondsHeld = (int)(currentTime - comboOpenTime);
  408. if(secondsHeld >= miniHoldTimeSec)
  409. {
  410. Print("Minimum time REACHED (", secondsHeld, "s) ");
  411. return true;
  412. }
  413. else
  414. {
  415. int secondsRemaining = miniHoldTimeSec - secondsHeld;
  416. Print("Minimum time NOT reached (", secondsHeld, "/", miniHoldTimeSec, "s) ",
  417. secondsRemaining, "s remaining");
  418. return false;
  419. }
  420. }
  421. //+------------------------------------------------------------------+
  422. //+------------------------------------------------------------------+