Нема описа

vol_hedge_strategy_mt5.mq5 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. //+------------------------------------------------------------------+
  2. //| vol_hedge_strategy_mt5.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. #define MaxOrders 100
  10. #include <Trade\Trade.mqh>
  11. CTrade trade;
  12. //+------------------------------------------------------------------+
  13. //| Expert initialization function |
  14. //+------------------------------------------------------------------+
  15. struct new_trade_store
  16. {
  17. ulong buy_ticket; // Buy Ticket
  18. ulong sell_ticket; // Sell Ticket
  19. string symbol; // Symbol
  20. double price; // Price
  21. double stop_loss; // StopLoss
  22. double take_profit; // TakeProfit
  23. datetime start_time; // Start time
  24. datetime end_time; // End Time
  25. new_trade_store()
  26. {
  27. buy_ticket = -1;
  28. sell_ticket = -1;
  29. }
  30. };
  31. new_trade_store newTradeStore[MaxOrders];
  32. enum lotcalculator
  33. {
  34. fix, //Fixed Lot Size
  35. rsk, //Risk Percentage
  36. dollar, // Risk in Dollars
  37. };
  38. sinput string string_0 = "<><><><><><> General SETTINGS <><><><><><>"; //__
  39. input int magic_no = 333; // Magic no
  40. input string string_1 = "<><><><><><> Lot Management<><><><><><>"; //__
  41. input lotcalculator lot_calculator = fix; // Lot Size Option
  42. input double lot_amount = 0.1; // Lot Size
  43. input double risk = 0.5; // Risk in Percentage %
  44. input double dollars = 10; // Risk in GBP
  45. input string string_2 = "<><><><><><> Time Filter Setting <><><><><><> ";//_
  46. input bool enableTimeSession = false; // Enable Time Session
  47. input string start_time = "01:00"; // Start Session
  48. input string end_time = "23:59"; // End Session
  49. // Global Variables
  50. static double tickCurrentBid = 0;
  51. double tickPreviousBid = 0;
  52. static double tickCurrentAsk = 0;
  53. double tickPreviousAsk = 0;
  54. datetime startSessionTime, endSessionTime;
  55. //+------------------------------------------------------------------+
  56. //| |
  57. //+------------------------------------------------------------------+
  58. int OnInit()
  59. {
  60. //---
  61. Print(" OnInIt. ");
  62. trade.SetExpertMagicNumber(magic_no);
  63. trade.SetDeviationInPoints(10);
  64. trade.SetTypeFilling(ORDER_FILLING_IOC);
  65. trade.LogLevel(LOG_LEVEL_ALL);
  66. trade.SetAsyncMode(false);
  67. int filehandle = FileOpen("vol_hedge_data.csv", FILE_READ | FILE_CSV | FILE_COMMON | FILE_ANSI);
  68. if(filehandle != INVALID_HANDLE)
  69. {
  70. Print(" Valid Handler. ");
  71. while(!FileIsEnding(filehandle))
  72. {
  73. string orderToRead = FileReadString(filehandle);
  74. string orderData[];
  75. //Print("Data: ", OrderToRead);
  76. StringSplit(orderToRead, StringGetCharacter(",",0), orderData);
  77. Print("Array Size: ", ArraySize(orderData));
  78. Print(" Order is: ", orderToRead);
  79. for(int i = 0 ; i < ArraySize(orderData) ; i++)
  80. {
  81. Print(" Order Data: ", orderData[i], " i: ", i);
  82. }
  83. if(ArraySize(orderData) >= 6)
  84. {
  85. if(orderData[0] == Symbol())
  86. {
  87. // store into local variables first (trim if needed)
  88. ulong buy_ticket_local = (ulong)-1; // keep -1 as per your convention
  89. ulong sell_ticket_local = (ulong)-1;
  90. string symbol_local = orderData[0];
  91. double price_local = StringToDouble(orderData[1]);
  92. double sl_local = StringToDouble(orderData[2]);
  93. double tp_local = StringToDouble(orderData[3]);
  94. // if your CSV has extra fields (tp2,tp3, etc.) parse here as needed
  95. datetime start_local = StringToTime(orderData[4]);
  96. datetime end_local = StringToTime(orderData[5]);
  97. // OPTIONAL: only add when price == 0:
  98. // if(MathAbs(price_local) > 1e-9) { Print("Skipped: price != 0"); continue; }
  99. // call the single-responsibility function that writes into struct array
  100. addToNewTradeStore(buy_ticket_local, sell_ticket_local,
  101. symbol_local, price_local,
  102. sl_local, tp_local,
  103. start_local, end_local);
  104. }
  105. }
  106. }
  107. FileClose(filehandle);
  108. }
  109. else
  110. {
  111. Print(" InValid Handler. Error: ", GetLastError());
  112. }
  113. timeFilter(true,start_time, end_time, startSessionTime, endSessionTime);
  114. Print(" Session Start = ", startSessionTime, " Asian Session End = ", endSessionTime);
  115. //---
  116. return(INIT_SUCCEEDED);
  117. }
  118. //+------------------------------------------------------------------+
  119. //| Expert deinitialization function |
  120. //+------------------------------------------------------------------+
  121. void OnDeinit(const int reason)
  122. {
  123. //---
  124. }
  125. //+------------------------------------------------------------------+
  126. //| Expert tick function |
  127. //+------------------------------------------------------------------+
  128. void OnTick()
  129. {
  130. //---
  131. double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
  132. double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
  133. if(tickPreviousBid == 0 && tickCurrentBid == 0)
  134. {
  135. tickPreviousBid = Bid;
  136. tickCurrentBid = Bid;
  137. }
  138. else
  139. {
  140. tickPreviousBid = tickCurrentBid;
  141. tickCurrentBid = Bid;
  142. }
  143. if(tickPreviousAsk == 0 && tickCurrentAsk == 0)
  144. {
  145. tickPreviousAsk = Ask;
  146. tickCurrentAsk = Ask;
  147. }
  148. else
  149. {
  150. tickPreviousAsk = tickCurrentAsk;
  151. tickCurrentAsk = Ask;
  152. }
  153. // Print(" Time is: ", TimeCurrent());
  154. timeFilter(false,start_time, end_time, startSessionTime, endSessionTime);
  155. Comment(" Session Start = ", startSessionTime, " Asian Session End = ", endSessionTime);
  156. if((!enableTimeSession) || (enableTimeSession && TimeCurrent() >= startSessionTime && TimeCurrent() <= endSessionTime))
  157. {
  158. tradePlacingCheck();
  159. }
  160. }
  161. //+------------------------------------------------------------------+
  162. //+------------------------------------------------------------------+
  163. //| |
  164. //+------------------------------------------------------------------+
  165. void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket,
  166. string r_symbol, double r_price,
  167. double r_stop_loss, double r_take_profit,
  168. datetime r_start_time, datetime r_end_time)
  169. {
  170. for(int i = 0; i < MaxOrders; i++)
  171. {
  172. // treat slot as empty when both tickets are -1 (same convention as constructor)
  173. if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
  174. {
  175. newTradeStore[i].buy_ticket = r_buy_ticket;
  176. newTradeStore[i].sell_ticket = r_sell_ticket;
  177. newTradeStore[i].symbol = r_symbol;
  178. newTradeStore[i].price = r_price;
  179. newTradeStore[i].stop_loss = r_stop_loss;
  180. newTradeStore[i].take_profit = r_take_profit;
  181. newTradeStore[i].start_time = r_start_time;
  182. newTradeStore[i].end_time = r_end_time;
  183. Print("Stored -> idx: ", i,
  184. " | sym: ", newTradeStore[i].symbol,
  185. " | price: ", DoubleToString(newTradeStore[i].price, Digits()),
  186. " | sl: ", DoubleToString(newTradeStore[i].stop_loss, Digits()),
  187. " | tp: ", DoubleToString(newTradeStore[i].take_profit, Digits()),
  188. " | start: ", TimeToString(newTradeStore[i].start_time, TIME_DATE|TIME_SECONDS),
  189. " | end: ", TimeToString(newTradeStore[i].end_time, TIME_DATE|TIME_SECONDS));
  190. break;
  191. }
  192. }
  193. }
  194. //+------------------------------------------------------------------+
  195. //| |
  196. //+------------------------------------------------------------------+
  197. void tradePlacingCheck()
  198. {
  199. for(int i = 0; i < MaxOrders; i++)
  200. {
  201. if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
  202. {
  203. if(newTradeStore[i].price > 0)
  204. {
  205. double levelPriceIs = newTradeStore[i].price;
  206. if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
  207. (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
  208. {
  209. ulong buyTicket = placeBuyTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
  210. ulong sellTicket = 0; // placeSellTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
  211. newTradeStore[i].buy_ticket = buyTicket;
  212. newTradeStore[i].sell_ticket = sellTicket;
  213. }
  214. }
  215. }
  216. }
  217. }
  218. //+------------------------------------------------------------------+
  219. //| |
  220. //+------------------------------------------------------------------+
  221. ulong placeBuyTrade(double stoploss, double takeprofit)
  222. {
  223. double buySL = 0, buyTp=0;
  224. //openPrice = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  225. double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  226. double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  227. if(stoploss != 0)
  228. {
  229. buySL = Ask - (stoploss * Point());
  230. }
  231. if(takeprofit != 0)
  232. {
  233. buyTp = Ask + (takeprofit * Point());
  234. }
  235. double distance = MathAbs((Ask - buySL) / Point());
  236. if(trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,getLot(distance),Ask,buySL,buyTp,"Buy Trade Placed"))
  237. {
  238. Print("Buy Trade Placed: ",trade.ResultOrder());
  239. return trade.ResultOrder();
  240. }
  241. else
  242. {
  243. Print("Error in placing Buy: "+Symbol()+" ",GetLastError());
  244. return -1;
  245. }
  246. return -1;
  247. }
  248. //+------------------------------------------------------------------+
  249. //| |
  250. //+------------------------------------------------------------------+
  251. ulong placeSellTrade(double stoploss, double takeprofit)
  252. {
  253. double sellSL = 0, sellTp = 0;
  254. double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  255. double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  256. if(stoploss != 0)
  257. {
  258. sellSL = Bid + (stoploss * Point());
  259. }
  260. if(takeprofit != 0)
  261. {
  262. sellTp = Bid - (takeprofit * Point());
  263. }
  264. double distance = MathAbs((Bid - sellSL) / Point());
  265. if(trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,getLot(distance),Bid,sellSL,sellTp,"Sell Trade Placed"))
  266. {
  267. Print("Sell Trade PLaced: ",trade.ResultOrder());
  268. return trade.ResultOrder();
  269. }
  270. else
  271. {
  272. Print("Error in placing Sell: "+Symbol()+" ",GetLastError());
  273. return -1;
  274. }
  275. return -1;
  276. }
  277. //+------------------------------------------------------------------+
  278. //| |
  279. //+------------------------------------------------------------------+
  280. double getLot(double stop_loss)
  281. {
  282. Print("Tick Value: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE));
  283. Print("Tick Size: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE));
  284. double modeTickV=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)
  285. ,modeTickS=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE);
  286. // Print("Pip value: ", NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point))*10),2));
  287. double pipvalue = NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point()))*10),2);
  288. // pipvalue=NormalizeDouble((modeTickV/modeTickS/Point()),)
  289. // pipvalue=
  290. pipvalue = pipvalue / 10;
  291. double lotSize = lot_amount;
  292. if(lot_calculator == rsk || lot_calculator == dollar) //calculating risk
  293. {
  294. double riskamount = 0;
  295. if(lot_calculator == rsk)
  296. {
  297. riskamount = (risk/100)*AccountInfoDouble(ACCOUNT_BALANCE);
  298. }
  299. if(lot_calculator == dollar)
  300. {
  301. riskamount = dollars;
  302. }
  303. double pipvalue_required=riskamount/stop_loss;
  304. lotSize = pipvalue_required/pipvalue;
  305. //sl=riskamount/pipValuelot
  306. int roundDigit=0;
  307. double step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
  308. while(step<1)
  309. {
  310. roundDigit++;
  311. step=step*10;
  312. }
  313. Print("Round Digits:",roundDigit);
  314. lotSize = NormalizeDouble(lotSize,roundDigit);
  315. //
  316. }
  317. Print("Lot Size: ",lotSize);
  318. if(lotSize > SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX))
  319. {
  320. lotSize=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
  321. }
  322. else
  323. if(lotSize<SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN))
  324. {
  325. lotSize=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
  326. }
  327. //---
  328. return lotSize;
  329. }
  330. //+------------------------------------------------------------------+
  331. //| |
  332. //+------------------------------------------------------------------+
  333. void timeFilter(bool onInit,string startTime,string endTime,datetime & sessionStart,datetime & sessionEnd)
  334. {
  335. int newYorkStartHour = 0, newYorkStartMin = 0, newYorkEndHour = 0, newYorkEndMin = 0;
  336. datetime newYorkStartTrading,newYorkEndTrading;
  337. string time[];
  338. StringSplit(startTime,':',time);
  339. newYorkStartHour = (int)StringToInteger(time[0]);
  340. newYorkStartMin = (int)StringToInteger(time[1]);
  341. EventSetMillisecondTimer(500);
  342. time[0] = "";
  343. time[1] = "";
  344. StringSplit(endTime,':',time);
  345. newYorkEndHour = (int)StringToInteger(time[0]);
  346. newYorkEndMin = (int)StringToInteger(time[1]);
  347. // Print(" Start Time Hour: ",newYorkStartHour," Start Time Min: ",newYorkStartMin);
  348. // Print(" End Time Hour: ",newYorkEndHour," End Time Min: ",newYorkEndMin);
  349. datetime startDateTime;
  350. MqlDateTime st;
  351. TimeCurrent(st); // get current date
  352. st.hour = newYorkStartHour;
  353. st.min = newYorkStartMin;
  354. st.sec = 0;
  355. startDateTime = StructToTime(st);
  356. datetime endDateTime;
  357. MqlDateTime et;
  358. TimeCurrent(et); // get current date
  359. et.hour = newYorkEndHour;
  360. et.min = newYorkEndMin;
  361. et.sec = 0;
  362. endDateTime = StructToTime(et);
  363. MqlDateTime sdate,edate;
  364. datetime start_Time = 0, end_Time = 0;
  365. if(startDateTime > endDateTime)
  366. {
  367. if(onInit)
  368. {
  369. start_Time = iTime(Symbol(),PERIOD_D1,1);
  370. end_Time = iTime(Symbol(),PERIOD_D1,0);
  371. }
  372. else
  373. {
  374. start_Time = sessionStart;
  375. end_Time = sessionEnd;
  376. if(TimeCurrent() >= sessionEnd && sessionEnd != 0)
  377. {
  378. start_Time = iTime(Symbol(),PERIOD_D1,0);
  379. end_Time = start_Time + 86400;
  380. }
  381. }
  382. }
  383. else
  384. {
  385. start_Time = iTime(Symbol(),PERIOD_D1,0);
  386. end_Time = iTime(Symbol(),PERIOD_D1,0);
  387. }
  388. if(TimeToStruct(end_Time,edate))
  389. {
  390. edate.hour = newYorkEndHour;
  391. edate.min = newYorkEndMin;
  392. edate.sec = 0;
  393. }
  394. else
  395. Print("Error in Converting Time: ",GetLastError());
  396. newYorkEndTrading = StructToTime(edate);
  397. if(TimeToStruct(start_Time,sdate))
  398. {
  399. sdate.hour = newYorkStartHour;
  400. sdate.min = newYorkStartMin;
  401. sdate.sec = 0;
  402. }
  403. else
  404. Print("Error in Converting Time: ",GetLastError());
  405. newYorkStartTrading = StructToTime(sdate);
  406. sessionStart = newYorkStartTrading;
  407. sessionEnd = newYorkEndTrading;
  408. }
  409. //+------------------------------------------------------------------+
  410. //| |
  411. //+------------------------------------------------------------------+