暫無描述

vol_hedge_strategy_mt5.mq5 55KB

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