Bez popisu

vol_hedge_strategy_mt5_v2.mq5 127KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588
  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.20"
  9. #define MaxOrders 100
  10. #include <Trade\Trade.mqh>
  11. CTrade trade;
  12. //+------------------------------------------------------------------+
  13. //| Expert initialization function |
  14. //+------------------------------------------------------------------+
  15. enum selectDay
  16. {
  17. prev, // Previous Day
  18. curr, // Current Day
  19. };
  20. struct new_trade_store
  21. {
  22. ulong buy_ticket; // Buy Ticket
  23. ulong sell_ticket; // Sell Ticket
  24. string symbol; // Symbol
  25. double price; // Price
  26. double stop_loss_buy; // StopLoss Buy
  27. double take_profit_buy; // TakeProfit Buy
  28. double stop_loss_sell; // StopLoss Sell
  29. double take_profit_sell; // TakeProfit Sell
  30. datetime start_time; // Start time
  31. datetime end_time; // End Time
  32. bool demand_level_hit; // Demand Level Hit
  33. bool buy_hit_virtual_sl; // Buy Hit Virtual StopLoss
  34. bool sell_hit_virtual_sl; // Sell Hit Virtual StopLoss
  35. new_trade_store()
  36. {
  37. buy_ticket = -1;
  38. sell_ticket = -1;
  39. price = 0;
  40. demand_level_hit = false;
  41. buy_hit_virtual_sl = false;
  42. sell_hit_virtual_sl = false;
  43. }
  44. };
  45. new_trade_store newTradeStore[MaxOrders];
  46. enum lotcalculator
  47. {
  48. fix, //Fixed Lot Size
  49. rsk, //Risk in Percentage
  50. dollar, // Risk in Dollars
  51. };
  52. sinput string string_0 = "<><><><><><> General SETTINGS <><><><><><>"; //__
  53. input string tempString = "Enter your text"; // Preset Name
  54. input int magic_no = 333; // Magic no
  55. input bool useTpSlPips = false; // Use Relative Tp/Sl in Points
  56. input double stopLoss = 1000; // Fixed Stop Loss in Points
  57. input double takeProfit = 1000; // Fixed Take Profit in Points
  58. input bool bothHitsSl = false; // Enable Topped & Tailed Pre-Demand Level
  59. input int maxTrades = 2; // Max Concurrent Trades
  60. input int maxSlippage = 5; // Max Slippage (Points)
  61. input bool enableSpreadFilter = false; // Enable Spread Filter
  62. input double maximumSpread = 10; // Maximum Spread (Points)
  63. input string tradeComment = "Trade Placed"; // Trade Comment Prefix
  64. input string dataFileName = "vol_hedge_data.csv"; // CSV File Name
  65. input bool enableDrawLevels = false; // Draw Levels
  66. input string string_1 = "<><><><><><> Lot Management<><><><><><>"; //__
  67. input lotcalculator lot_calculator = fix; // Lot Size Option
  68. input double lot_amount = 0.1; // Lot Size
  69. input double risk = 0.5; // Risk in Percentage %
  70. input double dollars = 10; // Risk in GBP
  71. input string time_setting = "<><><><><> Time Filter Settings <><><><><>"; //_
  72. input bool enableTimeFilter = false; // Enable Time Filter
  73. input string startTime = "03:00"; // Start Time Session
  74. input string endTime = "09:00"; // End Time Session
  75. input string weekFilterSettings = "<><><><><> Week Filter Settings <><><><><>"; //_
  76. input bool enableWeekFilter = false; // Enable Week Filter (true/false)
  77. input int filterMonthNumber = 9; // Month number to apply week filter (1..12)
  78. input int filterWeekNumber = 2; // Week number of month to block (1..5)
  79. input string monthFilterSettings = "<><><><><> Month Filter Settings <><><><><>"; //_
  80. input bool allowJanuary = true; // Allow Trading in January
  81. input bool allowFebruary = true; // Allow Trading in February
  82. input bool allowMarch = true; // Allow Trading in March
  83. input bool allowApril = true; // Allow Trading in April
  84. input bool allowMay = true; // Allow Trading in May
  85. input bool allowJune = true; // Allow Trading in June
  86. input bool allowJuly = true; // Allow Trading in July
  87. input bool allowAugust = true; // Allow Trading in August
  88. input bool allowSeptember = true; // Allow Trading in September
  89. input bool allowOctober = true; // Allow Trading in October
  90. input bool allowNovember = true; // Allow Trading in November
  91. input bool allowDecember = true; // Allow Trading in December
  92. input string string_0_2 = "<><><><><><> Trailing Setting<><><><><><>"; //__
  93. input bool indivial_trailing = false; // Indiviual Trailing
  94. input double ts_sl = 150; // Trailing Start in Points
  95. input double ts = 50; // Trailing Stop in Points
  96. input string strMA14 ="<><><><><><> BreakEven Settings <><><><><><>";//_
  97. input bool UseBreakEven = false; // Use Break Even
  98. input int breakEvenPoints = 150; // BreakEven Trigger Points
  99. input int breakStopPoint = 50; // BreakEven Above OpenPrice Points
  100. // Global Variables
  101. static double tickCurrentBid = 0;
  102. double tickPreviousBid = 0;
  103. static double tickCurrentAsk = 0;
  104. double tickPreviousAsk = 0;
  105. int newYorkStartTime = 0, newYorkStartMin = 0, newYorkEndHour = 0, newYorkEndMin = 0;
  106. datetime newYorkStartTrading = 0, newYorkEndTrading = 0;
  107. int GMT_Broker_Time = +2; // GMT_Broker_Time Time of your Broker
  108. int gmt = 0; // GMT_Broker_Time Time of your Broker
  109. double levelsAre[];
  110. selectDay newYorkSessionDay = curr; // Select Day for Start Time
  111. //+------------------------------------------------------------------+
  112. //| |
  113. //+------------------------------------------------------------------+
  114. int OnInit()
  115. {
  116. //---
  117. Print(" OnInIt. ");
  118. trade.SetExpertMagicNumber(magic_no);
  119. trade.SetDeviationInPoints(maxSlippage);
  120. trade.SetTypeFilling(ORDER_FILLING_IOC);
  121. trade.LogLevel(LOG_LEVEL_ALL);
  122. trade.SetAsyncMode(false);
  123. if(!MQLInfoInteger(MQL_TESTER))
  124. {
  125. loadNewTradeStoreFile();
  126. }
  127. int filehandle = FileOpen(dataFileName, FILE_READ | FILE_CSV | FILE_COMMON | FILE_ANSI);
  128. if(filehandle != INVALID_HANDLE)
  129. {
  130. Print(" Valid Handler. ");
  131. while(!FileIsEnding(filehandle))
  132. {
  133. string orderToRead = FileReadString(filehandle);
  134. string orderData[];
  135. //Print("Data: ", OrderToRead);
  136. StringSplit(orderToRead, StringGetCharacter(",",0), orderData);
  137. Print("Array Size: ", ArraySize(orderData));
  138. Print(" Order is: ", orderToRead);
  139. for(int i = 0 ; i < ArraySize(orderData) ; i++)
  140. {
  141. Print(" Order Data: ", orderData[i], " i: ", i);
  142. }
  143. if(ArraySize(orderData) >= 8)
  144. {
  145. if(orderData[0] == Symbol())
  146. {
  147. // store into local variables first (trim if needed)
  148. ulong buy_ticket_local = (ulong)-1; // keep -1 as per your convention
  149. ulong sell_ticket_local = (ulong)-1;
  150. string symbol_local = orderData[0];
  151. double price_local = StringToDouble(orderData[1]);
  152. double sl_buy_local = StringToDouble(orderData[2]);
  153. double tp_buy_local = StringToDouble(orderData[3]);
  154. double sl_sell_local = StringToDouble(orderData[4]);
  155. double tp_sell_local = StringToDouble(orderData[5]);
  156. // if your CSV has extra fields (tp2,tp3, etc.) parse here as needed
  157. datetime start_local = StringToTime(orderData[6]);
  158. datetime end_local = StringToTime(orderData[7]);
  159. if(orderData[6] == "0" || orderData[6] == NULL)
  160. {
  161. start_local = 0;
  162. }
  163. if(orderData[7] == "0" || orderData[7] == NULL)
  164. {
  165. end_local = 0;
  166. }
  167. ArrayResize(levelsAre,ArraySize(levelsAre)+1);
  168. levelsAre[ArraySize(levelsAre) - 1] = price_local;
  169. // OPTIONAL: only add when price == 0:
  170. // if(MathAbs(price_local) > 1e-9) { Print("Skipped: price != 0"); continue; }
  171. bool buy_virtual_tp_hit = true;
  172. bool sell_virtual_tp_hit = true;
  173. bool demand_level_hit_first = true;
  174. if(bothHitsSl)
  175. {
  176. buy_virtual_tp_hit = false;
  177. sell_virtual_tp_hit = false;
  178. demand_level_hit_first = false;
  179. }
  180. // call the single-responsibility function that writes into struct array
  181. if(!level_present(price_local))
  182. {
  183. Print(" --------------- Price: ", price_local, " Start Time: ", start_local, " End Time: ", end_local, " --------------------");
  184. addToNewTradeStore(buy_ticket_local, sell_ticket_local,
  185. symbol_local, price_local,
  186. sl_buy_local, tp_buy_local,
  187. sl_sell_local, tp_sell_local,
  188. start_local, end_local,
  189. demand_level_hit_first, buy_virtual_tp_hit, sell_virtual_tp_hit);
  190. }
  191. else
  192. {
  193. Print("Level is already Present. Level: ", price_local);
  194. }
  195. }
  196. }
  197. }
  198. FileClose(filehandle);
  199. }
  200. else
  201. {
  202. Print(" InValid Handler. Error: ", GetLastError());
  203. }
  204. struct_level_check();
  205. print_newTradeStore();
  206. string time[];
  207. StringSplit(startTime,':',time);
  208. newYorkStartTime = (int)StringToInteger(time[0]);
  209. newYorkStartMin = (int)StringToInteger(time[1]);
  210. Print("NewYork Start Time Hour: ",newYorkStartTime," Start Time Min: ",newYorkStartMin);
  211. time[0] = "";
  212. time[1] = "";
  213. StringSplit(endTime,':',time);
  214. newYorkEndHour = (int)StringToInteger(time[0]);
  215. newYorkEndMin = (int)StringToInteger(time[1]);
  216. Print("NewYork End Time Hour: ",newYorkEndHour," End Time Min: ",newYorkEndMin);
  217. StringSplit(startTime,':',time);
  218. int newYorkStartHour = (int)StringToInteger(time[0]);
  219. newYorkStartMin = (int)StringToInteger(time[1]);
  220. EventSetMillisecondTimer(500);
  221. time[0] = "";
  222. time[1] = "";
  223. StringSplit(endTime,':',time);
  224. newYorkEndHour = (int)StringToInteger(time[0]);
  225. newYorkEndMin = (int)StringToInteger(time[1]);
  226. datetime startDateTime;
  227. MqlDateTime st;
  228. TimeCurrent(st); // get current date
  229. st.hour = newYorkStartHour;
  230. st.min = newYorkStartMin;
  231. st.sec = 0;
  232. startDateTime = StructToTime(st);
  233. datetime endDateTime;
  234. MqlDateTime et;
  235. TimeCurrent(et); // get current date
  236. et.hour = newYorkEndHour;
  237. et.min = newYorkEndMin;
  238. et.sec = 0;
  239. endDateTime = StructToTime(et);
  240. datetime start_Time = 0, end_Time = 0;
  241. if(startDateTime > endDateTime)
  242. {
  243. Print(" --------------------------- Previous -------------------------------------- ");
  244. newYorkSessionDay = prev;
  245. }
  246. else
  247. {
  248. Print(" --------------------------- Current -------------------------------------- ");
  249. newYorkSessionDay = curr;
  250. }
  251. timeFilter(true);
  252. int timeDifference = (int)TimeCurrent() - (int)TimeGMT();
  253. Print("Time Difference is: ", timeDifference);
  254. if(timeDifference > 0)
  255. {
  256. GMT_Broker_Time = (int)MathRound((double)timeDifference / 3600.0);
  257. }
  258. else
  259. if(timeDifference < 0)
  260. {
  261. GMT_Broker_Time = (int)MathRound((double)timeDifference / 3600.0);
  262. }
  263. else // timeDifference == 0
  264. {
  265. GMT_Broker_Time = 0;
  266. }
  267. Print("Gmt Time: ", TimeGMT(), " Broker Gmt Time: ", GMT_Broker_Time);
  268. gmt = GMT_Broker_Time;
  269. if(enableDrawLevels)
  270. {
  271. drawLevels();
  272. }
  273. //---
  274. return(INIT_SUCCEEDED);
  275. }
  276. //+------------------------------------------------------------------+
  277. //| Expert deinitialization function |
  278. //+------------------------------------------------------------------+
  279. void OnDeinit(const int reason)
  280. {
  281. //---
  282. ObjectsDeleteAll(0, 0, OBJ_HLINE);
  283. if(!MQLInfoInteger(MQL_TESTER))
  284. {
  285. saveNewTradeStoreFile();
  286. }
  287. }
  288. //+------------------------------------------------------------------+
  289. //| Expert tick function |
  290. //+------------------------------------------------------------------+
  291. void OnTick()
  292. {
  293. mainActivity();
  294. }
  295. //+------------------------------------------------------------------+
  296. //| |
  297. //+------------------------------------------------------------------+
  298. void mainActivity()
  299. {
  300. //---
  301. if(enableDrawLevels)
  302. {
  303. drawLevels();
  304. }
  305. newBar();
  306. if(indivial_trailing)
  307. {
  308. Individual_Trailing();
  309. }
  310. if(UseBreakEven)
  311. {
  312. breakEven();
  313. }
  314. double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
  315. double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
  316. if(tickPreviousBid == 0 && tickCurrentBid == 0)
  317. {
  318. tickPreviousBid = Bid;
  319. tickCurrentBid = Bid;
  320. }
  321. else
  322. {
  323. tickPreviousBid = tickCurrentBid;
  324. tickCurrentBid = Bid;
  325. }
  326. if(tickPreviousAsk == 0 && tickCurrentAsk == 0)
  327. {
  328. tickPreviousAsk = Ask;
  329. tickCurrentAsk = Ask;
  330. }
  331. else
  332. {
  333. tickPreviousAsk = tickCurrentAsk;
  334. tickCurrentAsk = Ask;
  335. }
  336. timeFilter(false);
  337. // Comment(" Session Start = ", newYorkStartTrading, " Asian Session End = ", newYorkEndTrading);
  338. if((enableTimeFilter && TimeCurrent() >= newYorkStartTrading && TimeCurrent() <= newYorkEndTrading) || !enableTimeFilter)
  339. {
  340. removeFromStructure();
  341. if(bothHitsSl)
  342. {
  343. virtualSLHitCheck();
  344. }
  345. tradePlacingCheck();
  346. }
  347. }
  348. //+------------------------------------------------------------------+
  349. //+------------------------------------------------------------------+
  350. //| |
  351. //+------------------------------------------------------------------+
  352. bool isTradingAllowedByWeek()
  353. {
  354. if(!enableWeekFilter) // filter disabled -> allow trading
  355. return true;
  356. // validate inputs quickly
  357. if(filterMonthNumber < 1 || filterMonthNumber > 12)
  358. {
  359. PrintFormat("⚠️ filterMonthNumber out of range (%d). Week filter disabled.", filterMonthNumber);
  360. return true;
  361. }
  362. if(filterWeekNumber < 1 || filterWeekNumber > 5)
  363. {
  364. PrintFormat("⚠️ filterWeekNumber out of range (%d). Week filter disabled.", filterWeekNumber);
  365. return true;
  366. }
  367. MqlDateTime t;
  368. TimeToStruct(TimeCurrent(), t); // t.mon (1..12), t.day (1..31)
  369. // if the months don't match, week filter doesn't apply -> allow
  370. if(t.mon != filterMonthNumber)
  371. return true;
  372. // compute week of month: days 1-7 -> week 1, 8-14 -> week 2, etc.
  373. int weekOfMonth = ((t.day - 1) / 7) + 1; // yields 1..5
  374. // if current week equals the filtered week -> block trading (return false)
  375. if(weekOfMonth == filterWeekNumber)
  376. {
  377. return false; // trading NOT allowed this week of the specified month
  378. }
  379. return true; // otherwise allow trading
  380. }
  381. //+------------------------------------------------------------------+
  382. //| |
  383. //+------------------------------------------------------------------+
  384. bool isTradingAllowedByMonth()
  385. {
  386. MqlDateTime t;
  387. TimeToStruct(TimeCurrent(), t);
  388. switch(t.mon)
  389. {
  390. case 1:
  391. return allowJanuary;
  392. case 2:
  393. return allowFebruary;
  394. case 3:
  395. return allowMarch;
  396. case 4:
  397. return allowApril;
  398. case 5:
  399. return allowMay;
  400. case 6:
  401. return allowJune;
  402. case 7:
  403. return allowJuly;
  404. case 8:
  405. return allowAugust;
  406. case 9:
  407. return allowSeptember;
  408. case 10:
  409. return allowOctober;
  410. case 11:
  411. return allowNovember;
  412. case 12:
  413. return allowDecember;
  414. default:
  415. return true; // Safe fallback: allow trading if month invalid
  416. }
  417. }
  418. //+------------------------------------------------------------------+
  419. //| |
  420. //+------------------------------------------------------------------+
  421. bool newBar()
  422. {
  423. static datetime lastbar;
  424. datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0);
  425. if(lastbar != curbar)
  426. {
  427. lastbar = curbar;
  428. Print(" ---------------------- New Bar :: ---------------------- ",lastbar);
  429. return (true);
  430. }
  431. else
  432. {
  433. return (false);
  434. }
  435. }
  436. //+------------------------------------------------------------------+
  437. //| |
  438. //+------------------------------------------------------------------+
  439. void closeTrades(int type,int magicno)
  440. {
  441. Print("Total order: ",OrdersTotal());
  442. for(int i= PositionsTotal()-1; i>=0; i--)
  443. {
  444. // Print(" Selection: ",OrderSelect(i,SELECT_BY_POS)," i: ",i," OrdersTotal(): ", OrdersTotal());
  445. ulong ticket = PositionGetTicket(i);
  446. if(PositionSelectByTicket(ticket))
  447. {
  448. if(PositionGetInteger(POSITION_TYPE) == type)
  449. {
  450. if(PositionGetInteger(POSITION_MAGIC) == magicno && PositionGetString(POSITION_SYMBOL) == Symbol())
  451. {
  452. //trade.PositionClose(PositionGetInteger(POSITION_TICKET))
  453. if(!trade.PositionClose(PositionGetInteger(POSITION_TICKET)))
  454. {Print("Problem in closing order order ",PositionGetInteger(POSITION_TICKET)); }
  455. else
  456. {
  457. Print("Order Closed by closeTrades() new filter",PositionGetInteger(POSITION_TICKET));
  458. }
  459. }
  460. }
  461. }
  462. }
  463. }
  464. //+------------------------------------------------------------------+
  465. //| |
  466. //+------------------------------------------------------------------+
  467. int orderCount_1(int type,int magic)
  468. {
  469. int count1=0;
  470. for(int i= PositionsTotal()-1; i>=0; i--)
  471. {
  472. // Print(" Selection: ",OrderSelect(i,SELECT_BY_POS)," i: ",i," OrdersTotal(): ", OrdersTotal());
  473. ulong ticket = PositionGetTicket(i);
  474. if(PositionSelectByTicket(ticket))
  475. {
  476. // if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY || PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
  477. if(PositionGetInteger(POSITION_MAGIC) == magic && PositionGetString(POSITION_SYMBOL) == Symbol())
  478. {
  479. //trade.PositionClose(PositionGetInteger(POSITION_TICKET))
  480. if(PositionGetInteger(POSITION_TYPE) == type)
  481. {
  482. count1++;
  483. }
  484. }
  485. }
  486. }
  487. return count1;
  488. }
  489. //+------------------------------------------------------------------+
  490. //| |
  491. //+------------------------------------------------------------------+
  492. int orderCount(int type)
  493. {
  494. int count = 0;
  495. for(int i= PositionsTotal()-1; i>=0; i--)
  496. {
  497. ulong ticket = PositionGetTicket(i);
  498. if(PositionSelectByTicket(ticket))
  499. {
  500. if(PositionGetInteger(POSITION_MAGIC) == magic_no && PositionGetString(POSITION_SYMBOL) == Symbol())
  501. {
  502. if(PositionGetInteger(POSITION_TYPE) == type)
  503. {
  504. count++;
  505. }
  506. }
  507. }
  508. }
  509. return count;
  510. }
  511. //+------------------------------------------------------------------+
  512. //| |
  513. //+------------------------------------------------------------------+
  514. bool level_present(double priceIs)
  515. {
  516. for(int i = 0 ; i < MaxOrders ; i++)
  517. {
  518. if(newTradeStore[i].price > 0)
  519. {
  520. if(priceIs == newTradeStore[i].price)
  521. {
  522. return true;
  523. }
  524. }
  525. }
  526. return false;
  527. }
  528. //+------------------------------------------------------------------+
  529. //| |
  530. //+------------------------------------------------------------------+
  531. void struct_level_check()
  532. {
  533. for(int i = 0; i < MaxOrders; i++)
  534. {
  535. if(newTradeStore[i].price > 0)
  536. {
  537. bool found = false;
  538. for(int j = 0; j < ArraySize(levelsAre); j++)
  539. {
  540. if(newTradeStore[i].price == levelsAre[j])
  541. {
  542. found = true;
  543. break;
  544. }
  545. }
  546. if(!found)
  547. {
  548. Print("Price not found in levelsAre[] -> index:", i, " | price:", newTradeStore[i].price);
  549. newTradeStore[i].buy_ticket = (ulong)-1;
  550. newTradeStore[i].sell_ticket = (ulong)-1;
  551. bool buy_virtual_tp_hit = true;
  552. bool sell_virtual_tp_hit = true;
  553. if(bothHitsSl)
  554. {
  555. buy_virtual_tp_hit = false;
  556. sell_virtual_tp_hit = false;
  557. }
  558. newTradeStore[i].buy_hit_virtual_sl = buy_virtual_tp_hit;
  559. newTradeStore[i].sell_hit_virtual_sl = sell_virtual_tp_hit;
  560. newTradeStore[i].symbol = "";
  561. newTradeStore[i].price = 0.0;
  562. newTradeStore[i].stop_loss_buy = 0.0;
  563. newTradeStore[i].take_profit_buy = 0.0;
  564. newTradeStore[i].stop_loss_sell = 0.0;
  565. newTradeStore[i].take_profit_sell = 0.0;
  566. newTradeStore[i].start_time = 0;
  567. newTradeStore[i].end_time = 0;
  568. return;
  569. }
  570. }
  571. }
  572. return;
  573. }
  574. //+------------------------------------------------------------------+
  575. //| |
  576. //+------------------------------------------------------------------+
  577. void print_newTradeStore()
  578. {
  579. bool anyPrinted = false;
  580. Print("=== newTradeStore DUMP ===");
  581. for(int i = 0; i < MaxOrders; i++)
  582. {
  583. // only print populated slots (price > 0)
  584. if(newTradeStore[i].price > 0.0)
  585. {
  586. anyPrinted = true;
  587. // convert booleans to readable text
  588. string buyHit = newTradeStore[i].buy_hit_virtual_sl ? "true" : "false";
  589. string sellHit = newTradeStore[i].sell_hit_virtual_sl ? "true" : "false";
  590. // header line for the entry
  591. Print("---- Entry ", i, " ----");
  592. // summary line (symbol, price, times)
  593. Print(" symbol:", newTradeStore[i].symbol,
  594. " | price:", DoubleToString(newTradeStore[i].price, Digits()),
  595. " | start:", IntegerToString(newTradeStore[i].start_time),
  596. " | end:", IntegerToString(newTradeStore[i].end_time));
  597. // ticket line
  598. Print(" tickets -> buy:", newTradeStore[i].buy_ticket,
  599. " | sell:", newTradeStore[i].sell_ticket);
  600. // flags line
  601. Print(" flags -> buy_hit_virtual_sl:", buyHit,
  602. " | sell_hit_virtual_sl:", sellHit,
  603. " | bothHitsSl:", (bothHitsSl ? "true" : "false"));
  604. // SL/TP line
  605. Print(" SL/TP -> buySL:", DoubleToString(newTradeStore[i].stop_loss_buy, Digits()),
  606. " | buyTP:", DoubleToString(newTradeStore[i].take_profit_buy, Digits()),
  607. " | sellSL:", DoubleToString(newTradeStore[i].stop_loss_sell, Digits()),
  608. " | sellTP:", DoubleToString(newTradeStore[i].take_profit_sell, Digits()));
  609. }
  610. }
  611. if(!anyPrinted)
  612. Print(" (no active newTradeStore entries found)");
  613. Print("=== end dump ===");
  614. }
  615. //+------------------------------------------------------------------+
  616. //| |
  617. //+------------------------------------------------------------------+
  618. void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket,
  619. string r_symbol, double r_price,
  620. double r_stop_loss_buy, double r_take_profit_buy,
  621. double r_stop_loss_sell, double r_take_profit_sell,
  622. datetime r_start_time, datetime r_end_time, bool r_demand_level_hit, bool r_buy_hit_sl, bool r_sell_hit_sl)
  623. {
  624. Print(" Tier 1. ");
  625. for(int i = 0; i < MaxOrders; i++)
  626. {
  627. // treat slot as empty when both tickets are -1 (same convention as constructor)
  628. if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
  629. {
  630. if(newTradeStore[i].price == 0)
  631. {
  632. newTradeStore[i].buy_ticket = r_buy_ticket;
  633. newTradeStore[i].sell_ticket = r_sell_ticket;
  634. newTradeStore[i].symbol = r_symbol;
  635. newTradeStore[i].price = r_price;
  636. newTradeStore[i].stop_loss_buy = r_stop_loss_buy;
  637. newTradeStore[i].take_profit_buy = r_take_profit_buy;
  638. newTradeStore[i].stop_loss_sell = r_stop_loss_sell;
  639. newTradeStore[i].take_profit_sell = r_take_profit_sell;
  640. newTradeStore[i].start_time = r_start_time;
  641. newTradeStore[i].end_time = r_end_time;
  642. newTradeStore[i].demand_level_hit = r_demand_level_hit;
  643. newTradeStore[i].buy_hit_virtual_sl = r_buy_hit_sl;
  644. newTradeStore[i].sell_hit_virtual_sl = r_sell_hit_sl;
  645. Print("Stored -> idx: ", i,
  646. " | Symbol: ", newTradeStore[i].symbol,
  647. " | price: ", DoubleToString(newTradeStore[i].price, Digits()),
  648. " | Sl Buy: ", DoubleToString(newTradeStore[i].stop_loss_buy, Digits()),
  649. " | Tp Buy: ", DoubleToString(newTradeStore[i].take_profit_buy, Digits()),
  650. "\n | Sl Sell: ", DoubleToString(newTradeStore[i].stop_loss_sell, Digits()),
  651. " | Tp Sell: ", DoubleToString(newTradeStore[i].take_profit_sell, Digits()),
  652. " | start: ", TimeToString(newTradeStore[i].start_time, TIME_DATE|TIME_SECONDS),
  653. " | end: ", TimeToString(newTradeStore[i].end_time, TIME_DATE|TIME_SECONDS),
  654. " | Demand Level Hit: ", newTradeStore[i].demand_level_hit,
  655. " | Buy Virtal Sl Hit: ", newTradeStore[i].buy_hit_virtual_sl,
  656. " | Sell Virtual Sl Hit: ", newTradeStore[i].sell_hit_virtual_sl);
  657. break;
  658. }
  659. }
  660. }
  661. }
  662. //+------------------------------------------------------------------+
  663. //| |
  664. //+------------------------------------------------------------------+
  665. void tradePlacingCheck()
  666. {
  667. for(int i = 0; i < MaxOrders; i++)
  668. {
  669. if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
  670. {
  671. if(newTradeStore[i].price > 0)
  672. {
  673. if((TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time) || (newTradeStore[i].start_time == 0 || newTradeStore[i].end_time == 0))
  674. {
  675. if(newTradeStore[i].buy_hit_virtual_sl == true && newTradeStore[i].sell_hit_virtual_sl == true)
  676. {
  677. double levelPriceIs = newTradeStore[i].price;
  678. if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
  679. (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
  680. {
  681. Print(" ------------------- Level Crossed. Level is: ", levelPriceIs, " -------------------- ");
  682. if(isTradingAllowedByWeek())
  683. {
  684. if(isTradingAllowedByMonth())
  685. {
  686. if((enableSpreadFilter && spreadFilter()) || !enableSpreadFilter)
  687. {
  688. ulong buyTicket = -1, sellTicket = -1;
  689. if(countLiveTrades() < maxTrades)
  690. {
  691. buyTicket = placeBuyTrade(newTradeStore[i].stop_loss_buy, newTradeStore[i].take_profit_buy);
  692. sellTicket = placeSellTrade(newTradeStore[i].stop_loss_sell, newTradeStore[i].take_profit_sell);
  693. newTradeStore[i].buy_ticket = buyTicket;
  694. newTradeStore[i].sell_ticket = sellTicket;
  695. }
  696. }
  697. }
  698. }
  699. }
  700. }
  701. }
  702. }
  703. }
  704. }
  705. }
  706. //+------------------------------------------------------------------+
  707. //| |
  708. //+------------------------------------------------------------------+
  709. void draw_lines(string name, datetime dateTime, double price, color selectColor, long lineStyle)
  710. {
  711. if(!ObjectCreate(0, name, OBJ_HLINE, 0, dateTime, price))
  712. {
  713. Print(" Error in creating ", name," : ","line: "," ",GetLastError());
  714. }
  715. else
  716. {
  717. ObjectSetInteger(0, name, OBJPROP_COLOR, selectColor);
  718. ObjectSetInteger(0, name, OBJPROP_STYLE, lineStyle);
  719. }
  720. }
  721. //+------------------------------------------------------------------+
  722. //| |
  723. //+------------------------------------------------------------------+
  724. void drawLevels()
  725. {
  726. for(int i = 0; i < MaxOrders; i++)
  727. {
  728. if(newTradeStore[i].price > 0)
  729. {
  730. if((TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time) || (newTradeStore[i].start_time == 0 || newTradeStore[i].end_time == 0))
  731. {
  732. if(ObjectFind(0, "level" + (string)newTradeStore[i].price) < 0)
  733. {
  734. draw_lines("level" + (string)newTradeStore[i].price, TimeCurrent(), newTradeStore[i].price, clrAqua, STYLE_SOLID);
  735. }
  736. }
  737. else
  738. {
  739. if(ObjectFind(0, "level" + (string)newTradeStore[i].price) >= 0)
  740. {
  741. ObjectDelete(0, "level" + (string)newTradeStore[i].price);
  742. }
  743. }
  744. }
  745. }
  746. }
  747. //+------------------------------------------------------------------+
  748. //| |
  749. //+------------------------------------------------------------------+
  750. ulong placeBuyTrade(double stoploss, double takeprofit)
  751. {
  752. double buySL = 0, buyTp=0;
  753. //openPrice = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  754. double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  755. double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  756. if(useTpSlPips)
  757. {
  758. if(stopLoss != 0)
  759. {
  760. buySL = Ask - (stopLoss * Point());
  761. }
  762. if(takeProfit != 0)
  763. {
  764. buyTp = Ask + (takeProfit * Point());
  765. }
  766. }
  767. else
  768. {
  769. if(stoploss > 0)
  770. {
  771. buySL = stoploss;
  772. }
  773. if(takeprofit > 0)
  774. {
  775. buyTp = takeprofit;
  776. }
  777. }
  778. double distance = MathAbs((Ask - buySL) / Point());
  779. if(trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,getLot(distance),Ask,buySL,buyTp,tradeComment+" Buy"))
  780. {
  781. Print("Buy Trade Placed: ",trade.ResultOrder());
  782. return trade.ResultOrder();
  783. }
  784. else
  785. {
  786. Print("Error in placing Buy: "+Symbol()+" ",GetLastError());
  787. return -1;
  788. }
  789. return -1;
  790. }
  791. //+------------------------------------------------------------------+
  792. //| |
  793. //+------------------------------------------------------------------+
  794. ulong placeSellTrade(double stoploss, double takeprofit)
  795. {
  796. double sellSL = 0, sellTp = 0;
  797. double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  798. double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  799. if(useTpSlPips)
  800. {
  801. if(stopLoss != 0)
  802. {
  803. sellSL = Bid + (stopLoss * Point());
  804. }
  805. if(takeProfit != 0)
  806. {
  807. sellTp = Bid - (takeProfit * Point());
  808. }
  809. }
  810. else
  811. {
  812. if(stoploss > 0)
  813. {
  814. sellSL = stoploss;
  815. }
  816. if(takeprofit > 0)
  817. {
  818. sellTp = takeprofit;
  819. }
  820. }
  821. double distance = MathAbs((Bid - sellSL) / Point());
  822. if(trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,getLot(distance),Bid,sellSL,sellTp,tradeComment+ " Sell"))
  823. {
  824. Print("Sell Trade PLaced: ",trade.ResultOrder());
  825. return trade.ResultOrder();
  826. }
  827. else
  828. {
  829. Print("Error in placing Sell: "+Symbol()+" ",GetLastError());
  830. return -1;
  831. }
  832. return -1;
  833. }
  834. //+------------------------------------------------------------------+
  835. //| |
  836. //+------------------------------------------------------------------+
  837. double getLot(double stop_loss)
  838. {
  839. Print("Tick Value: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE));
  840. Print("Tick Size: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE));
  841. double modeTickV=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)
  842. ,modeTickS=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE);
  843. // Print("Pip value: ", NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point))*10),2));
  844. double pipvalue = NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point()))*10),2);
  845. // pipvalue=NormalizeDouble((modeTickV/modeTickS/Point()),)
  846. // pipvalue=
  847. pipvalue = pipvalue / 10;
  848. double lotSize = lot_amount;
  849. if(lot_calculator == rsk || lot_calculator == dollar) //calculating risk
  850. {
  851. double riskamount = 0;
  852. if(lot_calculator == rsk)
  853. {
  854. riskamount = (risk/100)*AccountInfoDouble(ACCOUNT_BALANCE);
  855. }
  856. if(lot_calculator == dollar)
  857. {
  858. riskamount = dollars;
  859. }
  860. double pipvalue_required=riskamount/stop_loss;
  861. lotSize = pipvalue_required/pipvalue;
  862. //sl=riskamount/pipValuelot
  863. int roundDigit=0;
  864. double step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
  865. while(step<1)
  866. {
  867. roundDigit++;
  868. step=step*10;
  869. }
  870. Print("Round Digits:",roundDigit);
  871. lotSize = NormalizeDouble(lotSize,roundDigit);
  872. //
  873. }
  874. Print(" Before Normalizing Lot Size By Step : ",lotSize);
  875. lotSize = NormalizeLot(lotSize,SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP));
  876. Print(" After Normalizing Lot Size By Step : ",lotSize);
  877. if(lotSize > SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX))
  878. {
  879. lotSize=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
  880. }
  881. else
  882. if(lotSize<SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN))
  883. {
  884. lotSize=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
  885. }
  886. //---
  887. return lotSize;
  888. }
  889. //+------------------------------------------------------------------+
  890. //| |
  891. //+------------------------------------------------------------------+
  892. double NormalizeLot(double lot, double step)
  893. {
  894. double steps = lot / step;
  895. double rounded_steps = MathRound(steps); // round to nearest whole step
  896. double rounded_lot = rounded_steps * step;
  897. return NormalizeDouble(rounded_lot, 2); // 2 decimals for safety
  898. }
  899. //+------------------------------------------------------------------+
  900. //| |
  901. //+------------------------------------------------------------------+
  902. void timeFilter(bool onInit)
  903. {
  904. MqlDateTime sdate,edate;
  905. datetime start_Time = 0, end_Time = 0;
  906. if(newYorkSessionDay == prev)
  907. {
  908. if(onInit)
  909. {
  910. start_Time = iTime(Symbol(),PERIOD_D1,1);
  911. end_Time = iTime(Symbol(),PERIOD_D1,0);
  912. }
  913. else
  914. {
  915. start_Time = newYorkStartTrading;
  916. end_Time = newYorkEndTrading;
  917. if(TimeCurrent() >= newYorkEndTrading && newYorkEndTrading != 0)
  918. {
  919. start_Time = iTime(Symbol(),PERIOD_D1,0);
  920. end_Time = start_Time + 86400;
  921. }
  922. }
  923. }
  924. else
  925. {
  926. start_Time = iTime(Symbol(),PERIOD_D1,0);
  927. end_Time = iTime(Symbol(),PERIOD_D1,0);
  928. }
  929. if(TimeToStruct(end_Time,edate))
  930. {
  931. edate.hour = newYorkEndHour;
  932. edate.min = newYorkEndMin;
  933. edate.sec = 0;
  934. }
  935. else
  936. Print("Error in Converting Time: ",GetLastError());
  937. newYorkEndTrading = StructToTime(edate);
  938. if(TimeToStruct(start_Time,sdate))
  939. {
  940. sdate.hour = newYorkStartTime;
  941. sdate.min = newYorkStartMin;
  942. sdate.sec = 0;
  943. }
  944. else
  945. Print("Error in Converting Time: ",GetLastError());
  946. newYorkStartTrading = StructToTime(sdate);
  947. // if(onInit)
  948. //Print("NewYork Start Time ",newYorkStartTrading,"End Date: ",newYorkEndTrading);
  949. //Print("Edate: ",edate.hour," ",edate.min," Sdate: ",sdate.hour," ",sdate.min);
  950. }
  951. //+------------------------------------------------------------------+
  952. //| |
  953. //+------------------------------------------------------------------+
  954. void removeFromStructure()
  955. {
  956. for(int i = 0 ; i < MaxOrders ; i++)
  957. {
  958. bool isBuyPresent=false, isSellPresent=false;
  959. if(newTradeStore[i].buy_ticket != -1 && newTradeStore[i].sell_ticket != -1)
  960. {
  961. for(int j = PositionsTotal()-1; j>=0; j--)
  962. {
  963. ulong ticket = PositionGetTicket(j);
  964. if(PositionSelectByTicket(ticket))
  965. {
  966. if(ticket == newTradeStore[i].buy_ticket)
  967. {
  968. isBuyPresent=true;
  969. }
  970. }
  971. }
  972. for(int j = PositionsTotal()-1; j>=0; j--)
  973. {
  974. ulong ticket = PositionGetTicket(j);
  975. if(PositionSelectByTicket(ticket))
  976. {
  977. if(ticket == newTradeStore[i].sell_ticket)
  978. {
  979. isSellPresent = true;
  980. }
  981. }
  982. }
  983. if(!isBuyPresent && !isSellPresent)
  984. {
  985. Print("Buy/Sell Ticket is closed so removed from struct. Buy Ticket: ", newTradeStore[i].buy_ticket, " Sell Ticket: ", newTradeStore[i].sell_ticket);
  986. newTradeStore[i].buy_ticket = (ulong)-1;
  987. newTradeStore[i].sell_ticket = (ulong)-1;
  988. bool buy_virtual_tp_hit = true;
  989. bool sell_virtual_tp_hit = true;
  990. bool demand_level_hit_value = true;
  991. if(bothHitsSl)
  992. {
  993. buy_virtual_tp_hit = false;
  994. sell_virtual_tp_hit = false;
  995. demand_level_hit_value = false;
  996. }
  997. newTradeStore[i].buy_hit_virtual_sl = buy_virtual_tp_hit;
  998. newTradeStore[i].sell_hit_virtual_sl = sell_virtual_tp_hit;
  999. newTradeStore[i].demand_level_hit = demand_level_hit_value;
  1000. //newTradeStore[i].symbol = "";
  1001. //newTradeStore[i].price = 0.0;
  1002. //newTradeStore[i].stop_loss = 0.0;
  1003. //newTradeStore[i].take_profit = 0.0;
  1004. //newTradeStore[i].start_time = 0;
  1005. //newTradeStore[i].end_time = 0;
  1006. }
  1007. }
  1008. }
  1009. }
  1010. //+------------------------------------------------------------------+
  1011. //| |
  1012. //+------------------------------------------------------------------+
  1013. void virtualSLHitCheck()
  1014. {
  1015. for(int i = 0 ; i < MaxOrders ; i++)
  1016. {
  1017. if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
  1018. {
  1019. if(TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time)
  1020. {
  1021. if(!newTradeStore[i].demand_level_hit)
  1022. {
  1023. double levelPriceIs = newTradeStore[i].price;
  1024. if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
  1025. (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
  1026. {
  1027. newTradeStore[i].demand_level_hit = true;
  1028. Print(" Demand Level Hit. newTradeStore[i].demand_level_hit: ", newTradeStore[i].demand_level_hit, " Order Price is: ", newTradeStore[i].price, " Time Demand Hit is: ", TimeCurrent());
  1029. }
  1030. }
  1031. if(newTradeStore[i].demand_level_hit)
  1032. {
  1033. double buy_sl = 0, sell_sl = 0;
  1034. if(!useTpSlPips)
  1035. {
  1036. buy_sl = newTradeStore[i].stop_loss_buy;
  1037. sell_sl = newTradeStore[i].stop_loss_sell;
  1038. }
  1039. else
  1040. {
  1041. buy_sl = stopLoss != 0 ? newTradeStore[i].price - (stopLoss * Point()) : 0;
  1042. sell_sl = stopLoss != 0 ? newTradeStore[i].price + (stopLoss * Point()) : 0;
  1043. }
  1044. if(newTradeStore[i].buy_hit_virtual_sl == false)
  1045. {
  1046. if((tickPreviousBid > buy_sl && tickCurrentBid <= buy_sl))
  1047. {
  1048. newTradeStore[i].buy_hit_virtual_sl = true;
  1049. Print(" Buy Virtual Sl Hit. newTradeStore[i].buy_hit_virtual_sl: ", newTradeStore[i].buy_hit_virtual_sl, " Order Price is: ", newTradeStore[i].price, " Stop Loss Price is: ", buy_sl, " Time Virtual Sl Hit is: ", TimeCurrent());
  1050. }
  1051. }
  1052. if(newTradeStore[i].sell_hit_virtual_sl == false)
  1053. {
  1054. if((tickPreviousAsk < sell_sl && tickCurrentAsk >= sell_sl))
  1055. {
  1056. newTradeStore[i].sell_hit_virtual_sl = true;
  1057. Print(" Sell Virtual Sl Hit. newTradeStore[i].sell_hit_virtual_sl: ", newTradeStore[i].sell_hit_virtual_sl, " Order Price is: ", newTradeStore[i].price, " Stop Loss Price is: ", sell_sl, " Time Virtual Sl Hit is: ", TimeCurrent());
  1058. }
  1059. }
  1060. }
  1061. }
  1062. }
  1063. }
  1064. }
  1065. //+------------------------------------------------------------------+
  1066. //| |
  1067. //+------------------------------------------------------------------+
  1068. int countLiveTrades()
  1069. {
  1070. int count = 0;
  1071. for(int i = 0; i < PositionsTotal(); i++)
  1072. {
  1073. ulong ticket = PositionGetTicket(i);
  1074. if(PositionSelectByTicket(ticket))
  1075. {
  1076. if(PositionGetInteger(POSITION_MAGIC) == magic_no)
  1077. {
  1078. if(PositionGetString(POSITION_SYMBOL) == Symbol())
  1079. {
  1080. if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY || PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
  1081. {
  1082. count++;
  1083. }
  1084. }
  1085. }
  1086. }
  1087. }
  1088. return count;
  1089. }
  1090. //+------------------------------------------------------------------+
  1091. //| |
  1092. //+------------------------------------------------------------------+
  1093. bool spreadFilter()
  1094. {
  1095. long spreadIs = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD);
  1096. if(spreadIs > maximumSpread)
  1097. {
  1098. return false;
  1099. }
  1100. return true;
  1101. }
  1102. //+------------------------------------------------------------------+
  1103. //| |
  1104. //+------------------------------------------------------------------+
  1105. void breakEven()
  1106. {
  1107. for(int i = PositionsTotal()-1; i>=0; i--)
  1108. {
  1109. ulong ticket = PositionGetTicket(i);
  1110. string symbol=PositionGetSymbol(i);
  1111. double mySL = 0,newSL = 0;
  1112. double SymbolTickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
  1113. ////Print("ticket ",ticket," Symbol : ",symbol);
  1114. if(PositionSelectByTicket(ticket))
  1115. {
  1116. if(PositionGetString(POSITION_SYMBOL)==Symbol() && PositionGetInteger(POSITION_MAGIC) == magic_no)
  1117. {
  1118. if(isCounterpartOpen(ticket))
  1119. {
  1120. // counterpart still open -> skip trailing for this position
  1121. continue;
  1122. }
  1123. //========================================================Buy Condition=========================================================================
  1124. if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
  1125. {
  1126. mySL = PositionGetDouble(POSITION_PRICE_OPEN) + (breakEvenPoints * SymbolTickSize);
  1127. if(SymbolInfoDouble(Symbol(),SYMBOL_BID) >= mySL && PositionGetDouble(POSITION_PRICE_OPEN) > PositionGetDouble(POSITION_SL))
  1128. {
  1129. newSL= PositionGetDouble(POSITION_PRICE_OPEN) + (breakStopPoint * SymbolTickSize);
  1130. if(trade.PositionModify(ticket,newSL,PositionGetDouble(POSITION_TP)))
  1131. {
  1132. Print("Buy Order BreakEven Successfully ");
  1133. }
  1134. else
  1135. {
  1136. Print("Error in BreakEven Buy Position ",GetLastError());
  1137. }
  1138. }
  1139. }
  1140. //=======================================================Sell condition ===============================================================
  1141. if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
  1142. {
  1143. mySL = PositionGetDouble(POSITION_PRICE_OPEN) - (breakEvenPoints * SymbolTickSize);
  1144. if(SymbolInfoDouble(Symbol(),SYMBOL_ASK) <= mySL && PositionGetDouble(POSITION_SL) > PositionGetDouble(POSITION_PRICE_OPEN))
  1145. {
  1146. newSL = PositionGetDouble(POSITION_PRICE_OPEN) - (breakStopPoint * SymbolTickSize);
  1147. if(trade.PositionModify(ticket,newSL,PositionGetDouble(POSITION_TP)))
  1148. {
  1149. Print("Order Sell BreakEven Successfully ");
  1150. }
  1151. else
  1152. {
  1153. Print("Error in BreakEven Sell Position ",GetLastError());
  1154. }
  1155. }
  1156. }
  1157. }
  1158. }
  1159. }
  1160. }
  1161. //+------------------------------------------------------------------+
  1162. //| |
  1163. //+------------------------------------------------------------------+
  1164. bool isCounterpartOpen(ulong ticket)
  1165. {
  1166. // scan stored pairs
  1167. for(int k=0; k<MaxOrders; k++)
  1168. {
  1169. // check if this ticket is the buy side in the pair
  1170. if(newTradeStore[k].buy_ticket == ticket)
  1171. {
  1172. ulong other = newTradeStore[k].sell_ticket;
  1173. if(other <= 0)
  1174. return false; // no counterpart recorded -> treat as closed
  1175. // check if counterpart ticket exists in current positions
  1176. for(int p = PositionsTotal()-1; p >= 0; p--)
  1177. {
  1178. ulong t = PositionGetTicket(p);
  1179. if(t == other)
  1180. return true; // counterpart still open
  1181. }
  1182. return false; // counterpart not found -> closed
  1183. }
  1184. // check if this ticket is the sell side in the pair
  1185. if(newTradeStore[k].sell_ticket == ticket)
  1186. {
  1187. ulong other = newTradeStore[k].buy_ticket;
  1188. if(other <= 0)
  1189. return false; // no counterpart recorded -> treat as closed
  1190. for(int p = PositionsTotal()-1; p >= 0; p--)
  1191. {
  1192. ulong t = PositionGetTicket(p);
  1193. if(t == other)
  1194. return true; // counterpart still open
  1195. }
  1196. return false; // counterpart not found -> closed
  1197. }
  1198. }
  1199. // ticket not found in the stored pairs -> treat as no counterpart open
  1200. return false;
  1201. }
  1202. //+------------------------------------------------------------------+
  1203. //| |
  1204. //+------------------------------------------------------------------+
  1205. void Individual_Trailing()
  1206. {
  1207. int openedpositions;
  1208. double mySL,myResult;
  1209. openedpositions=PositionsTotal();
  1210. if((openedpositions>0))
  1211. {
  1212. int totalorders=PositionsTotal();
  1213. for(int i=0; i<totalorders; i++) // scan all orders and positions. ..
  1214. {
  1215. ulong ticket = PositionGetTicket(i);
  1216. if(PositionSelectByTicket(ticket))
  1217. {
  1218. if(PositionGetString(POSITION_SYMBOL)==Symbol() && PositionGetInteger(POSITION_MAGIC) == magic_no) // only look if mygrid and symbol. ..
  1219. {
  1220. if(isCounterpartOpen(ticket))
  1221. {
  1222. // counterpart still open -> skip trailing for this position
  1223. continue;
  1224. }
  1225. double SymbolAsk = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_ASK);
  1226. double SymbolBid = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_BID);
  1227. int SymbolDigits = (int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_DIGITS);
  1228. double SymbolTickSize = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_SIZE);
  1229. int type= (int)PositionGetInteger(POSITION_TYPE);
  1230. if(type==POSITION_TYPE_BUY) // its a long position
  1231. {
  1232. mySL=NormalizeDouble(SymbolAsk-(ts*SymbolTickSize),Digits()); // new SL
  1233. double startSl=PositionGetDouble(POSITION_PRICE_OPEN)+(ts_sl*SymbolTickSize);
  1234. if(PositionGetDouble(POSITION_SL) != mySL)
  1235. if(mySL>PositionGetDouble(POSITION_SL) && SymbolAsk>=startSl)
  1236. {
  1237. myResult=trade.PositionModify(ticket,mySL,PositionGetDouble(POSITION_TP)); //OrderModify(OrderTicket(),OrderOpenPrice(),mySL,OrderTakeProfit(),0,clrGreen);
  1238. if(!myResult)
  1239. {
  1240. Print(" Buy Trade Trailing Error: ",GetLastError());
  1241. }
  1242. }
  1243. }
  1244. if(type==POSITION_TYPE_SELL)
  1245. {
  1246. mySL=NormalizeDouble(SymbolBid+(ts*SymbolTickSize),Digits()); // new SL
  1247. double startSlSell=PositionGetDouble(POSITION_PRICE_OPEN)-(ts_sl*SymbolTickSize);
  1248. if(PositionGetDouble(POSITION_SL) != mySL)
  1249. if(((mySL<PositionGetDouble(POSITION_SL)) || (PositionGetDouble(POSITION_SL)<SymbolTickSize)) && SymbolBid<=startSlSell)
  1250. {
  1251. myResult=trade.PositionModify(ticket,mySL,PositionGetDouble(POSITION_TP)); //OrderModify(OrderTicket(),OrderOpenPrice(),mySL,OrderTakeProfit(),0,clrRed);
  1252. if(!myResult)
  1253. {
  1254. Print(" Sell Trade Trailing Error: ",GetLastError());
  1255. }
  1256. }
  1257. }
  1258. }
  1259. }
  1260. }
  1261. }
  1262. }
  1263. //+------------------------------------------------------------------+
  1264. //| |
  1265. //+------------------------------------------------------------------+
  1266. void saveNewTradeStoreFile()
  1267. {
  1268. // don't run in strategy tester
  1269. if(MQLInfoInteger(MQL_TESTER))
  1270. return;
  1271. string file_name = "new_trade_store_updated.csv";
  1272. int fileHandle = FileOpen(file_name,
  1273. FILE_WRITE | FILE_CSV | FILE_COMMON |
  1274. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_READ);
  1275. if(fileHandle == INVALID_HANDLE)
  1276. {
  1277. PrintFormat("saveNewTradeStoreFile() -> Cannot open file '%s'. Error: %d", file_name, GetLastError());
  1278. return;
  1279. }
  1280. // header (optional) - comment out if you don't want header
  1281. //string header = "buy_ticket,sell_ticket,symbol,price,stop_loss,take_profit,start_time,end_time,buy_hit_virtual_sl,sell_hit_virtual_sl\r\n";
  1282. //FileWriteString(fileHandle, header);
  1283. for(int i = 0; i < MaxOrders; i++)
  1284. {
  1285. // if(newTradeStore[i].buy_ticket != -1 && newTradeStore[i].sell_ticket != -1)
  1286. {
  1287. // decide whether this slot has useful data:
  1288. // you can tweak this condition as you prefer (symbol != "" is simple)
  1289. bool slotPopulated = (StringLen(newTradeStore[i].symbol) > 0)
  1290. || (newTradeStore[i].price != 0.0)
  1291. || (newTradeStore[i].start_time != 0);
  1292. if(!slotPopulated)
  1293. continue;
  1294. // convert values to strings
  1295. string buyTicketStr = IntegerToString((long)newTradeStore[i].buy_ticket);
  1296. string sellTicketStr = IntegerToString((long)newTradeStore[i].sell_ticket);
  1297. string priceStr = DoubleToString(newTradeStore[i].price, Digits());
  1298. string slBuyStr = DoubleToString(newTradeStore[i].stop_loss_buy, Digits());
  1299. string tpBuyStr = DoubleToString(newTradeStore[i].take_profit_buy, Digits());
  1300. string slSellStr = DoubleToString(newTradeStore[i].stop_loss_sell, Digits());
  1301. string tpSellStr = DoubleToString(newTradeStore[i].take_profit_sell, Digits());
  1302. string startTimeStr = (newTradeStore[i].start_time != 0) ? TimeToString(newTradeStore[i].start_time, TIME_DATE|TIME_SECONDS) : "";
  1303. string endTimeStr = (newTradeStore[i].end_time != 0) ? TimeToString(newTradeStore[i].end_time, TIME_DATE|TIME_SECONDS) : "";
  1304. string buyHitStr = ""; // IntegerToString(newTradeStore[i].buy_hit_virtual_sl ? 1 : 0);
  1305. string sellHitStr = ""; // IntegerToString(newTradeStore[i].sell_hit_virtual_sl ? 1 : 0);
  1306. string demandHitStr = "";
  1307. if(newTradeStore[i].buy_hit_virtual_sl == true)
  1308. {
  1309. buyHitStr = "true";
  1310. }
  1311. else
  1312. {
  1313. buyHitStr = "false";
  1314. }
  1315. if(newTradeStore[i].sell_hit_virtual_sl == true)
  1316. {
  1317. sellHitStr = "true";
  1318. }
  1319. else
  1320. {
  1321. sellHitStr = "false";
  1322. }
  1323. if(newTradeStore[i].demand_level_hit == true)
  1324. {
  1325. demandHitStr = "true";
  1326. }
  1327. else
  1328. {
  1329. demandHitStr = "false";
  1330. }
  1331. // build CSV line and write
  1332. string line = buyTicketStr + "," + sellTicketStr + "," +
  1333. newTradeStore[i].symbol + "," +
  1334. priceStr + "," + slBuyStr + "," + tpBuyStr + "," +
  1335. slSellStr + "," + tpSellStr + "," +
  1336. startTimeStr + "," + endTimeStr + "," +
  1337. demandHitStr + "," + buyHitStr + "," + sellHitStr + "\r\n";
  1338. FileWriteString(fileHandle, line);
  1339. }
  1340. }
  1341. FileClose(fileHandle);
  1342. PrintFormat("saveNewTradeStoreFile() -> saved to '%s'.", file_name);
  1343. }
  1344. //+------------------------------------------------------------------+
  1345. //| |
  1346. //+------------------------------------------------------------------+
  1347. void loadNewTradeStoreFile()
  1348. {
  1349. if(MQLInfoInteger(MQL_TESTER))
  1350. return;
  1351. string file_name = "new_trade_store_updated.csv";
  1352. int fileHandle = FileOpen(file_name,
  1353. FILE_READ | FILE_CSV | FILE_COMMON |
  1354. FILE_SHARE_READ | FILE_SHARE_WRITE);
  1355. if(fileHandle == INVALID_HANDLE)
  1356. {
  1357. Print("loadNewTradeStoreFile() -> Cannot open file '", file_name, "'. Error: ", GetLastError());
  1358. return;
  1359. }
  1360. // reset defaults
  1361. for(int j = 0; j < MaxOrders; j++)
  1362. {
  1363. newTradeStore[j].buy_ticket = (ulong)-1;
  1364. newTradeStore[j].sell_ticket = (ulong)-1;
  1365. newTradeStore[j].symbol = "";
  1366. newTradeStore[j].price = 0.0;
  1367. newTradeStore[j].stop_loss_buy = 0.0;
  1368. newTradeStore[j].take_profit_buy = 0.0;
  1369. newTradeStore[j].stop_loss_sell = 0.0;
  1370. newTradeStore[j].take_profit_sell = 0.0;
  1371. newTradeStore[j].start_time = 0;
  1372. newTradeStore[j].end_time = 0;
  1373. newTradeStore[j].demand_level_hit = false;
  1374. newTradeStore[j].buy_hit_virtual_sl = false;
  1375. newTradeStore[j].sell_hit_virtual_sl = false;
  1376. }
  1377. int idx = 0;
  1378. while(!FileIsEnding(fileHandle) && idx < MaxOrders)
  1379. {
  1380. string line = FileReadString(fileHandle);
  1381. if(StringLen(line) == 0)
  1382. continue;
  1383. string tokens[];
  1384. int total = StringSplit(line, ',', tokens);
  1385. if(total >= 13)
  1386. {
  1387. // if((ulong)tokens[0] != -1 && (ulong)tokens[1] != -1)
  1388. {
  1389. newTradeStore[idx].buy_ticket = (ulong)tokens[0];
  1390. newTradeStore[idx].sell_ticket = (ulong)tokens[1];
  1391. newTradeStore[idx].symbol = tokens[2];
  1392. newTradeStore[idx].price = StringToDouble(tokens[3]);
  1393. newTradeStore[idx].stop_loss_buy = StringToDouble(tokens[4]);
  1394. newTradeStore[idx].take_profit_buy = StringToDouble(tokens[5]);
  1395. newTradeStore[idx].stop_loss_sell = StringToDouble(tokens[6]);
  1396. newTradeStore[idx].take_profit_sell = StringToDouble(tokens[7]);
  1397. string sStart = tokens[8];
  1398. string sEnd = tokens[9];
  1399. newTradeStore[idx].start_time = (StringLen(sStart) > 0) ? StringToTime(sStart) : 0;
  1400. newTradeStore[idx].end_time = (StringLen(sEnd) > 0) ? StringToTime(sEnd) : 0;
  1401. bool bHit = false;
  1402. bool sHit = false;
  1403. bool dHit = false;
  1404. if(tokens[10] == "true")
  1405. {
  1406. dHit = true;
  1407. }
  1408. else
  1409. {
  1410. dHit = false;
  1411. }
  1412. if(tokens[11] == "true")
  1413. {
  1414. bHit = true;
  1415. }
  1416. else
  1417. {
  1418. bHit = false;
  1419. }
  1420. if(tokens[12] == "true")
  1421. {
  1422. sHit = true;
  1423. }
  1424. else
  1425. {
  1426. sHit = false;
  1427. }
  1428. if(bothHitsSl == false)
  1429. {
  1430. newTradeStore[idx].buy_hit_virtual_sl = true;
  1431. newTradeStore[idx].sell_hit_virtual_sl = true;
  1432. newTradeStore[idx].demand_level_hit = true;
  1433. }
  1434. if(bothHitsSl == true)
  1435. {
  1436. newTradeStore[idx].buy_hit_virtual_sl = bHit;
  1437. newTradeStore[idx].sell_hit_virtual_sl = sHit;
  1438. newTradeStore[idx].demand_level_hit = dHit;
  1439. }
  1440. // --- simple Print instead of PrintFormat ---
  1441. Print(
  1442. "Loaded newTradeStore[", idx, "]:",
  1443. " buy_ticket=", newTradeStore[idx].buy_ticket,
  1444. " sell_ticket=", newTradeStore[idx].sell_ticket,
  1445. " symbol=", newTradeStore[idx].symbol,
  1446. " price=", DoubleToString(newTradeStore[idx].price, Digits()),
  1447. " \n sl buy=", DoubleToString(newTradeStore[idx].stop_loss_buy, Digits()),
  1448. " tp buy=", DoubleToString(newTradeStore[idx].take_profit_buy, Digits()),
  1449. " sl sell=", DoubleToString(newTradeStore[idx].stop_loss_sell, Digits()),
  1450. " tp sell=", DoubleToString(newTradeStore[idx].take_profit_sell, Digits()),
  1451. " start=", (newTradeStore[idx].start_time != 0 ? TimeToString(newTradeStore[idx].start_time, TIME_DATE|TIME_SECONDS) : ""),
  1452. " end=", (newTradeStore[idx].end_time != 0 ? TimeToString(newTradeStore[idx].end_time, TIME_DATE|TIME_SECONDS) : ""),
  1453. " demandHit=", newTradeStore[idx].demand_level_hit,
  1454. " buyHit=", newTradeStore[idx].buy_hit_virtual_sl,
  1455. " sellHit=", newTradeStore[idx].sell_hit_virtual_sl
  1456. );
  1457. idx++;
  1458. }
  1459. }
  1460. else
  1461. {
  1462. Print("loadNewTradeStoreFile(): skipping malformed line (tokens=", total, "): ", line);
  1463. }
  1464. }
  1465. FileClose(fileHandle);
  1466. Print("loadNewTradeStoreFile() -> loaded ", idx, " entries from '", file_name, "'.");
  1467. }
  1468. //+------------------------------------------------------------------+
  1469. //| |
  1470. //+------------------------------------------------------------------+
  1471. //+------------------------------------------------------------------+