Sin descripción

pulseBalanceIndicator.mq5 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. //+------------------------------------------------------------------+
  2. //| pulseBalaceIndicator.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. #property indicator_separate_window
  10. #property indicator_buffers 3
  11. #property indicator_plots 3
  12. #property indicator_label1 "ACCOUNT BALANCE"
  13. #property indicator_type1 DRAW_LINE
  14. #property indicator_color1 clrRed
  15. #property indicator_width1 1
  16. #property indicator_label2 "MA"
  17. #property indicator_type2 DRAW_LINE
  18. #property indicator_color2 clrDodgerBlue
  19. #property indicator_width2 1
  20. #property indicator_style2 STYLE_DOT
  21. #property indicator_label3 "MA2"
  22. #property indicator_type3 DRAW_LINE
  23. #property indicator_color3 clrGold
  24. #property indicator_width3 1
  25. #property indicator_style3 STYLE_DASH
  26. input color Dot_Color = clrOrangeRed;
  27. input double StartingBalance = 10000;
  28. input int MagicNumber = 0;
  29. input int MA_Period = 5;
  30. input int MA2_Period = 12;
  31. input ENUM_MA_METHOD MA_Method = MODE_SMA;
  32. double ACCOUNTBALANCE[];
  33. double MA[];
  34. double MA2[];
  35. int TOTAL_HISTORY = 0;
  36. datetime TT = 0;
  37. //+------------------------------------------------------------------+
  38. //| Custom indicator initialization function |
  39. //+------------------------------------------------------------------+
  40. int OnInit()
  41. {
  42. //--- indicator buffers mapping
  43. EventSetTimer(1);
  44. SetIndexBuffer(0, ACCOUNTBALANCE, INDICATOR_DATA);
  45. SetIndexBuffer(1, MA, INDICATOR_DATA);
  46. SetIndexBuffer(2, MA2, INDICATOR_DATA);
  47. ArraySetAsSeries(ACCOUNTBALANCE, true);
  48. ArraySetAsSeries(MA, true);
  49. ArraySetAsSeries(MA2, true);
  50. TOTAL_HISTORY = 0;
  51. TT = 0;
  52. //---
  53. return(INIT_SUCCEEDED);
  54. }
  55. //+------------------------------------------------------------------+
  56. //| Custom indicator deinitialization function |
  57. //+------------------------------------------------------------------+
  58. void OnDeinit(const int reason)
  59. {
  60. //--- destroy timer
  61. EventKillTimer();
  62. subDeleteObjects("Balance: ");
  63. subDeleteObjects("Start Balance: ");
  64. }
  65. //+------------------------------------------------------------------+
  66. //| Custom indicator iteration function |
  67. //+------------------------------------------------------------------+
  68. int OnCalculate(const int rates_total,
  69. const int prev_calculated,
  70. const datetime &time[],
  71. const double &open[],
  72. const double &high[],
  73. const double &low[],
  74. const double &close[],
  75. const long &tick_volume[],
  76. const long &volume[],
  77. const int &spread[])
  78. {
  79. //---
  80. MyStart(rates_total, prev_calculated);
  81. //--- return value of prev_calculated for next call
  82. return(rates_total);
  83. }
  84. //+------------------------------------------------------------------+
  85. //| Timer function |
  86. //+------------------------------------------------------------------+
  87. void OnTimer()
  88. {
  89. //MyStart();
  90. }
  91. //+------------------------------------------------------------------+
  92. //| |
  93. //+------------------------------------------------------------------+
  94. void MyStart(int ratesTotal, int prevCalculated)
  95. {
  96. if(TOTAL_HISTORY != HistoryDealsTotal() || TT != iTime(Symbol(), PERIOD_CURRENT, 0))
  97. {
  98. int limit = 0;
  99. if(prevCalculated == 0)
  100. {
  101. limit = ratesTotal - prevCalculated -2;
  102. }
  103. else
  104. {
  105. limit = ratesTotal - prevCalculated;
  106. }
  107. //subDeleteObjects("Balance: ");
  108. //subDeleteObjects("Start Balance: ");
  109. for(int i=limit; i>= 0; i--)
  110. {
  111. ACCOUNTBALANCE[i] = EMPTY_VALUE;
  112. MA[i] = EMPTY_VALUE;
  113. MA2[i] = EMPTY_VALUE;
  114. }
  115. if(!HistorySelect(0, TimeCurrent()))
  116. return;
  117. int deals = HistoryDealsTotal();
  118. int total = 0;
  119. int total2 = 0;
  120. int ticket = 0;
  121. double AB = StartingBalance;
  122. double BAL = AB;
  123. Print("ACCOUNT BALANCE: " + DoubleToString(AB));
  124. // First pass to count relevant deals
  125. for(int i = 0; i < deals; i++)
  126. {
  127. ulong deal_ticket = HistoryDealGetTicket(i);
  128. if(deal_ticket == 0)
  129. {
  130. Print("Error getting deal ticket!");
  131. break;
  132. }
  133. long deal_magic = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
  134. long deal_type = HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
  135. // Filter for position deals (open/close) with matching magic number
  136. if(HistoryDealGetInteger(deal_ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
  137. {
  138. if((deal_type == DEAL_TYPE_BUY || deal_type == DEAL_TYPE_SELL) && deal_magic == MagicNumber)
  139. {
  140. total2++;
  141. }
  142. }
  143. }
  144. total = total2;
  145. // Second pass to calculate balance
  146. for(int i = 0; i < deals; i++)
  147. {
  148. ulong deal_ticket = HistoryDealGetTicket(i);
  149. if(deal_ticket == 0)
  150. {
  151. Print("Error getting deal ticket!");
  152. break;
  153. }
  154. long deal_magic = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
  155. long deal_type = HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
  156. datetime deal_time = (datetime)HistoryDealGetInteger(deal_ticket, DEAL_TIME);
  157. //dealout check add
  158. if(HistoryDealGetInteger(deal_ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
  159. {
  160. if((deal_type == DEAL_TYPE_BUY || deal_type == DEAL_TYPE_SELL) && deal_magic == MagicNumber)
  161. {
  162. double deal_profit = HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);
  163. double deal_swap = HistoryDealGetDouble(deal_ticket, DEAL_SWAP);
  164. double deal_commission = HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION);
  165. double profit = deal_profit + deal_swap + deal_commission;
  166. if(total == total2)
  167. {
  168. ACCOUNTBALANCE[total + 1] = BAL;
  169. string name = "Start Balance: " + DoubleToString(ACCOUNTBALANCE[total + 1], 2) + "\n" + TimeToString(deal_time, TIME_DATE|TIME_SECONDS) + "\n";
  170. CreateDotLabel(name, "=", iTime(Symbol(), PERIOD_CURRENT, total + 1), ACCOUNTBALANCE[total + 1], Dot_Color);
  171. }
  172. BAL = BAL + profit;
  173. ACCOUNTBALANCE[total] = BAL;
  174. GlobalVariableSet("TIME:" + IntegerToString(total), deal_time);
  175. total--;
  176. }
  177. }
  178. }
  179. // Calculate moving averages and create labels
  180. for(int x = total2; x > 0; x--)
  181. {
  182. if(x < total2 - MathMax(MA_Period, MA2_Period))
  183. {
  184. MA[x] = iMAOnArray(ACCOUNTBALANCE, 0, MA_Period, 0, MA_Method, x);
  185. MA2[x] = iMAOnArray(ACCOUNTBALANCE, 0, MA2_Period, 0, MA_Method, x);
  186. datetime time_val = (datetime)GlobalVariableGet("TIME:" + IntegerToString(x));
  187. string name = "Balance: " + DoubleToString(ACCOUNTBALANCE[x], 2) + "\n" + TimeToString(time_val, TIME_DATE|TIME_SECONDS) + "\n" + DoubleToString(MA[x], 2) + ", " + DoubleToString(MA2[x], 2);
  188. CreateDotLabel(name, "=", iTime(Symbol(), PERIOD_CURRENT, x), ACCOUNTBALANCE[x], Dot_Color);
  189. }
  190. else
  191. {
  192. datetime time_val = (datetime)GlobalVariableGet("TIME:" + IntegerToString(x));
  193. string name = "Balance: " + DoubleToString(ACCOUNTBALANCE[x], 2) + "\n" + TimeToString(time_val, TIME_DATE|TIME_SECONDS);
  194. CreateDotLabel(name, "=", iTime(Symbol(), PERIOD_CURRENT, x), ACCOUNTBALANCE[x], Dot_Color);
  195. }
  196. }
  197. TOTAL_HISTORY = HistoryDealsTotal();
  198. TT = iTime(Symbol(), PERIOD_CURRENT, 0);
  199. }
  200. }
  201. //+------------------------------------------------------------------+
  202. //| |
  203. //+------------------------------------------------------------------+
  204. void CreateDotLabel(string name, string text, datetime T1, double P1, color C)
  205. {
  206. int window_x = ChartWindowFind();
  207. //Print("window_x",window_x);
  208. if(ObjectFind(0, name) == -1)
  209. {
  210. ObjectCreate(0, name, OBJ_TEXT, window_x, T1, NormalizeDouble(P1, Digits()));
  211. }
  212. ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_CENTER);
  213. ObjectSetString(0, name, OBJPROP_TEXT, text);
  214. ObjectSetString(0, name, OBJPROP_FONT, "webdings");
  215. ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 8);
  216. ObjectSetInteger(0, name, OBJPROP_COLOR, C);
  217. ObjectSetDouble(0, name, OBJPROP_PRICE, NormalizeDouble(P1, Digits()));
  218. ObjectSetInteger(0, name, OBJPROP_TIME, T1);
  219. ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
  220. }
  221. //+------------------------------------------------------------------+
  222. //| |
  223. //+------------------------------------------------------------------+
  224. void subDeleteObjects(string ObjName)
  225. {
  226. int obj_total = ObjectsTotal(0);
  227. string name;
  228. int i = 0;
  229. for(i = obj_total - 1; i >= 0; i--)
  230. {
  231. name = ObjectName(0, i);
  232. if(StringFind(name, ObjName, 0) != -1)
  233. {
  234. ObjectDelete(0, name);
  235. }
  236. }
  237. }
  238. //+------------------------------------------------------------------+
  239. //| |
  240. //+------------------------------------------------------------------+
  241. double iMAOnArray(double &array[],
  242. int total,
  243. int period,
  244. int ma_shift,
  245. int ma_method,
  246. int shift)
  247. {
  248. double buf[],arr[];
  249. if(total==0)
  250. total=ArraySize(array);
  251. if(total>0 && total<=period)
  252. return(0);
  253. if(shift>total-period-ma_shift)
  254. return(0);
  255. switch(ma_method)
  256. {
  257. case MODE_SMA :
  258. {
  259. total=ArrayCopy(arr,array,0,shift+ma_shift,period);
  260. if(ArrayResize(buf,total)<0)
  261. return(0);
  262. double sum=0;
  263. int i,pos=total-1;
  264. for(i=1;i<period;i++,pos--)
  265. sum+=arr[pos];
  266. while(pos>=0)
  267. {
  268. sum+=arr[pos];
  269. buf[pos]=sum/period;
  270. sum-=arr[pos+period-1];
  271. pos--;
  272. }
  273. return(buf[0]);
  274. }
  275. case MODE_EMA :
  276. {
  277. if(ArrayResize(buf,total)<0)
  278. return(0);
  279. double pr=2.0/(period+1);
  280. int pos=total-2;
  281. while(pos>=0)
  282. {
  283. if(pos==total-2)
  284. {
  285. buf[pos+1]=array[pos+1];
  286. }
  287. buf[pos]=array[pos]*pr+buf[pos+1]*(1-pr);
  288. pos--;
  289. }
  290. return(buf[shift+ma_shift]);
  291. }
  292. case MODE_SMMA :
  293. {
  294. if(ArrayResize(buf,total)<0)
  295. return(0);
  296. double sum=0;
  297. int i,k,pos;
  298. pos=total-period;
  299. while(pos>=0)
  300. {
  301. if(pos==total-period)
  302. {
  303. for(i=0,k=pos;i<period;i++,k++)
  304. {
  305. sum+=array[k];
  306. buf[k]=0;
  307. }
  308. }
  309. else
  310. sum=buf[pos+1]*(period-1)+array[pos];
  311. buf[pos]=sum/period;
  312. pos--;
  313. }
  314. return(buf[shift+ma_shift]);
  315. }
  316. case MODE_LWMA :
  317. {
  318. if(ArrayResize(buf,total)<0)
  319. return(0);
  320. double sum=0.0,lsum=0.0;
  321. double price;
  322. int i,weight=0,pos=total-1;
  323. for(i=1;i<=period;i++,pos--)
  324. {
  325. price=array[pos];
  326. sum+=price*i;
  327. lsum+=price;
  328. weight+=i;
  329. }
  330. pos++;
  331. i=pos+period;
  332. while(pos>=0)
  333. {
  334. buf[pos]=sum/weight;
  335. if(pos==0)
  336. break;
  337. pos--;
  338. i--;
  339. price=array[pos];
  340. sum=sum-lsum+price*period;
  341. lsum-=array[i];
  342. lsum+=price;
  343. }
  344. return(buf[shift+ma_shift]);
  345. }
  346. default:
  347. return(0);
  348. }
  349. return(0);
  350. }
  351. //+------------------------------------------------------------------+