Sen descrición

CribMarketEAV2.mq5 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 open positions
  31. string goldPairs[];
  32. int totalGoldPairs = 0;
  33. //+------------------------------------------------------------------+
  34. //| Expert initialization function |
  35. //+------------------------------------------------------------------+
  36. int OnInit()
  37. {
  38. //---
  39. trade.SetExpertMagicNumber(magicNo);
  40. trade.SetDeviationInPoints(10);
  41. trade.SetTypeFilling(ORDER_FILLING_IOC);
  42. trade.LogLevel(LOG_LEVEL_ALL);
  43. trade.SetAsyncMode(false);
  44. getSymbolsFromMarketWatch();
  45. // addToStructure(153718680, 153718681, "EURUSD", "XAUUSD.");
  46. //--- create timer
  47. EventSetMillisecondTimer(1000);
  48. //---
  49. return(INIT_SUCCEEDED);
  50. }
  51. //+------------------------------------------------------------------+
  52. //| Expert deinitialization function |
  53. //+------------------------------------------------------------------+
  54. void OnDeinit(const int reason)
  55. {
  56. //---
  57. EventKillTimer();
  58. }
  59. //+------------------------------------------------------------------+
  60. //| Expert tick function |
  61. //+------------------------------------------------------------------+
  62. void OnTick()
  63. {
  64. //---
  65. }
  66. //+------------------------------------------------------------------+
  67. //| |
  68. //+------------------------------------------------------------------+
  69. void OnTimer()
  70. {
  71. //---
  72. removeFromStruct();
  73. if(enableBasketTP == true)
  74. {
  75. checkBasketTakeProfit();
  76. }
  77. string symbolToBuy = getSymbolWithLowestAsk();
  78. string symbolToSell = getSymbolWithHighestBid();
  79. int buyTickett = -1, sellTickett = -1;
  80. //Print(" Symbol to Buy is: ", symbolToBuy, " Symbol to Sell: ", symbolToSell);
  81. if(canTradeSymbol(symbolToBuy, symbolToSell, POSITION_TYPE_BUY, POSITION_TYPE_SELL))
  82. {
  83. if(noOfActiveOrdersOfType(POSITION_TYPE_BUY) < maxOpenPositions)
  84. {
  85. if(symbolToBuy != NULL && symbolToBuy != "")
  86. {
  87. buyTickett = placeBuyTrade(symbolToBuy);
  88. }
  89. }
  90. if(noOfActiveOrdersOfType(POSITION_TYPE_SELL) < maxOpenPositions)
  91. {
  92. if(symbolToSell != NULL && symbolToSell != "")
  93. {
  94. sellTickett = placeSellTrade(symbolToSell);
  95. }
  96. }
  97. }
  98. if(buyTickett != -1 && sellTickett != -1)
  99. {
  100. addToStructure(buyTickett, sellTickett, symbolToBuy, symbolToSell);
  101. }
  102. }
  103. //+------------------------------------------------------------------+
  104. //| |
  105. //+------------------------------------------------------------------+
  106. bool newBar()
  107. {
  108. static datetime lastbar;
  109. datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0);
  110. if(lastbar != curbar)
  111. {
  112. lastbar = curbar;
  113. Print(" ---------------------- New Bar :: ---------------------- ",lastbar);
  114. return (true);
  115. }
  116. else
  117. {
  118. return (false);
  119. }
  120. }
  121. //+------------------------------------------------------------------+
  122. //| |
  123. //+------------------------------------------------------------------+
  124. int placeBuyTrade(string symbol)
  125. {
  126. double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
  127. double buySL = 0, buyTP = 0;
  128. if(trade.PositionOpen(symbol, ORDER_TYPE_BUY, lotSize, ask, buySL, buyTP, "Buy Trade Placed"))
  129. {
  130. Print("Buy Trade Placed on ", symbol, ": ", trade.ResultOrder());
  131. return (int)trade.ResultOrder();
  132. }
  133. else
  134. {
  135. Print("Error in placing Buy on ", symbol, ": ", GetLastError());
  136. }
  137. return 0;
  138. }
  139. //+------------------------------------------------------------------+
  140. //| |
  141. //+------------------------------------------------------------------+
  142. int placeSellTrade(string symbol)
  143. {
  144. double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
  145. double sellSL = 0, sellTP = 0;
  146. if(trade.PositionOpen(symbol, ORDER_TYPE_SELL, lotSize, bid, sellSL, sellTP, "Sell Trade Placed"))
  147. {
  148. Print("Sell Trade Placed on ", symbol, ": ", trade.ResultOrder());
  149. return (int)trade.ResultOrder();
  150. }
  151. else
  152. {
  153. Print("Error in placing Sell on ", symbol, ": ", GetLastError());
  154. }
  155. return 0;
  156. }
  157. //+------------------------------------------------------------------+
  158. //| |
  159. //+------------------------------------------------------------------+
  160. void getSymbolsFromMarketWatch()
  161. {
  162. int totalSymbols = SymbolsTotal(true);
  163. ArrayResize(goldPairs, 0);
  164. totalGoldPairs = 0;
  165. for(int i = 0; i < totalSymbols; i++)
  166. {
  167. string symbolName = SymbolName(i, true);
  168. //if(StringFind(symbolName, "GOLD") != -1 || StringFind(symbolName, "XAU") != -1)
  169. {
  170. ArrayResize(goldPairs, totalGoldPairs + 1);
  171. if(totalGoldPairs < ArraySize(goldPairs))
  172. {
  173. goldPairs[totalGoldPairs] = symbolName;
  174. totalGoldPairs++;
  175. }
  176. else
  177. {
  178. Print("Error: Array resize failed for symbol ", symbolName);
  179. }
  180. }
  181. }
  182. Print("Found ", totalGoldPairs, " Symbol pairs in Market Watch");
  183. }
  184. //+------------------------------------------------------------------+
  185. //| |
  186. //+------------------------------------------------------------------+
  187. string getSymbolWithLowestAsk()
  188. {
  189. if(totalGoldPairs == 0)
  190. return NULL;
  191. string lowestSymbol = "";
  192. //double lowestAsk = INT_MAX; // SymbolInfoDouble(lowestSymbol, SYMBOL_ASK);
  193. double lowestAsk = DBL_MAX;
  194. for(int i = 0; i < totalGoldPairs; i++)
  195. {
  196. double currentAsk = SymbolInfoDouble(goldPairs[i], SYMBOL_ASK);
  197. Print("Pair:",goldPairs[i]," Price Ask:",currentAsk);
  198. if(currentAsk < lowestAsk)
  199. {
  200. lowestAsk = currentAsk;
  201. lowestSymbol = goldPairs[i];
  202. }
  203. }
  204. Print("Lowest Ask Pair: ", lowestSymbol, " Lowest Ask: ", lowestAsk);
  205. return lowestSymbol;
  206. }
  207. //+------------------------------------------------------------------+
  208. //| |
  209. //+------------------------------------------------------------------+
  210. string getSymbolWithHighestBid()
  211. {
  212. if(totalGoldPairs == 0)
  213. return NULL;
  214. string highestSymbol = "";
  215. //double highestBid = INT_MIN; // SymbolInfoDouble(highestSymbol, SYMBOL_BID);
  216. double highestBid = 0;
  217. for(int i = 0; i < totalGoldPairs; i++)
  218. {
  219. double currentBid = SymbolInfoDouble(goldPairs[i], SYMBOL_BID);
  220. Print("Pair:",goldPairs[i]," Price Bid:",currentBid);
  221. if(currentBid > highestBid)
  222. {
  223. highestBid = currentBid;
  224. highestSymbol = goldPairs[i];
  225. }
  226. }
  227. Print("Highest Bid Pair: ", highestSymbol, " Highest Bid: ", highestBid);
  228. return highestSymbol;
  229. }
  230. //+------------------------------------------------------------------+
  231. //| |
  232. //+------------------------------------------------------------------+
  233. int noOfActiveOrdersOfType(ENUM_POSITION_TYPE type)
  234. {
  235. int count = 0;
  236. for(int i= PositionsTotal()-1; i>=0; i--)
  237. {
  238. ulong ticket = PositionGetTicket(i);
  239. if(PositionSelectByTicket(ticket))
  240. {
  241. if(PositionGetInteger(POSITION_MAGIC) == magicNo
  242. && (PositionGetInteger(POSITION_TYPE) == type)
  243. && isGoldPair(PositionGetString(POSITION_SYMBOL)))
  244. {
  245. count++;
  246. }
  247. }
  248. }
  249. return count;
  250. }
  251. //+------------------------------------------------------------------+
  252. //| |
  253. //+------------------------------------------------------------------+
  254. void checkBasketTakeProfit()
  255. {
  256. double netProfit = 0;
  257. for(int i = PositionsTotal() - 1; i >= 0; i--)
  258. {
  259. ulong ticket = PositionGetTicket(i);
  260. if(PositionSelectByTicket(ticket))
  261. {
  262. if(isGoldPair(PositionGetString(POSITION_SYMBOL)) &&
  263. PositionGetInteger(POSITION_MAGIC) == magicNo)
  264. {
  265. netProfit += PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
  266. }
  267. }
  268. }
  269. if(netProfit >= basketTakeProfit)
  270. {
  271. Print("Basket TP hit: Closing all trades. Profit = ", netProfit);
  272. closeAllActiveOrders();
  273. }
  274. }
  275. //+------------------------------------------------------------------+
  276. //| |
  277. //+------------------------------------------------------------------+
  278. void closeAllActiveOrders()
  279. {
  280. for(int i=PositionsTotal()-1; i >=0 ; i--)
  281. {
  282. ulong ticket = PositionGetTicket(i);
  283. if(PositionSelectByTicket(ticket))
  284. {
  285. if(PositionGetInteger(POSITION_MAGIC) == magicNo &&
  286. isGoldPair(PositionGetString(POSITION_SYMBOL)))
  287. {
  288. if(trade.PositionClose(ticket))
  289. {
  290. Print("Position closed ", ticket);
  291. }
  292. else
  293. {
  294. Print("Cannot close order: ",GetLastError());
  295. }
  296. }
  297. }
  298. }
  299. }
  300. //+------------------------------------------------------------------+
  301. //| |
  302. //+------------------------------------------------------------------+
  303. bool isGoldPair(string symbol)
  304. {
  305. for(int i = 0; i < totalGoldPairs; i++)
  306. {
  307. //Print("Total Gold pairs: ", totalGoldPairs, " Array: ", goldPairs[i], " Symbol: ", symbol);
  308. if(goldPairs[i] == symbol)
  309. return true;
  310. }
  311. return false;
  312. }
  313. //+------------------------------------------------------------------+
  314. //| |
  315. //+------------------------------------------------------------------+
  316. void addToStructure(ulong r_buyTicket,ulong r_sellTicket, string r_buySymbol, string r_sellSymbol)
  317. {
  318. for(int i=0; i<MaxOrders; i++)
  319. {
  320. if(newTradeStore[i].buyTicket==-1 && newTradeStore[i].sellTicket==-1)
  321. {
  322. newTradeStore[i].buyTicket = r_buyTicket;
  323. newTradeStore[i].sellTicket = r_sellTicket;
  324. newTradeStore[i].buySymbol = r_buySymbol;
  325. newTradeStore[i].sellSymbol = r_sellSymbol;
  326. Print("Stored new ticket in structure. Buy Ticket: ", newTradeStore[i].buyTicket, " Sell Ticket: ", newTradeStore[i].sellTicket,
  327. " Buy Symbol: ", newTradeStore[i].buySymbol, " Sell Symbol: ", newTradeStore[i].sellSymbol);
  328. break;
  329. }
  330. }
  331. }
  332. //+------------------------------------------------------------------+
  333. //| |
  334. //+------------------------------------------------------------------+
  335. void removeFromStruct()
  336. {
  337. for(int i = 0 ; i < MaxOrders ; i++)
  338. {
  339. bool buyPresent = false;
  340. bool sellPresent = false;
  341. if(newTradeStore[i].buyTicket !=-1 && newTradeStore[i].sellTicket !=-1)
  342. {
  343. for(int j = PositionsTotal()-1; j>=0; j--)
  344. {
  345. ulong ticket = PositionGetTicket(j);
  346. if(PositionSelectByTicket(ticket))
  347. {
  348. if(ticket == newTradeStore[i].buyTicket)
  349. {
  350. buyPresent = true;
  351. }
  352. if(ticket == newTradeStore[i].sellTicket)
  353. {
  354. sellPresent = true;
  355. }
  356. }
  357. }
  358. if(!buyPresent && !sellPresent)
  359. {
  360. Print("Buy ticket closed so removed from struct: ", newTradeStore[i].buyTicket);
  361. newTradeStore[i].buyTicket = -1;
  362. newTradeStore[i].buySymbol = "";
  363. Print("Sell ticket closed so removed from struct: ", newTradeStore[i].sellTicket);
  364. newTradeStore[i].sellTicket = -1;
  365. newTradeStore[i].sellSymbol = "";
  366. }
  367. }
  368. }
  369. }
  370. //+------------------------------------------------------------------+
  371. //| |
  372. //+------------------------------------------------------------------+
  373. bool canTradeSymbol(string symbol1, string symbol2, ENUM_POSITION_TYPE type1, ENUM_POSITION_TYPE type2)
  374. {
  375. for(int i = 0; i < MaxOrders; i++)
  376. {
  377. if(newTradeStore[i].buyTicket != -1 && newTradeStore[i].sellTicket != -1)
  378. {
  379. if(newTradeStore[i].buySymbol == symbol1 && newTradeStore[i].sellSymbol == symbol2)
  380. {
  381. if(type1 == POSITION_TYPE_BUY && type2 == POSITION_TYPE_SELL)
  382. {
  383. Print("Already Have Buy and Sell on this Pair");
  384. Print("----------- Symbol Buy: ", symbol1, " Symbol Sell: ", symbol2, " Buy Ticket: ", newTradeStore[i].buyTicket,
  385. " Sell Ticket: ", newTradeStore[i].sellTicket," ---------------");
  386. return false;
  387. }
  388. }
  389. }
  390. }
  391. return true;
  392. }
  393. //+------------------------------------------------------------------+
  394. //| |
  395. //+------------------------------------------------------------------+
  396. //+------------------------------------------------------------------+