Brak opisu

localHedgingMasterCopierMt5.mq5 114KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529
  1. //+------------------------------------------------------------------+
  2. //| localHedgingMasterCopierMt5.mq5 |
  3. //| Copyright 2025, MQL Development |
  4. //| https://www.mqldevelopment.com/ |
  5. //+------------------------------------------------------------------+
  6. #property copyright "Copyright 2025, MQL Development"
  7. #property link "https://www.mqldevelopment.com/"
  8. #property version "1.00"
  9. #include <Trade\Trade.mqh>
  10. CTrade trade;
  11. #define orderCount 2000
  12. #define count1 50
  13. #define testCounter 50
  14. #define MaxOrders 20000
  15. #define daysOfTradesToAdd 20
  16. #property description "Control Panels and Dialogs. Demonstration class CLabel"
  17. #include <Controls\Dialog.mqh>
  18. #include <Controls\Label.mqh>
  19. #include <Controls\Button.mqh>
  20. #include <Controls\RadioButton.mqh>
  21. #include <Controls\RadioGroup.mqh>
  22. #include <Controls\CheckBox.mqh>
  23. #include <Controls\ComboBox.mqh>
  24. //+------------------------------------------------------------------+
  25. //| Expert initialization function |
  26. //+------------------------------------------------------------------+
  27. struct historyTradesClientSide
  28. {
  29. ulong ticket;
  30. ulong magic;
  31. historyTradesClientSide()
  32. {
  33. ticket = -1;
  34. magic = 0;
  35. }
  36. };
  37. historyTradesClientSide historyTradeStore[MaxOrders];
  38. struct masterOrder
  39. {
  40. datetime opentime;
  41. string symbol;
  42. ulong ordertype;
  43. double price;
  44. double lots;
  45. double stoploss;
  46. double takeprofit;
  47. ulong ticket;
  48. int magic;
  49. double accountBalance;
  50. int contractSize;
  51. string comment;
  52. masterOrder()
  53. {
  54. ticket=-1;
  55. price=-1;
  56. symbol=Symbol();
  57. ordertype=-1;
  58. lots=0;
  59. stoploss=0;
  60. takeprofit=0;
  61. }
  62. };
  63. masterOrder mod1[orderCount];
  64. enum operation_mode
  65. {
  66. Master, //Master
  67. Slave, //Slave
  68. };
  69. enum lotcalculator
  70. {
  71. fix, //Fixed Lot Size
  72. rsk, //Risk Percentage
  73. };
  74. sinput string string_0 = "<><><><><><> General SETTINGS <><><><><><>"; //__
  75. input int magic_no = 333; // Magic no
  76. input string suffix = ""; // Suffix
  77. input string prefix = ""; // Prefix
  78. input bool useMinimumLot = false; // Use Minimum Lot Threshold
  79. input double takeprofitTrade = 10; // Fixed Take Profit in Pips
  80. input double stoplossTrade = 10; // Fixed Stop Loss in Pips
  81. input double inpPips = 0.2; // Pips To Start Copy
  82. input double minimumLot = 0.01; // Minimum Lot
  83. input bool useMaximumLot = false; // Use Maximum Lot Threshold
  84. input double maximumLot = 0.01; // Maximum Lot
  85. input string string_0_3 = "<><><><><><> Lot Management<><><><><><>"; //__
  86. input double lot_size = 0.1; // Lot Size
  87. input lotcalculator lot_calculator = fix; // Lot Size Calculator
  88. input double risk = 0.1; // Risk in Percentage %
  89. // Heart Beat
  90. sinput string string_1 = "<><><><><><> HeartBeat Setting <><><><><><>"; //__
  91. input string slaveServer = ""; // Slave Server
  92. input string slaveId = ""; // Slave Login ID
  93. input string masterServer = ""; // Master Server
  94. input string slaveVersion = "4"; // Slave Version
  95. input string localApiKey = "U2FsdGVkX18vBY4H1uzQiZwuh8B++8VBtCGJ3yGr2XPII0qCodmfuhjssKu5oug1J4e97bkwPtDQLi4py1OODQ=="; // Local API Key
  96. input string localHB_req_link = "http://localhost/api/mlastConnected"; // Request Link For LastConnected
  97. input string dashboardSettings = "<><><><><><> Dashboard Settings<><><><><><>";
  98. input int DashHeight = 115; // Enter Height of Dashboard
  99. input int DashWidth = 490; // Enter Width of Dashboard
  100. input int FontSize = 10; // Text Font Size
  101. // Global Variables
  102. int filehandle;
  103. int gmtDifference = 0;
  104. bool doReversal = true; // Reverse Trades
  105. bool auth = false;
  106. datetime last_check_expiry;
  107. ENUM_TIMEFRAMES check_expiry_timeframe = PERIOD_H1;
  108. int orderTotal=0;
  109. bool fileLastEmpty=false;
  110. bool fileHandlerIssue=false;
  111. int counter = 0, testCounterVar = 0;
  112. int yAxisGlobal = 5;
  113. int dashHeight; // Height of Dashboard
  114. int dashWidth; // Width of Dashboard
  115. long accountNumber = AccountInfoInteger(ACCOUNT_LOGIN);
  116. operation_mode mode1=Master; //Working Mode
  117. int OnInit()
  118. {
  119. //---
  120. trade.SetExpertMagicNumber(magic_no);
  121. trade.SetDeviationInPoints(10);
  122. trade.SetTypeFilling(ORDER_FILLING_IOC);
  123. trade.LogLevel(LOG_LEVEL_ALL);
  124. trade.SetAsyncMode(false);
  125. if(!ObjectFind(0,"mode") || ObjectGetString(0,"mode",OBJPROP_TEXT,0)!=EnumToString(mode1)+" Account")
  126. {
  127. ObjectDelete(0,"mode");
  128. ObjectCreate(0,"mode",OBJ_LABEL,0,0,0);
  129. ObjectSetInteger(0,"mode",OBJPROP_XDISTANCE,10);
  130. ObjectSetInteger(0,"mode",OBJPROP_YDISTANCE,25);
  131. ObjectSetInteger(0,"mode",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  132. ObjectSetInteger(0,"mode",OBJPROP_ANCHOR,ANCHOR_RIGHT_UPPER);
  133. ObjectSetInteger(0,"mode",OBJPROP_COLOR,clrLightBlue);
  134. ObjectSetString(0,"mode",OBJPROP_TEXT,EnumToString(mode1)+" Account");
  135. ObjectSetInteger(0,"mode",OBJPROP_FONTSIZE,14);
  136. }
  137. dashHeight = DashHeight;
  138. dashWidth = DashWidth;
  139. double width = double(ChartGetInteger(0,CHART_WIDTH_IN_PIXELS));
  140. double height = double(ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS));
  141. double minHeight = (110/height) * (height);
  142. double minWidth = (480.0/width) * (width);
  143. Print(" Minimum Required minHeight = ",minHeight," minWidth ",minWidth);
  144. if(dashWidth < minWidth)
  145. {
  146. dashWidth = (int)minWidth;
  147. Print(" Dashboard width is updated because user input is less than required width ");
  148. }
  149. if(dashHeight < minHeight)
  150. {
  151. dashHeight = (int)minHeight;
  152. Print(" Dashboard Height is updated because user input is less than required Height ");
  153. }
  154. if(!ExtDialog.Create(0,"Local Hedge Master",10,10,40,dashWidth,dashHeight)) // the panel position
  155. return(INIT_FAILED);
  156. ExtDialog.Run();
  157. gmtDifference = (int)TimeCurrent() - (int)TimeGMT();
  158. Print("GMT Difference(sec): ",gmtDifference);
  159. EventSetMillisecondTimer(500);
  160. //---
  161. return(INIT_SUCCEEDED);
  162. }
  163. //+------------------------------------------------------------------+
  164. //| Expert deinitialization function |
  165. //+------------------------------------------------------------------+
  166. void OnDeinit(const int reason)
  167. {
  168. //---
  169. ExtDialog.Destroy(reason);
  170. EventKillTimer();
  171. }
  172. //+------------------------------------------------------------------+
  173. //| Expert tick function |
  174. //+------------------------------------------------------------------+
  175. void OnTimer()
  176. {
  177. gmtDifference = (int)TimeCurrent() - (int)TimeGMT();
  178. dashboard_data();
  179. remove_old_tickets_from_store();
  180. store_live_and_history_tickets();
  181. writeData();
  182. }
  183. //+------------------------------------------------------------------+
  184. //| |
  185. //+------------------------------------------------------------------+
  186. void OnTick()
  187. {
  188. //---
  189. }
  190. //+------------------------------------------------------------------+
  191. //| |
  192. //+------------------------------------------------------------------+
  193. void OnChartEvent(const int id,
  194. const long &lparam,
  195. const double &dparam,
  196. const string &sparam)
  197. {
  198. //---
  199. ExtDialog.ChartEvent(id,lparam,dparam,sparam);
  200. }
  201. //+------------------------------------------------------------------+
  202. //| |
  203. //+------------------------------------------------------------------+
  204. void writeData()
  205. {
  206. if(PositionsTotal()==0 && OrdersTotal() == 0 && !fileLastEmpty && TerminalInfoInteger(TERMINAL_CONNECTED)) // && IsConnected()
  207. {
  208. filehandle=FileOpen("COF.csv",FILE_WRITE|FILE_CSV|FILE_COMMON);
  209. if(filehandle!=INVALID_HANDLE)
  210. {
  211. Print("Writing file to empty");
  212. FileWrite(filehandle,"");
  213. FileClose(filehandle);
  214. fileLastEmpty=true;
  215. emptyStruct();
  216. }
  217. else
  218. {
  219. Print("File handler issue:",GetLastError());
  220. }
  221. }
  222. else
  223. {
  224. bool updationReq=checkOrderUpdate();
  225. if(updationReq || fileHandlerIssue)
  226. {
  227. filehandle=FileOpen("COF.csv",FILE_WRITE|FILE_CSV|FILE_COMMON);
  228. if(filehandle!=INVALID_HANDLE)
  229. {
  230. fileHandlerIssue=false;
  231. for(int i = PositionsTotal()-1 ; i >= 0 ; i--)
  232. {
  233. ulong ticket = PositionGetTicket(i);
  234. if(PositionSelectByTicket(ticket))
  235. {
  236. if(((useMinimumLot && (PositionGetDouble(POSITION_VOLUME) > minimumLot))||!useMinimumLot) &&
  237. ((useMaximumLot && (PositionGetDouble(POSITION_VOLUME) < maximumLot)) || !useMaximumLot))
  238. {
  239. string time = TimeToString(PositionGetInteger(POSITION_TIME)-gmtDifference,TIME_DATE|TIME_SECONDS);
  240. string symbol = PositionGetString(POSITION_SYMBOL);
  241. double digits=getDoubleSymbolInfo(symbol,"digits");
  242. int symbolContractSize=(int)getDoubleSymbolInfo(symbol,"contract");
  243. ulong tempTicket = PositionGetInteger(POSITION_TICKET);
  244. if(suffix != "")
  245. symbol = StringSubstr(symbol, 0, StringFind(symbol, suffix, 0));
  246. if(prefix != "")
  247. StringReplace(symbol, prefix, "");
  248. long orderType = PositionGetInteger(POSITION_TYPE);
  249. double takeProfit = PositionGetDouble(POSITION_TP), stopLoss = PositionGetDouble(POSITION_SL);
  250. if(doReversal)
  251. {
  252. if(orderType == POSITION_TYPE_BUY)
  253. orderType = POSITION_TYPE_SELL;
  254. else
  255. if(orderType == POSITION_TYPE_SELL)
  256. orderType = POSITION_TYPE_BUY;
  257. takeProfit = PositionGetDouble(POSITION_SL);
  258. stopLoss = PositionGetDouble(POSITION_TP);
  259. }
  260. string OrderToWrite = time+","+symbol+","+IntegerToString(orderType)+","+DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN), (int)digits)+","+DoubleToString(PositionGetDouble(POSITION_VOLUME),2)+","+DoubleToString(stopLoss,(int) digits)+","+DoubleToString(takeProfit, (int) digits)+","+IntegerToString(PositionGetInteger(POSITION_TICKET))+","+IntegerToString(PositionGetInteger(POSITION_MAGIC))+","+(string)AccountInfoDouble(ACCOUNT_BALANCE)+","+(string)SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_TRADE_CONTRACT_SIZE)+PositionGetString(POSITION_COMMENT)+"\r\n";
  261. FileWrite(filehandle,OrderToWrite);
  262. }
  263. }
  264. }
  265. for(int i = OrdersTotal()-1 ; i >= 0 ; i--)
  266. {
  267. ulong ticket = OrderGetTicket(i);
  268. if(OrderSelect(ticket))
  269. {
  270. if(((useMinimumLot && (OrderGetDouble(ORDER_VOLUME_CURRENT) > minimumLot))||!useMinimumLot) &&
  271. ((useMaximumLot && (OrderGetDouble(ORDER_VOLUME_CURRENT) < maximumLot))||!useMaximumLot))
  272. {
  273. string time = TimeToString(OrderGetInteger(ORDER_TIME_SETUP)-gmtDifference,TIME_DATE|TIME_SECONDS);
  274. string symbol = OrderGetString(ORDER_SYMBOL);
  275. double digits=getDoubleSymbolInfo(symbol,"digits");
  276. int symbolContractSize=(int)getDoubleSymbolInfo(symbol,"contract");
  277. ulong tempTicket = OrderGetInteger(ORDER_TICKET);
  278. if(suffix != "")
  279. symbol = StringSubstr(symbol, 0, StringFind(symbol, suffix, 0));
  280. if(prefix != "")
  281. StringReplace(symbol, prefix, "");
  282. long orderType = OrderGetInteger(ORDER_TYPE);
  283. double takeProfit = OrderGetDouble(ORDER_TP), stopLoss = OrderGetDouble(ORDER_SL);
  284. if(doReversal)
  285. {
  286. if(orderType == ORDER_TYPE_BUY_STOP)
  287. orderType = ORDER_TYPE_SELL_LIMIT;
  288. else
  289. if(orderType == ORDER_TYPE_SELL_STOP)
  290. orderType = ORDER_TYPE_BUY_LIMIT;
  291. else
  292. if(orderType == ORDER_TYPE_BUY_LIMIT)
  293. orderType = ORDER_TYPE_SELL_STOP;
  294. else
  295. if(orderType == ORDER_TYPE_SELL_LIMIT)
  296. orderType = ORDER_TYPE_BUY_STOP;
  297. takeProfit = OrderGetDouble(ORDER_SL);
  298. stopLoss = OrderGetDouble(ORDER_TP);
  299. }
  300. string OrderToWrite = time+","+symbol+","+IntegerToString(orderType)+","+DoubleToString(OrderGetDouble(ORDER_PRICE_OPEN), (int)digits)+","+DoubleToString(OrderGetDouble(ORDER_VOLUME_CURRENT),2)+","+DoubleToString(stopLoss,(int) digits)+","+DoubleToString(takeProfit, (int) digits)+","+IntegerToString(OrderGetInteger(ORDER_TICKET))+","+IntegerToString(OrderGetInteger(ORDER_MAGIC))+","+(string)AccountInfoDouble(ACCOUNT_BALANCE)+","+(string)SymbolInfoDouble(OrderGetString(ORDER_SYMBOL),SYMBOL_TRADE_CONTRACT_SIZE)+OrderGetString(ORDER_COMMENT)+"\r\n";
  301. Print("Writing Pending Order Block.");
  302. FileWrite(filehandle,OrderToWrite);
  303. }
  304. }
  305. }
  306. FileClose(filehandle);
  307. fileLastEmpty=false;
  308. Print("File Updated:",TimeCurrent());
  309. }
  310. else
  311. {
  312. Print("File Handle Issue: ", GetLastError());
  313. }
  314. }
  315. else
  316. {
  317. if(counter>=count1 && TerminalInfoInteger(TERMINAL_CONNECTED))
  318. {
  319. if(testCounterVar>=testCounter)
  320. {
  321. testCounterVar=0;
  322. }
  323. adminHeartBeat();
  324. counter=0;
  325. }
  326. counter++;
  327. testCounterVar++;
  328. }
  329. }
  330. }
  331. //+------------------------------------------------------------------+
  332. //| |
  333. //+------------------------------------------------------------------+
  334. void adminHeartBeat()
  335. {
  336. string headers = "apikey:"+localApiKey+"\r\naccept: */* \r\nContent-Type: application/json\r\nUser-Agent: MetaTraderApi";
  337. string url =localHB_req_link;// Request_link+(string)accountNumber;
  338. bool isPost;
  339. int timeout = 100000;
  340. string lastConnected=TimeToString(TimeCurrent());
  341. StringReplace(lastConnected,".","-");
  342. StringReplace(lastConnected," ","T");
  343. string gmtTime=TimeToString(TimeGMT());
  344. string jsonData="{\"mLogin\":\""+(string)accountNumber+"\",\"mServer\":\""+masterServer+"\",\"mVersion\":\"5\" ,\"sLogin\":\""+slaveId+"\",\"sServer\":\""+slaveServer+"\",\"sVersion\":\""+slaveVersion+"\" ,\"mLastConnected\":\""+gmtTime+"\"}";//\",\"url\":"+"\""+url+"\""+headers+"}";
  345. uchar data[];
  346. StringToCharArray(jsonData, data, 0, StringLen(jsonData));
  347. // Print("Making the heart beat request to the local host");
  348. POST_function(url,headers,timeout,data,isPost);
  349. }
  350. //+------------------------------------------------------------------+
  351. //| |
  352. //+------------------------------------------------------------------+
  353. bool POST_function(string url, string headers, int timeout, uchar &data[], bool &IsPost)
  354. {
  355. ResetLastError(); // clear previous error
  356. static int lastErrorPrinted = 0;
  357. uchar result[]; // use uchar for WebRequest result
  358. string resultHeaders;
  359. int res = WebRequest("POST", url, headers, timeout, data, result, resultHeaders);
  360. if(res == 200 || res == 201)
  361. {
  362. Print("***Request success. HTTP response code POST: ", res);
  363. string result_string = CharArrayToString(result);
  364. Print("content POST: ", result_string);
  365. lastErrorPrinted = 0; // reset remembered error on success
  366. IsPost = true;
  367. return true;
  368. }
  369. else
  370. {
  371. int err = GetLastError(); // read the error once
  372. // only print when there's a real error and it's different from last time
  373. if(err != 0 && err != lastErrorPrinted)
  374. {
  375. Print("Get last error: ", err);
  376. Print("***Request failed. HTTP response code: ", res);
  377. string result_string = CharArrayToString(result);
  378. Print("content: ", result_string);
  379. lastErrorPrinted = err; // remember this error so we don't spam it
  380. }
  381. IsPost = false;
  382. return false;
  383. }
  384. }
  385. //+------------------------------------------------------------------+
  386. //| |
  387. //+------------------------------------------------------------------+
  388. void removeDeleteOrderMaster()
  389. {
  390. for(int i=0; i<orderCount; i++)
  391. {
  392. bool isPresent=false;
  393. if(mod1[i].ticket!=-1)
  394. {
  395. for(int j = PositionsTotal()-1; j>=0; j--)
  396. {
  397. ulong ticket = PositionGetTicket(j);
  398. if(PositionSelectByTicket(ticket))
  399. {
  400. if(ticket==mod1[i].ticket)
  401. {
  402. isPresent=true;
  403. }
  404. }
  405. }
  406. if(!isPresent)
  407. {
  408. Print("The order ticket:",mod1[i].ticket," found no more");
  409. //delete from list
  410. mod1[i].ticket=-1;
  411. }
  412. }
  413. }
  414. }
  415. //+------------------------------------------------------------------+
  416. //| |
  417. //+------------------------------------------------------------------+
  418. bool checkorderpips(double openPrice,int type,string symbol)
  419. {
  420. double points = inpPips*10*SymbolInfoDouble(symbol,SYMBOL_POINT);
  421. if(type == 0)
  422. {
  423. if(SymbolInfoDouble(symbol,SYMBOL_ASK) - openPrice > points)
  424. {
  425. return true;
  426. }
  427. }
  428. else
  429. {
  430. if(openPrice - SymbolInfoDouble(symbol,SYMBOL_BID) > points)
  431. {
  432. return true;
  433. }
  434. }
  435. return false;
  436. }
  437. //+------------------------------------------------------------------+
  438. //| |
  439. //+------------------------------------------------------------------+
  440. bool isOrderThere(ulong ticket,int &index)
  441. {
  442. for(int i=0; i<ArraySize(mod1); i++)
  443. {
  444. if(ticket != -1)
  445. {
  446. if(mod1[i].ticket==ticket)
  447. {
  448. index=i;
  449. return true;
  450. }
  451. }
  452. }
  453. return false;
  454. }
  455. //+------------------------------------------------------------------+
  456. //| |
  457. //+------------------------------------------------------------------+
  458. bool addOrderMaster(ulong ticket, string calledBy)
  459. {
  460. for(int i=0; i<ArraySize(mod1); i++)
  461. {
  462. if(mod1[i].ticket==-1)
  463. {
  464. if(calledBy == "Market")
  465. {
  466. //ulong ticket = PositionGetTicket(orderTicket);
  467. if(PositionSelectByTicket(ticket))
  468. {
  469. //Symbol Updation
  470. string symbol=PositionGetString(POSITION_SYMBOL);
  471. if(suffix!="")
  472. symbol = StringSubstr(symbol,0,StringFind(PositionGetString(POSITION_SYMBOL),suffix,0));
  473. if(prefix!="")
  474. StringReplace(symbol,prefix,"");
  475. //Digits
  476. double digits=getDoubleSymbolInfo(PositionGetString(POSITION_SYMBOL),"digits");
  477. //time
  478. datetime time = (datetime)(PositionGetInteger(POSITION_TIME)-gmtDifference);
  479. mod1[i].opentime=time;
  480. mod1[i].symbol=symbol;
  481. mod1[i].ordertype=PositionGetInteger(POSITION_TYPE);
  482. mod1[i].price=NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN),(int)digits);
  483. mod1[i].lots=NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2);
  484. mod1[i].stoploss=NormalizeDouble(PositionGetDouble(POSITION_SL),(int)digits);
  485. mod1[i].takeprofit=NormalizeDouble(PositionGetDouble(POSITION_TP),(int)digits);
  486. mod1[i].ticket=PositionGetInteger(POSITION_TICKET);
  487. mod1[i].magic=(int)PositionGetInteger(POSITION_MAGIC);
  488. mod1[i].comment=PositionGetString(POSITION_COMMENT);
  489. Print("Ticket:",PositionGetInteger(POSITION_TICKET)," stored in index:",i);
  490. return true;
  491. }
  492. }
  493. if(calledBy == "Pending")
  494. {
  495. if(OrderSelect(ticket))
  496. {
  497. string symbol = OrderGetString(ORDER_SYMBOL);
  498. if(suffix!="")
  499. symbol = StringSubstr(symbol,0,StringFind(OrderGetString(ORDER_SYMBOL),suffix,0));
  500. if(prefix!="")
  501. StringReplace(symbol,prefix,"");
  502. //Digits
  503. double digits=getDoubleSymbolInfo(OrderGetString(ORDER_SYMBOL),"digits");
  504. //time
  505. datetime time = (datetime)(OrderGetInteger(ORDER_TIME_SETUP) - gmtDifference);
  506. mod1[i].opentime=time;
  507. mod1[i].symbol=symbol;
  508. mod1[i].ordertype=OrderGetInteger(ORDER_TYPE);
  509. mod1[i].price=NormalizeDouble(OrderGetDouble(ORDER_PRICE_OPEN),(int)digits);
  510. mod1[i].lots=NormalizeDouble(OrderGetDouble(ORDER_VOLUME_CURRENT),2);
  511. mod1[i].stoploss=NormalizeDouble(OrderGetDouble(ORDER_SL),(int)digits);
  512. mod1[i].takeprofit=NormalizeDouble(OrderGetDouble(ORDER_TP),(int)digits);
  513. mod1[i].ticket=OrderGetInteger(ORDER_TICKET);
  514. mod1[i].magic=(int)OrderGetInteger(ORDER_MAGIC);
  515. mod1[i].comment=OrderGetString(ORDER_COMMENT);
  516. Print("Ticket: ",OrderGetInteger(ORDER_TICKET)," stored in index by pending order:",i);
  517. return true;
  518. }
  519. }
  520. }
  521. }
  522. return false;
  523. }
  524. //+------------------------------------------------------------------+
  525. //| |
  526. //+------------------------------------------------------------------+
  527. void emptyStruct()
  528. {
  529. for(int i = 0 ; i < orderCount ; i++)
  530. {
  531. if(mod1[i].ticket != -1)
  532. {
  533. mod1[i].ticket=-1;
  534. mod1[i].price=-1;
  535. mod1[i].symbol="";
  536. mod1[i].ordertype=-1;
  537. mod1[i].lots=0;
  538. mod1[i].stoploss=0;
  539. mod1[i].takeprofit=0;
  540. }
  541. }
  542. }
  543. //+------------------------------------------------------------------+
  544. //| |
  545. //+------------------------------------------------------------------+
  546. bool checkOrderUpdate()
  547. {
  548. bool updationRequired=false,currCheck=false;
  549. for(int i = PositionsTotal()-1 ; i >= 0 ; i--)
  550. {
  551. ulong ticket = PositionGetTicket(i);
  552. if(PositionSelectByTicket(ticket))
  553. {
  554. int orderIndex=-1;
  555. bool alreadyAdded=isOrderThere(ticket, orderIndex);
  556. if(!alreadyAdded)
  557. {
  558. currCheck=false;
  559. currCheck=addOrderMaster(ticket, "Market");
  560. if(!updationRequired)
  561. updationRequired=currCheck;
  562. }
  563. else
  564. {
  565. if(orderIndex!=-1)
  566. {
  567. currCheck=false;
  568. currCheck=IsOrderChanged(PositionGetInteger(POSITION_TICKET),orderIndex, "Market");
  569. if(!updationRequired)
  570. {
  571. updationRequired=currCheck;
  572. }
  573. }
  574. }
  575. }
  576. }
  577. for(int i = OrdersTotal()-1 ; i >= 0 ; i--)
  578. {
  579. ulong ticket = OrderGetTicket(i);
  580. if(OrderSelect(ticket))
  581. {
  582. if(OrderGetInteger(ORDER_TYPE) != ORDER_TYPE_BUY && OrderGetInteger(ORDER_TYPE) != ORDER_TYPE_SELL && OrderGetInteger(ORDER_TYPE) != ORDER_TYPE_CLOSE_BY)
  583. {
  584. int orderIndex=-1;
  585. bool alreadyAdded=isOrderThere(ticket, orderIndex);
  586. if(!alreadyAdded)
  587. {
  588. Print("Inside pending Adding to master order: ",ticket," type: ",OrderGetInteger(ORDER_TYPE)," ",OrdersTotal()," ",ORDER_TYPE_CLOSE_BY);
  589. currCheck=false;
  590. currCheck=addOrderMaster(ticket, "Pending");
  591. if(!updationRequired)
  592. updationRequired=currCheck;
  593. }
  594. else
  595. {
  596. if(orderIndex!=-1)
  597. {
  598. currCheck=false;
  599. currCheck=IsOrderChanged(OrderGetInteger(ORDER_TICKET), orderIndex, "Pending");
  600. if(!updationRequired)
  601. {
  602. updationRequired=currCheck;
  603. }
  604. }
  605. }
  606. }
  607. }
  608. }
  609. for(int i=0; i<ArraySize(mod1); i++)
  610. {
  611. bool isPresent=false;
  612. if(mod1[i].ticket !=-1)
  613. {
  614. for(int j = PositionsTotal()-1; j>=0; j--)
  615. {
  616. ulong ticket = PositionGetTicket(j);
  617. if(PositionSelectByTicket(ticket))
  618. {
  619. if(ticket==mod1[i].ticket)
  620. {
  621. isPresent=true;
  622. break;
  623. }
  624. }
  625. }
  626. // Pending Order
  627. for(int j = OrdersTotal()-1; j>=0; j--)
  628. {
  629. ulong ticket = OrderGetTicket(j);
  630. if(OrderSelect(ticket))
  631. {
  632. if(ticket==mod1[i].ticket)
  633. {
  634. isPresent=true;
  635. break;
  636. }
  637. }
  638. }
  639. if(!isPresent)
  640. {
  641. Print("Ticket is closed so removed from struct: ",mod1[i].ticket);
  642. mod1[i].ticket=-1;
  643. mod1[i].price=-1;
  644. mod1[i].symbol="";
  645. mod1[i].ordertype=-1;
  646. mod1[i].lots=0;
  647. mod1[i].stoploss=0;
  648. mod1[i].takeprofit=0;
  649. currCheck=true;
  650. //currCheck=clearStructIndex(mod1[i].ticket);
  651. if(!updationRequired)
  652. updationRequired=currCheck;
  653. }
  654. }
  655. }
  656. return updationRequired;
  657. }
  658. //+------------------------------------------------------------------+
  659. //| |
  660. //+------------------------------------------------------------------+
  661. bool clearStructIndex(ulong ticket)
  662. {
  663. for(int index=0; index<ArraySize(mod1); index++)
  664. {
  665. if(mod1[index].ticket == ticket)
  666. {
  667. mod1[index].ticket=-1;
  668. mod1[index].price=-1;
  669. mod1[index].symbol="";
  670. mod1[index].ordertype=-1;
  671. mod1[index].lots=0;
  672. mod1[index].stoploss=0;
  673. mod1[index].takeprofit=0;
  674. Print("Clear Structure Called. ");
  675. return true;
  676. }
  677. }
  678. return false;
  679. }
  680. //+------------------------------------------------------------------+
  681. //| |
  682. //+------------------------------------------------------------------+
  683. bool IsOrderChanged(ulong orderTicket, int index, string calledBy)
  684. {
  685. if(mod1[index].ticket!=-1)
  686. {
  687. if(calledBy == "Market")
  688. {
  689. if(PositionSelectByTicket(orderTicket))
  690. {
  691. //Digits
  692. double digits=getDoubleSymbolInfo(PositionGetString(POSITION_SYMBOL),"digits");
  693. double tp=NormalizeDouble(PositionGetDouble(POSITION_TP), (int)digits),
  694. sl=NormalizeDouble(PositionGetDouble(POSITION_SL),(int)digits),
  695. lot=NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2);
  696. if(mod1[index].takeprofit!=tp || mod1[index].stoploss != sl || mod1[index].lots!=lot || mod1[index].ordertype!=PositionGetInteger(POSITION_TYPE) || mod1[index].price != PositionGetDouble(POSITION_PRICE_OPEN))
  697. {
  698. Print(" Inside IsOrderChanged() ",mod1[index].lots," lot: ",lot," calledBy: ",calledBy," mod1 ticket ",mod1[index].ticket," orderTicket: ",orderTicket);
  699. // Time
  700. datetime time = (datetime)(PositionGetInteger(POSITION_TIME) - gmtDifference);
  701. mod1[index].opentime=time;
  702. mod1[index].lots=lot;
  703. mod1[index].stoploss=sl;
  704. mod1[index].takeprofit=tp;
  705. mod1[index].comment=PositionGetString(POSITION_COMMENT);
  706. mod1[index].ordertype=PositionGetInteger(POSITION_TYPE);
  707. mod1[index].price=PositionGetDouble(POSITION_PRICE_OPEN);
  708. return true;
  709. }
  710. }
  711. }
  712. if(calledBy == "Pending")
  713. {
  714. if(OrderSelect(orderTicket))
  715. {
  716. double digits=getDoubleSymbolInfo(OrderGetString(ORDER_SYMBOL),"digits");
  717. double tp=NormalizeDouble(OrderGetDouble(ORDER_TP), (int)digits),
  718. sl=NormalizeDouble(OrderGetDouble(ORDER_SL),(int)digits),
  719. lot=NormalizeDouble(OrderGetDouble(ORDER_VOLUME_CURRENT),2);
  720. if(mod1[index].takeprofit!=tp || mod1[index].stoploss != sl || mod1[index].lots!=lot || mod1[index].ordertype!=OrderGetInteger(ORDER_TYPE) || mod1[index].price != OrderGetDouble(ORDER_PRICE_OPEN))
  721. {
  722. //time
  723. datetime time = (datetime)(OrderGetDouble(ORDER_PRICE_OPEN) - gmtDifference);
  724. mod1[index].opentime=time;
  725. mod1[index].lots=lot;
  726. mod1[index].stoploss=sl;
  727. mod1[index].takeprofit=tp;
  728. mod1[index].comment=OrderGetString(ORDER_COMMENT);
  729. mod1[index].ordertype=OrderGetInteger(ORDER_TYPE);
  730. mod1[index].price=OrderGetDouble(ORDER_PRICE_OPEN);
  731. return true;
  732. }
  733. }
  734. }
  735. }
  736. return false;
  737. }
  738. //+------------------------------------------------------------------+
  739. //| |
  740. //+------------------------------------------------------------------+
  741. double getlot(double stop_loss)
  742. {
  743. Print("Tick Value: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE));
  744. Print("Tick Size: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE));
  745. double modeTickV=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)
  746. ,modeTickS=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE);
  747. // Print("Pip value: ", NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point))*10),2));
  748. double pipvalue = NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point()))*10),2);
  749. // pipvalue=NormalizeDouble((modeTickV/modeTickS/Point()),)
  750. // pipvalue=
  751. pipvalue = pipvalue / 10;
  752. double lotSize = lot_size;
  753. if(lot_calculator==rsk) //calculating risk
  754. {
  755. double riskamount=(risk/100)*AccountInfoDouble(ACCOUNT_BALANCE);
  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. double getDoubleSymbolInfo(string symbol,string info)
  787. {
  788. long digits=8;
  789. //Symbol without the suffix and prefix
  790. string updatedSymbol=symbol;
  791. if(suffix!="")
  792. updatedSymbol = StringSubstr(updatedSymbol,0,StringFind(updatedSymbol,suffix,0));
  793. if(prefix!="")
  794. StringReplace(updatedSymbol,prefix,"");
  795. //Digits calculation could be used in other calculations
  796. digits = SymbolInfoInteger(symbol,SYMBOL_DIGITS);
  797. if(digits==0)
  798. {
  799. digits=SymbolInfoInteger(updatedSymbol,SYMBOL_DIGITS);
  800. if(digits==0)
  801. digits=8;
  802. }
  803. if(info=="digits")
  804. {
  805. return (double)digits;
  806. }
  807. else
  808. if(info=="point" || info=="points")
  809. {
  810. double points=SymbolInfoDouble(symbol, SYMBOL_POINT);
  811. if(points==0)
  812. {
  813. points=SymbolInfoDouble(updatedSymbol,SYMBOL_POINT);
  814. if(points==0)
  815. points=0.00001;
  816. }
  817. return points;
  818. }
  819. else
  820. if(info=="ask")
  821. {
  822. double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
  823. if(ask==0)
  824. {
  825. ask=SymbolInfoDouble(updatedSymbol,SYMBOL_ASK);
  826. }
  827. return NormalizeDouble(ask,(int)digits);
  828. }
  829. else
  830. if(info=="bid")
  831. {
  832. double bid=SymbolInfoDouble(symbol, SYMBOL_BID);
  833. if(bid==0)
  834. {
  835. bid=SymbolInfoDouble(updatedSymbol,SYMBOL_BID);
  836. }
  837. return NormalizeDouble(bid,(int)digits);
  838. }
  839. else
  840. if(info=="contract"||info=="contractSize")
  841. {
  842. double contract=SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
  843. if(contract==0)
  844. {
  845. contract=SymbolInfoDouble(updatedSymbol,SYMBOL_TRADE_CONTRACT_SIZE);
  846. }
  847. return contract;
  848. }
  849. return 0;
  850. }
  851. //+------------------------------------------------------------------+
  852. //| |
  853. //+------------------------------------------------------------------+
  854. void placeBuyTrade()
  855. {
  856. double buySL = 0, buyTp=0;
  857. //openPrice = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  858. double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  859. double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  860. if(stoplossTrade != 0)
  861. {
  862. buySL = Ask - (stoplossTrade * 10 * Point());
  863. }
  864. if(takeprofitTrade != 0)
  865. {
  866. buyTp = Ask + (takeprofitTrade * 10 * Point());
  867. }
  868. double sl_distance = ((Ask - buySL) / Point());
  869. if(trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,getlot(sl_distance),Ask,buySL,buyTp,"Buy Trade Placed"))
  870. {
  871. Print("Buy Trade Placed: ",trade.ResultOrder());
  872. }
  873. else
  874. {
  875. Print("Error in placing Buy: "+Symbol()+" ",GetLastError());
  876. }
  877. }
  878. //+------------------------------------------------------------------+
  879. //| |
  880. //+------------------------------------------------------------------+
  881. void placeSellTrade()
  882. {
  883. double sellSL = 0, sellTp = 0;
  884. //openPrice = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  885. double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  886. double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
  887. if(stoplossTrade != 0)
  888. {
  889. sellSL = Bid + (stoplossTrade * 10 * Point());
  890. }
  891. if(takeprofitTrade != 0)
  892. {
  893. sellTp = Bid - (takeprofitTrade * 10 * Point());
  894. }
  895. double sl_distance = ((sellSL - Bid) / Point());
  896. if(trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,getlot(sl_distance),Bid,sellSL,sellTp,"Sell Trade Placed"))
  897. {
  898. Print("Sell Trade PLaced: ",trade.ResultOrder());
  899. }
  900. else
  901. {
  902. Print("Error in placing Sell: "+Symbol()+" ",GetLastError());
  903. }
  904. }
  905. //+------------------------------------------------------------------+
  906. //| |
  907. //+------------------------------------------------------------------+
  908. void dashboard_data()
  909. {
  910. ExtDialog.m_label0.Text(" Master Trades Lots Calc: " + DoubleToString(totalLiveLots(), 2));
  911. }
  912. //+------------------------------------------------------------------+
  913. //| |
  914. //+------------------------------------------------------------------+
  915. double totalLiveLots()
  916. {
  917. double total_lots = 0.0;
  918. for(int i = 0; i < PositionsTotal(); i++)
  919. {
  920. ulong ticket = PositionGetTicket(i);
  921. if(PositionSelectByTicket(ticket))
  922. {
  923. //if(PositionGetInteger(POSITION_MAGIC) == magic_no)
  924. {
  925. //if(PositionGetString(POSITION_SYMBOL) == Symbol())
  926. {
  927. int type = (int)PositionGetInteger(POSITION_TYPE);
  928. if(type == POSITION_TYPE_BUY || type == POSITION_TYPE_SELL)
  929. {
  930. total_lots += PositionGetDouble(POSITION_VOLUME);
  931. }
  932. }
  933. }
  934. }
  935. }
  936. return total_lots;
  937. }
  938. //+------------------------------------------------------------------+
  939. //| |
  940. //+------------------------------------------------------------------+
  941. void store_live_and_history_tickets()
  942. {
  943. // cutoff time = now - N days
  944. datetime cutoff = (datetime)(TimeCurrent() - (datetime)daysOfTradesToAdd * 86400);
  945. // --- history orders loop (closed / cancelled / executed orders) ---
  946. // select history for the required period
  947. if(HistorySelect(cutoff, TimeCurrent()))
  948. {
  949. int deals_count = (int)HistoryDealsTotal();
  950. for(int j = deals_count - 1; j >= 0; --j)
  951. {
  952. ulong deal_ticket = HistoryDealGetTicket(j);
  953. if(deal_ticket == 0)
  954. continue;
  955. // deal execution time
  956. long dealTime = (long)HistoryDealGetInteger(deal_ticket, DEAL_TIME);
  957. if((datetime)dealTime < cutoff)
  958. continue; // older than cutoff, skip
  959. // position id related to this deal (the stored "ticket" you track)
  960. long position_id = (long)HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID);
  961. if(position_id <= 0)
  962. continue; // no position id to store
  963. if(HistoryDealGetInteger(deal_ticket, DEAL_ENTRY) != DEAL_ENTRY_IN)
  964. continue;
  965. ulong ticket = position_id;
  966. ulong magic = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
  967. double dealInLot = HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
  968. double dealOutLot = dealOutLotsCheck(cutoff, position_id);
  969. if(dealInLot == dealOutLot)
  970. if(!history_ticket_present(ticket))
  971. {
  972. Print(" Position Id: ", position_id," Deal In Lot: ", dealInLot, " Deal Out Lot: ", dealOutLot);
  973. add_history_ticket(ticket, magic);
  974. }
  975. }
  976. }
  977. else
  978. {
  979. // optional: failed to select history — you may handle/log if needed
  980. // Print("HistorySelect failed. LastError=", GetLastError());
  981. }
  982. int ordersTotal=HistoryOrdersTotal();
  983. ulong orderTicket=0;
  984. for(int j=0; j<ordersTotal; j++)
  985. {
  986. orderTicket=HistoryOrderGetTicket(j);
  987. long type=HistoryOrderGetInteger(orderTicket,ORDER_TYPE);
  988. if(type==ORDER_TYPE_BUY_LIMIT || type==ORDER_TYPE_SELL_LIMIT || type==ORDER_TYPE_BUY_STOP
  989. || type==ORDER_TYPE_SELL_STOP ||type==ORDER_TYPE_BUY_STOP_LIMIT || type==ORDER_TYPE_SELL_STOP_LIMIT)
  990. {
  991. long state=HistoryOrderGetInteger(orderTicket,ORDER_STATE);
  992. if(state==ORDER_STATE_CANCELED || state==ORDER_STATE_REJECTED || state==ORDER_STATE_EXPIRED || state==ORDER_STATE_REQUEST_CANCEL)
  993. {
  994. datetime openTime = (datetime)HistoryOrderGetInteger(orderTicket, ORDER_TIME_SETUP);
  995. if(openTime >= cutoff)
  996. {
  997. ulong magic = HistoryOrderGetInteger(orderTicket, ORDER_MAGIC);
  998. if(!history_ticket_present(orderTicket))
  999. {
  1000. add_history_ticket(orderTicket, magic);
  1001. }
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. //+------------------------------------------------------------------+
  1008. //| |
  1009. //+------------------------------------------------------------------+
  1010. double dealOutLotsCheck(datetime cutOffTimeIs, ulong positionId)
  1011. {
  1012. double sumOfLots = 0.0;
  1013. if(HistorySelect(cutOffTimeIs, TimeCurrent()))
  1014. {
  1015. int totalDeals = HistoryDealsTotal();
  1016. for(int i = 0; i < totalDeals; i++)
  1017. {
  1018. ulong dealTicket = HistoryDealGetTicket(i);
  1019. ulong dealPositionID = (ulong)HistoryDealGetInteger(dealTicket, DEAL_POSITION_ID);
  1020. if(HistoryDealGetInteger(dealTicket, DEAL_ENTRY) == DEAL_ENTRY_OUT
  1021. && dealPositionID == positionId)
  1022. {
  1023. sumOfLots += HistoryDealGetDouble(dealTicket, DEAL_VOLUME);
  1024. }
  1025. }
  1026. }
  1027. return sumOfLots;
  1028. }
  1029. //+------------------------------------------------------------------+
  1030. //| |
  1031. //+------------------------------------------------------------------+
  1032. bool history_ticket_present(ulong ticket)
  1033. {
  1034. for(int i = 0 ; i < MaxOrders ; i++)
  1035. {
  1036. if(historyTradeStore[i].ticket == ticket)
  1037. return true;
  1038. }
  1039. return false;
  1040. }
  1041. //+------------------------------------------------------------------+
  1042. //| |
  1043. //+------------------------------------------------------------------+
  1044. void add_history_ticket(ulong ticket, ulong magicIs)
  1045. {
  1046. for(int i = 0; i < MaxOrders; i++)
  1047. {
  1048. if(historyTradeStore[i].ticket == -1)
  1049. {
  1050. historyTradeStore[i].ticket = ticket;
  1051. historyTradeStore[i].magic = magicIs;
  1052. Print("Ticket Added to History Structure. Ticket: ", ticket, " Magic: ", magicIs);
  1053. save_history_store("add_history_ticket()");
  1054. return;
  1055. }
  1056. }
  1057. Print("historyTradeStore full, cannot add ticket: ", ticket);
  1058. }
  1059. //+------------------------------------------------------------------+
  1060. //| |
  1061. //+------------------------------------------------------------------+
  1062. void clear_history_store()
  1063. {
  1064. for(int i = 0; i < MaxOrders; i++)
  1065. {
  1066. historyTradeStore[i].ticket = -1;
  1067. historyTradeStore[i].magic = 0;
  1068. }
  1069. Print("History store cleaned");
  1070. }
  1071. //+------------------------------------------------------------------+
  1072. //| |
  1073. //+------------------------------------------------------------------+
  1074. void save_history_store(string calledBy)
  1075. {
  1076. string file_nameIs = "history_trades.csv";
  1077. int fileHandle = FileOpen(file_nameIs, FILE_WRITE | FILE_CSV | FILE_COMMON);
  1078. if(fileHandle != INVALID_HANDLE)
  1079. {
  1080. for(int i = 0; i < MaxOrders; i++)
  1081. {
  1082. if(historyTradeStore[i].ticket != -1)
  1083. {
  1084. string data_to_store = IntegerToString(historyTradeStore[i].ticket) + "," + IntegerToString(historyTradeStore[i].magic) + "\r\n";
  1085. FileWriteString(fileHandle, data_to_store);
  1086. }
  1087. }
  1088. //Print("save_history_store() called by: ", calledBy, " Time: ", TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS));
  1089. FileClose(fileHandle);
  1090. }
  1091. else
  1092. {
  1093. Print("Error opening file save_history_store(): ", GetLastError());
  1094. }
  1095. }
  1096. //+------------------------------------------------------------------+
  1097. //| |
  1098. //+------------------------------------------------------------------+
  1099. void remove_old_tickets_from_store()
  1100. {
  1101. datetime cutoff = TimeCurrent() - (datetime)daysOfTradesToAdd * 86400;
  1102. // Print("remove_old_tickets_from_store: cutoff = ", TimeToString(cutoff, TIME_DATE|TIME_SECONDS));
  1103. // Prepare history selection ranges once (for deals we limit by cutoff; for orders we select full history)
  1104. for(int i = 0; i < MaxOrders; i++)
  1105. {
  1106. ulong tk = historyTradeStore[i].ticket;
  1107. if(tk == -1) // empty slot
  1108. continue;
  1109. bool found = false;
  1110. ulong pos_ticket = (ulong)tk;
  1111. if(HistorySelect(cutoff, TimeCurrent()))
  1112. {
  1113. int deals_count = (int)HistoryDealsTotal();
  1114. for(int j = deals_count - 1; j >= 0; --j)
  1115. {
  1116. ulong deal_ticket = HistoryDealGetTicket(j);
  1117. if(deal_ticket == 0)
  1118. continue;
  1119. // deal execution time
  1120. long dealTime = (long)HistoryDealGetInteger(deal_ticket, DEAL_TIME);
  1121. if((datetime)dealTime < cutoff)
  1122. continue; // older than cutoff, skip
  1123. if(HistoryDealGetInteger(deal_ticket, DEAL_ENTRY) != DEAL_ENTRY_IN)
  1124. continue;
  1125. // position id related to this deal (the stored "ticket" you track)
  1126. long position_id = (long)HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID);
  1127. if(position_id <= 0)
  1128. continue; // no position id to store
  1129. double dealInLot = HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
  1130. double dealOutLot = dealOutLotsCheck(cutoff, position_id);
  1131. if(dealInLot == dealOutLot)
  1132. if(position_id == pos_ticket)
  1133. {
  1134. found = true;
  1135. break;
  1136. }
  1137. }
  1138. }
  1139. else
  1140. {
  1141. // optional: failed to select history — you may handle/log if needed
  1142. // Print("HistorySelect failed. LastError=", GetLastError());
  1143. }
  1144. if(!found)
  1145. {
  1146. int ordersTotal = HistoryOrdersTotal();
  1147. for(int j = 0; j < ordersTotal; j++)
  1148. {
  1149. ulong orderTicket = HistoryOrderGetTicket(j);
  1150. if(orderTicket == 0)
  1151. continue;
  1152. long type = HistoryOrderGetInteger(orderTicket, ORDER_TYPE);
  1153. if(type != ORDER_TYPE_BUY_LIMIT && type != ORDER_TYPE_SELL_LIMIT &&
  1154. type != ORDER_TYPE_BUY_STOP && type != ORDER_TYPE_SELL_STOP)
  1155. continue;
  1156. datetime openTime = (datetime)HistoryOrderGetInteger(orderTicket, ORDER_TIME_SETUP);
  1157. long state=HistoryOrderGetInteger(orderTicket,ORDER_STATE);
  1158. if(state==ORDER_STATE_CANCELED || state==ORDER_STATE_REJECTED || state==ORDER_STATE_EXPIRED || state==ORDER_STATE_REQUEST_CANCEL)
  1159. {
  1160. if(orderTicket == pos_ticket)
  1161. {
  1162. if(openTime > cutoff)
  1163. {
  1164. found = true;
  1165. break;
  1166. }
  1167. }
  1168. }
  1169. }
  1170. }
  1171. // 3) Final action: remove if not found
  1172. if(!found)
  1173. {
  1174. Print("Ticket not found, removing from store: ", tk, " index=", i);
  1175. historyTradeStore[i].ticket = -1;
  1176. historyTradeStore[i].magic = 0;
  1177. // (optionally clear other fields if your struct has them)
  1178. }
  1179. } // for i
  1180. }
  1181. //+------------------------------------------------------------------+
  1182. //+------------------------------------------------------------------+
  1183. //| |
  1184. //+------------------------------------------------------------------+
  1185. //================================================ Dashboard ====================================
  1186. //+------------------------------------------------------------------+
  1187. //| |
  1188. //+------------------------------------------------------------------+
  1189. class CControlsDialog : public CAppDialog
  1190. {
  1191. public:
  1192. CLabel m_label0;
  1193. CButton m_button;
  1194. CButton m_button1;
  1195. CControlsDialog(void);
  1196. ~CControlsDialog(void);
  1197. //--- create
  1198. virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
  1199. virtual bool OnEvent(const int id, const long &lparam,const double &dparam, const string &sparam);
  1200. bool CreateLabel0(void);
  1201. bool CreateButton(void);
  1202. bool CreateButton1(void);
  1203. void OnClickButton(void);
  1204. void OnClickButton1(void);
  1205. bool CreatePanel(void);
  1206. };
  1207. //+------------------------------------------------------------------+
  1208. //| |
  1209. //+------------------------------------------------------------------+
  1210. EVENT_MAP_BEGIN(CControlsDialog)
  1211. ON_EVENT(ON_CLICK,m_button,OnClickButton)
  1212. ON_EVENT(ON_CLICK,m_button1,OnClickButton1)
  1213. EVENT_MAP_END(CAppDialog)
  1214. //+------------------------------------------------------------------+
  1215. //| Constructor |
  1216. //+------------------------------------------------------------------+
  1217. CControlsDialog::CControlsDialog(void)
  1218. {
  1219. }
  1220. //+------------------------------------------------------------------+
  1221. //| Destructor |
  1222. //+------------------------------------------------------------------+
  1223. CControlsDialog::~CControlsDialog(void)
  1224. {
  1225. }
  1226. //+------------------------------------------------------------------+
  1227. //| Create |
  1228. //+------------------------------------------------------------------+
  1229. bool CControlsDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  1230. {
  1231. if(!CAppDialog::Create(chart,name,subwin,20,20,dashWidth,dashHeight))
  1232. return(false);
  1233. //--- create dependent controls
  1234. if(!CreatePanel())
  1235. return(false);
  1236. if(!CreateLabel0())
  1237. return(false);
  1238. if(!CreateButton())
  1239. return(false);
  1240. if(!CreateButton1())
  1241. return(false);
  1242. //--- succeed
  1243. return(true);
  1244. }
  1245. //+------------------------------------------------------------------+
  1246. //| |
  1247. //+------------------------------------------------------------------+
  1248. bool CControlsDialog::CreateLabel0(void) //Trend Info
  1249. {
  1250. //--- coordinates
  1251. int x1 = (dashWidth/2) - 235;
  1252. int y1 = yAxisGlobal + 15;
  1253. int x2 = 0;
  1254. int y2 = 0;
  1255. //--- create
  1256. if(!m_label0.Create(m_chart_id,m_name+"Label0",m_subwin,x1,y1,x2,y2))
  1257. return(false);
  1258. if(!m_label0.Text(" Master Trades Lots Calc: 0.00"))
  1259. return(false);
  1260. if(!m_label0.Color(clrBlack))
  1261. return(false);
  1262. if(!m_label0.Font("Calibri"))
  1263. return(false);
  1264. if(!m_label0.FontSize(FontSize))
  1265. return(false);
  1266. if(!Add(m_label0))
  1267. return(false);
  1268. //--- succeed
  1269. return(true);
  1270. }
  1271. //+------------------------------------------------------------------+
  1272. //| |
  1273. //+------------------------------------------------------------------+
  1274. bool CControlsDialog::CreateButton(void)
  1275. {
  1276. //--- coordinates
  1277. // Buy
  1278. int x1 = (dashWidth/2) + 14;
  1279. int y1 = yAxisGlobal + 10;
  1280. int x2 = x1 + 70;
  1281. int y2 = y1 + 30;
  1282. //--- create
  1283. if(!m_button.Create(m_chart_id,"button",m_subwin,x1,y1,x2,y2))
  1284. return(false);
  1285. if(!m_button.ColorBackground(clrSlateGray))
  1286. return(false);
  1287. if(!m_button.Text("Sell"))
  1288. return(false);
  1289. if(!m_button.FontSize(FontSize))
  1290. return(false);
  1291. if(!m_button.ColorBackground(clrRed))
  1292. return(false);
  1293. if(!m_button.Font("Calibri Bold"))
  1294. return(false);
  1295. if(!m_button.Color(clrWhiteSmoke))
  1296. return(false);
  1297. if(!m_button.ColorBorder(clrRed))
  1298. return(false);
  1299. if(!Add(m_button))
  1300. return(false);
  1301. m_button.Locking(true);
  1302. m_button.BringToTop();
  1303. //--- succeed
  1304. return(true);
  1305. }
  1306. //+------------------------------------------------------------------+
  1307. //| |
  1308. //+------------------------------------------------------------------+
  1309. bool CControlsDialog::CreateButton1(void)
  1310. {
  1311. //--- coordinates
  1312. // Sell
  1313. int x1 = (dashWidth/2) + 100;
  1314. int y1 = yAxisGlobal + 10;
  1315. int x2 = x1 + 70;
  1316. int y2 = y1 + 30;
  1317. //--- create
  1318. if(!m_button1.Create(m_chart_id,"button1",m_subwin,x1,y1,x2,y2))
  1319. return(false);
  1320. if(!m_button1.ColorBackground(clrBlue))
  1321. return(false);
  1322. if(!m_button1.Text("Buy"))
  1323. return(false);
  1324. if(!m_button1.FontSize(FontSize))
  1325. return(false);
  1326. if(!m_button1.Font("Calibri Bold"))
  1327. return(false);
  1328. if(!m_button1.Color(clrWhiteSmoke))
  1329. return(false);
  1330. if(!m_button1.ColorBorder(clrBlack))
  1331. return(false);
  1332. if(!Add(m_button1))
  1333. return(false);
  1334. m_button1.Locking(true);
  1335. m_button1.BringToTop();
  1336. //--- succeed
  1337. return(true);
  1338. }
  1339. //+------------------------------------------------------------------+
  1340. //| |
  1341. //+------------------------------------------------------------------+
  1342. void CControlsDialog::OnClickButton(void)
  1343. {
  1344. if(m_button.Pressed())
  1345. {
  1346. Print(" Clicked on Button");
  1347. m_button.Pressed(false);
  1348. placeSellTrade();
  1349. }
  1350. }
  1351. //+------------------------------------------------------------------+
  1352. //| |
  1353. //+------------------------------------------------------------------+
  1354. void CControlsDialog::OnClickButton1(void)
  1355. {
  1356. if(m_button1.Pressed())
  1357. {
  1358. Print(" Clicked on Button 1");
  1359. m_button1.Pressed(false);
  1360. placeBuyTrade();
  1361. }
  1362. }
  1363. //+------------------------------------------------------------------+
  1364. //| |
  1365. //+------------------------------------------------------------------+
  1366. bool CControlsDialog::CreatePanel(void)
  1367. {
  1368. //--- coordinates
  1369. int x1=0;
  1370. int y1=0;
  1371. int x2=dashWidth;
  1372. int y2=dashHeight;
  1373. //--- create
  1374. if(!backgroundPanel.Create(0,ExtDialog.Name()+"backPanel",m_subwin,x1,y1,x2,y2))
  1375. return(false);
  1376. if(!backgroundPanel.ColorBackground(clrWhiteSmoke))
  1377. return(false);
  1378. if(!backgroundPanel.ColorBorder(00128))
  1379. return(false);
  1380. if(!ExtDialog.Add(backgroundPanel))
  1381. return(false);
  1382. ExtDialog.Minimized(false);
  1383. backgroundPanel.Alignment(WND_ALIGN_CLIENT,0,0,0,0);
  1384. //--- succeed
  1385. return(true);
  1386. }
  1387. CControlsDialog ExtDialog;
  1388. CPanel backgroundPanel;
  1389. //+------------------------------------------------------------------+
  1390. //| |
  1391. //+------------------------------------------------------------------+