説明なし

pulseBalanceIndicator.mq5 26KB

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