Przeglądaj źródła

Ticket: 5131 Trade Placing and File Fetching Data Store

Huzaifa-MQLDev 4 miesięcy temu
rodzic
commit
a9d595ca2c
2 zmienionych plików z 452 dodań i 0 usunięć
  1. BIN
      vol_hedge_strategy_mt5.ex5
  2. 452 0
      vol_hedge_strategy_mt5.mq5

BIN
vol_hedge_strategy_mt5.ex5


+ 452 - 0
vol_hedge_strategy_mt5.mq5

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