From f7fd579a9de336d335f86d63271dfea130083222 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 22 Apr 2024 07:42:50 +0330 Subject: [PATCH] add MQL5Test Workspace Content as BKP Solution ... --- .../x-saherelm.x121.xama.helper.class.ex5 | Bin 0 -> 6676 bytes .../x-saherelm.x121.xama.helper.class.mq5 | 470 ++ .../x-saherelm.x121.xcc.helper.class.ex5 | Bin 0 -> 6060 bytes .../x-saherelm.x121.xcc.helper.class.mq5 | 330 ++ .../x-saherelm.x121.xche.helper.class.ex5 | Bin 0 -> 6362 bytes .../x-saherelm.x121.xche.helper.class.mq5 | 648 ++ .../x-saherelm.x121.xhk.helper.class.ex5 | Bin 0 -> 6260 bytes .../x-saherelm.x121.xhk.helper.class.mq5 | 432 ++ .../x-saherelm.x121.xhull.helper.class.ex5 | Bin 0 -> 7190 bytes .../x-saherelm.x121.xhull.helper.class.mq5 | 565 ++ .../x-saherelm.x121.xich.helper.class.ex5 | Bin 0 -> 6572 bytes .../x-saherelm.x121.xich.helper.class.mq5 | 1052 ++++ .../x-saherelm.x121.xmrb.helper.class.ex5 | Bin 0 -> 6608 bytes .../x-saherelm.x121.xmrb.helper.class.mq5 | 908 +++ .../x-saherelm.x121.xpv.helper.class.ex5 | Bin 0 -> 6672 bytes .../x-saherelm.x121.xpv.helper.class.mq5 | 518 ++ .../x-saherelm.x121.xsslc.helper.class.ex5 | Bin 0 -> 7680 bytes .../x-saherelm.x121.xsslc.helper.class.mq5 | 509 ++ .../x-saherelm.x121.xtm.helper.class.ex5 | Bin 0 -> 6562 bytes .../x-saherelm.x121.xtm.helper.class.mq5 | 468 ++ .../x-saherelm.x121.xtrnd.helper.class.ex5 | Bin 0 -> 6916 bytes .../x-saherelm.x121.xtrnd.helper.class.mq5 | 1158 ++++ .../Providers/x.saherelm.x121.provider.ex5 | Bin 0 -> 10212 bytes .../Providers/x.saherelm.x121.provider.mq5 | 965 +++ .../BKPS/BKP/Smapls/Ichimoku.mql4 | 262 + .../BKPS/BKP/Smapls/MT5-TradingView.ex5 | Bin 0 -> 346602 bytes .../BKPS/BKP/Smapls/atrstoploss_ind.ex5 | Bin 0 -> 17136 bytes .../BKPS/BKP/Smapls/atrstoploss_ind.mq5 | 675 +++ .../BKP/Smapls/candle_time_end_and_spread.ex5 | Bin 0 -> 13682 bytes .../BKP/Smapls/candle_time_end_and_spread.mq5 | 62 + .../BKPS/BKP/Smapls/chandelier_exit.ex5 | Bin 0 -> 13954 bytes .../BKPS/BKP/Smapls/chandelier_exit.mq5 | Bin 0 -> 11578 bytes .../BKP/Smapls/demotradeeventprocessing.ex5 | Bin 0 -> 9878 bytes .../BKP/Smapls/demotradeeventprocessing.mq5 | 172 + .../detrended_synthetic_price_dbarsf.mq4 | 247 + ...ay_total_stoploss_and_takeprofit_value.ex5 | Bin 0 -> 11060 bytes ...ay_total_stoploss_and_takeprofit_value.mq5 | 143 + .../BKPS/BKP/Smapls/heiken_ashi.ex5 | Bin 0 -> 7278 bytes .../BKPS/BKP/Smapls/heiken_ashi.mq5 | 87 + .../BKPS/BKP/Smapls/hull_average_2.ex5 | Bin 0 -> 16540 bytes .../BKPS/BKP/Smapls/hull_average_2.mq5 | Bin 0 -> 12964 bytes .../BKPS/BKP/Smapls/hull_trend.ex5 | Bin 0 -> 18372 bytes .../BKPS/BKP/Smapls/hull_trend.mq5 | Bin 0 -> 15062 bytes .../BKP/Smapls/relative_moving_average.ex5 | Bin 0 -> 10714 bytes .../BKP/Smapls/relative_moving_average.mq5 | Bin 0 -> 7284 bytes MQLTestWorkspace/BKPS/BKP/Smapls/rma.ex5 | Bin 0 -> 10776 bytes MQLTestWorkspace/BKPS/BKP/Smapls/rma.mq5 | Bin 0 -> 7284 bytes .../BKPS/BKP/Smapls/ssl.channel.ex5 | Bin 0 -> 10122 bytes .../BKPS/BKP/Smapls/ssl.channel.mq5 | 115 + .../BKPS/BKP/Smapls/ssl_channel_chart.mq5 | 115 + .../BKPS/BKP/Smapls/tradecontrol_en.ex5 | Bin 0 -> 24624 bytes .../BKPS/BKP/Smapls/tradecontrol_en.mq5 | 505 ++ MQLTestWorkspace/BKPS/BKP/Smapls/wma.ex5 | Bin 0 -> 12470 bytes MQLTestWorkspace/BKPS/BKP/Smapls/wma.mq5 | Bin 0 -> 8684 bytes .../BKPS/BKP/x-saherelm.x121.indicator.ex5 | Bin 0 -> 66940 bytes .../BKPS/BKP/x-saherelm.x121.indicator.mq5 | 1874 ++++++ .../BKPS/BKP/x-saherelm.x121.xpv.mq5 | 640 ++ .../x-saherelm.x121.xtrnd.single.cycle.mq5 | 459 ++ MQLTestWorkspace/BKPS/BKP/x-saherelm.xea.mq5 | 1359 +++++ .../BKPS/BKP/x-saherelm.xhull.class.mq5 | 216 + ...m.xtrade.before.ontrade.handlers.class.mq5 | 2838 +++++++++ .../Experts/Test/x-saherelm.xea.test.mq5 | 1353 +++++ .../Experts/x-saherelm.xea.mq5 | 1553 +++++ .../Helpers/Test/x121.xatrsl.test.helper.mq5 | 235 + .../Helpers/Test/x121.xichi.test.helper.mq5 | 938 +++ .../Helpers/Test/x121.xmc.test.helper.mq5 | 309 + .../Helpers/Test/x121.xmrb.test.helper.mq5 | 314 + .../Helpers/Test/x121.xpv.test.helper.mq5 | 803 +++ .../Helpers/Test/x121.xtrnd.test.helper.mq5 | 1383 +++++ .../Helpers/x-saherelm.x121.xatrsl.helper.mq5 | 324 + .../Helpers/x-saherelm.x121.xhk.helper.mq5 | 215 + .../Helpers/x-saherelm.x121.xich.helper.mq5 | 690 +++ .../Helpers/x-saherelm.x121.xmc.helper.mq5 | 418 ++ .../Helpers/x-saherelm.x121.xmrb.helper.mq5 | 1102 ++++ .../Helpers/x-saherelm.x121.xppsr.helper.mq5 | 575 ++ .../Helpers/x-saherelm.x121.xpv.helper.mq5 | 707 +++ .../Helpers/x-saherelm.x121.xsslc.helper.mq5 | 332 ++ .../Helpers/x-saherelm.x121.xtrnd.helper.mq5 | 469 ++ .../Indicators/x-saherelm.x121.xama.mq5 | 367 ++ .../Indicators/x-saherelm.x121.xatrsl.mq5 | 765 +++ .../Indicators/x-saherelm.x121.xcclear.mq5 | 481 ++ .../Indicators/x-saherelm.x121.xche.mq5 | 629 ++ .../Indicators/x-saherelm.x121.xct.ex5 | Bin 0 -> 12826 bytes .../Indicators/x-saherelm.x121.xct.mq5 | 214 + .../Indicators/x-saherelm.x121.xhk.mq5 | 500 ++ .../Indicators/x-saherelm.x121.xhull.mq5 | 587 ++ .../Indicators/x-saherelm.x121.xich.mq5 | 895 +++ .../Indicators/x-saherelm.x121.xmc.mq5 | 469 ++ .../Indicators/x-saherelm.x121.xmrb.mq5 | 802 +++ .../Indicators/x-saherelm.x121.xppsr.mq5 | 1214 ++++ .../Indicators/x-saherelm.x121.xpv.mq5 | 1124 ++++ .../Indicators/x-saherelm.x121.xsslc.mq5 | 453 ++ .../Indicators/x-saherelm.x121.xtm.mq5 | 355 ++ .../Indicators/x-saherelm.x121.xtrnd.mq5 | 1151 ++++ .../Providers/Test/x121.test.provider.mq5 | 917 +++ .../Providers/x.saherelm.x121.provider.mq5 | 1590 +++++ .../x-saherelm.x121.chart.tools.lib.mq5 | 193 + .../BKPS/Temp/supprot_resistance_sample.yaml | 269 + MQLTestWorkspace/BKPS/Temp/xtm.old.mq5 | 361 ++ .../BKPS/Templates/Guard Handlers.mq5 | 227 + .../Templates/draw.support.resistance.mql5 | 124 + .../Templates/how to use xtrnd helper.mq5 | 30 + .../Templates/how-to-use.xichi.helper.mq5 | 100 + .../Templates/ichimoku.test.short.signals.mq5 | 251 + .../BKPS/Templates/old.long.signals.mq5 | 79 + .../BKPS/Templates/old.short.signals.mq5 | 130 + .../open.support.positions.old.ea.mq5 | 181 + .../BKPS/Templates/short.sl.calc.test.mql5 | 62 + .../static.indicator.helper.library.mql5 | 83 + .../trader.generate.support.signals.mq5 | 129 + .../Templates/x-121.indicator.template.mq5 | 253 + .../x-saherelm.chart_drawing.template.ex5 | Bin 0 -> 8122 bytes .../x-saherelm.chart_drawing.template.mq5 | 164 + ...x-saherelm.xxhelper.indicator.template.mq5 | 151 + ...x.helper.implementation.class.template.mq5 | 435 ++ .../BKPS/Templates/xpv.find.supres.old.mq5 | 310 + .../BKPS/Templates/xpv.helper.test.tools.mq5 | 164 + .../Classes/x-saherelm.http.class.mq5 | 385 ++ .../x-saherelm.x121.provider.class.ex5 | Bin 0 -> 10406 bytes .../x-saherelm.x121.provider.class.mq5 | 1788 ++++++ .../Classes/x-saherelm.x121.xea.class.mq5 | 443 ++ .../Classes/x-saherelm.xaccount.class.mq5 | 398 ++ .../x-saherelm.xdatacollector.class.mq5 | 1582 +++++ .../Classes/x-saherelm.xea.class.ex5 | Bin 0 -> 9654 bytes .../Classes/x-saherelm.xea.class.mq5 | 814 +++ .../Classes/x-saherelm.xhelper.class.mq5 | 209 + .../Classes/x-saherelm.xnotifier.class.mq5 | 295 + .../Classes/x-saherelm.xprovider.class.mq5 | 304 + .../Classes/x-saherelm.xtrade.class.mq5 | 4111 +++++++++++++ MQLTestWorkspace/Experts/x-saherelm.xea.ex5 | Bin 0 -> 447484 bytes MQLTestWorkspace/Experts/x-saherelm.xea.mq5 | 262 + .../x-saherelm.x121.xama.helper.class.ex5 | Bin 0 -> 5204 bytes .../x-saherelm.x121.xama.helper.class.mq5 | 438 ++ .../x-saherelm.x121.xcc.helper.class.ex5 | Bin 0 -> 5662 bytes .../x-saherelm.x121.xcc.helper.class.mq5 | 293 + .../x-saherelm.x121.xche.helper.class.ex5 | Bin 0 -> 5566 bytes .../x-saherelm.x121.xche.helper.class.mq5 | 594 ++ .../x-saherelm.x121.xct.helper.class.ex5 | Bin 0 -> 6052 bytes .../x-saherelm.x121.xct.helper.class.mq5 | 248 + .../x-saherelm.x121.xhk.helper.class.ex5 | Bin 0 -> 5578 bytes .../x-saherelm.x121.xhk.helper.class.mq5 | 427 ++ .../x-saherelm.x121.xhull.helper.class.ex5 | Bin 0 -> 5920 bytes .../x-saherelm.x121.xhull.helper.class.mq5 | 530 ++ .../x-saherelm.x121.xich.helper.class.ex5 | Bin 0 -> 5824 bytes .../x-saherelm.x121.xich.helper.class.mq5 | 965 +++ .../x-saherelm.x121.xmrb.helper.class.ex5 | Bin 0 -> 6520 bytes .../x-saherelm.x121.xmrb.helper.class.mq5 | 849 +++ .../x-saherelm.x121.xpv.helper.class.ex5 | Bin 0 -> 5900 bytes .../x-saherelm.x121.xpv.helper.class.mq5 | 644 ++ .../x-saherelm.x121.xsslc.helper.class.ex5 | Bin 0 -> 6168 bytes .../x-saherelm.x121.xsslc.helper.class.mq5 | 473 ++ .../x-saherelm.x121.xtm.helper.class.ex5 | Bin 0 -> 6902 bytes .../x-saherelm.x121.xtm.helper.class.mq5 | 439 ++ .../x-saherelm.x121.xtrnd.helper.class.ex5 | Bin 0 -> 5598 bytes .../x-saherelm.x121.xtrnd.helper.class.mq5 | 1074 ++++ .../Indicators/x-saherelm.x121.xama.ex5 | Bin 0 -> 10504 bytes .../Indicators/x-saherelm.x121.xama.mq5 | 350 ++ .../Indicators/x-saherelm.x121.xcc.ex5 | Bin 0 -> 10770 bytes .../Indicators/x-saherelm.x121.xcc.mq5 | 454 ++ .../Indicators/x-saherelm.x121.xche.ex5 | Bin 0 -> 17704 bytes .../Indicators/x-saherelm.x121.xche.mq5 | 631 ++ .../Indicators/x-saherelm.x121.xct.ex5 | Bin 0 -> 13694 bytes .../Indicators/x-saherelm.x121.xct.mq5 | 264 + .../Indicators/x-saherelm.x121.xhk.ex5 | Bin 0 -> 11108 bytes .../Indicators/x-saherelm.x121.xhk.mq5 | 486 ++ .../Indicators/x-saherelm.x121.xhull.ex5 | Bin 0 -> 18034 bytes .../Indicators/x-saherelm.x121.xhull.mq5 | 602 ++ .../Indicators/x-saherelm.x121.xich.ex5 | Bin 0 -> 19182 bytes .../Indicators/x-saherelm.x121.xich.mq5 | 743 +++ .../Indicators/x-saherelm.x121.xmrb.ex5 | Bin 0 -> 20740 bytes .../Indicators/x-saherelm.x121.xmrb.mq5 | 786 +++ .../Indicators/x-saherelm.x121.xpv.ex5 | Bin 0 -> 23320 bytes .../Indicators/x-saherelm.x121.xpv.mq5 | 992 ++++ .../Indicators/x-saherelm.x121.xsslc.ex5 | Bin 0 -> 13690 bytes .../Indicators/x-saherelm.x121.xsslc.mq5 | 437 ++ .../Indicators/x-saherelm.x121.xtm.ex5 | Bin 0 -> 11030 bytes .../Indicators/x-saherelm.x121.xtm.mq5 | 354 ++ .../Indicators/x-saherelm.x121.xtrnd.ex5 | Bin 0 -> 36482 bytes .../Indicators/x-saherelm.x121.xtrnd.mq5 | 1253 ++++ .../Indicators/x-saherelm.xchnl.ex5 | Bin 0 -> 24258 bytes .../Indicators/x-saherelm.xchnl.mq5 | 775 +++ .../Libraries/x-saherelm.alert.lib.ex5 | Bin 0 -> 6372 bytes .../Libraries/x-saherelm.alert.lib.mq5 | 187 + .../Libraries/x-saherelm.common.lib.ex5 | Bin 0 -> 5616 bytes .../Libraries/x-saherelm.common.lib.mq5 | 5193 +++++++++++++++++ .../Libraries/x-saherelm.draw.lib.ex5 | Bin 0 -> 7102 bytes .../Libraries/x-saherelm.draw.lib.mq5 | 2462 ++++++++ .../Libraries/x-saherelm.http.lib.ex5 | Bin 0 -> 3648 bytes .../Libraries/x-saherelm.http.lib.mq5 | 177 + .../Libraries/x-saherelm.log.lib.ex5 | Bin 0 -> 5894 bytes .../Libraries/x-saherelm.log.lib.mq5 | 117 + .../Libraries/x-saherelm.models.lib.ex5 | Bin 0 -> 4014 bytes .../Libraries/x-saherelm.models.lib.mq5 | 238 + .../Libraries/x-saherelm.seriallizer.lib.ex5 | Bin 0 -> 7924 bytes .../Libraries/x-saherelm.seriallizer.lib.mq5 | 85 + .../Libraries/x-saherelm.x121.draw.lib.ex5 | Bin 0 -> 6756 bytes .../Libraries/x-saherelm.x121.draw.lib.mq5 | 241 + 197 files changed, 80113 insertions(+) create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xcc.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xcc.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xche.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xche.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhull.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhull.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xpv.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xpv.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xsslc.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xsslc.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/Ichimoku.mql4 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/MT5-TradingView.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/candle_time_end_and_spread.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/candle_time_end_and_spread.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/chandelier_exit.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/chandelier_exit.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/demotradeeventprocessing.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/demotradeeventprocessing.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/detrended_synthetic_price_dbarsf.mq4 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/display_total_stoploss_and_takeprofit_value.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/display_total_stoploss_and_takeprofit_value.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/heiken_ashi.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/heiken_ashi.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/hull_average_2.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/hull_average_2.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/hull_trend.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/hull_trend.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/relative_moving_average.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/relative_moving_average.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/rma.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/rma.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/ssl.channel.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/ssl.channel.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/ssl_channel_chart.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/wma.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/Smapls/wma.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xpv.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xtrnd.single.cycle.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.xea.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.xhull.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x-saherelm.xtrade.before.ontrade.handlers.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/Test/x-saherelm.xea.test.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/x-saherelm.xea.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xatrsl.test.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xichi.test.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmc.test.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmrb.test.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xpv.test.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xtrnd.test.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xatrsl.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xhk.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xich.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmc.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmrb.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xppsr.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xpv.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xsslc.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xtrnd.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xama.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xatrsl.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xcclear.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xche.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.ex5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhk.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhull.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xich.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmc.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmrb.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xppsr.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xpv.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xsslc.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtm.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtrnd.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/Test/x121.test.provider.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/x.saherelm.x121.provider.mq5 create mode 100644 MQLTestWorkspace/BKPS/BKP/x121 old style indicators/x-saherelm.x121.chart.tools.lib.mq5 create mode 100644 MQLTestWorkspace/BKPS/Temp/supprot_resistance_sample.yaml create mode 100644 MQLTestWorkspace/BKPS/Temp/xtm.old.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/Guard Handlers.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/draw.support.resistance.mql5 create mode 100644 MQLTestWorkspace/BKPS/Templates/how to use xtrnd helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/how-to-use.xichi.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/ichimoku.test.short.signals.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/old.long.signals.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/old.short.signals.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/open.support.positions.old.ea.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/short.sl.calc.test.mql5 create mode 100644 MQLTestWorkspace/BKPS/Templates/static.indicator.helper.library.mql5 create mode 100644 MQLTestWorkspace/BKPS/Templates/trader.generate.support.signals.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/x-121.indicator.template.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.ex5 create mode 100644 MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/x-saherelm.xxhelper.indicator.template.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/x.helper.implementation.class.template.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/xpv.find.supres.old.mq5 create mode 100644 MQLTestWorkspace/BKPS/Templates/xpv.helper.test.tools.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.http.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.ex5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.x121.xea.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xaccount.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xdatacollector.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xea.class.ex5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xea.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xhelper.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xnotifier.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xprovider.class.mq5 create mode 100644 MQLTestWorkspace/Classes/x-saherelm.xtrade.class.mq5 create mode 100644 MQLTestWorkspace/Experts/x-saherelm.xea.ex5 create mode 100644 MQLTestWorkspace/Experts/x-saherelm.xea.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xama.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xama.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xche.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xche.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xct.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xct.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xhk.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xhk.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xmrb.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xmrb.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xpv.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xpv.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xtm.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xtm.helper.class.mq5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.ex5 create mode 100644 MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xama.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xama.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xche.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xche.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xct.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xct.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xich.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xich.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xmrb.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xmrb.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xpv.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xpv.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.mq5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.xchnl.ex5 create mode 100644 MQLTestWorkspace/Indicators/x-saherelm.xchnl.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.alert.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.common.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.common.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.draw.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.http.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.http.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.log.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.log.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.models.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.models.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.seriallizer.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.seriallizer.lib.mq5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.x121.draw.lib.ex5 create mode 100644 MQLTestWorkspace/Libraries/x-saherelm.x121.draw.lib.mq5 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..723b28373cb54563f2777929fd6ff680d752b53f GIT binary patch literal 6676 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 JYqjQc{||jDt)Kt^ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.mq5 new file mode 100644 index 0000000..42de1bb --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xama.helper.class.mq5 @@ -0,0 +1,470 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXAMAHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XAMAInputs +{ + // + // Makret ... + int length; // Length + int fastEMA; // Fast EMA Length + int slowEMA; // Slow EMA Length + int maShift; // Shift + ENUM_APPLIED_PRICE appliedTo; // Applied To + + // + // Presentation ... + bool showLine; // Show Line +}; + +// +// Index of Lines ... +enum ENUM_XAMA_BUFFERS +{ + // + // Main Requirements ... + XAMA_LINE = 0, + XAMA_STATE_LINE = 1, +}; + +// +// XAMA Indicator States ... +enum ENUM_XAMA_STATES +{ + X_XAMA_BULLISH = 0, + X_XAMA_BEARISH = 2, + X_XAMA_NEUTURAL = 1, +}; + +// +// Retrieve Info Model ... +struct XAMAInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double value; + + // + // State ... + ENUM_XAMA_STATES state; + + // + // Conditions ... + + // + // Detect Trend is Bullish or not ... + bool isBullish; + + // + // Detect Trend is Switched to Bullish Or not ... + bool isSwitchedBullish; + + // + // Detect Trend is Bearish or not ... + bool isBearish; + + // + // Detect Trend is Switched to Bearish Or not ... + bool isSwitchedBearish; + + // + // Detect Trend is Neutural or not ... + bool isNeutural; + + // + // Detect Trend is Switched to Neutural Or not ... + bool isSwitchedNeutural; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXAMAHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double valueBuffer[]; + double stateBuffer[]; + + // + // Constructor ... + void XSCXAMAHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + XAMAInputs &config // Indicator Properties ... + ) : XSCBaseHelper(symbol, period) + { + // + XSCXAMAHelper(symbol, + period, + config.length, + config.fastEMA, + config.slowEMA, + config.maShift, + config.appliedTo, + config.showLine); + } + void XSCXAMAHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int length = 52, + // + // Fast EMA Length ... + int fastEMA = 2, + // + // Slow EMA Length ... + int slowEMA = 30, + // + // Shift ... + int maShift = 0, + // + // Applied To ... + ENUM_APPLIED_PRICE appliedTo = PRICE_LOW, + // + // Presentation ... + // + // Show Line ... + bool showLine = true + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mLength = length; + mFastEMA = fastEMA; + mSlowEMA = slowEMA; + mMaShift = maShift; + mShowLine = showLine; + mAppliedTo = appliedTo; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXAMAHelper() + { + } + + // + // START Properties ... + // + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XAMA" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Args ... + result = + // + (mLength >= 2) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xama", + // + // Inputs ... + // + // Makret ... + "", + // + // Length ... + mLength, + // + // Fast EMA Length ... + mFastEMA, + // + // Slow EMA Length ... + mSlowEMA, + // + // Shift ... + mMaShift, + // + // Applied To ... + mAppliedTo, + // + // Presentation ... + "", + // + // Show Line ... + mShowLine + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XAMAInputs GetConfig() + { + // + XAMAInputs result; + + // + result.length = mLength; + result.fastEMA = mFastEMA; + result.slowEMA = mSlowEMA; + result.maShift = mMaShift; + result.appliedTo = mAppliedTo; + result.showLine = mShowLine; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XAMAInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mFastEMA = config.fastEMA; + mSlowEMA = config.slowEMA; + mMaShift = config.maShift; + mAppliedTo = config.appliedTo; + mShowLine = config.showLine; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // VALUE ... + ArraySetAsSeries(valueBuffer, true); + CopyBuffer( + mHandler, + XAMA_LINE, + barIndex, + mLoopbackBars, + valueBuffer); + + // + // STATE ... + ArraySetAsSeries(stateBuffer, true); + CopyBuffer( + mHandler, + XAMA_STATE_LINE, + barIndex, + mLoopbackBars, + stateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XAMAInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XAMAInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + result.value = valueBuffer[barIndex]; + + // + ENUM_XAMA_STATES state = (ENUM_XAMA_STATES)stateBuffer[barIndex]; + ENUM_XAMA_STATES prevState = (ENUM_XAMA_STATES)stateBuffer[barIndex + 1]; + result.state = state; + + // + result.isBullish = state == X_XAMA_BULLISH; + result.isBearish = state == X_XAMA_BEARISH; + result.isNeutural = state == X_XAMA_NEUTURAL; + + // + result.isSwitchedBullish = + state == X_XAMA_BULLISH && prevState != X_XAMA_BULLISH; + result.isSwitchedBearish = + state == X_XAMA_BEARISH && prevState != X_XAMA_BEARISH; + result.isSwitchedNeutural = + state == X_XAMA_NEUTURAL && prevState != X_XAMA_NEUTURAL; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Fast EMA Length ... + int mFastEMA; + // + // Slow EMA Length ... + int mSlowEMA; + // + // Shift ... + int mMaShift; + // + // Applied To ... + ENUM_APPLIED_PRICE mAppliedTo; + // + // Presentation ... + // + // Show Line ... + bool mShowLine; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xcc.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xcc.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..f7c02aa41abf49c4bbf4254694138c0acb6003b3 GIT binary patch literal 6060 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 9 && + mLoopback >= 0; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xche", + // + // Inputs ... + // + // Market ... + "", + // + // Length ... + mLength, + // + // Loopback ... + mLoopback, + // + // 1st Multiplier ... + mMultiplier1, + // + // 2nd Multiplier ... + mMultiplier2, + // + // Calculation ... + "", + // + // Up Zone Applied to ... + mUpAppliedTo, + // + // Down Zone Applied to ... + mDownAppliedTo, + // + // Presentation ... + "", + // + // Show 1st Long Exit ... + mShowLongExit1Line, + // + // Show 1st Short Exit ... + mShowShortExit1Line, + // + // Show 2st Long Exit ... + mShowLongExit2Line, + // + // Show 2st Short Exit ... + mShowShortExit2Line + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XCHEInputs GetConfig() + { + // + XCHEInputs result; + + // + result.length = mLength; + result.loopback = mLoopback; + result.multiplier1 = mMultiplier1; + result.multiplier2 = mMultiplier2; + result.upAppliedTo = mUpAppliedTo; + result.downAppliedTo = mDownAppliedTo; + result.showLongExit1Line = mShowLongExit1Line; + result.showShortExit1Line = mShowShortExit1Line; + result.showLongExit2Line = mShowLongExit2Line; + result.showShortExit2Line = mShowShortExit2Line; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XCHEInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mLoopback = config.loopback; + mMultiplier1 = config.multiplier1; + mMultiplier2 = config.multiplier2; + mUpAppliedTo = config.upAppliedTo; + mDownAppliedTo = config.downAppliedTo; + mShowLongExit1Line = config.showLongExit1Line; + mShowShortExit1Line = config.showShortExit1Line; + mShowLongExit2Line = config.showLongExit2Line; + mShowShortExit2Line = config.showShortExit2Line; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // LEVEL 1 .. + + // + // LONG Exit ... + ArraySetAsSeries(longExit1Buffer, true); + CopyBuffer( + mHandler, + XCHE_1ST_LONG_EXIT_LINE, + barIndex, + mLoopbackBars, + longExit1Buffer); + + // + // SHORT Exit ... + ArraySetAsSeries(shortExit1Buffer, true); + CopyBuffer( + mHandler, + XCHE_1ST_SHORT_EXIT_LINE, + barIndex, + mLoopbackBars, + shortExit1Buffer); + + // + // LEVEL 2 .. + + // + // LONG Exit ... + ArraySetAsSeries(longExit2Buffer, true); + CopyBuffer( + mHandler, + XCHE_2ND_LONG_EXIT_LINE, + barIndex, + mLoopbackBars, + longExit2Buffer); + + // + // SHORT Exit ... + ArraySetAsSeries(shortExit2Buffer, true); + CopyBuffer( + mHandler, + XCHE_2ND_SHORT_EXIT_LINE, + barIndex, + mLoopbackBars, + shortExit2Buffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XCHEInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XCHEInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double longExit1 = longExit1Buffer[barIndex]; + double longExit1Prev = longExit1Buffer[barIndex + 1]; + double shortExit1 = shortExit1Buffer[barIndex]; + double shortExit1Prev = shortExit1Buffer[barIndex + 1]; + + // + double longExit2 = longExit2Buffer[barIndex]; + double longExit2Prev = longExit2Buffer[barIndex + 1]; + double shortExit2 = shortExit2Buffer[barIndex]; + double shortExit2Prev = shortExit2Buffer[barIndex + 1]; + + // + result.longExit1 = longExit1; + result.shortExit1 = shortExit1; + result.longExit2 = longExit2; + result.shortExit2 = shortExit2; + + // + result.isLongExit1Start = + longExit1 != EMPTY_VALUE && + longExit1Prev == EMPTY_VALUE; + + // + result.isShortExit1Start = + shortExit1 != EMPTY_VALUE && + shortExit1Prev == EMPTY_VALUE; + + // + result.isLongExit2Start = + longExit2 != EMPTY_VALUE && + longExit2Prev == EMPTY_VALUE; + + // + result.isShortExit2Start = + shortExit2 != EMPTY_VALUE && + shortExit2Prev == EMPTY_VALUE; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Loopback ... + int mLoopback; + // + // 1st Multiplier ... + double mMultiplier1; + // + // 2nd Multiplier ... + double mMultiplier2; + // + // Calculation ... + // + // Up Zone Applied to ... + ENUM_APPLIED_PRICE mUpAppliedTo; + // + // Down Zone Applied to ... + ENUM_APPLIED_PRICE mDownAppliedTo; + // + // Presentation ... + // + // Show 1st Long Exit ... + bool mShowLongExit1Line; + // + // Show 1st Short Exit ... + bool mShowShortExit1Line; + // + // Show 2st Long Exit ... + bool mShowLongExit2Line; + // + // Show 2st Short Exit ... + bool mShowShortExit2Line; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..e06ad5c2ca813cf0dcd65355bcc7b44c1304e98a GIT binary patch literal 6260 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 Lnr|k#t=#_yebeGH literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.mq5 new file mode 100644 index 0000000..5244956 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhk.helper.class.mq5 @@ -0,0 +1,432 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXHKHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XHKInputs +{ + // + // Presentation ... + bool drawCandles; // Draw Hiken Ashi Candle + bool drawCandleLines; // Show HikenAshi Lines +}; + +// +// Index of Lines ... +enum ENUM_XHK_BUFFERS +{ + // + // Main Requirements ... + XHK_OPEN_LINE = 0, + XHK_HIGH_LINE = 1, + XHK_LOW_LINE = 2, + XHK_CLOSE_LINE = 3, +}; + +// +// Retrieve Info Model ... +struct XHKInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double open; + double high; + double low; + double close; + + // + // Conditions ... + + // + // Detect Candle is Bullish or not ... + bool isBullish; + + // + // Detect Candle is Bearish or not ... + bool isBearish; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXHKHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double openBuffer[]; + double highBuffer[]; + double lowBuffer[]; + double closeBuffer[]; + + // + // Constructor ... + void XSCXHKHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + XHKInputs &config // Indicator Properties ... + // + ) : XSCBaseHelper(symbol, period) + { + // + XSCXHKHelper(symbol, + period, + config.drawCandles, + config.drawCandleLines); + } + void XSCXHKHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // Presentation ... + // + // Draw Hiken Ashi Candle ... + bool drawCandles = true, + // + // Show HikenAshi Lines ... + bool drawCandleLines = false + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mDrawCandles = drawCandles; + mDrawCandleLines = drawCandleLines; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXHKHelper() + { + } + + // + // START Properties ... + // + + // + // Draw Candles ... + bool DrawCandles( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mDrawCandles == show) + { + return true; + } + + // + mDrawCandles = show; + result = Init(); + + // + return result; + } + + // + // Show HikenAshi Lines ... + bool DrawCandleLines( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mDrawCandleLines == show) + { + return true; + } + + // + mDrawCandleLines = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XHK" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xhk", + // + // Inputs ... + // + // Presentation ... + "", + // + // Draw Hiken Ashi Candle ... + mDrawCandles, + // + // Show HikenAshi Lines ... + mDrawCandleLines + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XHKInputs GetConfig() + { + // + XHKInputs result; + + // + result.drawCandles = mDrawCandles; + result.drawCandleLines = mDrawCandleLines; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XHKInputs &config) + { + // + bool result = false; + + // + mDrawCandles = config.drawCandles; + mDrawCandleLines = config.drawCandleLines; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // OPEN ... + ArraySetAsSeries(openBuffer, true); + CopyBuffer( + mHandler, + XHK_OPEN_LINE, + barIndex, + mLoopbackBars, + openBuffer); + + // + // HIGH ... + ArraySetAsSeries(highBuffer, true); + CopyBuffer( + mHandler, + XHK_HIGH_LINE, + barIndex, + mLoopbackBars, + highBuffer); + + // + // LOW ... + ArraySetAsSeries(lowBuffer, true); + CopyBuffer( + mHandler, + XHK_LOW_LINE, + barIndex, + mLoopbackBars, + lowBuffer); + + // + // CLOSE ... + ArraySetAsSeries(closeBuffer, true); + CopyBuffer( + mHandler, + XHK_CLOSE_LINE, + barIndex, + mLoopbackBars, + closeBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XHKInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XHKInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double open = openBuffer[barIndex]; + double high = highBuffer[barIndex]; + double low = lowBuffer[barIndex]; + double close = closeBuffer[barIndex]; + + // + result.open = open; + result.high = high; + result.low = low; + result.close = close; + + // + result.isBullish = open < close; + result.isBearish = open >= close; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Presentation ... + // + // Draw Hiken Ashi Candle ... + bool mDrawCandles; + // + // Show HikenAshi Lines ... + bool mDrawCandleLines; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhull.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xhull.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..11f968599096b74c1464714f14de2b3fea9aa65e GIT binary patch literal 7190 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 9 && + mDivisor >= 0.5; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xhull", + // + // Inputs ... + // + // Market ... + "", + // + // Length ... + mLength, + // + // Divisor (Speed) ... + mDivisor, + // + // Calculation ... + "", + // + // Up Zone Applied to ... + mUpAppliedTo, + // + // Down Zone Applied to ... + mDownAppliedTo, + // + // Presentation ... + "", + // + // Show Up Zone ... + mShowUpZone, + // + // Show Down Zone ... + mShowDownZone + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XHULLInputs GetConfig() + { + // + XHULLInputs result; + + // + result.length = mLength; + result.divisor = mDivisor; + result.upAppliedTo = mUpAppliedTo; + result.downAppliedTo = mDownAppliedTo; + result.showUpZone = mShowUpZone; + result.showDownZone = mShowDownZone; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XHULLInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mDivisor = config.divisor; + mUpAppliedTo = config.upAppliedTo; + mDownAppliedTo = config.downAppliedTo; + mShowUpZone = config.showUpZone; + mShowDownZone = config.showDownZone; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // UP ... + ArraySetAsSeries(upBuffer, true); + CopyBuffer( + mHandler, + XHULL_UP_ZONE_LINE, + barIndex, + mLoopbackBars, + upBuffer); + + // + // UP State ... + ArraySetAsSeries(upStateBuffer, true); + CopyBuffer( + mHandler, + XHULL_UP_ZONE_STATE_LINE, + barIndex, + mLoopbackBars, + upStateBuffer); + + // + // DOWN ... + ArraySetAsSeries(downBuffer, true); + CopyBuffer( + mHandler, + XHULL_DOWN_ZONE_LINE, + barIndex, + mLoopbackBars, + downBuffer); + + // + // DOWN State ... + ArraySetAsSeries(downStateBuffer, true); + CopyBuffer( + mHandler, + XHULL_DOWN_ZONE_STATE_LINE, + barIndex, + mLoopbackBars, + downStateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XHULLInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XHULLInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double up = upBuffer[barIndex]; + XHULL_ZONE_STATES upState = (XHULL_ZONE_STATES)upStateBuffer[barIndex]; + XHULL_ZONE_STATES upStatePrev = (XHULL_ZONE_STATES)upStateBuffer[barIndex + 1]; + + // + double down = downBuffer[barIndex]; + XHULL_ZONE_STATES downState = (XHULL_ZONE_STATES)downStateBuffer[barIndex]; + XHULL_ZONE_STATES downStatePrev = (XHULL_ZONE_STATES)downStateBuffer[barIndex + 1]; + + // + result.up = up; + result.upState = upState; + result.down = down; + result.downState = downState; + + // + result.isUpBullish = upState = XHULL_STATE_BULLISH; + result.isUpBearish = upState = XHULL_STATE_BEARISH; + result.isUpNeutural = upState = XHULL_STATE_NEUTURAL; + + // + result.isUpSwitchedToBullish = upState == XHULL_STATE_BULLISH && + upStatePrev != XHULL_STATE_BULLISH; + result.isUpSwitchedToBearish = upState == XHULL_STATE_BEARISH && + upStatePrev != XHULL_STATE_BEARISH; + result.isUpSwitchedToNeutural = upState == XHULL_STATE_NEUTURAL && + upStatePrev != XHULL_STATE_NEUTURAL; + + // + result.isDownBullish = downState = XHULL_STATE_BULLISH; + result.isDownBearish = downState = XHULL_STATE_BEARISH; + result.isDownNeutural = downState = XHULL_STATE_NEUTURAL; + + // + result.isDownSwitchedToBullish = downState == XHULL_STATE_BULLISH && + downStatePrev != XHULL_STATE_BULLISH; + result.isDownSwitchedToBearish = downState == XHULL_STATE_BEARISH && + downStatePrev != XHULL_STATE_BEARISH; + result.isDownSwitchedToNeutural = downState == XHULL_STATE_NEUTURAL && + downStatePrev != XHULL_STATE_NEUTURAL; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Divisor (Speed) ... + double mDivisor; + // + // Calculation ... + // + // Up Zone Applied to ... + ENUM_APPLIED_PRICE mUpAppliedTo; + // + // Down Zone Applied to ... + ENUM_APPLIED_PRICE mDownAppliedTo; + // + // Presentation ... + // + // Show Up Zone ... + bool mShowUpZone; + // + // Show Down Zone ... + bool mShowDownZone; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..07e4e35d71ef76b2e9d9c545925c3b0a7926b15b GIT binary patch literal 6572 zcmdT>Ra_L_)*S@t?hfgWp}U5Z4gm#}8k#|JfI+&uQ$k7_9O*_%NeLOcLFtYmKL7Xo z-M9O2U+>z#efBCwuKIcLCj#%rvmkL||%L-ga(xnI{ zyMO*F0o(u(02J^Z-~a#v>;awtMt~4N;BNu}Jb!xwz`MV!?Oz=Pa0a;iWz+$Ne@~^q zoa^7$|0w^<_{Xv5-wAjCBmw+?!{=YY_xJv9-?snq&G&ac|JzRg^Oghwe1Eqs@Sny1 zf(<1WCSnU%#Tjl`j%)oTap9Mlmi8>k&( zL@rG#gL2V)LIjuEB%W$|vJyV-4letiPPo5pl$G!a;kRQ1Zx$uj>Q%-VCwB0sQF1({5cN3>m^YYpP!0xDEE#)r+RSTbKSIW7b-s0$Beq+ zZMY?*K(7+FB%LhE*+ta$8>xs@c8DHzu*Rq`WX$<3>#MeNLVmY|B2U<@Gzn1k#kW;P z&oFY0%!6bd8KhnAmKK_B(a%VXcJiwN{w*c%cImo{*G_M*z;&g21e(TU66)E zbADj%5seCR693H3otL6p{U_GQjISvAV&ntf&YoJY4O8Td)*MXENk?57_%=8Dnl9P$ z1XS)>_?67Q*SGoSy$!Cf3fe12Sl20EY4YuWJUKXIkJ^BIC)#g}?Utyr^fk7Uc=nw) z)3-cPh>y7Jv)=K?S0{KSS<%?3ID2|Jw9VhyUUk>=VT%DHlbECJhUqzO6)JODi2}4< z!*DVu2n{}N5G$q)+{w6poF2?IwK8!Ei(_4Bk@~XmHr9#O^0%yPJWK6Pl`ba9%7YJW z6ypM{=;q@t=#KWXE-E2=SBUOAORWM|FViHO_8Xm8Q3kd8xq{IFdXVbX>Pg^7{MarI zYWMgbL&>_=$l9y3aI4oKyB}5$zWOH$3kW6m6(NTX&D{5yL6T7_9B&_k#FLxlU7Qbt zc?#tL?i$@QQLNEv?0eRzu^!(9d;JMHlM)q4f(%ePR8etr z{NgSgNCp#Gm7roaT+D8r+P;&VmaW)ee>NKjCs<=Qjef>Jl_I~=jMII^)*>1lb?svO zvzXNj%+wI^BdF!dw%7ibCa(PgRo9q(3 zeK8Z>OMy8_n;4gpJb6MdM`!d9Wd52byo7hN+?qPpjpOG`volAvBD$L2xCwn^Lt=IV zjlSHE44u#A#vHo>L_|uK-vTzdT3!`xlSkZB}VAO|;656K_jgKv3 z0shabLhiA0G9p}3$%q|GRmpzFrPra$>UI*Jo0-6=Dk%=wl8Dmkv;0G-h=Cxmtn^;L zFMa2oQ>C}fr4eW~z-VO8yGoVz3@Mb>=j2#CFnfmWo)k{=u12oWD1eeZ-4HF=kaz$+ zG=-~pC~sXA@_WCn#6iG%=h9v!eKw-uV^~dsvGi!Ua}FF%F-9!3p?(>Z?)GF?Q@bX} zL(^g8W8UIb!_kn6JS=e748IBS#EK+{<}j5ymN<(3YTPkYpwg=x?ZIumEf(((^D-!y z*z&d5xebM|(m?Jcl7-B8P-gEOP+=Uojs@|k5!7^`ih+MG{hmKuc9_=s>B`@X^)T_B z{&hBnAC*ue?sW>wQWLr~X^S|;#?kgV{7Yi)`$A#xk}g9JAnhbP5#x;-hMB>sb(GGl< zH}%Y+HY%As0a=mK7QB%39^KWZ61@OK*!XdPB>3dQa~ zKkK!(zGbz{F7GzbwzoC*ll+Og9RlcDzGi*1y8lRuJ%@T7M;2cCw3MCptT zs17+B3N$a=@RWI>-ZlBLHiSfPX%%@(15f9<-b$O_^UejEGI#Sh)5rjENr$aEzK%TsWxep%z{L+r_!Ok!%t1f(8ZCQA}#mh+NO?JYb# z1y+zk-!QlO%(of@)x*dw=ti4M@CkS8S4j_sz};ri2v^uv<)lY?14(U=yKi7crV|2_ zI=P0L>%C`&u6P$kBP;k*seQRYNocjY;}L{&`PO=ofriEm*Y<^!>E7Lw+4}tHm>4fK zz|;y&A`Ne9W=)g+V+~?v4&^40Rf4gpO6%#p&lcf#Hm~#^4sx0@8lwe1)5~4|NjY#h zUeEm}HtuSwIr?j<)pX5uD%V^^8jGF?;y<;^(1`LdJNxjahxbYIBTsd}K{0$au$x5g z%Of{12LfF$>UG;(=0&ZGwUny#cMNMb42I7N!*G``ZsM9EkzM=+@GG!J@_N~C8@jo{ z$-QgV97U#=c~44zpd`XUmIm0BY3U&w=8AGIx>EuTYDnCv)UIDwSuI|h>-6lxsfR;c zn@|~SYzKfPn-CKw>8q(IL8f&(6k-OZ1*?onk|WFcrw7NJc7qYs6-09hmwjCsp$yuI zDCcqHvyy7aXvO$$-3_aLe6%W89YNH)p=$yQ_p=*uqfl1S5YZG+h_lINk=->73BTk* zT|6u-6zvDP@F*%Hs5>3#l;u1o3%Rq<9x0O=MfI-UflcQjEd3?x+&kO)>kKc##Il%F zUKXwmhdE7D)&-P$RKC$5ZJYQlcsQsa#k^Iy2Q*l~yz(IP@?`b50-^a6w5RrT)XO5X>`mzgOVer44;t$%9s5*<=%=@wJFz9J@KTWwXe_XU7 zeLqm!%bJLXn(xj!OfeLh*t0=;*})OS!UddoLZHD zIcWJeuyBJ!$+r__07D|4Vp#>EZDQYr#)XJ=+actftrvji2&C@2TRr#VmNJmWgYcqc zH~+G~CfdFp(}Ui8Xk~QPGo%rvud(Uv$+=yl9kOsBnw<(s(L_^HG9;Y}^)mlFKE!+1 zEhJwr=##rXc{HMtfGLQ%qmKJA(`p4OiF}O==q9O_6wjtL6Rw~5^{E?GZ>ldcCfjfY zOKO$#xP|Q7^@Jb3^hmUB8*TT@vgJOT8Hft_TiA2E=f2~rdiQ*;UE_M~Lt4H#IXBM0 zJlXQX_6tGVcRuGAe*6+HSeSv6YT6V*9h725`3avDGlfOo-|x2`f+-1qF79VZj|X_Y zSy&yU3c@XaC%l1=$8)n%LrcMX@QqV8IRvGT2G=VOX#Bn zZ}TljazCPx8~M(8v{rlC=#iqAWhnwW3?ru4D1d~6M5rwYs+IAQ z%K#!Bc^Aqec;Cf(X%-yr5$;MaKJiFPF`mjzsX2|TP8iORtzM=XfW9MfZF&b)s8P0= zZL>(co-l|SxmdEUM-lvDQ@Ft;b9!X`ELGM)T`A45jUR}{%s=2&P$kyzyHm7^bTmgL zH%`xlaa7V&fvQtV-p&Ux7KN~~NqM{ThMBC`jRGT(-LbO121(=R-DArgOYj8u305S} zpEy-k-<-SHFg(~i9A91)i&Lve5!GoHj^q+C6rP(+>!uCjkNrXwVlKI7jc^KN4xP@N zmsOLr+_K%0@j_@)p;og6g=b&AC~O#YS(M})9wFt_ue)^oGKOn&F4luvP{AVQVDENB zU(U^}1`E=VT71a>d&x)!BqfyQR-X$|9I-FQRL8b>kj%ZRw0o=&&d6REYPqp z&XLf8pwjo5stXRYNzNbm&>Pw{;JYk<#O|*?j1@*>8MJL2pt43YXjqq5E!#n5I;0S- ziCn!a6)2&h)mNi=zZ~Zu@QQt&TP%Y)M%3vNGXG&-;h2Eg2^3cC3 znc(81?w)4mI|i+Ke8B=TPlrgZcA89-+Rs;L!7E|PHdSRvlfQC3YZsOw|9$pMyR$`&nw-V@*6wnGM`%$OujuY?QuPl=W;7i z+DDGly|-LDkb20rW(hi$*0bZX?M%UPp!v!0jIg{r_n)#Hi%(Yq62Ckz& zBv;`u9=DJtP=FF+jHi|z=NI(|Mv(Y)+LBf>9pJCLCD*2};6c56+^~gI&#A+$nKN3wPhX26$!52ZcIK&EIF(ER%)7 zbDb_HaZT0^BVb>}&U$9zik6?ZyOzE*eAXOQG3iG0J&GKfIq%!T8udN7+kZ+Hd6@WO zdB#=7Q{y(wOP^=5KFfTYr*Q~xu=JrcQWP6;BsVMjEQCf7`t^y%Dl*Li`fznGMfqp} z=~(gXe;BtEh#B;{z5~8ECA#0OgK*D96JiO9*p7-5C$*|4y(mKSfB8rdcAQ;mddikf z3)VLrWYN92UbbR5DJJA60!wPaF+%`+{3CYh$d_&Km#@=sB3`aAXPM%o73YW)Xz*G= zRD%JmS7e{JR?9v}g=yukJnEy>#^-BKT34X;KGb zzk8T{rS(7d-IlB$tR{Z)z_Z-{TGLVUP3G&H76>b@7SB#NxK&s7G&7BCo7=MX$#}zB zI~GR-yh{M|(ZA5JnEN`br13}oLVF3Jo8) zrv3DFio5_bdGm59|;Pe-S|O_!lw3zA7cf{${w z&s~3J&SdaH7w4Q@xZosa?6$p7*0K1?9N^CySw)Nc51LrKLA2%m`huQdA~&p9-52Yo za`5;~RV%RrLcFf{dL5xV!X42;rQj%S|HoJzkVAkZJPx<8-fBHRVgzi?uEeM*T;vB< zW@!x=c}k7XJMO#?@$JVD1GoNRuuAQ}kqMrQNw45Gc+zU*b4(v0-TXe1g@dkK`tG3U zJFUBRBV9D}u%N*OJbj{72zLBSZ_w^|ISCVVexLtpqqR=6Jgr=Q{9Fi&rGNbMW&ER=*+@fn}(qZp=<`e~WhEVB&gQD$$bc(5l{Lw>U$ z0xPjxmFm3mZ=;x)F;N5<`;Dr(yq)}nO0Fi2j*y~i6>B*IvpH(?OPNl4eur(iP>m~W z&*+_b^cjDE;!`_aKr8%7{U;#Ce}dwkD}OmD+)!?P0?%hhrQkiyAaP80qWzj3;Z}Jx zzrJX{Zj(;cEGkpbND60%;af!|#zcxG6w%!p;&Akjl^FfuWM479ETC8Z LYeumli_ZT61=(_~ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.mq5 new file mode 100644 index 0000000..af66c56 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xich.helper.class.mq5 @@ -0,0 +1,1052 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXICHHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// Inputs ... +struct XICHInputs +{ + // + // TENKANSEN ... + // Tenkan Sen ... + int tenkanSenLength; // Length + ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode; // Calculation Mode + + // + // KIJUNSEN ... + // Kijun Sen ... + int kijunSenLength; // Length + ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode; // Calculation Mode + + // + // SENKOUSPANB ... + // Senkou Span B ... + int senkouSpanBLength; // Length + ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode; // Calculation Mode + + // + // CHIKOUSPAN ... + // Chikou Span ... + ENUM_APPLIED_PRICE chikuoSpanAppliedTo; // Price Type + + // + // Presentation ... + bool showTenkanSen; // Show Tenkan Sen + bool showKijunSen; // Show Kijun Sen + bool showKijunSenPlus; // Show Kijun Sen + + bool showKijunSenNegative; // Show Kijun Sen - + bool showChikouSpan; // Show Chikou Span + bool showSenkouSpanA; // Show Senkou Span A + bool showSenkouSpanB; // Show Senkou Span B + bool showKumo; // Show Kumo + bool shiftKumo; // Shift Kumo to Future +}; + +// +// Index of Lines ... +enum ENUM_XICH_BUFFERS +{ + // + // Main Requirements ... + XICH_TEANKANSEN_LINE = 0, + XICH_KIJUNSEN_LINE = 1, + XICH_CHIKOUSPAN_LINE = 4, + XICH_SENKOUSPANA_LINE = 5, + XICH_SENKOUSPANB_LINE = 6, +}; + +// +// Retrieve Info Model ... +struct XICHInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double tenkanSen; + double kijunSen; + double chikouSpan; + double senkouSpanA; + double senkouSpanB; + double senkouSpanAFuture; + double senkouSpanBFuture; + + // + // Conditions ... + + // + bool isTenkanSenOverKijunSen; + bool isTenkanSenUnderKijunSen; + bool isTenkanSenCrossedOverKijunSen; + bool isTenkanSenCrossedUnderKijunSen; + + // + bool isKumoBullish; + bool isKumoBearish; + bool isFutureKumoBullish; + bool isFutureKumoBearish; + bool isKumoSwitchedToBullish; + bool isKumoSwitchedToBearish; + bool isFutureKumoSwitchedToBullish; + bool isFutureKumoSwitchedToBearish; + + // + bool isTenkanSenOverSenkouSpanA; + bool isTenkanSenUnderSenkouSpanA; + bool isTenkanSenOverFutureSenkouSpanA; + bool isTenkanSenUnderFutureSenkouSpanA; + bool isTenkanSenCrossedOverSenkouSpanA; + bool isTenkanSenCrossedUnderSenkouSpanA; + bool isTenkanSenCrossedOverFutureSenkouSpanA; + bool isTenkanSenCrossedUnderFutureSenkouSpanA; + + // + bool isTenkanSenOverSenkouSpanB; + bool isTenkanSenUnderSenkouSpanB; + bool isTenkanSenOverFutureSenkouSpanB; + bool isTenkanSenUnderFutureSenkouSpanB; + bool isTenkanSenCrossedOverSenkouSpanB; + bool isTenkanSenCrossedUnderSenkouSpanB; + bool isTenkanSenCrossedOverFutureSenkouSpanB; + bool isTenkanSenCrossedUnderFutureSenkouSpanB; + + // + bool isKijunSenOverSenkouSpanA; + bool isKijunSenUnderSenkouSpanA; + bool isKijunSenOverFutureSenkouSpanA; + bool isKijunSenUnderFutureSenkouSpanA; + bool isKijunSenCrossedOverSenkouSpanA; + bool isKijunSenCrossedUnderSenkouSpanA; + bool isKijunSenCrossedOverFutureSenkouSpanA; + bool isKijunSenCrossedUnderFutureSenkouSpanA; + + // + bool isKijunSenOverSenkouSpanB; + bool isKijunSenUnderSenkouSpanB; + bool isKijunSenOverFutureSenkouSpanB; + bool isKijunSenUnderFutureSenkouSpanB; + bool isKijunSenCrossedOverSenkouSpanB; + bool isKijunSenCrossedUnderSenkouSpanB; + bool isKijunSenCrossedOverFutureSenkouSpanB; + bool isKijunSenCrossedUnderFutureSenkouSpanB; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXICHHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double tenkanSenBuffer[]; + double kijunSenBuffer[]; + double chikouSpanBuffer[]; + double senkouSpanABuffer[]; + double senkouSpanBBuffer[]; + + // + // Constructor ... + void XSCXICHHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + XICHInputs &config // Indicator Properties ... + ) : XSCBaseHelper(symbol, period) + { + // + XSCXICHHelper(symbol, + period, + config.tenkanSenLength, + config.tenkanSenMode, + config.kijunSenLength, + config.kijunSenMode, + config.senkouSpanBLength, + config.senkouSpanBMode, + config.chikuoSpanAppliedTo, + config.showTenkanSen, + config.showKijunSen, + config.showKijunSenPlus, + config.showKijunSenNegative, + config.showChikouSpan, + config.showSenkouSpanA, + config.showSenkouSpanB, + config.showKumo, + config.shiftKumo); + } + void XSCXICHHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // TENKANSEN ... + // + // Length ... + int tenkanSenLength = 9, + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode = X_XICH_HH_LL_MODE, + // + // KIJUNSEN ... + // + // Length ... + int kijunSenLength = 26, + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode = X_XICH_HH_LL_MODE, + // + // SENKOUSPANB ... + // + // Length ... + int senkouSpanBLength = 52, + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode = X_XICH_HH_LL_MODE, + // + // CHIKOUSPAN ... + // + // Price Type ... + ENUM_APPLIED_PRICE chikuoSpanAppliedTo = PRICE_CLOSE, + // + // Presentation ... + // + // Show Tenkan Sen ... + bool showTenkanSen = true, + // + // Show Kijun Sen ... + bool showKijunSen = true, + // + // Show Kijun Sen + ... + bool showKijunSenPlus = false, + // + // Show Kijun Sen - ... + bool showKijunSenNegative = false, + // + // Show Chikou Span ... + bool showChikouSpan = true, + // + // Show Senkou Span A ... + bool showSenkouSpanA = true, + // + // Show Senkou Span B ... + bool showSenkouSpanB = true, + // + // Show Kumo ... + bool showKumo = true, + // + // Shift Kumo to Future ... + bool shiftKumo = true + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mTenkanSenLength = tenkanSenLength; + mTenkanSenMode = tenkanSenMode; + mKijunSenLength = kijunSenLength; + mKijunSenMode = kijunSenMode; + mSenkouSpanBLength = senkouSpanBLength; + mSenkouSpanBMode = senkouSpanBMode; + mChikuoSpanAppliedTo = chikuoSpanAppliedTo; + mShowTenkanSen = showTenkanSen; + mShowKijunSen = showKijunSen; + mShowKijunSenPlus = showKijunSenPlus; + mShowKijunSenNegative = showKijunSenNegative; + mShowChikouSpan = showChikouSpan; + mShowSenkouSpanA = showSenkouSpanA; + mShowSenkouSpanB = showSenkouSpanB; + mShowKumo = showKumo; + mShiftKumo = shiftKumo; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXICHHelper() + { + } + + // + // START Properties ... + // + + // + // Show Tenkan Sen ... + bool ShowTenkanSen( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowTenkanSen == show) + { + return true; + } + + // + mShowTenkanSen = show; + result = Init(); + + // + return result; + } + + // + // Show Kijun Sen ... + bool ShowKijunSen( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowKijunSen == show) + { + return true; + } + + // + mShowKijunSen = show; + result = Init(); + + // + return result; + } + + // + // Show Chikou Span ... + bool ShowChikouSpan( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowChikouSpan == show) + { + return true; + } + + // + mShowChikouSpan = show; + result = Init(); + + // + return result; + } + + // + // Show Senkou Span A ... + bool ShowSenkouSpanA( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowSenkouSpanA == show) + { + return true; + } + + // + mShowSenkouSpanA = show; + result = Init(); + + // + return result; + } + + // + // Show Senkou Span B ... + bool ShowSenkouSpanB( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowSenkouSpanB == show) + { + return true; + } + + // + mShowSenkouSpanB = show; + result = Init(); + + // + return result; + } + + // + // Show Kumo ... + bool ShowKumo( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowKumo == show) + { + return true; + } + + // + mShowKumo = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XICH" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Inputs ... + // + result = + (mTenkanSenLength > 2 && + mKijunSenLength > mTenkanSenLength && + mSenkouSpanBLength > mKijunSenLength); + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xich", + // + // Inputs ... + // + // TENKANSEN ... + "", + // + // Length ... + mTenkanSenLength, + // + // Calculation Mode ... + mTenkanSenMode, + // + // KIJUNSEN ... + "", + // + // Length ... + mKijunSenLength, + // + // Calculation Mode ... + mKijunSenMode, + // + // SENKOUSPANA ... + "", + // + // Length ... + mSenkouSpanBLength, + // + // Calculation Mode ... + mSenkouSpanBMode, + // + // CHIKOUSPAN ... + "", + // + // Price Type ... + mChikuoSpanAppliedTo, + // + // PRESENTATION ... + "", + // + // Show Tenkan Sen ... + mShowTenkanSen, + // + // Show Kijun Sen ... + mShowKijunSen, + // + // Show Kijun Sen + ... + mShowKijunSenPlus, + // + // Show Kijun Sen - ... + mShowKijunSenNegative, + // + // Show Chikou Span ... + mShowChikouSpan, + // + // Show Senkou Span A ... + mShowSenkouSpanA, + // + // Show Senkou Span B ... + mShowSenkouSpanB, + // + // Show Kumo ... + mShowKumo, + // + // Shift Kumo to Future ... + mShiftKumo + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XICHInputs GetConfig() + { + // + XICHInputs result; + + // + result.tenkanSenLength = mTenkanSenLength; + result.tenkanSenMode = mTenkanSenMode; + result.kijunSenLength = mKijunSenLength; + result.kijunSenMode = mKijunSenMode; + result.senkouSpanBLength = mSenkouSpanBLength; + result.senkouSpanBMode = mSenkouSpanBMode; + result.chikuoSpanAppliedTo = mChikuoSpanAppliedTo; + result.showTenkanSen = mShowTenkanSen; + result.showKijunSen = mShowKijunSen; + result.showKijunSenPlus = mShowKijunSenPlus; + result.showKijunSenNegative = mShowKijunSenNegative; + result.showChikouSpan = mShowChikouSpan; + result.showSenkouSpanA = mShowSenkouSpanA; + result.showSenkouSpanB = mShowSenkouSpanB; + result.showKumo = mShowKumo; + result.shiftKumo = mShiftKumo; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XICHInputs &config) + { + // + bool result = false; + + // + mTenkanSenLength = config.tenkanSenLength; + mTenkanSenMode = config.tenkanSenMode; + mKijunSenLength = config.kijunSenLength; + mKijunSenMode = config.kijunSenMode; + mSenkouSpanBLength = config.senkouSpanBLength; + mSenkouSpanBMode = config.senkouSpanBMode; + mChikuoSpanAppliedTo = config.chikuoSpanAppliedTo; + mShowTenkanSen = config.showTenkanSen; + mShowKijunSen = config.showKijunSen; + mShowKijunSenPlus = config.showKijunSenPlus; + mShowKijunSenNegative = config.showKijunSenNegative; + mShowChikouSpan = config.showChikouSpan; + mShowSenkouSpanA = config.showSenkouSpanA; + mShowSenkouSpanB = config.showSenkouSpanB; + mShowKumo = config.showKumo; + mShiftKumo = config.shiftKumo; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // Since Ichimoku Has Some Issues ... + mLoopbackBars = 52; + + // + // TENKANSEN ... + ArraySetAsSeries(tenkanSenBuffer, true); + CopyBuffer( + mHandler, + XICH_TEANKANSEN_LINE, + barIndex, + mLoopbackBars, + tenkanSenBuffer); + + // + // KIJUNSEN ... + ArraySetAsSeries(kijunSenBuffer, true); + CopyBuffer( + mHandler, + XICH_KIJUNSEN_LINE, + barIndex, + mLoopbackBars, + kijunSenBuffer); + + // + // CHIKOUSPAN ... + ArraySetAsSeries(chikouSpanBuffer, true); + CopyBuffer( + mHandler, + XICH_CHIKOUSPAN_LINE, + barIndex + mKijunSenLength + 1, + mLoopbackBars, + chikouSpanBuffer); + + // + // SENKOUSPANA ... + ArraySetAsSeries(senkouSpanABuffer, true); + CopyBuffer( + mHandler, + XICH_SENKOUSPANA_LINE, + -1 * (barIndex + mKijunSenLength), + mLoopbackBars, + senkouSpanABuffer); + + // + // SENKOUSPANB ... + ArraySetAsSeries(senkouSpanBBuffer, true); + CopyBuffer( + mHandler, + XICH_SENKOUSPANB_LINE, + -1 * (barIndex + mKijunSenLength), + mLoopbackBars, + senkouSpanBBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XICHInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XICHInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double tenkanSen = tenkanSenBuffer[barIndex]; + double tenkanSenPrev = tenkanSenBuffer[barIndex + 1]; + + // + double kijunSen = kijunSenBuffer[barIndex]; + double kijunSenPrev = kijunSenBuffer[barIndex + 1]; + + // + double chikouSpan = chikouSpanBuffer[barIndex + mKijunSenLength]; + double chikouSpanPrev = chikouSpanBuffer[barIndex + mKijunSenLength + 1]; + + // + double senkouSpanA = senkouSpanABuffer[barIndex + mKijunSenLength]; + double senkouSpanAPrev = senkouSpanABuffer[barIndex + mKijunSenLength + 1]; + + // + double senkouSpanB = senkouSpanBBuffer[barIndex + mKijunSenLength]; + double senkouSpanBPrev = senkouSpanBBuffer[barIndex + mKijunSenLength + 1]; + + // + double senkouSpanAFuture = senkouSpanABuffer[barIndex]; + double senkouSpanAFuturePrev = senkouSpanABuffer[barIndex + 1]; + + // + double senkouSpanBFuture = senkouSpanBBuffer[barIndex]; + double senkouSpanBFuturePrev = senkouSpanBBuffer[barIndex + 1]; + + // + bool isTenkanSenOverKijunSen = + tenkanSen > kijunSen; + bool isTenkanSenUnderKijunSen = + tenkanSen < kijunSen; + bool isTenkanSenCrossedOverKijunSen = + tenkanSen > kijunSen && + tenkanSenPrev <= kijunSenPrev; + bool isTenkanSenCrossedUnderKijunSen = + tenkanSen < kijunSen && + tenkanSenPrev >= kijunSenPrev; + + // + bool isKumoBullish = + senkouSpanA > senkouSpanB; + bool isKumoBearish = + senkouSpanA < senkouSpanB; + bool isFutureKumoBullish = + senkouSpanAFuture > senkouSpanBFuture; + bool isFutureKumoBearish = + senkouSpanAFuture < senkouSpanBFuture; + bool isKumoSwitchedToBullish = + senkouSpanA > senkouSpanB && + senkouSpanAPrev <= senkouSpanBPrev; + bool isKumoSwitchedToBearish = + senkouSpanA < senkouSpanB && + senkouSpanAPrev >= senkouSpanBPrev; + bool isFutureKumoSwitchedToBullish = + senkouSpanAFuture > senkouSpanBFuture && + senkouSpanAFuturePrev <= senkouSpanBFuturePrev; + bool isFutureKumoSwitchedToBearish = + senkouSpanAFuture < senkouSpanBFuture && + senkouSpanAFuturePrev >= senkouSpanBFuturePrev; + + // + bool isTenkanSenOverSenkouSpanA = + tenkanSen > senkouSpanA; + bool isTenkanSenUnderSenkouSpanA = + tenkanSen < senkouSpanA; + bool isTenkanSenOverFutureSenkouSpanA = + tenkanSen > senkouSpanAFuture; + bool isTenkanSenUnderFutureSenkouSpanA = + tenkanSen < senkouSpanAFuture; + bool isTenkanSenCrossedOverSenkouSpanA = + tenkanSen > senkouSpanA && + tenkanSenPrev <= senkouSpanAPrev; + bool isTenkanSenCrossedUnderSenkouSpanA = + tenkanSen < senkouSpanA && + tenkanSenPrev >= senkouSpanAPrev; + bool isTenkanSenCrossedOverFutureSenkouSpanA = + tenkanSen > senkouSpanAFuture && + tenkanSenPrev <= senkouSpanAFuturePrev; + bool isTenkanSenCrossedUnderFutureSenkouSpanA = + tenkanSen < senkouSpanAFuture && + tenkanSenPrev >= senkouSpanAFuturePrev; + + // + bool isTenkanSenOverSenkouSpanB = + tenkanSen > senkouSpanB; + bool isTenkanSenUnderSenkouSpanB = + tenkanSen < senkouSpanB; + bool isTenkanSenOverFutureSenkouSpanB = + tenkanSen > senkouSpanBFuture; + bool isTenkanSenUnderFutureSenkouSpanB = + tenkanSen < senkouSpanBFuture; + bool isTenkanSenCrossedOverSenkouSpanB = + tenkanSen > senkouSpanB && + tenkanSenPrev <= senkouSpanBPrev; + bool isTenkanSenCrossedUnderSenkouSpanB = + tenkanSen < senkouSpanB && + tenkanSenPrev >= senkouSpanBPrev; + bool isTenkanSenCrossedOverFutureSenkouSpanB = + tenkanSen > senkouSpanBFuture && + tenkanSenPrev <= senkouSpanBFuturePrev; + bool isTenkanSenCrossedUnderFutureSenkouSpanB = + tenkanSen < senkouSpanBFuture && + tenkanSenPrev >= senkouSpanBFuturePrev; + + // + bool isKijunSenOverSenkouSpanA = + kijunSen > senkouSpanA; + bool isKijunSenUnderSenkouSpanA = + kijunSen < senkouSpanA; + bool isKijunSenOverFutureSenkouSpanA = + kijunSen > senkouSpanAFuture; + bool isKijunSenUnderFutureSenkouSpanA = + kijunSen < senkouSpanAFuture; + bool isKijunSenCrossedOverSenkouSpanA = + kijunSen > senkouSpanA && + kijunSenPrev <= senkouSpanAPrev; + bool isKijunSenCrossedUnderSenkouSpanA = + kijunSen < senkouSpanA && + kijunSenPrev >= senkouSpanAPrev; + bool isKijunSenCrossedOverFutureSenkouSpanA = + kijunSen > senkouSpanAFuture && + kijunSenPrev <= senkouSpanAFuturePrev; + bool isKijunSenCrossedUnderFutureSenkouSpanA = + kijunSen < senkouSpanAFuture && + kijunSenPrev >= senkouSpanAFuturePrev; + + // + bool isKijunSenOverSenkouSpanB = + kijunSen > senkouSpanB; + bool isKijunSenUnderSenkouSpanB = + kijunSen < senkouSpanB; + bool isKijunSenOverFutureSenkouSpanB = + kijunSen > senkouSpanBFuture; + bool isKijunSenUnderFutureSenkouSpanB = + kijunSen < senkouSpanBFuture; + bool isKijunSenCrossedOverSenkouSpanB = + kijunSen > senkouSpanB && + kijunSenPrev <= senkouSpanB; + bool isKijunSenCrossedUnderSenkouSpanB = + kijunSen < senkouSpanB && + kijunSenPrev >= senkouSpanB; + bool isKijunSenCrossedOverFutureSenkouSpanB = + kijunSen > senkouSpanBFuture && + kijunSenPrev <= senkouSpanBFuturePrev; + bool isKijunSenCrossedUnderFutureSenkouSpanB = + kijunSen < senkouSpanBFuture && + kijunSenPrev >= senkouSpanBFuturePrev; + + // + result.tenkanSen = tenkanSen; + result.kijunSen = kijunSen; + result.chikouSpan = chikouSpan; + result.senkouSpanA = senkouSpanA; + result.senkouSpanB = senkouSpanB; + result.senkouSpanAFuture = senkouSpanAFuture; + result.senkouSpanBFuture = senkouSpanBFuture; + + // + result.isTenkanSenOverKijunSen = isTenkanSenOverKijunSen; + result.isTenkanSenUnderKijunSen = isTenkanSenUnderKijunSen; + result.isTenkanSenCrossedOverKijunSen = isTenkanSenCrossedOverKijunSen; + result.isTenkanSenCrossedUnderKijunSen = isTenkanSenCrossedUnderKijunSen; + + // + result.isKumoBullish = isKumoBullish; + result.isKumoBearish = isKumoBearish; + result.isFutureKumoBullish = isFutureKumoBullish; + result.isFutureKumoBearish = isFutureKumoBearish; + result.isKumoSwitchedToBullish = isKumoSwitchedToBullish; + result.isKumoSwitchedToBearish = isKumoSwitchedToBearish; + result.isFutureKumoSwitchedToBullish = isFutureKumoSwitchedToBullish; + result.isFutureKumoSwitchedToBearish = isFutureKumoSwitchedToBearish; + + // + result.isTenkanSenOverSenkouSpanA = isTenkanSenOverSenkouSpanA; + result.isTenkanSenUnderSenkouSpanA = isTenkanSenUnderSenkouSpanA; + result.isTenkanSenOverFutureSenkouSpanA = isTenkanSenOverFutureSenkouSpanA; + result.isTenkanSenUnderFutureSenkouSpanA = isTenkanSenUnderFutureSenkouSpanA; + result.isTenkanSenCrossedOverSenkouSpanA = isTenkanSenCrossedOverSenkouSpanA; + result.isTenkanSenCrossedUnderSenkouSpanA = isTenkanSenCrossedUnderSenkouSpanA; + result.isTenkanSenCrossedOverFutureSenkouSpanA = isTenkanSenCrossedOverFutureSenkouSpanA; + result.isTenkanSenCrossedUnderFutureSenkouSpanA = isTenkanSenCrossedUnderFutureSenkouSpanA; + + // + result.isTenkanSenOverSenkouSpanB = isTenkanSenOverSenkouSpanB; + result.isTenkanSenUnderSenkouSpanB = isTenkanSenUnderSenkouSpanB; + result.isTenkanSenOverFutureSenkouSpanB = isTenkanSenOverFutureSenkouSpanB; + result.isTenkanSenUnderFutureSenkouSpanB = isTenkanSenUnderFutureSenkouSpanB; + result.isTenkanSenCrossedOverSenkouSpanB = isTenkanSenCrossedOverSenkouSpanB; + result.isTenkanSenCrossedUnderSenkouSpanB = isTenkanSenCrossedUnderSenkouSpanB; + result.isTenkanSenCrossedOverFutureSenkouSpanB = isTenkanSenCrossedOverFutureSenkouSpanB; + result.isTenkanSenCrossedUnderFutureSenkouSpanB = isTenkanSenCrossedUnderFutureSenkouSpanB; + + // + result.isKijunSenOverSenkouSpanA = isKijunSenOverSenkouSpanA; + result.isKijunSenUnderSenkouSpanA = isKijunSenUnderSenkouSpanA; + result.isKijunSenOverFutureSenkouSpanA = isKijunSenOverFutureSenkouSpanA; + result.isKijunSenUnderFutureSenkouSpanA = isKijunSenUnderFutureSenkouSpanA; + result.isKijunSenCrossedOverSenkouSpanA = isKijunSenCrossedOverSenkouSpanA; + result.isKijunSenCrossedUnderSenkouSpanA = isKijunSenCrossedUnderSenkouSpanA; + result.isKijunSenCrossedOverFutureSenkouSpanA = isKijunSenCrossedOverFutureSenkouSpanA; + result.isKijunSenCrossedUnderFutureSenkouSpanA = isKijunSenCrossedUnderFutureSenkouSpanA; + + // + result.isKijunSenOverSenkouSpanB = isKijunSenOverSenkouSpanB; + result.isKijunSenUnderSenkouSpanB = isKijunSenUnderSenkouSpanB; + result.isKijunSenOverFutureSenkouSpanB = isKijunSenOverFutureSenkouSpanB; + result.isKijunSenUnderFutureSenkouSpanB = isKijunSenUnderFutureSenkouSpanB; + result.isKijunSenCrossedOverSenkouSpanB = isKijunSenCrossedOverSenkouSpanB; + result.isKijunSenCrossedUnderSenkouSpanB = isKijunSenCrossedUnderSenkouSpanB; + result.isKijunSenCrossedOverFutureSenkouSpanB = isKijunSenCrossedOverFutureSenkouSpanB; + result.isKijunSenCrossedUnderFutureSenkouSpanB = isKijunSenCrossedUnderFutureSenkouSpanB; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // TENKANSEN ... + // + // Length ... + int mTenkanSenLength; + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE mTenkanSenMode; + // + // KIJUNSEN ... + // + // Length ... + int mKijunSenLength; + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE mKijunSenMode; + // + // SENKOUSPANB ... + // + // Length ... + int mSenkouSpanBLength; + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE mSenkouSpanBMode; + // + // CHIKOUSPAN ... + // + // Price Type ... + ENUM_APPLIED_PRICE mChikuoSpanAppliedTo; + // + // Presentation ... + // + // Show Tenkan Sen ... + bool mShowTenkanSen; + // + // Show Kijun Sen ... + bool mShowKijunSen; + // + // Show Kijun Sen + ... + bool mShowKijunSenPlus; + // + // Show Kijun Sen - ... + bool mShowKijunSenNegative; + // + // Show Chikou Span ... + bool mShowChikouSpan; + // + // Show Senkou Span A ... + bool mShowSenkouSpanA; + // + // Show Senkou Span B ... + bool mShowSenkouSpanB; + // + // Show Kumo ... + bool mShowKumo; + // + // Shift Kumo to Future ... + bool mShiftKumo; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..8204095bc045a1ca40469b4b1f46ac17de735df9 GIT binary patch literal 6608 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.mq5 new file mode 100644 index 0000000..ed790b5 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xmrb.helper.class.mq5 @@ -0,0 +1,908 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXMRBHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XMRBInputs +{ + // + // Ribbon 1 ... + int fast1Length; // Fast + int slow1Length; // Slow + + // + // Ribbon 2 ... + int fast2Length; // Fast + int slow2Length; // Slow + + // + // Ribbon 3 ... + int fast3Length; // Fast + int slow3Length; // Slow + + // + // Ribbon 4 ... + int fast4Length; // Fast + int slow4Length; // Slow + + // + // Ribbon 5 ... + int fast5Length; // Fast + int slow5Length; // Slow + + // + // Calculation ... + ENUM_MA_METHOD ribbonMode; // Mode + ENUM_APPLIED_PRICE ribbonAppliedTo; // Applied To + + // + // Presentation ... + bool showFastMa; // Show Fast + bool showSlowMa; // Show Slow + bool showRibbon; // Show Ribbon +}; + +// +// Index of Lines ... +enum ENUM_XMRB_BUFFERS +{ + // + // Main Requirements ... + XMRB_FAST_LINE = 0, + XMRB_SLOW_LINE = 1, + // + // RIBBON 1 ... + XMRB_R1_FAST_LINE = 2, + XMRB_R1_SLOW_LINE = 3, + // + // RIBBON 2 ... + XMRB_R2_FAST_LINE = 4, + XMRB_R2_SLOW_LINE = 5, + // + // RIBBON 3 ... + XMRB_R3_FAST_LINE = 6, + XMRB_R3_SLOW_LINE = 7, + // + // RIBBON 4 ... + XMRB_R4_FAST_LINE = 8, + XMRB_R4_SLOW_LINE = 9, + // + // RIBBON 5 ... + XMRB_R5_FAST_LINE = 10, + XMRB_R5_SLOW_LINE = 11, +}; + +// +// Retrieve Info Model ... +struct XMRBInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double fast; + double slow; + double fastR1; + double slowR1; + double fastR2; + double slowR2; + double fastR3; + double slowR3; + double fastR4; + double slowR4; + double fastR5; + double slowR5; + + // + // Conditions ... + + // + bool isFastOverSlow; + bool isFastCrossedOverSlow; + bool isFastUnderSlow; + bool isFastCrossedUnderSlow; + + // + bool isR1FastOverSlow; + bool isR1FastCrossedOverSlow; + bool isR1FastUnderSlow; + bool isR1FastCrossedUnderSlow; + + // + bool isR2FastOverSlow; + bool isR2FastCrossedOverSlow; + bool isR2FastUnderSlow; + bool isR2FastCrossedUnderSlow; + + // + bool isR3FastOverSlow; + bool isR3FastCrossedOverSlow; + bool isR3FastUnderSlow; + bool isR3FastCrossedUnderSlow; + + // + bool isR4FastOverSlow; + bool isR4FastCrossedOverSlow; + bool isR4FastUnderSlow; + bool isR4FastCrossedUnderSlow; + + // + bool isR5FastOverSlow; + bool isR5FastCrossedOverSlow; + bool isR5FastUnderSlow; + bool isR5FastCrossedUnderSlow; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXMRBHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double fastBuffer[]; + double slowBuffer[]; + double fastR1Buffer[]; + double slowR1Buffer[]; + double fastR2Buffer[]; + double slowR2Buffer[]; + double fastR3Buffer[]; + double slowR3Buffer[]; + double fastR4Buffer[]; + double slowR4Buffer[]; + double fastR5Buffer[]; + double slowR5Buffer[]; + + // + // Constructor ... + void XSCXMRBHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + XMRBInputs &config // Indicator Properties ... + ) : XSCBaseHelper(symbol, period) + { + // + XSCXMRBHelper(symbol, + period, + config.fast1Length, + config.slow1Length, + config.fast2Length, + config.slow2Length, + config.fast3Length, + config.slow3Length, + config.fast4Length, + config.slow4Length, + config.fast5Length, + config.slow5Length, + config.ribbonMode, + config.ribbonAppliedTo, + config.showFastMa, + config.showSlowMa, + config.showRibbon); + } + void XSCXMRBHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // Market ... + // + // Ribbon 1 ... + int fast1Length = 3, + int slow1Length = 5, + // + // Ribbon 2 ... + int fast2Length = 8, + int slow2Length = 13, + // + // Ribbon 3 ... + int fast3Length = 21, + int slow3Length = 34, + // + // Ribbon 4 ... + int fast4Length = 55, + int slow4Length = 89, + // + // Ribbon 5 ... + int fast5Length = 144, + int slow5Length = 233, + // + // Calculation ... + // + // Mode ... + ENUM_MA_METHOD ribbonMode = MODE_EMA, + // + // Applied To ... + ENUM_APPLIED_PRICE ribbonAppliedTo = PRICE_CLOSE, + // + // Presentation ... + // + // Show Fast ... + bool showFastMa = true, + // + // Show Slow ... + bool showSlowMa = true, + // + // Show Ribbon ... + bool showRibbon = false + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mFast1Length = fast1Length; + mSlow1Length = slow1Length; + mFast2Length = fast2Length; + mSlow2Length = slow2Length; + mFast3Length = fast3Length; + mSlow3Length = slow3Length; + mFast4Length = fast4Length; + mSlow4Length = slow4Length; + mFast5Length = fast5Length; + mSlow5Length = slow5Length; + mRibbonMode = ribbonMode; + mRibbonAppliedTo = ribbonAppliedTo; + mShowFastMa = showFastMa; + mShowSlowMa = showSlowMa; + mShowRibbon = showRibbon; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXMRBHelper() + { + } + + // + // START Properties ... + // + + // + // Show Fast ... + bool ShowFast( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowFastMa == show) + { + return true; + } + + // + mShowFastMa = show; + result = Init(); + + // + return result; + } + + // + // Show Slow ... + bool ShowSlow( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowSlowMa == show) + { + return true; + } + + // + mShowSlowMa = show; + result = Init(); + + // + return result; + } + + // + // Show Ribbon ... + bool ShowRibbon( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowRibbon == show) + { + return true; + } + + // + mShowRibbon = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XMRB" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Inputs ... + result = + // + (mFast1Length > 2 && + mFast2Length > mFast1Length && + mFast3Length > mFast2Length && + mFast4Length > mFast3Length && + mFast5Length > mFast4Length && + mSlow1Length > mFast1Length && + mSlow2Length > mFast2Length && + mFast3Length > mFast3Length && + mSlow4Length > mFast4Length && + mSlow5Length > mFast5Length && + mSlow2Length > mSlow1Length && + mFast3Length > mSlow2Length && + mSlow4Length > mFast3Length && + mSlow5Length > mSlow4Length + // + ) + // + ; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xmrb", + // + // Inputs ... + // + // Ribbon 1 ... + "", + mFast1Length, + mSlow1Length, + // + // Ribbon 2 ... + "", + mFast2Length, + mSlow2Length, + // + // Ribbon 3 ... + "", + mFast3Length, + mSlow3Length, + // + // Ribbon 4 ... + "", + mFast4Length, + mSlow4Length, + // + // Ribbon 5 ... + "", + mFast5Length, + mSlow5Length, + // + // Calculation ... + "", + // + // Mode ... + mRibbonMode, + // + // Applied To ... + mRibbonAppliedTo, + // + // Presentation ... + "", + // + // Show Fast ... + mShowFastMa, + // + // Show Slow ... + mShowSlowMa, + // + // Show Ribbon ... + mShowRibbon + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XMRBInputs GetConfig() + { + // + XMRBInputs result; + + // + result.fast1Length = mFast1Length; + result.slow1Length = mSlow1Length; + result.fast2Length = mFast2Length; + result.slow2Length = mSlow2Length; + result.fast3Length = mFast3Length; + result.slow3Length = mSlow3Length; + result.fast4Length = mFast4Length; + result.slow4Length = mSlow4Length; + result.fast5Length = mFast5Length; + result.slow5Length = mSlow5Length; + result.ribbonMode = mRibbonMode; + result.ribbonAppliedTo = mRibbonAppliedTo; + result.showFastMa = mShowFastMa; + result.showSlowMa = mShowSlowMa; + result.showRibbon = mShowRibbon; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XMRBInputs &config) + { + // + bool result = false; + + // + mFast1Length = config.fast1Length; + mSlow1Length = config.slow1Length; + mFast2Length = config.fast2Length; + mSlow2Length = config.slow2Length; + mFast3Length = config.fast3Length; + mSlow3Length = config.slow3Length; + mFast4Length = config.fast4Length; + mSlow4Length = config.slow4Length; + mFast5Length = config.fast5Length; + mSlow5Length = config.slow5Length; + mRibbonMode = config.ribbonMode; + mRibbonAppliedTo = config.ribbonAppliedTo; + mShowFastMa = config.showFastMa; + mShowSlowMa = config.showSlowMa; + mShowRibbon = config.showRibbon; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // FAST ... + ArraySetAsSeries(fastBuffer, true); + CopyBuffer( + mHandler, + XMRB_FAST_LINE, + barIndex, + mLoopbackBars, + fastBuffer); + + // + // SLOW ... + ArraySetAsSeries(slowBuffer, true); + CopyBuffer( + mHandler, + XMRB_SLOW_LINE, + barIndex, + mLoopbackBars, + slowBuffer); + + // + // RIBBON 1 ... + + // + // FAST ... + ArraySetAsSeries(fastR1Buffer, true); + CopyBuffer( + mHandler, + XMRB_R1_FAST_LINE, + barIndex, + mLoopbackBars, + fastR1Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR1Buffer, true); + CopyBuffer( + mHandler, + XMRB_R1_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR1Buffer); + + // + // RIBBON 2 ... + + // + // FAST ... + ArraySetAsSeries(fastR2Buffer, true); + CopyBuffer( + mHandler, + XMRB_R2_FAST_LINE, + barIndex, + mLoopbackBars, + fastR2Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR2Buffer, true); + CopyBuffer( + mHandler, + XMRB_R2_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR2Buffer); + + // + // RIBBON 3 ... + + // + // FAST ... + ArraySetAsSeries(fastR3Buffer, true); + CopyBuffer( + mHandler, + XMRB_R3_FAST_LINE, + barIndex, + mLoopbackBars, + fastR3Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR3Buffer, true); + CopyBuffer( + mHandler, + XMRB_R3_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR3Buffer); + + // + // RIBBON 4 ... + + // + // FAST ... + ArraySetAsSeries(fastR4Buffer, true); + CopyBuffer( + mHandler, + XMRB_R4_FAST_LINE, + barIndex, + mLoopbackBars, + fastR4Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR4Buffer, true); + CopyBuffer( + mHandler, + XMRB_R4_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR4Buffer); + + // + // RIBBON 5 ... + + // + // FAST ... + ArraySetAsSeries(fastR5Buffer, true); + CopyBuffer( + mHandler, + XMRB_R5_FAST_LINE, + barIndex, + mLoopbackBars, + fastR5Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR5Buffer, true); + CopyBuffer( + mHandler, + XMRB_R5_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR5Buffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XMRBInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XMRBInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double fast = fastBuffer[barIndex]; + double fastPrev = fastBuffer[barIndex + 1]; + double slow = slowBuffer[barIndex]; + double slowPrev = slowBuffer[barIndex + 1]; + double fastR1 = fastR1Buffer[barIndex]; + double fastR1Prev = fastR1Buffer[barIndex + 1]; + double slowR1 = slowR1Buffer[barIndex]; + double slowR1Prev = slowR1Buffer[barIndex + 1]; + double fastR2 = fastR2Buffer[barIndex]; + double fastR2Prev = fastR2Buffer[barIndex + 1]; + double slowR2 = slowR2Buffer[barIndex]; + double slowR2Prev = slowR2Buffer[barIndex + 1]; + double fastR3 = fastR3Buffer[barIndex]; + double fastR3Prev = fastR3Buffer[barIndex + 1]; + double slowR3 = slowR3Buffer[barIndex]; + double slowR3Prev = slowR3Buffer[barIndex + 1]; + double fastR4 = fastR4Buffer[barIndex]; + double fastR4Prev = fastR4Buffer[barIndex + 1]; + double slowR4 = slowR4Buffer[barIndex]; + double slowR4Prev = slowR4Buffer[barIndex + 1]; + double fastR5 = fastR5Buffer[barIndex]; + double fastR5Prev = fastR5Buffer[barIndex + 1]; + double slowR5 = slowR5Buffer[barIndex]; + double slowR5Prev = slowR5Buffer[barIndex + 1]; + + // + result.fast = fast; + result.slow = slow; + result.fastR1 = fastR1; + result.slowR1 = slowR1; + result.fastR2 = fastR2; + result.slowR2 = slowR2; + result.fastR3 = fastR3; + result.slowR3 = slowR3; + result.fastR4 = fastR4; + result.slowR4 = slowR4; + result.fastR5 = fastR5; + result.slowR5 = slowR5; + + // + result.isFastOverSlow = + fast > slow; + result.isFastCrossedOverSlow = + fast > slow && fastPrev <= slowPrev; + result.isFastUnderSlow = + fast < slow; + result.isFastCrossedUnderSlow = + fast < slow && fastPrev >= slowPrev; + + // + result.isR1FastOverSlow = + fastR1 > slowR1; + result.isR1FastCrossedOverSlow = + fastR1 > slowR1 && fastR1Prev <= slowR1Prev; + result.isR1FastUnderSlow = + fastR1 < slowR1; + result.isR1FastCrossedUnderSlow = + fastR1 < slowR1 && fastR1Prev >= slowR1Prev; + + // + result.isR2FastOverSlow = + fastR2 > slowR2; + result.isR2FastCrossedOverSlow = + fastR2 > slowR2 && fastR2Prev <= slowR2Prev; + result.isR2FastUnderSlow = + fastR2 < slowR2; + result.isR2FastCrossedUnderSlow = + fastR2 < slowR2 && fastR2Prev >= slowR2Prev; + + // + result.isR3FastOverSlow = + fastR3 > slowR3; + result.isR3FastCrossedOverSlow = + fastR3 > slowR3 && fastR3Prev <= slowR3Prev; + result.isR3FastUnderSlow = + fastR3 < slowR3; + result.isR3FastCrossedUnderSlow = + fastR3 < slowR3 && fastR3Prev >= slowR3Prev; + + // + result.isR4FastOverSlow = + fastR4 > slowR4; + result.isR4FastCrossedOverSlow = + fastR4 > slowR4 && fastR4Prev <= slowR4Prev; + result.isR4FastUnderSlow = + fastR4 < slowR4; + result.isR4FastCrossedUnderSlow = + fastR4 < slowR4 && fastR4Prev >= slowR4Prev; + + // + result.isR5FastOverSlow = + fastR5 > slowR5; + result.isR5FastCrossedOverSlow = + fastR5 > slowR5 && fastR5Prev <= slowR5Prev; + result.isR5FastUnderSlow = + fastR5 < slowR5; + result.isR5FastCrossedUnderSlow = + fastR5 < slowR5 && fastR5Prev >= slowR5Prev; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Ribbon 1 ... + int mFast1Length; + int mSlow1Length; + // + // Ribbon 2 ... + int mFast2Length; + int mSlow2Length; + // + // Ribbon 3 ... + int mFast3Length; + int mSlow3Length; + // + // Ribbon 4 ... + int mFast4Length; + int mSlow4Length; + // + // Ribbon 5 ... + int mFast5Length; + int mSlow5Length; + // + // Calculation ... + // + // Mode ... + ENUM_MA_METHOD mRibbonMode; + // + // Applied To ... + ENUM_APPLIED_PRICE mRibbonAppliedTo; + // + // Presentation ... + // + // Show Fast ... + bool mShowFastMa; + // + // Show Slow ... + bool mShowSlowMa; + // + // Show Ribbon ... + bool mShowRibbon; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xpv.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xpv.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..fbf479aabb069b2ec340f07ac2a2af4b502a4a90 GIT binary patch literal 6672 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 2 && + mMediumLength > mShortLength && + mLongLength > mMediumLength && + mHindLength > mLongLength) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xpv", + // + // Inputs ... + // + // Market ... + "", + // + // Short Length ... + mShortLength, + // + // Medium Length + mMediumLength, + // + // Long Length ... + mLongLength, + // + // Hind Length ... + mHindLength, + // + // Detection Mode ... + "", + // + // Highest High Calculation Method ... + mHHMode, + // + // Lowest Low Calculation Method ... + mLLMode, + // + // Presentations ... + "", + // + // Show Peaks and Vales ... + mShowPeaksAndVales, + // + // Show Levels ... + mShowLevels + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XPVInputs GetConfig() + { + // + XPVInputs result; + + // + result.shortLength = mShortLength; + result.mediumLength = mMediumLength; + result.longLength = mLongLength; + result.hindLength = mHindLength; + result.hhMode = mHHMode; + result.llMode = mLLMode; + result.showPeaksAndVales = mShowPeaksAndVales; + result.showLevels = mShowLevels; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XPVInputs &config) + { + // + bool result = false; + + // + mShortLength = config.shortLength; + mMediumLength = config.mediumLength; + mLongLength = config.longLength; + mHindLength = config.hindLength; + mHHMode = config.hhMode; + mLLMode = config.llMode; + mShowPeaksAndVales = config.showPeaksAndVales; + mShowLevels = config.showLevels; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + CopyBuffer( + mHandler, + XPV_PEAKS_LINE, + barIndex, + mLoopbackBars, + peaksBuffer); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + CopyBuffer( + mHandler, + XPV_VALES_LINE, + barIndex, + mLoopbackBars, + valesBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XPVInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XPVInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + result.peak = peaksBuffer[barIndex]; + result.vale = valesBuffer[barIndex]; + + // + result.isNewPeak = + peaksBuffer[barIndex] != peaksBuffer[barIndex + 1]; + result.isNewVale = + valesBuffer[barIndex] != valesBuffer[barIndex + 1]; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Short Length ... + int mShortLength; + // + // Medium Length + int mMediumLength; + // + // Long Length ... + int mLongLength; + // + // Hind Length ... + int mHindLength; + // + // Detection Mode ... + // + // Highest High Calculation Method ... + ENUM_SERIESMODE mHHMode; + // + // Lowest Low Calculation Method ... + ENUM_SERIESMODE mLLMode; + // + // Presentations ... + // + // Show Peaks and Vales ... + bool mShowPeaksAndVales; + // + // Show Levels ... + bool mShowLevels; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xsslc.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xsslc.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..d2130ad1c7eb2ba8f594dbb5538435b0eb700031 GIT binary patch literal 7680 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 2) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xsslc", + // + // Inputs ... + // + // Market ... + "", + // + // Length ... + mLength, + // + // Calculation ... + "", + // + // Method ... + mMethod, + // + // Up Applied To ... + mUpAppliedTo, + // + // Down Applied To ... + mDownAppliedTo, + // + // Presentation ... + "", + // + // Show Up ... + mShowUp, + // + // Show Down ... + mShowDown + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XSSLCInputs GetConfig() + { + // + XSSLCInputs result; + + // + result.length = mLength; + result.method = mMethod; + result.upAppliedTo = mUpAppliedTo; + result.downAppliedTo = mDownAppliedTo; + result.showUp = mShowUp; + result.showDown = mShowDown; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XSSLCInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mMethod = config.method; + mUpAppliedTo = config.upAppliedTo; + mDownAppliedTo = config.downAppliedTo; + mShowUp = config.showUp; + mShowDown = config.showDown; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // UP ... + ArraySetAsSeries(upBuffer, true); + CopyBuffer( + mHandler, + XSSLC_UP_LINE, + barIndex, + mLoopbackBars, + upBuffer); + + // + // DOWN ... + ArraySetAsSeries(downBuffer, true); + CopyBuffer( + mHandler, + XSSLC_DOWN_LINE, + barIndex, + mLoopbackBars, + downBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XSSLCInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XSSLCInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double up = upBuffer[barIndex]; + double upPrev = upBuffer[barIndex + 1]; + double down = downBuffer[barIndex]; + double downPrev = downBuffer[barIndex + 1]; + + // + result.up = up; + result.down = down; + + // + result.isBullish = up > down; + result.isBearish = up < down; + + // + result.isSwitchedBullish = + up > down && + upPrev <= downPrev; + result.isSwitchedBearish = + up < down && + upPrev >= downPrev; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Calculation ... + // + // Method ... + ENUM_MA_METHOD mMethod; + // + // Up Applied To ... + ENUM_APPLIED_PRICE mUpAppliedTo; + // + // Down Applied To ... + ENUM_APPLIED_PRICE mDownAppliedTo; + // + // Presentation ... + // + // Show Up ... + bool mShowUp; + // + // Show Down ... + bool mShowDown; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..f9efcc9ad4bfe54e14edbd629968ab96946b115d GIT binary patch literal 6562 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.mq5 new file mode 100644 index 0000000..00899e2 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtm.helper.class.mq5 @@ -0,0 +1,468 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXTMHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XTMInputs +{ + // + // Makret ... + int length; // Length + int shift; // Shift + + // + // Calculations ... + ENUM_MA_METHOD method; // Method + ENUM_APPLIED_PRICE appliedTo; // Applied To + + // + // Presentation ... + bool showLine; // Show Line +}; + +// +// Index of Lines ... +enum ENUM_XTM_BUFFERS +{ + // + // Main Requirements ... + XTM_LINE = 0, + XTM_STATE_LINE = 1, +}; + +// +// XTM Indicator States ... +enum ENUM_XTM_STATES +{ + X_XTM_BULLISH = 0, + X_XTM_BEARISH = 2, + X_XTM_NEUTURAL = 1, +}; + +// +// Retrieve Info Model ... +struct XTMInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double value; + + // + // State ... + ENUM_XTM_STATES state; + + // + // Conditions ... + + // + // Detect Trend is Bullish or not ... + bool isBullish; + + // + // Detect Trend is Switched to Bullish Or not ... + bool isSwitchedBullish; + + // + // Detect Trend is Bearish or not ... + bool isBearish; + + // + // Detect Trend is Switched to Bearish Or not ... + bool isSwitchedBearish; + + // + // Detect Trend is Neutural or not ... + bool isNeutural; + + // + // Detect Trend is Switched to Neutural Or not ... + bool isSwitchedNeutural; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXTMHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double valueBuffer[]; + double stateBuffer[]; + + // + // Constructor ... + void XSCXTMHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + XTMInputs &config // Indicator Properties ... + ) : XSCBaseHelper(symbol, period) + { + // + XSCXTMHelper(symbol, + period, + config.length, + config.shift, + config.method, + config.appliedTo, + config.showLine); + } + void XSCXTMHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int length = 35, + // + // Shift ... + int shift = 0, + // + // Calculations ... + // + // Method ... + ENUM_MA_METHOD method = MODE_SMA, + // + // Applied To ... + ENUM_APPLIED_PRICE appliedTo = PRICE_LOW, + // + // Presentation ... + // + // Show Line ... + bool showLine = true + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mShift = shift; + mLength = length; + mMethod = method; + mShowLine = showLine; + mAppliedTo = appliedTo; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXTMHelper() + { + } + + // + // START Properties ... + // + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XTM" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Args ... + result = + // + (mLength >= 2) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xtm", + // + // Inputs ... + // + // Makret ... + "", + // + // Length ... + mLength, + // + // Shift ... + mShift, + // + // Calculations ... + "", + // + // Method ... + mMethod, + // + // Applied To ... + mAppliedTo, + // + // Presentation ... + "", + // + // Show Line ... + mShowLine + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XTMInputs GetConfig() + { + // + XTMInputs result; + + // + result.length = mLength; + result.shift = mShift; + result.method = mMethod; + result.appliedTo = mAppliedTo; + result.showLine = mShowLine; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XTMInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mShift = config.shift; + mMethod = config.method; + mAppliedTo = config.appliedTo; + mShowLine = config.showLine; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // VALUE ... + ArraySetAsSeries(valueBuffer, true); + CopyBuffer( + mHandler, + XTM_LINE, + barIndex, + mLoopbackBars, + valueBuffer); + + // + // STATE ... + ArraySetAsSeries(stateBuffer, true); + CopyBuffer( + mHandler, + XTM_STATE_LINE, + barIndex, + mLoopbackBars, + stateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XTMInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XTMInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + result.value = valueBuffer[barIndex]; + + // + ENUM_XTM_STATES state = (ENUM_XTM_STATES)stateBuffer[barIndex]; + ENUM_XTM_STATES prevState = (ENUM_XTM_STATES)stateBuffer[barIndex + 1]; + result.state = state; + + // + result.isBullish = state == X_XTM_BULLISH; + result.isBearish = state == X_XTM_BEARISH; + result.isNeutural = state == X_XTM_NEUTURAL; + + // + result.isSwitchedBullish = + state == X_XTM_BULLISH && prevState != X_XTM_BULLISH; + result.isSwitchedBearish = + state == X_XTM_BEARISH && prevState != X_XTM_BEARISH; + result.isSwitchedNeutural = + state == X_XTM_NEUTURAL && prevState != X_XTM_NEUTURAL; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Makret ... + // + // Length ... + int mLength; + // + // Shift ... + int mShift; + + // + // Calculations ... + // + // Method ... + ENUM_MA_METHOD mMethod; + // + // Applied To ... + ENUM_APPLIED_PRICE mAppliedTo; + + // + // Presentation ... + // + // Show Line ... + bool mShowLine; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..0fe2535a2f361c1f8f74a679f86661b3ee931bc3 GIT binary patch literal 6916 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 new file mode 100644 index 0000000..e325a2e --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 @@ -0,0 +1,1158 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXTRNDHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// Inputs ... +struct XTRNDInputs +{ + // + // Makret ... + int cycleLength; // Cycle Length to Check + int numberOfVerifications; // Number of Verifications + + // + // Calculation ... + ENUM_SERIESMODE hhMode; // Detect Up + ENUM_SERIESMODE llMode; // Detect Low + + // + // Cycles ... + + // + // Level 1 ... + ENUM_X_PERIOD_METHOD l1Method; // How to Find Period + ENUM_TIMEFRAMES l1Period; // Time Period + + // + // Level 2 ... + ENUM_X_PERIOD_METHOD l2Method; // How to Find Period + ENUM_TIMEFRAMES l2Period; // Time Period + + // + // Level 3 ... + ENUM_X_PERIOD_METHOD l3Method; // How to Find Period + ENUM_TIMEFRAMES l3Period; // Time Period + + // + // Presentation ... + bool showConsolidations; // Show Consolidations + bool showTrend; // Show Trend + bool showL1Trend; // Show Cycle 1 Trend + bool showL2Trend; // Show Cycle 2 Trend + bool showL3Trend; // Show Cycle 3 Trend +}; + +// +// Index of Lines ... +enum ENUM_XTRND_BUFFERS +{ + // + // Main Requirements ... + XTRND_UP_LINE = 0, + XTRND_UP_STATE_LINE = 1, + XTRND_DOWN_LINE = 2, + XTRND_DOWN_STATE_LINE = 3, + // + // LEVEL 1 ... + XTRND_L1_UP_LINE = 4, + XTRND_L1_UP_STATE_LINE = 5, + XTRND_L1_DOWN_LINE = 6, + XTRND_L1_DOWN_STATE_LINE = 7, + // + // LEVEL 2 ... + XTRND_L2_UP_LINE = 8, + XTRND_L2_UP_STATE_LINE = 9, + XTRND_L2_DOWN_LINE = 10, + XTRND_L2_DOWN_STATE_LINE = 11, + // + // LEVEL 3 ... + XTRND_L3_UP_LINE = 12, + XTRND_L3_UP_STATE_LINE = 13, + XTRND_L3_DOWN_LINE = 14, + XTRND_L3_DOWN_STATE_LINE = 15, +}; + +// +enum ENUM_XTRND_STATES +{ + XTRND_STATE_BULLISH = 1, + XTRND_STATE_BEARISH = 2, + XTRND_STATE_CONSOLIDATION = 0, +}; + +// +// Retrieve Info Model ... +struct XTRNDInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double hh; + ENUM_XTRND_STATES hhState; + double ll; + double llState; + double l1hh; + ENUM_XTRND_STATES l1hhState; + double l1ll; + ENUM_XTRND_STATES l1llState; + double l2hh; + ENUM_XTRND_STATES l2hhState; + double l2ll; + ENUM_XTRND_STATES l2llState; + double l3hh; + ENUM_XTRND_STATES l3hhState; + double l3ll; + ENUM_XTRND_STATES l3llState; + + // + // Conditions ... + // + bool isTrendBullish; + bool isTrendSwitchedToBullish; + bool isTrendBearish; + bool isTrendSwitchedToBearish; + bool isTrendConsolidation; + bool isTrendSwitchedToConsolidation; + + // + bool isL1TrendBullish; + bool isL1TrendSwitchedToBullish; + bool isL1TrendBearish; + bool isL1TrendSwitchedToBearish; + bool isL1TrendConsolidation; + bool isL1TrendSwitchedToConsolidation; + + // + bool isL2TrendBullish; + bool isL2TrendSwitchedToBullish; + bool isL2TrendBearish; + bool isL2TrendSwitchedToBearish; + bool isL2TrendConsolidation; + bool isL2TrendSwitchedToConsolidation; + + // + bool isL3TrendBullish; + bool isL3TrendSwitchedToBullish; + bool isL3TrendBearish; + bool isL3TrendSwitchedToBearish; + bool isL3TrendConsolidation; + bool isL3TrendSwitchedToConsolidation; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXTRNDHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double hhBuffer[]; + double hhStateBuffer[]; + double llBuffer[]; + double llStateBuffer[]; + double l1hhBuffer[]; + double l1hhStateBuffer[]; + double l1llBuffer[]; + double l1llStateBuffer[]; + double l2hhBuffer[]; + double l2hhStateBuffer[]; + double l2llBuffer[]; + double l2llStateBuffer[]; + double l3hhBuffer[]; + double l3hhStateBuffer[]; + double l3llBuffer[]; + double l3llStateBuffer[]; + + // + // Constructor ... + void XSCXTRNDHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + XTRNDInputs &config // Indicator Properties ... + ) : XSCBaseHelper(symbol, period) + { + // + XSCXTRNDHelper(symbol, + period, + config.cycleLength, + config.numberOfVerifications, + config.hhMode, + config.llMode, + config.l1Method, + config.l1Period, + config.l2Method, + config.l2Period, + config.l3Method, + config.l3Period, + config.showConsolidations, + config.showTrend, + config.showL1Trend, + config.showL2Trend, + config.showL3Trend); + } + void XSCXTRNDHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // Market ... + // + // Cycle Length to Check ... + int cycleLength = 2, + // + // Number of Verifications ... + int numberOfVerifications = 2, + // + // Calculations ... + // + // Detect Up ... + ENUM_SERIESMODE hhMode = MODE_HIGH, + // + // Detect Low ... + ENUM_SERIESMODE llMode = MODE_LOW, + // + // Cycles ... + // + // LEVEL 1 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD l1Method = X_PERIOD_AUTO, + // + // Time Period ... + ENUM_TIMEFRAMES l1Period = NULL, + // + // LEVEL 2 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD l2Method = X_PERIOD_AUTO, + // + // Time Period ... + ENUM_TIMEFRAMES l2Period = NULL, + // + // LEVEL 3 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD l3Method = X_PERIOD_AUTO, + // + // Time Period ... + ENUM_TIMEFRAMES l3Period = NULL, + // + // Presentation ... + // + // Show Consolidations ... + bool showConsolidations = false, + // + // Show Trend ... + bool showTrend = true, + // + // Show Cycle 1 Trend ... + bool showL1Trend = false, + // + // Show Cycle 2 Trend ... + bool showL2Trend = false, + // + // Show Cycle 3 Trend ... + bool showL3Trend = false + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mCycleLength = cycleLength; + mNumberOfVerifications = numberOfVerifications; + mHHMode = hhMode; + mLLMode = llMode; + mLLMethod = l1Method; + mL1Period = l1Period; + mL2Method = l2Method; + mL2Period = l2Period; + mL3Method = l3Method; + mL3Period = l3Period; + mShowConsolidations = showConsolidations; + mShowTrend = showTrend; + mShowL1Trends = showL1Trend; + mShowL2Trends = showL2Trend; + mShowL3Trends = showL3Trend; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXTRNDHelper() + { + } + + // + // START Properties ... + // + + // + // Show Trend ... + bool ShowTrend( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowTrend == show) + { + return true; + } + + // + mShowTrend = show; + result = Init(); + + // + return result; + } + + // + // Show Cycle 1 Trend ... + bool ShowL1Trends( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowL1Trends == show) + { + return true; + } + + // + mShowL1Trends = show; + result = Init(); + + // + return result; + } + + // + // Show Cycle 2 Trend ... + bool ShowL2Trends( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowL2Trends == show) + { + return true; + } + + // + mShowL2Trends = show; + result = Init(); + + // + return result; + } + + // + // Show Cycle 3 Trend ... + bool ShowL3Trends( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowL3Trends == show) + { + return true; + } + + // + mShowL3Trends = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XTRND" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Inputs ... + // + // + result = + // + (mCycleLength > 0 && + mNumberOfVerifications > 0) + // + ; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xtrnd", + // + // Inputs ... + // + // Market ... + "", + // + // Cycle Length to Check ... + mCycleLength, + // + // Number of Verifications ... + mNumberOfVerifications, + // + // Calculations ... + "", + // + // Detect Up ... + mHHMode, + // + // Detect Low ... + mLLMode, + // + // Cycles ... + "", + // + // LEVEL 1 ... + "", + // + // How to Find Period ... + mLLMethod, + // + // Time Period ... + mL1Period, + // + // LEVEL 2 ... + "", + // + // How to Find Period ... + mL2Method, + // + // Time Period ... + mL2Period, + // + // LEVEL 3 ... + "", + // + // How to Find Period ... + mL3Method, + // + // Time Period ... + mL3Period, + // + // Presentation ... + "", + // + // Show Consolidations ... + mShowConsolidations, + // + // Show Trend ... + mShowTrend, + // + // Show Cycle 1 Trend ... + mShowL1Trends, + // + // Show Cycle 2 Trend ... + mShowL2Trends, + // + // Show Cycle 3 Trend ... + mShowL3Trends + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XTRNDInputs GetConfig() + { + // + XTRNDInputs result; + + // + result.cycleLength = mCycleLength; + result.numberOfVerifications = mNumberOfVerifications; + result.hhMode = mHHMode; + result.llMode = mLLMode; + result.l1Method = mLLMethod; + result.l1Period = mL1Period; + result.l2Method = mL2Method; + result.l2Period = mL2Period; + result.l3Method = mL3Method; + result.l3Period = mL3Period; + result.showConsolidations = mShowConsolidations; + result.showTrend = mShowTrend; + result.showL1Trend = mShowL1Trends; + result.showL2Trend = mShowL2Trends; + result.showL3Trend = mShowL3Trends; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XTRNDInputs &config) + { + // + bool result = false; + + // + mCycleLength = config.cycleLength; + mNumberOfVerifications = config.numberOfVerifications; + mHHMode = config.hhMode; + mLLMode = config.llMode; + mLLMethod = config.l1Method; + mL1Period = config.l1Period; + mL2Method = config.l2Method; + mL2Period = config.l2Period; + mL3Method = config.l3Method; + mL3Period = config.l3Period; + mShowConsolidations = config.showConsolidations; + mShowTrend = config.showTrend; + mShowL1Trends = config.showL1Trend; + mShowL2Trends = config.showL2Trend; + mShowL3Trends = config.showL3Trend; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // HH ... + ArraySetAsSeries(hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_UP_LINE, + barIndex, + mLoopbackBars, + hhBuffer); + + // + // HH State ... + ArraySetAsSeries(hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_UP_STATE_LINE, + barIndex, + mLoopbackBars, + hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(llBuffer, true); + CopyBuffer( + mHandler, + XTRND_DOWN_LINE, + barIndex, + mLoopbackBars, + llBuffer); + + // + // LL State ... + ArraySetAsSeries(llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + llStateBuffer); + + // + // CYCLES ... + + // + // LEVEL 1 ... + + // + // HH ... + ArraySetAsSeries(l1hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_UP_LINE, + barIndex, + mLoopbackBars, + l1hhBuffer); + + // + // HH State ... + ArraySetAsSeries(l1hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_UP_STATE_LINE, + barIndex, + mLoopbackBars, + l1hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(l1llBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_DOWN_LINE, + barIndex, + mLoopbackBars, + l1llBuffer); + + // + // LL State ... + ArraySetAsSeries(l1llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + l1llStateBuffer); + + // + // LEVEL 2 ... + + // + // HH ... + ArraySetAsSeries(l2hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_UP_LINE, + barIndex, + mLoopbackBars, + l2hhBuffer); + + // + // HH State ... + ArraySetAsSeries(l2hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_UP_STATE_LINE, + barIndex, + mLoopbackBars, + l2hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(l2llBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_DOWN_LINE, + barIndex, + mLoopbackBars, + l2llBuffer); + + // + // LL State ... + ArraySetAsSeries(l2llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + l2llStateBuffer); + + // + // LEVEL 3 ... + + // + // HH ... + ArraySetAsSeries(l3hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_UP_LINE, + barIndex, + mLoopbackBars, + l3hhBuffer); + + // + // HH State ... + ArraySetAsSeries(l3hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_UP_STATE_LINE, + barIndex, + mLoopbackBars, + l3hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(l3llBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_DOWN_LINE, + barIndex, + mLoopbackBars, + l3llBuffer); + + // + // LL State ... + ArraySetAsSeries(l3llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + l3llStateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XTRNDInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XTRNDInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double hh = hhBuffer[barIndex]; + ENUM_XTRND_STATES hhState = (ENUM_XTRND_STATES)hhStateBuffer[barIndex]; + ENUM_XTRND_STATES hhStatePrev = (ENUM_XTRND_STATES)hhStateBuffer[barIndex + 1]; + + // + double ll = llBuffer[barIndex]; + ENUM_XTRND_STATES llState = (ENUM_XTRND_STATES)llStateBuffer[barIndex]; + ENUM_XTRND_STATES llStatePrev = (ENUM_XTRND_STATES)llStateBuffer[barIndex + 1]; + + // + double l1hh = l1hhBuffer[barIndex]; + ENUM_XTRND_STATES l1hhState = (ENUM_XTRND_STATES)l1hhStateBuffer[barIndex]; + ENUM_XTRND_STATES l1hhStatePrev = (ENUM_XTRND_STATES)l1hhStateBuffer[barIndex + 1]; + + // + double l1ll = l1llBuffer[barIndex]; + ENUM_XTRND_STATES l1llState = (ENUM_XTRND_STATES)l1llStateBuffer[barIndex]; + ENUM_XTRND_STATES l1llStatePrev = (ENUM_XTRND_STATES)l1llStateBuffer[barIndex + 1]; + + // + double l2hh = l2hhBuffer[barIndex]; + ENUM_XTRND_STATES l2hhState = (ENUM_XTRND_STATES)l2hhStateBuffer[barIndex]; + ENUM_XTRND_STATES l2hhStatePrev = (ENUM_XTRND_STATES)l2hhStateBuffer[barIndex + 1]; + + // + double l2ll = l2llBuffer[barIndex]; + ENUM_XTRND_STATES l2llState = (ENUM_XTRND_STATES)l2llStateBuffer[barIndex]; + ENUM_XTRND_STATES l2llStatePrev = (ENUM_XTRND_STATES)l2llStateBuffer[barIndex + 1]; + + // + double l3hh = l3hhBuffer[barIndex]; + ENUM_XTRND_STATES l3hhState = (ENUM_XTRND_STATES)l3hhStateBuffer[barIndex]; + ENUM_XTRND_STATES l3hhStatePrev = (ENUM_XTRND_STATES)l3hhStateBuffer[barIndex + 1]; + + // + double l3ll = l3llBuffer[barIndex]; + ENUM_XTRND_STATES l3llState = (ENUM_XTRND_STATES)l3llStateBuffer[barIndex]; + ENUM_XTRND_STATES l3llStatePrev = (ENUM_XTRND_STATES)l3llStateBuffer[barIndex + 1]; + + // + bool isTrendBullish = + hhState == XTRND_STATE_BULLISH && + llState == XTRND_STATE_BULLISH; + bool isPrevTrendBullish = + hhStatePrev == XTRND_STATE_BULLISH && + llStatePrev == XTRND_STATE_BULLISH; + bool isTrendBearish = + hhState == XTRND_STATE_BEARISH && + llState == XTRND_STATE_BEARISH; + bool isPrevTrendBearish = + hhStatePrev == XTRND_STATE_BEARISH && + llStatePrev == XTRND_STATE_BEARISH; + bool isTrendConsolidation = + hhState == XTRND_STATE_CONSOLIDATION && + llState == XTRND_STATE_CONSOLIDATION; + bool isPrevTrendConsolidation = + hhStatePrev == XTRND_STATE_CONSOLIDATION && + llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isTrendSwitchedToBullish = + isTrendBullish && + !isPrevTrendBullish; + bool isTrendSwitchedToBearish = + isTrendBearish && + !isPrevTrendBearish; + bool isTrendSwitchedToConsolidation = + isTrendConsolidation && + !isPrevTrendConsolidation; + + // + bool isL1TrendBullish = + l1hhState == XTRND_STATE_BULLISH && + l1llState == XTRND_STATE_BULLISH; + bool isL1PrevTrendBullish = + l1hhStatePrev == XTRND_STATE_BULLISH && + l1llStatePrev == XTRND_STATE_BULLISH; + bool isL1TrendBearish = + l1hhState == XTRND_STATE_BEARISH && + l1llState == XTRND_STATE_BEARISH; + bool isL1PrevTrendBearish = + l1hhStatePrev == XTRND_STATE_BEARISH && + l1llStatePrev == XTRND_STATE_BEARISH; + bool isL1TrendConsolidation = + l1hhState == XTRND_STATE_CONSOLIDATION && + l1llState == XTRND_STATE_CONSOLIDATION; + bool isL1PrevTrendConsolidation = + l1hhStatePrev == XTRND_STATE_CONSOLIDATION && + l1llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isL1TrendSwitchedToBullish = + isL1TrendBullish && + !isL1PrevTrendBullish; + bool isL1TrendSwitchedToBearish = + isL1TrendBearish && + !isL1PrevTrendBearish; + bool isL1TrendSwitchedToConsolidation = + isL1TrendConsolidation && + !isL1PrevTrendConsolidation; + + // + bool isL2TrendBullish = + l2hhState == XTRND_STATE_BULLISH && + l2llState == XTRND_STATE_BULLISH; + bool isL2PrevTrendBullish = + l2hhStatePrev == XTRND_STATE_BULLISH && + l2llStatePrev == XTRND_STATE_BULLISH; + bool isL2TrendBearish = + l2hhState == XTRND_STATE_BEARISH && + l2llState == XTRND_STATE_BEARISH; + bool isL2PrevTrendBearish = + l2hhStatePrev == XTRND_STATE_BEARISH && + l2llStatePrev == XTRND_STATE_BEARISH; + bool isL2TrendConsolidation = + l2hhState == XTRND_STATE_CONSOLIDATION && + l2llState == XTRND_STATE_CONSOLIDATION; + bool isL2PrevTrendConsolidation = + l2hhStatePrev == XTRND_STATE_CONSOLIDATION && + l2llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isL2TrendSwitchedToBullish = + isL2TrendBullish && + !isL2PrevTrendBullish; + bool isL2TrendSwitchedToBearish = + isL2TrendBearish && + !isL2PrevTrendBearish; + bool isL2TrendSwitchedToConsolidation = + isL2TrendConsolidation && + !isL2PrevTrendConsolidation; + + // + bool isL3TrendBullish = + l3hhState == XTRND_STATE_BULLISH && + l3llState == XTRND_STATE_BULLISH; + bool isL3PrevTrendBullish = + l3hhStatePrev == XTRND_STATE_BULLISH && + l3llStatePrev == XTRND_STATE_BULLISH; + bool isL3TrendBearish = + l3hhState == XTRND_STATE_BEARISH && + l3llState == XTRND_STATE_BEARISH; + bool isL3PrevTrendBearish = + l3hhStatePrev == XTRND_STATE_BEARISH && + l3llStatePrev == XTRND_STATE_BEARISH; + bool isL3TrendConsolidation = + l3hhState == XTRND_STATE_CONSOLIDATION && + l3llState == XTRND_STATE_CONSOLIDATION; + bool isL3PrevTrendConsolidation = + l3hhStatePrev == XTRND_STATE_CONSOLIDATION && + l3llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isL3TrendSwitchedToBullish = + isL3TrendBullish && + !isL3PrevTrendBullish; + bool isL3TrendSwitchedToBearish = + isL3TrendBearish && + !isL3PrevTrendBearish; + bool isL3TrendSwitchedToConsolidation = + isL3TrendConsolidation && + !isL3PrevTrendConsolidation; + + // + result.hh = hh; + result.hhState = hhState; + result.ll = ll; + result.llState = llState; + result.l1hh = l1hh; + result.l1hhState = l1hhState; + result.l1ll = l1ll; + result.l1llState = l1llState; + result.l2hh = l2hh; + result.l2hhState = l2hhState; + result.l2ll = l2ll; + result.l2llState = l2llState; + result.l3hh = l3hh; + result.l3hhState = l3hhState; + result.l3ll = l3ll; + result.l3llState = l3llState; + + // + result.isTrendBullish = isTrendBullish; + result.isTrendBearish = isTrendBearish; + result.isTrendConsolidation = isTrendConsolidation; + + // + result.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + result.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + result.isTrendSwitchedToConsolidation = isTrendSwitchedToConsolidation; + + // + result.isL1TrendBullish = isL1TrendBullish; + result.isL1TrendBearish = isL1TrendBearish; + result.isL1TrendConsolidation = isL1TrendConsolidation; + + // + result.isL1TrendSwitchedToBullish = isL1TrendSwitchedToBullish; + result.isL1TrendSwitchedToBearish = isL1TrendSwitchedToBearish; + result.isL1TrendSwitchedToConsolidation = isL1TrendSwitchedToConsolidation; + + // + result.isL2TrendBullish = isL2TrendBullish; + result.isL2TrendBearish = isL2TrendBearish; + result.isL2TrendConsolidation = isL2TrendConsolidation; + + // + result.isL2TrendSwitchedToBullish = isL2TrendSwitchedToBullish; + result.isL2TrendSwitchedToBearish = isL2TrendSwitchedToBearish; + result.isL2TrendSwitchedToConsolidation = isL2TrendSwitchedToConsolidation; + + // + result.isL3TrendBullish = isL3TrendBullish; + result.isL3TrendBearish = isL3TrendBearish; + result.isL3TrendConsolidation = isL3TrendConsolidation; + + // + result.isL3TrendSwitchedToBullish = isL3TrendSwitchedToBullish; + result.isL3TrendSwitchedToBearish = isL3TrendSwitchedToBearish; + result.isL3TrendSwitchedToConsolidation = isL3TrendSwitchedToConsolidation; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Cycle Length to Check ... + int mCycleLength; + // + // Number of Verifications ... + int mNumberOfVerifications; + // + // Calculations ... + // + // Detect Up ... + ENUM_SERIESMODE mHHMode; + // + // Detect Low ... + ENUM_SERIESMODE mLLMode; + // + // Cycles ... + // + // LEVEL 1 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD mLLMethod; + // + // Time Period ... + ENUM_TIMEFRAMES mL1Period; + // + // LEVEL 2 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD mL2Method; + // + // Time Period ... + ENUM_TIMEFRAMES mL2Period; + // + // LEVEL 3 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD mL3Method; + // + // Time Period ... + ENUM_TIMEFRAMES mL3Period; + // + // Presentation ... + // + // Show Consolidations ... + bool mShowConsolidations; + // + // Show Trend ... + bool mShowTrend; + // + // Show Cycle 1 Trend ... + bool mShowL1Trends; + // + // Show Cycle 2 Trend ... + bool mShowL2Trends; + // + // Show Cycle 3 Trend ... + bool mShowL3Trends; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.ex5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..88d365546db987638fe5e3845246a9126b0a3d96 GIT binary patch literal 10212 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.mq5 b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.mq5 new file mode 100644 index 0000000..3bd4acf --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Constructor Issues/Providers/x.saherelm.x121.provider.mq5 @@ -0,0 +1,965 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCX121Provider +// Description: X121 Signal Provider ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Classes/x-saherelm.xprovider.class.mq5" +#include "../Helpers/x-saherelm.x121.xcc.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xhk.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xtm.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xpv.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xama.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xmrb.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xche.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xich.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xtrnd.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xsslc.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xhull.helper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// Here we Have to Define an Input Structure Model +// for Provider Class to Handle Helpers Definitions ... +struct X121ProviderInputs +{ + // + // XCC ... + // Candle Styling ... + XCCInputs xccConfig; + + // + // XHK ... + // HikenAshi Candle Representing ... + XHKInputs xhkConfig; + + // + // XTM ... + // Trend Magic ... + XTMInputs xtmConfig; + + // + // XPV ... + // Peaks And Vales ... + XPVInputs xpvConfig; + + // + // XAMA ... + // Adaptive Moving Average ... + XAMAInputs xamaConfig; + + // + // XMRB ... + // Moving Average Ribbon ... + XMRBInputs xmrbConfig; + + // + // XCHE ... + // Chandelier Exit Points ... + XCHEInputs xcheConfig; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + XICHInputs xichConfig; + + // + // XTRND ... + // Trend Detector ... + XTRNDInputs xtrndConfig; + + // + // XSSLC ... + // SSL Channel ... + XSSLCInputs xsslcConfig; + + // + // XHULL ... + // Hull Trend Detection Channel ... + XHULLInputs xhullConfig; +}; + +// +// Model Market Sense based On Current Captured conditions ... +struct X121MarketConditions +{ + // + // Commonly Used Info ... + + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Check Current Market Condition has Signal or not ... + bool hasSignal; + + // + // If has any Signal, Models it's related info here ... + XSignalInfo signal; + + // + // INDICATORS Market Sense ... + + // + // XCC ... + // there is not any Info provided here ... + + // + // XHK ... + XHKInfo xhkInfo; + + // + // XTM ... + XTMInfo xtmInfo; + + // + // XPV ... + XPVInfo xpvInfo; + + // + // XAMA ... + XAMAInfo xamaInfo; + + // + // XMRB ... + XMRBInfo xmrbInfo; + + // + // XCHE ... + XCHEInfo xcheInfo; + + // + // XICH ... + XICHInfo xichInfo; + + // + // XTRND ... + XTRNDInfo xtrndInfo; + + // + // XSSLC ... + XSSLCInfo xsslcInfo; + + // + // XHULL ... + XHULLInfo xhullInfo; +}; + +// +// Notified a Signal was Appears ... +typedef void (*TOnSignalConditions)( + X121MarketConditions &info); + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Base Class for All of our EA's ... +class XSCX121Provider : public XSCEABaseProvider +{ + // + // Public ... +public: + // + // Props ... + X121ProviderInputs providedConfig; + X121ProviderInputs currentConfig; + X121ProviderInputs cleanConfig; + + // + // Indicator Helper Classes Instance ... + + // + // XCC ... + XSCXCCHelper *mXCCHelper; + + // + // XHK ... + XSCXHKHelper *mXHKHelper; + + // + // XTM ... + XSCXTMHelper *mXTMHelper; + + // + // XPV ... + XSCXPVHelper *mXPVHelper; + + // + // XAMA ... + XSCXAMAHelper *mXAMAHelper; + + // + // XMRB ... + XSCXMRBHelper *mXMRBHelper; + + // + // XCHE ... + XSCXCHEHelper *mXCHEHelper; + + // + // XICH ... + XSCXICHHelper *mXICHHelper; + + // + // XTRND ... + XSCXTRNDHelper *mXTRNDHelper; + + // + // XSSLC ... + XSCXSSLCHelper *mXSSLCHelper; + + // + // XHULL ... + XSCXHULLHelper *mXHULLHelper; + + // + // Define Helpers ... + + // + // Constructor ... + void XSCX121Provider() : XSCEABaseProvider(_Symbol, _Period){}; + void XSCX121Provider( + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period // Trading Time Frame ... + ) : XSCEABaseProvider(symbol, period) + { + // + // Prepare Default and Clean Config ... + // in this Config non of Indicators doesn't Draw anything on chart ... + X121ProviderInputs configs; + + // + // XCC ... + // Candle Styling ... + configs.xccConfig.upColor = clrLime; + configs.xccConfig.downColor = clrRed; + configs.xccConfig.lineColor = clrLime; + configs.xccConfig.bearishColor = clrRed; + configs.xccConfig.bullishColor = clrLime; + configs.xccConfig.volumesColor = clrGreen; + configs.xccConfig.showCandles = true; + + // + // XHK ... + // HikenAshi Candle Representing ... + configs.xhkConfig.drawCandles = false; + configs.xhkConfig.drawCandleLines = false; + + // + // XTM ... + // Trend Magic ... + configs.xtmConfig.length = 35; + configs.xtmConfig.shift = 0; + configs.xtmConfig.method = MODE_SMA; + configs.xtmConfig.appliedTo = PRICE_LOW; + configs.xtmConfig.showLine = false; + + // + // XPV ... + // Peaks And Vales ... + configs.xpvConfig.shortLength = 9; + configs.xpvConfig.mediumLength = 17; + configs.xpvConfig.longLength = 26; + configs.xpvConfig.hindLength = 35; + configs.xpvConfig.hhMode = MODE_HIGH; + configs.xpvConfig.llMode = MODE_LOW; + configs.xpvConfig.showPeaksAndVales = false; + configs.xpvConfig.showLevels = false; + + // + // XAMA ... + // Adaptive Moving Average ... + configs.xamaConfig.length = 52; + configs.xamaConfig.fastEMA = 2; + configs.xamaConfig.slowEMA = 30; + configs.xamaConfig.maShift = 0; + configs.xamaConfig.appliedTo = PRICE_LOW; + configs.xamaConfig.showLine = false; + + // + // XMRB ... + // Moving Average Ribbon ... + configs.xmrbConfig.fast1Length = 3; + configs.xmrbConfig.slow1Length = 5; + configs.xmrbConfig.fast2Length = 8; + configs.xmrbConfig.slow2Length = 13; + configs.xmrbConfig.fast3Length = 21; + configs.xmrbConfig.slow3Length = 34; + configs.xmrbConfig.fast4Length = 55; + configs.xmrbConfig.slow4Length = 89; + configs.xmrbConfig.fast5Length = 144; + configs.xmrbConfig.slow5Length = 233; + configs.xmrbConfig.ribbonMode = MODE_EMA; + configs.xmrbConfig.ribbonAppliedTo = PRICE_CLOSE; + configs.xmrbConfig.showFastMa = false; + configs.xmrbConfig.showSlowMa = false; + configs.xmrbConfig.showRibbon = false; + + // + // XCHE ... + // Chandelier Exit Points ... + configs.xcheConfig.length = 35; + configs.xcheConfig.loopback = 26; + configs.xcheConfig.multiplier1 = 3; + configs.xcheConfig.multiplier2 = 3; + configs.xcheConfig.upAppliedTo = PRICE_HIGH; + configs.xcheConfig.downAppliedTo = PRICE_LOW; + configs.xcheConfig.showLongExit1Line = false; + configs.xcheConfig.showShortExit1Line = false; + configs.xcheConfig.showLongExit2Line = false; + configs.xcheConfig.showShortExit2Line = false; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + configs.xichConfig.tenkanSenLength = 9; + configs.xichConfig.tenkanSenMode = X_XICH_HH_LL_MODE; + configs.xichConfig.kijunSenLength = 26; + configs.xichConfig.kijunSenMode = X_XICH_HH_LL_MODE; + configs.xichConfig.senkouSpanBLength = 52; + configs.xichConfig.senkouSpanBMode = X_XICH_HH_LL_MODE; + configs.xichConfig.chikuoSpanAppliedTo = PRICE_CLOSE; + configs.xichConfig.showTenkanSen = false; + configs.xichConfig.showKijunSen = false; + configs.xichConfig.showKijunSenPlus = false; + configs.xichConfig.showKijunSenNegative = false; + configs.xichConfig.showChikouSpan = false; + configs.xichConfig.showSenkouSpanA = false; + configs.xichConfig.showSenkouSpanB = false; + configs.xichConfig.showKumo = false; + configs.xichConfig.shiftKumo = true; + + // + // XTRND ... + // Trend Detector ... + configs.xtrndConfig.cycleLength = 2; + configs.xtrndConfig.numberOfVerifications = 2; + configs.xtrndConfig.hhMode = MODE_HIGH; + configs.xtrndConfig.llMode = MODE_LOW; + configs.xtrndConfig.l1Method = X_PERIOD_AUTO; + configs.xtrndConfig.l1Period = NULL; + configs.xtrndConfig.l2Method = X_PERIOD_AUTO; + configs.xtrndConfig.l2Period = NULL; + configs.xtrndConfig.l3Method = X_PERIOD_AUTO; + configs.xtrndConfig.l3Period = NULL; + configs.xtrndConfig.showConsolidations = false; + configs.xtrndConfig.showTrend = false; + configs.xtrndConfig.showL1Trend = false; + configs.xtrndConfig.showL2Trend = false; + configs.xtrndConfig.showL3Trend = false; + + // + // XSSLC ... + // SSL Channel ... + configs.xsslcConfig.length = 36; + configs.xsslcConfig.method = MODE_SMA; + configs.xsslcConfig.upAppliedTo = PRICE_HIGH; + configs.xsslcConfig.downAppliedTo = PRICE_LOW; + configs.xsslcConfig.showUp = false; + configs.xsslcConfig.showDown = false; + + // + // XHULL ... + // Hull Trend Detection Channel ... + configs.xhullConfig.length = 72; + configs.xhullConfig.divisor = 2; + configs.xhullConfig.upAppliedTo = PRICE_HIGH; + configs.xhullConfig.downAppliedTo = PRICE_LOW; + configs.xhullConfig.showUpZone = false; + configs.xhullConfig.showDownZone = false; + + // + // Clean Config ... + cleanConfig = configs; + + // + XSCX121Provider(symbol, period, configs); + } + void XSCX121Provider( + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period, // Trading Time Frame ... + X121ProviderInputs &config // Configs ... + ) + { + // + mTag = "X121Provider|" + mSymbol + "," + ToString(mPeriod); + + // // + // mCTimerHandler = iCustom( + // mSymbol, + // mPeriod, + // "x-saherelm.x121.xct", + // // + // // Inputs ... + // clrYellow, + // CORNER_RIGHT_LOWER, + // true + // // + // ); + + // + currentConfig = config; + providedConfig = config; + + // + // Here we Have to Make Provided Config in Clean Style ... + PrepareCleanConfig(); + } + + // + // Deconstructor ... + void ~XSCX121Provider() + { + // + IndicatorRelease(mCTimerHandler); + + // + // De construct Helpers ... + delete mXCCHelper; + delete mXHKHelper; + delete mXTMHelper; + delete mXPVHelper; + delete mXAMAHelper; + delete mXMRBHelper; + delete mXCHEHelper; + delete mXICHHelper; + delete mXTRNDHelper; + delete mXSSLCHelper; + delete mXHULLHelper; + } + + // + bool Init() + { + // + bool result = false; + + // + // Instantiate all Indicators Helper Classes ... + // + // // XCC ... + // mXCCHelper = new XSCXCCHelper( + // mSymbol, + // mPeriod, + // currentConfig.xccConfig); + // result = mXCCHelper.Init(); + // if (!result) + // { + // return result; + // } + + // // + // // XHK ... + // mXHKHelper = new XSCXHKHelper( + // mSymbol, + // mPeriod, + // currentConfig.xhkConfig); + // result = mXHKHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // + // XTM ... + // mXTMHelper = new XSCXTMHelper( + // mSymbol, + // mPeriod, + // currentConfig.xtmConfig); + // result = mXTMHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XPV ... + // mXPVHelper = new XSCXPVHelper( + // mSymbol, + // mPeriod, + // currentConfig.xpvConfig); + // result = mXPVHelper.Init(); + // if (!result) + // { + // LogMessage("XPV Error: "); + // return result; + // }; + + // // + // // XAMA ... + // mXAMAHelper = new XSCXAMAHelper( + // mSymbol, + // mPeriod, + // currentConfig.xamaConfig); + // result = mXAMAHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XMRB ... + // mXMRBHelper = new XSCXMRBHelper( + // mSymbol, + // mPeriod, + // currentConfig.xmrbConfig); + // result = mXMRBHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XCHE ... + // mXCHEHelper = new XSCXCHEHelper( + // mSymbol, + // mPeriod, + // currentConfig.xcheConfig); + // result = mXCHEHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XICH ... + // mXICHHelper = new XSCXICHHelper( + // mSymbol, + // mPeriod, + // currentConfig.xichConfig); + // result = mXICHHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XTRND ... + // mXTRNDHelper = new XSCXTRNDHelper( + // mSymbol, + // mPeriod, + // currentConfig.xtrndConfig); + // result = mXTRNDHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XSSLC ... + // mXSSLCHelper = new XSCXSSLCHelper( + // mSymbol, + // mPeriod, + // currentConfig.xsslcConfig); + // result = mXSSLCHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // // + // // XHULL ... + // mXHULLHelper = new XSCXHULLHelper( + // mSymbol, + // mPeriod, + // currentConfig.xhullConfig); + // result = mXHULLHelper.Init(); + // if (!result) + // { + // return result; + // }; + + // + return result; + } + + // + virtual void ProcessBuffers() + { + } + + // + virtual void ProcessTick() + { + ProcessSignals(); + } + + // + // Generate Market Sense ... + X121MarketConditions GetMarketConditions( + int barIndex // Specified Bar Index + ) + { + // + X121MarketConditions result; + + // + // Fill Common Data ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barIndex = barIndex; + + // + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + result.barTime = barTime; + + // + result.xhkInfo = mXHKHelper.GetInfo(barIndex); + result.xtmInfo = mXTMHelper.GetInfo(barIndex); + result.xpvInfo = mXPVHelper.GetInfo(barIndex); + result.xamaInfo = mXAMAHelper.GetInfo(barIndex); + result.xmrbInfo = mXMRBHelper.GetInfo(barIndex); + result.xcheInfo = mXCHEHelper.GetInfo(barIndex); + result.xichInfo = mXICHHelper.GetInfo(barIndex); + result.xtrndInfo = mXTRNDHelper.GetInfo(barIndex); + result.xsslcInfo = mXSSLCHelper.GetInfo(barIndex); + result.xhullInfo = mXHULLHelper.GetInfo(barIndex); + + // + return result; + } + + // + // Add Specific On SignalConditions Event Handler ... + int AddOnSignalConditionEventHandler(TOnSignalConditions handler) + { + // + ArrayResize( + mSignalConditionsEventHandlers, + ArraySize(mSignalConditionsEventHandlers) + 1); + + // + int result = ArraySize(mSignalConditionsEventHandlers) - 1; + mSignalConditionsEventHandlers[result] = handler; + + // + return result; + } + + // + // Remove All On Signal Event Handler ... + void ReoveOnSignalEventHandlers() + { + // + ArrayFree(mSignalConditionsEventHandlers); + } + + // + // Notify a Signal Found on all Event Listeners ... + void NotifyOnSignalConditionsEvent(X121MarketConditions &info) + { + // + int listenerCount = ArraySize(mSignalConditionsEventHandlers); + if (listenerCount <= 0) + { + return; + } + + // + // Loop Through Listeners ... + for (int i = 0; i < listenerCount; i++) + { + // + TOnSignalConditions listener = mSignalConditionsEventHandlers[i]; + + // + listener(info); + } + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // CCandle Timer ... + int mCTimerHandler; + + // + // Signal Event Handlers ... + TOnSignalConditions mSignalConditionsEventHandlers[]; + + // + // Make Provided Config in Clean Style ... + void PrepareCleanConfig() + { + // + cleanConfig = providedConfig; + + // + // XCC ... + // Candle Styling ... + cleanConfig.xccConfig.showCandles = true; + + // + // XHK ... + // HikenAshi Candle Representing ... + cleanConfig.xhkConfig.drawCandles = false; + cleanConfig.xhkConfig.drawCandleLines = false; + + // + // XTM ... + // Trend Magic ... + cleanConfig.xtmConfig.showLine = false; + + // + // XPV ... + // Peaks And Vales ... + cleanConfig.xpvConfig.showPeaksAndVales = false; + cleanConfig.xpvConfig.showLevels = false; + + // + // XAMA ... + // Adaptive Moving Average ... + cleanConfig.xamaConfig.showLine = false; + + // + // XMRB ... + // Moving Average Ribbon ... + cleanConfig.xmrbConfig.showFastMa = false; + cleanConfig.xmrbConfig.showSlowMa = false; + cleanConfig.xmrbConfig.showRibbon = false; + + // + // XCHE ... + // Chandelier Exit Points ... + cleanConfig.xcheConfig.showLongExit1Line = false; + cleanConfig.xcheConfig.showShortExit1Line = false; + cleanConfig.xcheConfig.showLongExit2Line = false; + cleanConfig.xcheConfig.showShortExit2Line = false; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + cleanConfig.xichConfig.showTenkanSen = false; + cleanConfig.xichConfig.showKijunSen = false; + cleanConfig.xichConfig.showKijunSenPlus = false; + cleanConfig.xichConfig.showKijunSenNegative = false; + cleanConfig.xichConfig.showChikouSpan = false; + cleanConfig.xichConfig.showSenkouSpanA = false; + cleanConfig.xichConfig.showSenkouSpanB = false; + cleanConfig.xichConfig.showKumo = false; + + // + // XTRND ... + // Trend Detector ... + cleanConfig.xtrndConfig.showConsolidations = false; + cleanConfig.xtrndConfig.showTrend = false; + cleanConfig.xtrndConfig.showL1Trend = false; + cleanConfig.xtrndConfig.showL2Trend = false; + cleanConfig.xtrndConfig.showL3Trend = false; + + // + // XSSLC ... + // SSL Channel ... + cleanConfig.xsslcConfig.showUp = false; + cleanConfig.xsslcConfig.showDown = false; + + // + // XHULL ... + // Hull Trend Detection Channel ... + cleanConfig.xhullConfig.showUpZone = false; + cleanConfig.xhullConfig.showDownZone = false; + } + + // + // Here we are Capture Conditions and Check Signals ... + // The Signals Must be Unique for each providers ... + void ProcessSignals() + { + // + X121MarketConditions conditions = GetMarketConditions(1); + + // + // BUY ... + + // + Clean(conditions.signal); + bool hasLongSignal = HasLongSignal(conditions); + if (hasLongSignal) + { + // + NotifyOnSignalEvent( + conditions.signal); + NotifyOnSignalConditionsEvent(conditions); + mWaitUntilNewCandle = true; + return; + } + + // + // SELL ... + + // + Clean(conditions.signal); + bool hasShortignal = HasShortSignal(conditions); + if (hasShortignal) + { + // + NotifyOnSignalEvent( + conditions.signal); + NotifyOnSignalConditionsEvent(conditions); + mWaitUntilNewCandle = true; + return; + } + } + + // + // Check has Long Signal on Each Strategies ... + bool HasLongSignal(X121MarketConditions &conditions) + { + // + bool result = false; + + // + if (result) + { + } + + // + return result; + } + + // + // Check has Short Signal on Each Strategies ... + bool HasShortSignal(X121MarketConditions &conditions) + { + // + bool result = false; + + // + if (result) + { + } + + // + return result; + } +}; + +// +// START Definitions ... +// + +// +// Model Signal Providers Definitions ... +struct X121SignalProvider +{ + // + // Provider use Which Symbol ... + string symbol; + + // + // Provider use Which Time Frame ... + ENUM_TIMEFRAMES period; + + // + // Risk Amount Per Trades Related to Time Frames ... + // Percent of Available Balance ... + double riskAmount; + + // + // Desired Magic Number ... + ulong magicNumber; + + // + // Provider ... + XSCX121Provider provider; +}; + +// +// END Definitions ... +// + +// +// START Usefull Functions ... +// + +// +// Add Specific Provider to List ... +void Add( + X121SignalProvider &item, // item want to add + X121SignalProvider &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Generate Identifier Tag ... +string GenerateTag(X121SignalProvider &descriptor) +{ + // + string result = ""; + + // + result = descriptor.symbol + "," + ToString(descriptor.period); + + // + return result; +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/Ichimoku.mql4 b/MQLTestWorkspace/BKPS/BKP/Smapls/Ichimoku.mql4 new file mode 100644 index 0000000..f0e7a65 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Smapls/Ichimoku.mql4 @@ -0,0 +1,262 @@ +//+------------------------------------------------------------------+ +//| Demo_iIchimoku.mq5 | +//| Copyright 2011, MetaQuotes Software Corp. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" +#property description "The indicator demonstrates how to obtain data" +#property description "of indicator buffers for the iIchimoku technical indicator." +#property description "A symbol and timeframe used for calculation of the indicator," +#property description "are set by the symbol and period parameters." +#property description "The method of creation of the handle is set through the 'type' parameter (function type)." +#property description "All other parameters just like in the standard Ichimoku Kinko Hyo." + +#property indicator_chart_window +#property indicator_buffers 5 +#property indicator_plots 4 +//--- the Tenkan_sen plot +#property indicator_label1 "Tenkan_sen" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +//--- the Kijun_sen plot +#property indicator_label2 "Kijun_sen" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrBlue +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 +//--- the Senkou_Span plot +#property indicator_label3 "Senkou Span A;Senkou Span B" // two fields will be shown in Data Window +#property indicator_type3 DRAW_FILLING +#property indicator_color3 clrSandyBrown, clrThistle +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 +//--- the Chikou_Span plot +#property indicator_label4 "Chinkou_Span" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLime +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 +//+------------------------------------------------------------------+ +//| Enumeration of the methods of handle creation | +//+------------------------------------------------------------------+ +enum Creation + { + Call_iIchimoku, // use iIchimoku + Call_IndicatorCreate // use IndicatorCreate + }; +//--- input parameters +input Creation type=Call_iIchimoku; // type of the function +input int tenkan_sen=9; // period of Tenkan-sen +input int kijun_sen=26; // period of Kijun-sen +input int senkou_span_b=52; // period of Senkou Span B +input string symbol=" "; // symbol +input ENUM_TIMEFRAMES period=PERIOD_CURRENT; // timeframe +//--- indicator buffer +double Tenkan_sen_Buffer[]; +double Kijun_sen_Buffer[]; +double Senkou_Span_A_Buffer[]; +double Senkou_Span_B_Buffer[]; +double Chinkou_Span_Buffer[]; +//--- variable for storing the handle of the iIchimoku indicator +int handle; +//--- variable for storing +string name=symbol; +//--- name of the indicator on a chart +string short_name; +//--- we will keep the number of values in the Ichimoku Kinko Hyo indicator +int bars_calculated=0; +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- assignment of arrays to indicator buffers + SetIndexBuffer(0,Tenkan_sen_Buffer,INDICATOR_DATA); + SetIndexBuffer(1,Kijun_sen_Buffer,INDICATOR_DATA); + SetIndexBuffer(2,Senkou_Span_A_Buffer,INDICATOR_DATA); + SetIndexBuffer(3,Senkou_Span_B_Buffer,INDICATOR_DATA); + SetIndexBuffer(4,Chinkou_Span_Buffer,INDICATOR_DATA); +//--- set the shift for the Senkou Span channel of kijun_sen bars in the future direction + PlotIndexSetInteger(2,PLOT_SHIFT,kijun_sen); +//--- setting a shift for the Chikou Span line is not required, since the Chinkou data Span +//--- is already stored with a shift in iIchimoku +//--- determine the symbol the indicator is drawn for + name=symbol; +//--- delete spaces to the right and to the left + StringTrimRight(name); + StringTrimLeft(name); +//--- if it results in zero length of the 'name' string + if(StringLen(name)==0) + { + //--- take the symbol of the chart the indicator is attached to + name=_Symbol; + } +//--- create handle of the indicator + if(type==Call_iIchimoku) + handle=iIchimoku(name,period,tenkan_sen,kijun_sen,senkou_span_b); + else + { + //--- fill the structure with parameters of the indicator + MqlParam pars[3]; + //--- periods and shifts of the Alligator lines + pars[0].type=TYPE_INT; + pars[0].integer_value=tenkan_sen; + pars[1].type=TYPE_INT; + pars[1].integer_value=kijun_sen; + pars[2].type=TYPE_INT; + pars[2].integer_value=senkou_span_b; + //--- create handle + handle=IndicatorCreate(name,period,IND_ICHIMOKU,3,pars); + } +//--- if the handle is not created + if(handle==INVALID_HANDLE) + { + //--- tell about the failure and output the error code + PrintFormat("Failed to create handle of the iIchimoku indicator for the symbol %s/%s, error code %d", + name, + EnumToString(period), + GetLastError()); + //--- the indicator is stopped early + return(INIT_FAILED); + } +//--- show the symbol/timeframe the Ichimoku Kinko Hyo indicator is calculated for + short_name=StringFormat("iIchimoku(%s/%s, %d, %d ,%d)",name,EnumToString(period), + tenkan_sen,kijun_sen,senkou_span_b); + IndicatorSetString(INDICATOR_SHORTNAME,short_name); +//--- normal initialization of the indicator + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) + { +//--- number of values copied from the iIchimoku indicator + int values_to_copy; +//--- determine the number of values calculated in the indicator + int calculated=BarsCalculated(handle); + if(calculated<=0) + { + PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError()); + return(0); + } +//--- if it is the first start of calculation of the indicator or if the number of values in the iIchimoku indicator changed +//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history) + if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1) + { + //--- if the Tenkan_sen_Buffer array is greater than the number of values in the iIchimoku indicator for symbol/period, then we don't copy everything + //--- otherwise, we copy less than the size of indicator buffers + if(calculated>rates_total) values_to_copy=rates_total; + else values_to_copy=calculated; + } + else + { + //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate() + //--- for calculation not more than one bar is added + values_to_copy=(rates_total-prev_calculated)+1; + } +//--- fill the arrays with values of the Ichimoku Kinko Hyo indicator +//--- if FillArraysFromBuffer returns false, it means the information is nor ready yet, quit operation + if(!FillArraysFromBuffers(Tenkan_sen_Buffer,Kijun_sen_Buffer,Senkou_Span_A_Buffer,Senkou_Span_B_Buffer,Chinkou_Span_Buffer, + kijun_sen,handle,values_to_copy)) return(0); +//--- form the message + string comm=StringFormat("%s ==> Updated value in the indicator %s: %d", + TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS), + short_name, + values_to_copy); +//--- display the service message on the chart + Comment(comm); +//--- memorize the number of values in the Ichimoku Kinko Hyo indicator + bars_calculated=calculated; +//--- return the prev_calculated value for the next call + return(rates_total); + } +//+------------------------------------------------------------------+ +//| Filling indicator buffers from the iIchimoku indicator | +//+------------------------------------------------------------------+ +bool FillArraysFromBuffers(double &tenkan_sen_buffer[], // indicator buffer of the Tenkan-sen line + double &kijun_sen_buffer[], // indicator buffer of the Kijun_sen line + double &senkou_span_A_buffer[], // indicator buffer of the Senkou Span A line + double &senkou_span_B_buffer[], // indicator buffer of the Senkou Span B line + double &chinkou_span_buffer[], // indicator buffer of the Chinkou Span line + int senkou_span_shift, // shift of the Senkou Span lines in the future direction + int ind_handle, // handle of the iIchimoku indicator + int amount // number of copied values + ) + { +//--- reset error code + ResetLastError(); +//--- fill a part of the Tenkan_sen_Buffer array with values from the indicator buffer that has 0 index + if(CopyBuffer(ind_handle,0,0,amount,tenkan_sen_buffer)<0) + { + //--- if the copying fails, tell the error code + PrintFormat("1.Failed to copy data from the iIchimoku indicator, error code %d",GetLastError()); + //--- quit with zero result - it means that the indicator is considered as not calculated + return(false); + } + +//--- fill a part of the Kijun_sen_Buffer array with values from the indicator buffer that has index 1 + if(CopyBuffer(ind_handle,1,0,amount,kijun_sen_buffer)<0) + { + //--- if the copying fails, tell the error code + PrintFormat("2.Failed to copy data from the iIchimoku indicator, error code %d",GetLastError()); + //--- quit with zero result - it means that the indicator is considered as not calculated + return(false); + } + +//--- fill a part of the Chinkou_Span_Buffer array with values from the indicator buffer that has index 2 +//--- if senkou_span_shift>0, the line is shifted in the future direction by senkou_span_shift bars + if(CopyBuffer(ind_handle,2,-senkou_span_shift,amount,senkou_span_A_buffer)<0) + { + //--- if the copying fails, tell the error code + PrintFormat("3.Failed to copy data from the iIchimoku indicator, error code %d",GetLastError()); + //--- quit with zero result - it means that the indicator is considered as not calculated + return(false); + } + +//--- fill a part of the Senkou_Span_A_Buffer array with values from the indicator buffer that has index 3 +//--- if senkou_span_shift>0, the line is shifted in the future direction by senkou_span_shift bars + if(CopyBuffer(ind_handle,3,-senkou_span_shift,amount,senkou_span_B_buffer)<0) + { + //--- if the copying fails, tell the error code + PrintFormat("4.Failed to copy data from the iIchimoku indicator, error code %d",GetLastError()); + //--- quit with zero result - it means that the indicator is considered as not calculated + return(false); + } + +//--- fill a part of the Senkou_Span_B_Buffer array with values from the indicator buffer that has 0 index +//--- when copying Chinkou Span, we don't need to consider the shift, since the Chinkou Span data +//--- is already stored with a shift in iIchimoku + if(CopyBuffer(ind_handle,4,0,amount,chinkou_span_buffer)<0) + { + //--- if the copying fails, tell the error code + PrintFormat("5.Failed to copy data from the iIchimoku indicator, error code %d",GetLastError()); + //--- quit with zero result - it means that the indicator is considered as not calculated + return(false); + } +//--- everything is fine + return(true); + } +//+------------------------------------------------------------------+ +//| Indicator deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + if(handle!=INVALID_HANDLE) + IndicatorRelease(handle); +//--- clear the chart after deleting the indicator + Comment(""); + } \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/MT5-TradingView.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/MT5-TradingView.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..1d8465cc51b3faa1a81f5ea7d21c19f157999043 GIT binary patch literal 346602 zcmdqGQ;;q^v<3LJ&C~AFwr$(CZQHhO+qP}nwvE%A|IVFCq|HdFJEW~PNN4hy&FO+qzb9$=4J1Q3> zalEUrpX@=3{q|I%C;U0KqlUg0^G5$uLI_|7um^Ym903*pGk`h3`M>Tm0_gu!CIIz+ zw!nWL6M*f1mN38o;QC)K9|L2)o|F*rRiw44f~+pJIAzXt*3H=lt~LfjexWmQuJh_I`mf>9&hxpo zKSopk(m@oT;_+OW_fbF7utn*tRbP>fhiySrzsk9ECVovZAz;Uf0I;K0Y@68bk{$>* zqB{h1?=DzIQ)YKxmDeXcqi>bo2COZ&EGtn&PpA*!9YC%c1*G0dvI_oX?MpLgT)plh z57|o&fRAd;m(IH?gz*ZfiE!B9?tw?bq^coef z2zbEt$QV4HWWmVk)!F!eL@Ak8&90cWe5q(BIj#whNgB0;h52Q;F$uJa5o4H?fo<53 zu%p<#5i2NwBttTYQ8MAjjQ?5{9g{h>o}!s&%pwUomW@JhoQu1jBak*&rK%+eeY)vBRdAPY7C}`yeuhqDW>W1gFho#bs9U`6_cV$NMnd_g zjcE~7UJwmi(`eGi;+nGl=HJL~wglbV+iixO&4qJijtb##lPIXc# z9#)lSnK#|OvoXe+XHx$Dcy}KtqW&L!EUh%WTRhq=#wp*g67Jv$zj0dxFPMFE(qDZm z5LWPLf#opoPfVPfaSi6efW=K@Fh=whr;roArLk`mJR0M!1rL#=HcG8-LI}sHT-0WY zZzFDH;a}zh!Q+SFofQ_-)U0Ngm5-h#J`$xV*0J+`nMJDsR{IWiG;oSngJx4Y8nRO; z`RMFkU^nbl$SKJ;E7lUWc@V7Z9E9Vo3}RitdRJ#gV2=&Q3~x3d`}PBw;rWr4nGwk6 zYoM%0I3i<>8}!blL>phH5znvLePLu-UTNCt+Gj8cdeY2io7I<8&i_T4R`2nLo0~K+ zHiuK!^Nht(J5uEseg}r3H=u4)+UH$A)`at3x@E2>ZfwIo z(-Mvw3+gF!dAaC$QS%)YbAf@re?njyUR1b<@^YBtx9_aM;bwe{zjk_71u95z#M^6I z;13*$Px8S!7-3OtuNeHTb#A+N1o;i#5NtEuJSn$gHcUP_>c5BfTe)SZ{qvMhkw|v4 zmb0$!svl6FQL(o=T~yIYb_s$DU6ZfQ|DZY4W@23{jH&U!#Zk7$83x|%NeOJ$R~m6< z4=C}(tzxw{n3^W_QTg5ffFvk7+;-zkwde=6N~yHINBae5*oJvQkNIfM~hb~R)lnvSXEF1A;7M?-LeSaXeK!XhyAClkEv6&(_5Ckdr zu977v41JZf0RPEi**mm|N)XJG%-7j$aO+kMhqrN+d;&&#Pn6drhq(t@#+D*i1KIc)hV zk8&R>vMW!=DcTNT45nfLb8vuT_hseh1)xBN55w=n8bNr*=gK$jh6$(?NjgOEy5jlf zmI1A%b@Xc%(YXF@pd&ja2M#^Hg<+mlM;EM+qe^cJd`LojcGUBaYTjG2;G$wCAUKVv zD(`fSd#B{b7G?0X_~2Xy44HnzfY3h zF)n5NvRdWeua1m*FEPUS3Yme=4j5g*W5l|%%+mx8c6t5S;hUD}4@t*SL)lK#319R3 zAA6i*r zAI@JeG+EP5v!g{l=O%X-Sx34uUTdM)ka!Vfd)mc zm~l5@yss`aHRQ|_pr5wVfx6%mmM@)^wC{UqAd8S{_IKv z#)BlgqVez9wMYFZX7|YleA&_LWFL6axRWZ)CU zHI_9l1^+w0RMK&e=KaSj2r}oxU|2id$ng7H5vMe7=s>Y{IVd%rE(L7tJLuP)h?nq8Sfv}()qmp3;;*Z!XS7i z$1h5TvUFG6O)JpE6;@keI@H%QR~Ps`aHgy&XHAyW5y%}WJ&V>3B&HJN< zg#@K;X1z%wO+|d?pmlM#_xHBjphGgEUV*=>7^TAp$UV%Hmw`blrFV4abSLq&QiKzl z&ZbjRQz(Fs-EP0sPkE$o@DJ3?xtWlV!@lzLhMiBsLcgvv|HTf!JoweW66Q$8@OBs7 zhAb-a4sI)eg)3o}n-w^CvCbPk@Lj`pJ#8B<^pyA$pSRV;HpA~_J~?jV-;9CRWLJGC zh-C0GpXw8^Y1Rk zaz)GYe&r*l$y}`14UbV|4h6QIgMc-b-}+E_k-E?`WhI)@y@~-5@CW$tS!L5d9@LzP{1E%CV%U}l zDj#a41Bb`5r#ZfNcLdaR#-c(UOWr^O`OGdrPdIZsI_@-VtP=q54?Y062SXr#%>7 zy+wW6ONFNL6}o&4>`B$*g_DDJ$B*(5j&J2|KCp*hpYfHcJri!6^@iZ5*Xpo(F`4(s znhmcY0K2ZCn!&dmd!)R|RAS~Fo4g!65iICq*T1CPi>-UI^M631i}vOlZF0=cSz@C3 zg~B$!OgRPCRI`ut8L#}&dgZH28@K0V0W(QZIkkeQyk!#sO3FqXyA|Bq_Oy$&Tt+@< z_^uESpZl(FYwRc$mMa6XsI%V6)rKx5~yq7kKCE95jfWK6&U1_qnZC5-hue0mXCm)kw^FgkbEk>g9Gk$Qd1=`$kR$jUK?c}R1Ajz3K*oVr9_c} zC@Jf{#p}>0&$3q#J13R>PLiB^R^*}vFXD_xVPlcOZzrss$3U%>kN@6{c&1?Dvjpmz zh@{ZW5)$5gn+2QKRIA`}3hE?*mhVV0y(0AF0lnWofLlt67{m6ZV0v5kw@{tyR-4Z=B=AKr)y&XMpPoRbKX%wA9OQw=W7&m zY4(qh)5t58ZQdNHL`+gUr}<5%0aiSyM;Sxu27R#+YhJE|9U=x=8CW5rA-8324?FES zKqz`AJ-c5-@cImU-9d-qw)HH1L?g>uf@+tX@wfQq$BooFJ6l)bNRB5nNy_|W7>8O*H^xv!Zu|<8Qfy&DPju0 za22gNPJM<{WK@o@m(sx5vM&kDyLHe1Z=xidmo2dtKl8TK@!Z>53Nt7WI&U8p)0G~t zqWL~#_I!*fkyDUd^Ws0|`c6HO3cPoTff@~ZO{4e4D3IpA?cR>mlhIi{oW^WzeYC8Q zhS>u514_#7LDBHbgQZ;~BBUBY zkSWle)pg(E>D*J*T{elB8)baG^yoL%+Pre!Kb*`3*FEf*5sff&%CcJWKyNHqV8Jp` zgTmatSpD&@-6xv>6nOe?XumZ8Uzd;m2uv#*9wOUkMrj{V{yNI#)SzL5iqlfXBh}15 za(2I}&O^(c<-@`Gn8LTAuIcK|9ByRu+cK|ykgE6k{-udWkE`GAgK@y&1YCBgWG09SK)gp>@^;fyd zP{Yzun2?bRYHUzb3NY5+p%q4f7J>Ux(?xuSc}W-~!4lO6_4@TWRXlip<0`E$B2L=3MP(?nzKRo+p!FLPgSerJ9N6 zGbn%g9+>`zw=9=`I3Nhbp%4<9P3iFh!g%6OtgTs-B5}Bm@+~&i|CDRNbFVL~2xe#y zSaF$M;H+b?tn6>d9DH01&uw<)|CFqI1>T}J{*TdBqqlE zMox*F?!Jow3*`(MX3q6+tJ-wKmANUaU+5w(eJF4b*Gkm_i@@UaNq>G#f+u#EP$M0zI{4|?-t z24BTfA}mN8n~%^4tFam#8q>aY2& zuPGXTB~&{-^sO6PV`QUl_;~mAs>8XCD-!Rg&9{&J*g8>A!lrX{1+5jE{PsU>1m(#a z(3SG!A8pMzBeIASYK4BNyo>gF`7JFa4Wo4_-st70_}fjhONmTgsbUEa=kT>X^8>Pq zK5Wp_WZVW4Ttem_9r|>_Y!A_M^C@&cB#wr5+Oih6Qi9!O4r%tDS0$bty-1jGj1GuD z=c^dc95wfy#oW27Oa&UHilrf}udt5zMMSSI?mf%I!)S`~)P%(zMk~_9Vysc`cBpmo zHr=-*ixh@V9&`HPR z!?dM0l*7EjK8@+Nc+G&4r(vVheWdR|Es1|!hy@9?44n&a!i~Y`->?H(!L8|IA;%B} zmqff{`5Xf%Sn*fpvx8oW%bf&gy;)&L74)5&e9>(Nnqwl5voTLtC~c1o5q;*e9VR9H z8S1NPBewr`jV`--w%XO$VgV{x-(-ep%9?Q4q9iVqg>a46|L`5s4R+R)1O;&!qK0$c ziNJPTL8}PVPaj~6z4?@mN@Q-!lT4z0J+2Y`TJtc!_L&qHX3zeE$^JjG9 zuDba>o9a{ZBmpX@t#rqxH~-i~f6<4<9}U_XkH?QAV^X@P*dPdqh7OV?mI_4*ds;!r1@Vhox*rV1$KHI_v0tq~hQHBT>ty;3yY-WAyy-${j}=p%P1txbGR*Y%j2lwQ?t;#W z=Cz!!-6)h4cQYti!t|v=5OSs9V02P7jysw%?~?R7@ylfV{Ir+B;vms5%+|bN!I3wW z1X$euKY^xs#R3jNAsTJ0hb}Ek802LxxM2x5Ms}^T4nJMg#*c?akXpvHB9RVC!p`2k zf#=HYAG!Aojl7=?++|2x5LK z&0BMXx)}@1_Ko@X4yAbc$Se#ki~Gge$<%!*(%CCSiT@r{LXGZ+M=kf_3?F0CRPO~N zgN*RQTfZ2$0cP$w4=WgCEp=mL!yyaI4PRG);2=3xs9D(K~cy@n06CZu!XZ{yfczC?x{7TZL(3UMO_zNG_YY#VfR-%JD$a;g*+jr@$*NC zBO($=amje4V~^oK)=|W?o;3i`EYm;irj`hevvEFM`8T<9KnMgLNsP zYfCgfw2ull*%`RGjiLYWm}8v4cDXsHTsL&;cjZNCRKdpIj817(DUR#_#<5R6pjLKG z6cRbisO<_rKNMs>ZCfwFX-4NV-T9W{4EZ?trCS7Ibf(9BybI>=^U@^klrt=A#D&vR zgdqfaA|ySO*xLc_(EKG*89i>)Z#@;>#42PxCb>fjl*#J9%FX+#8SC!2fd;mb%A_?w z+sRL+Q8E)dU-*;unsxGi4Avkxb`~k{pfaew30_A>awZy@hLo~+Ja>uiHxY)q3{IV_qzo&jzi0}m9@70h!l$%rHQ$= zN;X<2N5F|x)?TEOb$e|z>z}SWfHkYpxSOl#$kYhqP%s7xcvS!^AWV84^v)sP^LF8e3_W5eY z^@Gv7C=9f4e*=pJ4AU53n~VM13MSW~K+Y8Ux~Mb4TU2lc>im3o4;`05e6I^vCPc1$ z#e-j%avtEl!rwj08e?l+n@{Tn$GxajJJngw!EY{v_1+9NF~P#Y={|D&GY==zp8n@O zJA~k9PT(ry!`!fEXz$tuM`;)NzXkENYS9`RDR#9=3*GQk;sa9JZ4Wi04jXt5>^%?B zT)D4Aw8_1bWn8BA-GsG9a*Ps6Rqu2+mxIbE4eT6mRaa2x#t|G&lD%ayeGtI4gHiFD zr$$E4CRkE!>0R#>kHsRy{nq{B@VZeC%;mGWZ*m*nO6>-bx}8@j?)o=XNgT#Z8xdI0 zP6}D!+2n2V@n6N5%7jGpBM{{!L`!?|u=a?p#Ti|G(*+Nf2gVn);F*HFC4;%9_CJox z=TTVacIJTo7)q?tVDj`|DEH}D?H2Ds3e2oG_~>bek@6V_2B=1HbJto+%z|`i>r)qj zo0qL_a$<>MM*1qu6JOO?b_|EQ5?Huh;kQrPY>jcnfALjYGvgnX=|1u8Gb=MF3}*W| zWZ+v-77QucK$o}xiSMTtOyU^xjh9Zu{7JaG!Nb`2$+#^~MQjiPaY0-C7A^=R`}_(- z1g6386_ni+PMiK4@44T9D1#`iVmcDShh_@}qyoM{WItxQLPr&(mmoKoN~<6be5F9T z8j|#nY>zpb4reZpZB`cSUz=!DdX=&wxMPSr+GMWtjNe)v5~{w}sRs}Qo*2qU&lj+^ zPzh~9hCrcvAeIO?*MFh)?13Z{XjD0a^c6o_RY~KsZ>-7`wnwe_3^lID@j*~3Kkh7v z|6*`|<>%dOQyRBw8u8F#5j4c@s(YJKw}#V;JS0dZAl7}yN4+__22E&ISx-KzK7CWIX;JU%g@rybl&H}>{PF` z7-^aNcClYPobX3QD1p^lzx}g$o)<*QB`htXo5ghY(mRKl@$=+ZLx)2+$WJoDoRk>b zBP4@a1{5-MDd``(sOpVjmY7rrgus{k0ucA{W+}&{fZ{!?_DL-4lF@{fLMj*HiT}t$ z?t#dNSvm3R2<`eTd%^GwJ3T%DAjufhPTn<#a7IP0iO}(XbzTLJ z!B%cwWeB`-`U?}u5r0w(rJ)MY!SzYn5e5yDSCxoTG^dtzR{RMWO1H`k$L!VW?(7y@ zsCB*Utg0bDLr`KD5TBt+0xZ&;3{+0h_AkkX1U!FbV2oL1DYvfrHbq#|fIOPEeK6z1 zn1!-fE#DnZuoit>70-$`8X3D3nJ9I)4{EBy|CU>> zbE(N!P5CA)M9aBQ<39h2@6~Pr;N#{BR25BDMp z8mKwfurJlhcu&T~9sxJrK(nij*jvGExd7-W6FX?>#I&HB{nmjYPO*$H#4G%-Xk zN{!lI-U-wn!3&CaHC85VD=JmYOb2>dAQkg4^v4p2zDhM7IVHIU0>HZ9f7<%-v$qtt zHn0F|EKPlLK%_FT`Ek=zIVQA;43UQx*4|x&87KFYiG@Euc%lT75!1hLz3Fb2tU~fg zgtC{;11u_JwHd!H^3=+bA^G^wuO_H}k&hb+DO|&Vj{m;@YxB8T!z1$&7ez{^M}TsE z-kDJK*$Ew^^dx?s>-(;6)tOfqXpIu>juR*3l{_j<14X7{RHL^fuqfiOBxwSo7P^Ec zlCw!vv)iXX*W+?^L}RXt@`*kU6*sB1To-gu@z%2kSABI}8TZU;)6I7Hlw_PhpkmAt zKgcLPCWKi_?MOEOQAn}o#!yi%k6VhDQ;IQCEKJw?aMyB=#$Psu%b!2YzjHRv*Qa4u zWQ6||j1~`01PXlz-xsxkq!ufuQ$TDL zax7w*GemupUkV9kec|1ff*nIvgE@G=e4ug)7wSS?GpfStSCVx4dV5N50&j0{ot3i= z4n}IqDj_o0_@P{MY=67CqT{6xQn@4e&PHmFTZcWA1^#nsNR7+CUWk4^W*D=J8%olt z!YYK1#aRtUR^fOclp%-pkC}I-fQhj;l9;)`De}m|M6R!Tv3`1CWvCb2G5oxZ*^qPJ zH`Qqo#M)Sta7QqW9 z8W}75?wClc!ML`w!GW^)o6J>wG}iZ>%1zjg9?^s++U)kYY>s)@M|6Nq@%$vdvoVs9 zQ&}uXr-R}?$d-MUPXuN7+mpcQ!yYhfiiWf2#) z7kM^Z_r>(-L%iLKbd=m=JWk|_dZ`1pufM#TWwdV|*wrJ@MR%C3z|b6zv~RZjPqJvG zAV;rzUXXVzE%0@>$E1`;DyAb0XW7x1E8$FDK zV;OxEYM`bNK`Q&_qz-S+3d9Evq&-L$M_3p)_oO(s+3bw`Q<%Yi71>unK`3b?ifC5i zT4lsRILF++rnR;_cYx^RKfU>K&i<}ct1M69Xl-Oo@|-`q7HoVb(w~%FQU*$XBsnvW zlf2?DT74{^-t_kbM7cR!CI(XLd-O5+(N@D?wTWl+M)SvyUEM_;>4=`hg2k)bjchrP zEN|1IX%3XShEGCtqAU$PJ*pIEM;W)#p~d)%9D()zrZ71td{QhXg6@bHIs3OOSm9Yd zfyNq1q>TFPtd)3~2zIngs-Z6q-MOi?E@$3OsO6nXYj8ukR$&+9P787&1VV8Ld`ud$ zJr%XWdoJwgExLb>+$hP8rkuZ^(id+^aL_$HdLNLz55kf<0C;Ku#N1B z@`786PsJ^7U;lz7%nLo@yltm?CiF;01w>I~)Wff<1+#=tE(+hJ8P~NP694$tTFKo9 zLbByTX5Yn!75-s+Iina3O+#sc3%V*vz|v3iw_`WoFtdx*@U3&JB-^i=&d`xOJs!)% zqn@i%0uB3~8jXD}aRZU|m!TPW!Q~oN3Xc8BlG%NnGbTJ_GGNXz@+3GUsgQry!I2G) zrEF2^^j^u3rO>kR_H)wY2F+wd>x(4U4Z?XzE&clBXD9K2%RZGYElHDO8t^G{Aj5Km z?oGpc>v)-Z^J3J`pIORmvZ6VX@nOEsapbhI&81sY2g?>-6I4&VO&7Tzs(>%gcaqBbkTFXb zh|sl&0;Xm@jR3Yr9!ZV9>a1N}Y8e_R>9`Hx7AH(DHdVreTMV{0A#bd&acu#)*D< zRdxq$n)nt|vo8YT=Kb&ANV@qAoDc|?fR(u^CcoGdp-7?zd>W@5bpqKyV2)VQ*MKb^<{K& z3&4Dx*Z@4^hcWS?P+qaos7R0GBN0?fn<7M+)mi|JL5?TCvMmC3GzIt+pMZ@HA%@6>lD7KZh)ZAp&I|0rvK zU_G3~W1yE9`$Y|Oe5eTLWmI+OdWAI4fYz2nDfdo9yR|S=ZR-aHxn3t#EAL;>G+{mu zQho?9U0%j!{?7gAu3!w#*1Ys2YBu%Wn_MY7-QuC3pTs95HP>wW)cBP%Q5iMb+D&VU z(@UbSwBAzneoNy^w!zw~>oKB_V#M|L2N{iWNYDzxPeE>5#GdqhdDF5pmbr8tqw(6i z3#W4R(y@#g$T_3XvX7Ns3C9Jbbuo>tfJdWTCc_0sk7PF?9hG>WS0q#;*Y!J37D z%|GeDKUoH`7+!T(e=Rf&Vs`4byl+qFnYZP`ndgh6++b-`4H!-#NFv+yLnd1xUkMav zf_eWtgjxeKMoL%XGn(ERlyy82!XN8wttoDqS%&u*Q48WoT*V#3$Y;2raQI_-wLmjB z7=0xcUb6dQ<8kBc4F2W){PcJTEYnq74lu4~kW{$c=G3Kt`&hnO?OYU$tplS`du1v209%DbtqIv1VA_l0B1H=l{>oT0#;dB~D;6OSvb?3por!m<8AxN&HDq+sCw z?9n#S-SRJOz4MSB?VXfqn*_u%GVa3fS}bo6=HrHzD+K!swyXNFNTUHxH(72qbg9r> zUh|Ylt2Waq04|*dm@Ampx7%uG(~}A6PqDm_nIeO%%sd59;hiw3c+^o@$co5D=7C8# z8C^o2Pv-(H9|J7(!o>c_GJ z@17U5SnCJ%Pq6)hng@*L82bYUX-m5e)Mo>>AT zZ6cZYFj@UxNS1&8MDDX8CC$Ge$f2MU$yt*mK|i~`H>TxbCz#b-YwF_#pfOj0g|(22 zg1SXS;I?iJhg+G?Tn2(LU*IQeHZ(sW<+ZUH5f68#vS{<+n;qMRD7!=Ii>hCDwac{Z z1+|_#=F`m(56sRk2;<5P-jRMXD!psvBH3v0)oe+2v)YeSE=8?u(>Qqp4{Dw~dOjJs z#m%-gDyEv`E!8DY=rNnEJGZ~pW^*CojtXi2@h9t(BkDyE3B<`LNNQ*WpB}YwQjZmL zIE?o!fzUG3T9u+>zIZ(MxbaEw!))&!2qSKMPHo%Ff+g2nb@Xy>m2jlk!fPb%3ArXc zl?L5a;_!@=FVmaTqa;L-H%aPCJp0&9s6-K5{Hm9PfX|KMwPyM$U37TF-#olO@d@b|!KO9I!pss92XjNA!aX8Ka@?Icaoea z8mM51-U)XxM5X};tTjZV0pj0*7h0kLOa3vcW!yVkRZy7LFD}^*Ymm1SaulJNli%Fx;fpqd3kg@K&1Q! ziSkvZ)Vkbim=hw;XXWhQs=-_hA@FOMwif4ru0T?@UuO9xN6f?*lKvGg9}>n__(1B1 zAitjvP8UgK23X%;SBmTv`0;%l1?qhTcn* zXf{PeCF0t*wzJ%1J(8XDx!9egX=oRQ5x!$yHsAorS5DzdJ1i(0$WQkHes{R4JVSep zKHI(LzZ(i_!&;n-S8fHX*cJ_8Gx5dd96^%>krQBH*YxKWf5ya&*XdhHGD(2==>;;< za8O}6%pkTNRC>&Mxhk}+PcqV+M8D{%s?Ls3+rpk#)K%8=fu(~BknTjKeGs6}D%}4x z9yygx8uIx^TCrz-Neg# zLiK!KX`x}7!l)5Tnoi(qW_+{_1W2w-{*nFf|0;6MIJ-!`@f)<$#?j3l?HuOLF=4pz zxV`U&!-SwXgX;)~yEZte+DFI86VK#nFNUZr{vRlxSRTgW%7ca3fwFWeTyZX{8tzaj zCnTsFF4jKLUwb4J=*FN%K$)##JLgV(?SSGt4eLmRht46I zq6L+~KdHT?K`z|>P8}Qx3e`CN`{1nt%*14}+R#^I;Q%XoBfWl@InUIRH9~uiNLo)i z_pa_%)JEtbO9fo=xAvmVQGm}fH8`{3OF`0Pf?EVGFyX-P(gX9xs5wpPs<_N-+^dYs z$kz3IwcA;rpMuD7LZ#KnyV=fN!GeUrl2I0(;Sc`~UD=jy+98@&A}nQddE2iVii|*X zZjcc=1=a;1Yo2_`pK?x6%IZ_#4qe}$<$=70ZeKE!G(U*+NNM16w{o`~_20#i9x;KI zZ~_mgGc`z6LEC}{{Rs>tXdgoY(2;Yq!1r5zpmnb7v)L9pVV6{Owkp%-R-E0EX_4Cc z6e#Fr0J3_&;b9Rkb|TxENY6(qonB&3INorMxwWtgw>rcgi4bm#_A0>p21Nu2?;ouz zTb~}ObR7;`8wtsKjyVa}h~^)KU<{}m?j};T$h@g!-t+~(*|GH#FDdw~FjxKiyM7Yy zys5jU>lwQpmeRStz+XU&r#E#tw8X4@kC)vwGq%9Z@~ygGl-Eb{LAA=$4T>C|H|2y*+EXsu6C zL7FW&@j1R1QXEfbcZ8gp_6NXUpDNy8%-roIFK8uW4IMErCtU8Dg>X8u1{mlk>$TQ& zLNTi*c1)1?ySJ5%ltc3GP&u+X$lz;L4Z)Qs^Ww_nPqKxNLq+gEMAqoM7!t>P8CR4u@ACiA=E``n#~q=T>`Cl1jRw-?lT4-?eis0Yt$jReO@L~0s;+LP)!sc#A zNm7;^0tvWHah0$yH6t#4co_w{*IWlo?|B4O1XpMWZhaA7Ru+K`pz%Z>0`>JKnygN- zOQ?gjnTao1WA1O15c(*+SNM)bNx2Wd4jK%Q3*l0<8g0-cCvz zn^b0qf5FVsGHO4Y%Xbd}S?%Omj*&`c)U7642QLk@O0z*-YOi)SA%R7!PfTldxCeZ% z@HY3rBItfandN?K=+D!dZ3D-@*H`+rrW1mk`4Ppve{!rKl8Mzj8l6y^P%xN%u37k4e&lZ$){59gv z{Nm1LEQ4pGzaf(M^1(mOwr@mSL`&$)FxRo3$B%)__LzVZi$*&Q9?(ad%F954k=s+_%69uod9ppPBByS>#~rpptajCUyZgPg>H2m>5&5uodq zNk-iP#Ny7~O9CBK7xVSIKe+|qh3T?KVyL^siqAwn?h%eq$GKbvb@6S0bC+LYz!fh5 zNs^@|@OaB6Bxdzujo(;iFv4GA*!sgZD2?<79dw~7Dwd$H7lg@L)%qC^4+30f7dV(C z5wO5&@e}~x=0)?!r*8w27|ju>x=afUqGV~1umHtX5y#KZ7c)5n=yg0n^@^dKf83w4Gk_@f<5YP>lsgU`$8ltj_`5 z`KCgPwQfY-u*e=tGj;<);<3!hdUMX5?~~|m*mt=REeC+QrTaQ)!P>1wB<3H*$Jz0kj4vvjj;s5bKWj8JvdWCS)?j3u9qWKH+%{QHaDo^6m8=$BG!$B! zO2w58Kd+~!o5VHX2ay94j~lwP9dyIX)w2yMLKqMAUtNsDVvz`;)eWW5v77&imyrM7 z;s_tNl_12MZBM`;_{HT1hDwlV zWMa}%DvS7~E?r%F>1zOq$W-#@st)LQZ8zT?V#&v^<(tDvg1YQ|FOY_;2yu!^b^bn*>v`yHC_j_}hXSr7HAX2x-1xcT*2QQ4zy&W_>{gq3W3!L~3W$^8TFBaftQ4 zim4(^dA;qe)@GUSh+ML$gPZHT57a#V-en5sR&_g(7Ql6Oa@DMe0L&&>#lij!YlEBC z4~wRX<_i4fEeBLs>F|j*mdEPS1fG}LqqzY4$%TdNMtq^G{C6kYci=crtI3~mcrf1Z zvat9e=VaGSOq_XlC({Vw^YxwKZ}%i^j{TrOCP9#JtbHNwo1r9VIy^I=ErAtj^4Epy zDR3HwdA8DC)gdpnJi=-jn!*8NhsY&9e&wX~q&9YxI0z5nJG3zYK8+i~(reuN1fI_V zqcrBe_HU?u@FmQzB3O(>`#ckZ57?fCCkMs&NY}EcCT1?NbaJoVZVWXE0a|iypy~Vb ztVw4J4h(LEEi6u0&?L~`bqS^jW@v8aLe4#9+W0`krUVS~yNSly zRezxzF>*%D{s%t^{A^ZD!Uatjm^u?+rWRG=O}P%eKuQ)Atx?PofJfWW?67e;{muj> zjEfIzKmLe_Fm--4bXn$~&SFso>CiL^iewimHa7Xr+)pz;d*imgg?-}^k5(;GtD5tz zP^et7Bh}kR(c>_skPdBAs9n3gOG~NQIUO$LSV?r6s1m%4xa=oD~P9g;TWarv`98~Au ziBGW5l)=m*S=;C^p~}{hSI^xy^Uyl*`la^j=SvcQxifPEF$X8_r@B>qZECs3d;u=t zGh>*817)|qRJ`MaluiSKtqjy^R1%Kdg=#%l3$V9f{%2_T=+FKKu5Z~p1q<5Zkfgw@ z03cBHIFrT!eo5Nmk;%D~sJug0l7MZkos?+F8bLgE(W>oZ7hv;BcV~kQrV~3mDMM1% z+^$};k7pd@n#egm5%YNBLr38E_JVbLJXm)6bZ;G~RlUnEi~8yG&T+=Wij+=Tk1bD{ zG3zMiRo^u+;;$)=SiEV*3_h>qur)5eDi&6+vIA0Bh@^M=4CuJvuB1T*a<`ieh9lg? zNmcBNX5Ju^s;*iO8)u)gJEGbI$A`xeF~w9~ytg_=u8y2$f_3chbNltJ@ z73NpumULXq`igBKe>tS(HKz5tPSbr z{RXozrQm`ept0g8*DLULY;mt}9)*{m@;Oo7?JoHI0wg_arTo^hfNjLw{VW#_T;J#WXkB z`^29s1o*~5|5kav7-ikUA8q%@Y739V1pJ_mY0wTCZrnk#HVc)1-q zTRRF33f6J^r=$t3F?o38e`&d$5Q!Fykb=_u&<#h9ZPJ1Tz%j&b@HQ)KzCtck1;{6N zxHQyQ&y@GjQYzq5#IpaJ#|sef5!S88<t_dY1TY zsu)-YXzNrmnbAE)IMExOjgcUWUO0m+Y2^02f`N$`g%v}^Z976Cz>rz2`P}1?pIY2RtvEWBizUlG{_1tG~xJ(>L}pWM`W>C<#Fn0{_ud+XA7 zxo&mle>>Xo+`TF58oK46vJHTbI*%%A=A3}DmJzsVD#>{5b&uf4Vs`Jp*Xeeo%%ZOA zN1LDh7i7?Y%u9CAZP`MG_BZ)N6QnzwV%HW_BGcUcI@g;nX$TW$Wtfri2=eCDE!qF_QqUO>Ls2aV(n#@}{@H-Gy4veko)g4ZQabfUv%g>=83ogB$9RvMTDl)Ya2>S9_dFXLCb- zHyAKofBVXa>{orHT%p2A>#)^C=3plGJWHGO1o}0QAM8g$7m|54q0r0v>b}S(&ndu> z)uFvqj>(+qhZaWmI@=!#yV=pk)*+QT4KMSolxHpizFloR&G<gTNN*LVrZGM{-9MGeK3iy2R-Vc>$ zogKCz3w!Snd{rfHa-i`gWU^pyKg@O{T?y-Jaq(o-WW&cSLnb3K({)4tRVwS9 zdtiT2*Ju@==S2&``xhEOM1}&~Y$@R`7cAX=B!c7T_IERDkMMUK}T(A73i77tOeIB zH3SRZYZizESR`wk5V()~##OQa4ywvLNOO-)=Vb)PdieqNF;PBvESovpP`@=x&hvv> zIHu&A4Y!+-Ou+~~BRu^14YzoVz&laj;%e{k@R0$+1J6eps5oX|E@yCF6upin&Oj*? zfkceyyT`e}MbX!#m7adJsjX@7e`NX^{yApr{&Twhz3%(NP-`=Vi z%Tfb(HfWrB8r1Nu8;8ob_@b`oK{SM!7fZ`yH+3}Zt{#4b|e@rpK33;=Hg(JFs>H`!cTeV;s0+s=NRQ2E4isxq{ki6K2fvmfhLF98MG6n3=(Q{sZf3E4%E7sSMSpg{YvL_`QPUvu=vIrfX7UoJm_93!MYv;6T zj(P_qvuuQ4s^TY@re{gG1x;l2{GzBTAQAz|w~w8qiPQH2XsuHFE92i2;j7UKHcmF` z6^SnKd;98XtiwlH3gnj>JVnB_*kO20rL608g(q53e3vK}b73XR0G{>r2uEBkY;QFT z?_WwI%vDXk3tR`2K~69v;&M$n`AlQGORecy$$U$1`&tv|I7~F#d}<%tc%sxw$mlKa z^0T;X#^JIQ-W19neh!U@Uv%XcxSml;dv#uvDN~Q5uYg|NM-`}$QIUvt^J$35^>LID z*}PuQ0Yp#hvQ?}5R|0ZS{ARz4h)$2aCA5t3s)CYWUb`YP;G{{f=%DoTu;2=AnRj-< ziG;st_}MP!b(fm9EN@-s@x54{IQ}DfUOdoP4dH5p{KYjci!EbBgqoe@rKI7fZ~TFU z@4w)s94f1{iO5-R@~t2HUn|jM3QOI>I^o3Ia>&0>rVsVBMof3W1&4~AG{(zn=q|wm zGL;eVi|X56zW^$qD*2}lh`gqiF%^1~v;G%zAREGxB*6>0!kfN6+(smNfJi6IZCsY4 zc|0MNRb#f@4}=nA8%?DD{9jpy5YmpeM0~Zuu?&A}X`wEZjUtjFwYt^l_yU`P3lT`k zCxCw4dPHdfHR|@G;9yR*e0J(z4Y4Est@&?%#$4OUohBQ1%F-&{igOUc_X%qe0N4_n zx`Cu+*9|Am@fa(j}r9!2Y~mrxkL-hrW+#na#iGJvuC3+MbNM_d`F1xu#%x zzDi3k9(|GYbqw@HgG;`9b>{=?F+FG6Ea|(A8O@P&ZUO+!Wu5Acr3~hpcra=M>;Hxs zuKoEXY6znNd5OMm+Wg>WZ0a>P5?(_;TuFQ8wd+MHse2{l-J`3HSzkk`gp&&(u+g0# z)<{Y{(yLYnh%(jo>*m8G{x|~hb9)9<{is$$Te(JBhQ6AQB3&)Q@^;c4r!Lk7d($+I zvlP6deASy1MV|h-!cEXC_@O1apo-O4U|x=%K?@Y8jZ}FS@rH2-H*#GXYX%S6?Cfxy za-M8?prw-L1KD1HG;@U$WHeuk$dJJcKcsd;K21(NNB8xAw7g==)aA7+43Jb2`LPQE zqZ*)`wSq#|*Mc(0j|?J2(TSAJtUr-|o>zgxZIUmIUT|pNN3)I&L2Jq!`}V(B@Z6SR zh4kITj6`{IlU?!K#VABjmR>|7xc)Tjle=z0-~#W0#swYA>F{HR*MO)9oPNJ0(fz9( zFA#M-U}RJNsWOE*CS@cSeIhsf9c0Tt3g^6G*jhsZH;htOvP8njNwFLL4~F4~q4`;? zMGW4#-sv6xZp{%Eja~2ajiAB2V_JcWl^vxj!NEX7_lH^93Fe|R4c7Hv6G9WL+%3^NI1|;KU%Ns&)jaT|iGkkLmr3eBg3-I)erCh68N6 zuZ>l$XG@U>yBDQ43@|7rc>(f*dHh>6_Iv_%3s}vuInv zvmIOhgMeYV-ru5K*{<|Niz^=hs`eGsSlBs^XnUmx9eN0iWnh}#nPH?5nE!wQ+U-f1 ztSekVN^sFc3ZjFkjXPNAygn|cTpJM;uIrK*l6%O*%U_bXM^5mm_92V$bXOe( zsR7OCJi5J5y|V+0>$ck@Yy2vWJk<_EdsuS$rZfeb?P{2i$y4xXcNfk&OwBM@U4q7A z{Gz>M@~2E1wSHw0X2AR=VBXH}CfQp+)AI38(mAtRQ5Rrl?@{}-98D}0Twqou11#&* z&ha+z)02})((>>FQGF+9-al%}Xa#vHx$thNM$1_j48=Qt$7ha_bfQ+P&m_9 zzUH`EzD$(*KLCK49~#IVL?z+F-(1Muwev%l7nopIHPdPdKoU-?aNg)UxU_h(FUzdT zV_i50j18$q^zcRu>sjItYjuZ7a(!0_N@3qtr`xD(5&4Z+>>G4tS=#c*J*a1ldnq*> zXx`2wP*M{|NM`4^d3d!k{|HT}T_eA`9SVwxiDM9GF9p_wOB8w`Hz9`M6~Ra4Ij2{S zBms)DDsUoNHqOs=pGJy^r311ZeT9Z0FId)7JTjFUuWLYp;R-&9(+Qv1w3eTyzF zJmTwpCQ8npTbP1isQl6(Mr&8#Yhx^da@tN@K3m`N&moY1_!gTQlA&CspZ>quC2li# zw!W?gVNnzcp)NpFdgN(Qwr0IcYCO3%j~^t zJH~D8k47d_H4agXtZB~ph9wqZYF3fy!mWGKmH5-%4W$xa_Y5vKFlwgS${}X{R#fVK zrwhrR`+=^-ub*IIg%sV$G_TFul9(p!Dx|=d?xOAX(%T=; z;dwtqT|d{}#@6DJ-n=}Me_KDH3ijY+XC!cv=U3!s^x%7=#Ar1zQ>COd>z==rMD;{W#|+DrgN$()|Ik( z%Om+|bmA}_PqN~oTmRm_C6&I{fK)*M_wzzs<;mysx~89TI%#M?pACM6B%RqLdHQjNamyEm|b(s zJF2uzOzL#ob86c*h)-?bDF(^Z-g>E9rwOj85+Se& zFBVNhH{TJ2QUP7hPc%zZg}aqDw9PSjLHW1!cK=)~3B?aN=g}^DhyhRa%A`ebg2cM# zHZ(iIq-+_g?VOtRX_yN+M^5oU9aNWiy_!*{num5xd=VvjW7$FVFDaPUz-ci&=ZAn6 zU+LC-@}Zd*go>|!Q|i>s{AvTXQ>~so4?vT$71!j~^tw2@vd~c|3bp59*%~+v*0>n% z4F_kHK$&wRcYYg1%4q@hhPhzD+^X345SIUPHhuE1624qpRuZ9jgV)W|k(aw+jt#gi z;ZHMjt5p`)k*U^ar_Vd=eQLBaz9X{n1bTR;j5C>s^NG`d8Mfv$58Guwx*s7;tH-P> z^TL2@Tz=U5uL?8rx^HkOr&LDbg-US7x+?MgNFsi>Y1<0pzipyQ^JJsYib)z~yaoH% z_@>c*wqL18-FA3)kO>>jGKIb>&IYfL=!7)5*@ETYTS$jZMWrf6O?}Poy{7eQ1Cz%kE~>d~bHQC^>M?b# zL4YEUOg>YCU6@`{O#r^3{N8;>d!+ziLWeXqOyn-nVa(8!G2jr9uV(Rl;bAncZO&OC zU%*vE^Ahz)f>rg+&O7OG;~MBe$wklc77e5LWaqw86&DJ00fy5BJI<~!Tl}Pfm!i>Q zKtI&^l|@Bu(X3X>WGT@EHM*DyO0Swo?TxKRFSJq3OC(lELZuI4nM7x@{Zt(ytsM=s?mG|UYj9gp^US1#XhBoDNy*xnv~X*tk@t7f zlSlN^{wu9C>$B@Rp*7CHkb}smlta+5gsB3^)s@iVx&^B zB(XvXzqs6@@c19neJ_5sPeDqjHZnOq#uw*K(Q+PDT$cMqSMB3-v^MjDo{8JgN*9X@_eNl8%Vg zMB>2?MY`Jr+$rXNZ&Q`yq4qP4(hOIOr-9|yz`zkR-NU7fX|*``qQg*4NK|*TIIkl~ z(giO*zV}0w39Zk<@xb0l-_L<@`|Dn%Z4K!7U%TzPLxuq}gGSRbSYlP^moRm{k zg(C04fJ$XLiP#2!blvABI|NATxlPY8t${WDEXm;&{op+@fkHvom;Gzo7wji1i#7o3 zpn4X!0UN0=x(^x1|E;fcVfsueXv4g$QIYPnVtAZ-{h~ zhTVjQENfx-YCNL&&iIX$@Oz{pV5-ue2MQL@fq3E-WX)T3p5(SGXj6^+^s~-{@QeN7 z67Vb4K33w4W=s~86!4j7z3}*v{q~kO>DNc{NcemAd_J@Wh=Ob)psm%nmS z`+tINID1{3P;&?;z)2>|@*ao;*mg#=5ef9aYumVYJ+q!Ig(J$i z4HbeWrXPq{Qk(b^1~^3^k!{=G;iHaDqOIgcUsx03h?B1f<3)FMbQ?44Qm_ihsP63g z9G`kuNC>hdU?kR*V&7l!>N#BCh9t~r@5wP=Hj&mn2~yVmZ2oJb{ zgM{@w=DXN#bU@g}d6VGP9X~-V2B>wKnv{T-c50~F^%48G`0ykmP%kMVazsw-9X1B2 zn;8u7vgC5zF^o^sexMvu49f!8qAIq!P5srrx@8t@HC>78mkSh%mmJ6&62+Y|y7#5= zh^qh@xdw*u+Fj!~OIuFJGnRDdo*>B)#NfnPkOY#{H0?GQ z<{;Mvt|_q}VZ+`W$}-?>pM>Vj(Wrqz;X`sXWiz`UV3g|Tg(t#Uw`u!e=sO9Kf zblIyTr}y?xpa4w!;D`n#HNC>h^r4t5Sxt1o)A2y}72H%_+8uta5Q#JpflQa?B6GwB zu?TpYGsME7!7j3$F|T=11^6cWv`&OoQ6-5~&&Zf$Y61$Xri1Qjf&&e*P7PYf1pXpAs{7Z20UsG`?qg0tjR{}gEHT%ms>0R-*qp3y5kYq$s$bBSxh)Uy^o zl(=UGvVP+D>0&N{f^OtHHHTPqwgXt!D28?4d8np%nCOqt)De$jvucq zXP1v!?|S)@7*m%Iz0y!-k^FqIYut{VLBYu?6Dme@!Xp#j+VJI2tl%EuW&xkG%p+aQ ztBNKAxk1T^-O)SqqnV4f>7Q1O$J2z=BB-}F#}=xbO)|?3^d==%H4x^r zXO663ilEie;GS=t%pe~GlabaF$hYbl8M9^Bf~(Q?7dNSVn}up!M#A@Ucn5tGd58Ad zy#?h_}55}rCV`hG{^$F*YgbQ#h-u_7&uEHK2;Gcp9_^gV_$`W~uz%quIe?AgWKc|@#A87qqhGg*5zF|n4G%Pt|t zASxagM>K*{814=u8mVQcC`qZ|RoC6Z9Ob1~d8=R!B>&+CcCS4ZuFz^Dnl0Dveczj# zwhzMehJzBMP|s)VA8iX5UJ3#ldbdf$T6#UrbZZl!v?vf-)@KRzm*0}7h*U2-U!n*$ zz<{*T3H6vxd!8HW33TqiMw}NedSLDbqY06yn4|pG;Hq%1vkP)%l#zbyE6Q4T)@bl1 z1QxLEOy)HLObxV9NewHl{q+h;pJ#UdI#E7b4GEyzD>jxPgIq^x&@zmXsJP+l+_tor zp|4;?{QKlyAQx&=7C~Wr0^PCj_FJwW#)Qrocj72DQLtkf4T<}nkk$kRD`llwM5quF zq)!=@6wu3_Z}GHDRCu&brV{AuvsoR#u5@f$ufO24`Bzajtmo{I z<*Ql*{#K~^5(6-sJ6zI%#M(=x*Gi;+IzF>V*~Nuii8|8kxar?>Ge z=zbWiHfqt-|17b~i za;!Wn<3X?9ACr%{62VAQ;;qeqQ1XAYk)UJb?1COPZlF}47XUl_dn|lek4oiNYo{H*7*{OP< zPg_43hpr14?R28h;^AePcuH(mZ>z^dj3Lz0aDy4Eh?OCWN1QIw!*Rr__RkYT?asgdc4^#yI+*~upt|L7qtx6TBSiGuT+bTa}P!k+BqyVnW_KDjxyL=oqz18V! z(mrdaHmQi+t}}7oJ~yqaY==LEGB3&OB8JyEPO{Ufu$tcHnTO3P`;t_r8i0r8um8oX zNkK-j|87HhU~KR~r2LCq3ARpZ2Wl6Li3U#v$`()wg5Sce1GlP<@U z))=AK9~AjpeAk?0FsVqoM?bA(M;F_8#dhbZFh|2RBp0$p5Z$~EG zuN*<0kvC<9`$Pel#=XN@6-#+cUA1bK%-^ADOxhWxWORx#0+V0v*YLPo8D}uGWFs$9 zY!?2#4eLfsF1l|VsSh?AjXo4I2K|%KT}pwVXWeW9Y}XZX_MBD+)6g9svq%u2HIwO7 zZ?3VeRnGYgK6`*9N-ClEcXX?@Z<*L^qVuvaBi_Kekr;=Zs?-Z|m(QzbT+S*bUwK{& zq(aVf_xvUHU6G#q8KEB5+D0sC?3fDVReEd4eDk5n3^1BVLx`+1ecaE?^o2=EnI~o} zfs_G)1HP(F?|UF}Ds<838Rz8FG2eT@x5hyS&v4}8rc3UWbE|-l{IxH|09BC zyyAARTz6-Hj4Zvet$VT+wqRFz+vZ5YHwJPg|piRkythM!%`L6yQQP zFXZF2WtH*Cq!_{6DL%e`MYNQn`BS%~>Sy<*XP}hLZZnDsS|xU;C?DCOU;N#}ihs;% zT58-oww#yt>pK37*;qIG6+fr0jsO+ zMTz?gQv7X=bhv?%)KjDO0Y|VeCU&^ zLrCbENI5T5ql50Qk8IbsWLHKQ@1Uj7gV}Rp5_N(jN{xyl6q?l zcI9HVNa?ftHMb9S=g4;vaKQY-zi-cEnGtC{)>%ZCW2+C+;F*^0& zzG|hS(?`c(#!A>6koh;D!ks^1lj+0QSuoa#MKMT`7t)e`WL<<=yV{rovZt)rDSEC% zfr9VuVb-9_H7yMQ+IzW7xBOHTH6%ykm7tbH82=L-)VE*q^{myOcV2gaS)}*qy4Bs6 zl)<-~zR+d3Q8l(N!~bGUnM~fEH^5c;>!OtQQSRA$ z0-_tcg8Wa3ZXGIG@ajao96%O1WOO?oXJIg>YFb#wA z>$r8GW%9O;TqSvnb(IkDIPS>#v_@H1GjUpilC4nlM`9E6o(FytnvjFJ3s&QqLSC8x z{> zAn{#pU@Rz*2P|Tgk@4RPzVlH`h_s{LYXk+V&pN%zbMt=-x#Y7~3YV;cgojD=hryyQ zmwS9a)r*34!7R3uJ=>CU^#mpYOOq`B+p{Q)=I^ERd{@#|ft!zk+0(<%ttdCNzjos(&W@ca;sTKlICvc| zl{>hG>uU&%R<(eTr+qgt*|v1Iy0vVgo3U1oNR*x=ifo4lKBnCAtd6kprjwIvm_~+@l}Z@Aud)fWR9h&|X`T{;cT~i9QJHCuIXYyWt$P|CpLA@Gh=*Ok z8c4J0YhDTo6x$VAOYjawJYt_Sj}%i46>)^w-|2~l%-PEGtSP#ip%pt8mp!ziE0N%GW_6{g!_M%PZ-@qRoR`T>IDASe1c*1Irx zA*H9RO@su>$<5-xJow&>Dum#}m)EDAM>afyo=ek=WU{Oa1avKz%>=7rXqmG-dF5MXk$)RsmmcfG zJs1!d49yA_dfR%r6X7#OTU(yDmG9VT1cZdj@>qx|@a&J}>=GqDZ_rC3Pm3DY7nQvf zUM?(L0qFg}T+Bw_>~R9ka0Nhem$b*2xRoQx8lxekHr(TwZWP6Ea*y(MDU3@N$_8*$ z?0Rp_d#&@Y$lv!Ih7F%ZCbnS-TQXKzU#xF{L-e*@%nN9sce>$We&TYe=oO0`{h2=w zu?_=B7yW-@cBJKipcD^iQs)W_>P&zUz(I=xXn2cY1zjXR;nW-WnHNR(=h$@SmZ)18 z5dQvJtY$>;s|yW)`zYS$Pss@mZY}UzFCx2xZiz?~Q5$fr(0k`GFP?6io7LY0{wpkd zZ#F6Q1Q8HAu3)fi1*QsPI=>GT@m`>o)gP!?hxE^ds?nw%<>6czOg3G&j)jAd*eG71 z1-!)}n7E_Pjp&RMU;Tg@4O6BqZNc?SPUWs|c3kkRaITqtw%X+0Gd0vu6SC?y?T=<7 zf&!LxKhoqqREe{+qfzdKBREB`V&Q64?^kRhT}m!AT8A_&)<_IFUzlq3#)<16YtQSh zvsO()O#zOI+VpD%dT~0_6!{}@{G*y8BP|V27*GBQ)zTH`T0i6$q+vdTxFopWyz0T% zNh^w14K1U!2K9BMip4^~%TL}LyVCS?e6l+y4r;MKKw=xqLl?M(jhTc72n`@0yIBT) zacmx-7St#guPt61H|iqV_HAjWZ6icZtAekfvLv(v-@34fH{MJ~oZ11@?@rI^&r-D( zuQY`Ao3y=N=Xpz@nlj$LDKb`;q`D&undTyX#~=Yr{h}CF!?T<>|GL2%lvk0S?#+zW z%da~Usw{07)p{z&FbCGDH)rb@;O<=eqceJ(mHsv zvMf_ds$W>IRZd||-!EPmbqJNFI`~V+f}F6>`&{6gMm}^Oa&ykKm{Szdl3k*YX&DU4Hltbui_rI^Dg`nq?~Eq z29U2SxoE-a(47>93TMv*(_jZS9$g*`M8|}UvRwO|yICf{H9(^pN}6x!{eU!X!biTd zY*kHa!!;3o{4zaKTw9H$5O=WYl;NGTOgvoA0z%^?Mk?+i@ z-JiU566aJcsI{>vR|X5`JydgyBU6!F1)77*CP0f(0^gM5_p+1k8!()-$!xjuTBIg7 zfGpOepE$SYM%HfB#+B;yZA|e}4W{OaGu|Tl&YSy#GhfRCM+uQ3p|w_?vIDrUOO@ip z7nq+%me9%g8L>@DeoQZS+^&l7@cAbma%*CS=leQ~m{*Vz);#_7W(B_X)egyS7NNz! z%Lwh6;L!Ox*GUZ@s59;0q4>Cv3FRJ~5aQjNu&v5U`i@D{rKU1E zdRD2yz%oS*1}A!-D3fRqnlG-!Fw9!)Z)Cn4jKjk>CHlF*BCR*i2VQ!39L6k1K0pIx zQ#6G6j+_dA+UKTDJLw;I1@h(sxZGd(xj!M5tSkvucMPWvNiFgtUPK21nmjElX^hKE z_Lp`=*a&PbRVbL>#N;cDspG_iD;6=}xm!m5b^x^Ag)^vDr(E^wf2jN8s(!$Nn}uC} zac2>4LkSgTzNiUy^e(^z8ir4IP7m(kxO1wFcMhikYU*ch+)}S{I3XP#Rduv! z>+mTFZnXTF1s6?hZcsl2er+mH^=*r$*(2~U3Mm-v4Az%9iIP>>FBbg2JDsQr%@*sh zoPpU;-jffNXjcAtf0b{ezi1cDb}-7(Hx-)K$eNHSKvg)nxv&byDn$O&{FjQ(-@Wxe z7Iqi9&pMVD&h6nJWwA5(COhi<%4AAf1`c{(&hn-Fz`98pe51f>NljSsUSPW6l~nWRB@Hr{U4tOszVFn9SUhB!2SWN1s&-%cG3;lA?-A3a+rji`yi<~sUk5jn*_NK` z+a&T&aoEcG{H^I0VIdXY8K#>de>vSoLwHUu*r^7tw{@788x65Cb^>t0rAW z7VXy+?n^loXCSgJ^*ww-#Q-l9uv~ZK76>x*1JB(}V4mIdjh5)?XNBB?deaR^(hRVQ zJ!<0->!(=J{D|dePT1ixGe3QTR)v|J3oyvvCEVdM6_eoe1};?N(~(eko|B-i@freq z@AcYAMrNNCjXvJ1k6TbIoRzTDuJ*{j5FcO^K4>L5XG~kdyzp8Wu12j(f)$bY9Hu~- zWo8=pTmJ5}&3H;*N^XFHlMPONqKm*3!{Ptr$Ol%(mUQ3Yeq7kIyilVZY5_tc8Hfr( zC3VL8NoO8`(C~^Gsq!>PV24_7pQZy-)Bk4(0T@lh(t7&Gg--_8H76kV5GT4ne0vCtCC((>^lQn!s1O{vj=Q-DqIwnqNq?kTxSO@?^*}9SlGn2oCD;xhzav z0eVsPC^m8H`K_7LV?ESjj`?7QLL1eDfhm>~#-0bKTN^FMBtnfDJ7$cx*pr~%ev9=2 z*CO7~$#Zubui0QXQPu~s7XFfzXDtA|HZ<$kdCa}E+Z$($4pi=KZ8yxc*sSUZxLxq! z&9Y-Wb7aveymd)9OnI_0#iYzL!3kYZb@uc8xw0-I3HTm_y>2_$Aji8?3iK`%fqN6S zI2T(=Bb857A*u~mxL?0VGcWvtWquB|GxwBZJK&{G!JA_4ORLS7ITykjNv zXd0t>*7~>M(Yc2O=vFtN+xnJx?b8D+P$#v$K=QIuKdWbLcA*w>?s=O7bOxKzbN^s@ zkMT)KH`Z(#58R%)edFs!^|Mc!YJ6F!N)vI3L0=!Sk){4xJ=?mg{>A{-WZLx`h*mHY z)m!L}%sPanYTey>=TL;_I47uf5cTT8k%ynES(DzeLLZ&TYRN9eSnTq#=3pLroXsxz zhjJuHe?HjkxozV9rmM+T9p+oa+j;>{*&|v(t+uUelaWpfgDfjz1%827| z@_7xR00FGeGB}FYY#4reDiMY;gP9WO1n?=6eSMJeZt^g)RlM5d_)=WLJpSI=>a`xW z@Xx`cVY{ofRRihlI|-{Otj!ryxL&>y4Y54nLLIaQ0VSv5V`$}OdYQqv&gF0gN?-F7 z@EOTabjx!|h+Fr?W{>Li)h6OoKjfVfR@m%P=cfr|a_xH9FB^g6kHoyClhaLTYVJaK zw6EY?BkC?njS0`uk_CCG`qgb*2g)NOtg72Na?d@NS5jwzY!u?Ic<$ z+RtG7?CIG0Y+vzzYF3csiRfVq?zYI*x|QWV2aSXrUD`Z@#$Tk?p|FkfNc07m;+y=q z<?yc1Ue5-U#!l#OHO> z4@YFbEU?daA05I@eXO;Wb?~PmS4q{;4 zV0_~H!cxmwU0l41&Nd=iij(kUmrHkzPV&z0@8~l~6r)73(RtBpq z71y8}c@T{L`uA_Q=SFd*$}>W2N>c0RYii zd!FLGT*el(R#F3Sl@*p)D2G;E9=>+U!lJ-Xd}ElC~- z&S?gXkhlfbs>e@?0SJ2O-=L>a^Kz5I?*tM;1lm$rRjos{?~sbBW`unP*uZn!se~G7 zV&*WuHuYFjQ4yxO`YNzw4xD5mEk9!wk9g~|Ga1ON(J|G6NHYh|jj4WcB+W38Z+cObQWxSBB8R6@7Ug(}*yCUVTDt(=6b(0DegCNFq2f{|aK|!~1 zi_T(9KYLgzCMT7Bw|tDB&bj-S+E7m&*VTv z7NuZ)s5g>bL_=DraBx<9Cj6VKOZLPY)*uGrCV|ENkrx3NyxCkid#hTW1^8Ya`5b)m z)E}-F`OtoXvtprjqX!{St-rjR>uEpY;E*KfSFL%( z;kT)oj(%uc^WAMJrz7E5iF?2H(Qw)>N(M+1g>Mv@UEoi-z%QOaF5g%e=d`H2wO5sB0w(iD4CeOfOdFfpGj9L6<$r*#s{r3muBQIZ!V(w#z^E>@dkgDKe;k>P+?@iRXA;9THvia6X^ubN>WIR*@*I5_=(nW5%E2XscQV z4V;U(x*3QAN#*A9zB?C?h?RH7&sQ!5X8wH4{R2)FT$(E6f|U1Qm^mrb?_!~invS6j zpJwQR}#V#W&0f$-O}qM_c?S^mM@)Z38K2sJy?{qz^5>mG9FL z^<`KQV@%P2{ii`z+(~S&9RTA;BR zZc9|xTwEb07Sm`ca%YmEjP^0LflaohQoEg17%t7OW9&uwc+Rqc&Pj@*OOab1YQ8AR ziDw^ISzkD_S10q#)CKf(ES$)IhRAIwYK_JN8|0^c9AXqR&|4D&EymT zWYmuf#Ma;Z?>|nScEIV0n_#rsFd7DmO8JYyvKfi+a*VRy(KE#1W-CnefCl|(yBivr zN>lPffp-2J1l60C8XUEG6x5 ziv)25!CS`IFhyx~ulcOTf99g$S1Fu#A~wvaR1^*gF08uAlSs_Kp@uNg)h0@J6_|9_ z7mdVWMjau0>SIHDNNT(nZJ~I9ASR6*%n5wb?g#F+#I+0IyM-z)fjyi8Mn|KPl*jPre^GuntVSH#+epGs z5)yWo8Z29o8Mg8inUNybu1E&;qj9K;I%YINRbYUFl+N&P_(wFCq2OzI-o80qt?FrR zH4A*j0vi#L+(%U6Dm_j2ad}-ko7>J2(#8qTOa}4)VQwW129!0P*}vYQhF_Vf7J3k|bwXJ!=B4`@8RL_uS@h zwT)XuCz2}SuMDFV1Y5Fb}|1bs8iC+};yssXDtJn!K`W&J` zd87`7fYRWY773$kxWB9H5oI8TZ|;EanAi;~!rJMk%L%?+Oy$3hWxlvBbxeIzUh^2i zH#|A74*ChA9^)Us(;}iO%mPq_LMU+JyM!k)(hiJeHg$9B%630Vy!;}-@$Ln#7&s>J zf?t1V)SN(U`cYc(h#v#IJt7`u!E_2HMV9!vmPSRQW%%1zlcCG#jG@$giN0@a^;+%> zhCJmWReg-cc1>{4s$YQpv9rS2zLZIhzw}4^fh>m%&X6I9%*M;$^l@{9JQ=9UpROC1yPkU5>ZI7~NJejQcHS7+Ta(7L&1G8@ zO?l`IvO3%WlHqX*@}qTJilv$psi|g2z}})qid)Q zfv{~TwA{?BY7@Ai#NWgzYh7cSS!he&C+HZAl$RXJyfMmbYwh}=p= z+FmBu)kGRVh{o6nPj5F$&?O}0)!j#qQYz6{;7W!nxkN4j*O0){tCQ?mmdi1J#Z&5p zG`keh&pz?&XYS^r35W>R-JrZ&eKlLh#osYnb_hBy5$s{oy7R0ai;3MhOXrf$r>+kLxNx*aHikyj*K2+7 zx)TbCJeoF)^Z2QNWo1j0!NWjzE2QnJ;KAxg=(_2}8d+>$54ZnM)ayb#X4J86qpwm4 ze8h&WU14-_IyC1Sr!=xgmRH=ZQFUwQu;UL+65)}Wwj)yDadUAd0P0Y65w=Zyw3*deNOaPA^TF?ee?A{;s zBDa+AS)7u6I|fgM8c)T7$jh z$*2z8%^_GBi)h*A_vMcXnQ;ymt`v*h(?#nR2)Gau^LmB4vC5|58P29G*)$0Tdn=lxUz3O}wO=I5=W@E9pk%#2+g^X5XCskVK)N&23P`?1 zT_EvtDbVkdWI~(GztJe-r=9I=Kz}{$ju=LX}_-;q9G3jmdIwWT}1|gyd{QI zshn4OpT#k_`QUa8>y2&;Z`W$(5E`bys&{uY(OY#P5DKm!0AK znzBTf4`8(w0<*e5c~Oa&8;_AiW+axN$5-G)G+(wb;mri<$bmdLC07va`kQ^F*?_2B zxR3bLtm%8MPgG4&-Vg7#qispG#76PqwV98hk1`X?ZaFO}d_thMxTl-LZBfGuW2^G@ zywjoy{r|TEZN9b;1b0zX^Zlm(HP<$^x|;Db0S+~_%pf1Wd`vl}k!>WNk(iF+k6WMw z*<--kUHU&!c(&%GSoG7bY2LVYf%stI~7-8FRk6N6l3qI?_K zE#AK_5z0-Otvg>UODB@v??GO^mf%ZrsSb0|ff%_@t{+{z^0#HC5`~^H;2iECLlWGi zxa_Jaul}?)j4=#953OjN*x0!bMD3g=zZVmC5ByA<$+t2kxYAf`a0GKo)A0XncNmqd z=YDtlEIIO;kQY?7wqZ$CrC*NweB$4f0`{?PQjXBkyixP;#Zce_Mdd^YQ4l|a-Ya2N zAQ1vpx7`m$d7`>_3xYtRq|k zq1#OZ-Caz&!V)+2KA`umxDr~I^W6@T!?DvBCl;RBhHG zIx-{{8pC^Gaar7)6ocm-`4<#)ab|$8FJ7U8luqT-j^aA^cFRq}D4Za~@s z9c9)7WAaE4o#-YFiYVX^5;qvNr4z-CEF5TePs_gl&~AoyI$&vS-mZY47r>3&`ago# ze`BPB^z;#JokJ9wF!OfA1Oaaj^OYup3oM@r@-kw9MTCNq-1yNvU?;*%FLS+ZV!q&s z`f0W*V>ZK`y%65wg}`^DNL{O#)E(j3dT<~R68t(LX~?vuJGIVQkiFhUdm^gmLT(PX zEf`=vKk50y^EbQU7{(M$QdUn$PtQ{VydL%m#kx|q(!(omN(#Z60>2zac+Nnx+rqZu1#`Ql*Kd-@w9E;m1ZMN$XvwHIpoaW#~NWc zAWH;C>n~!lZRSzm;~V#;?(2_sF#YCXAt2e@)-7o!=PCpA$g2a5<+0RJ?3g?=96jWn zKO1=rY>dZJ+=S&y71HbCxdt41K(`zfTcLfJ&?AuCDlT08DojAsUEfX|wsrVtg6Z6I zr9{0X}mN42wME`wWU&!kJ1o6f8*0udjGrl9Jk1;WHaE_R#WkbP0VBr+!E9zBz_!Zbc7K9-?YZil z>Mqvz^qFVW^S2MmsJIp2U~HRcYCeW~!Hp9-96%V!iij&ojD{X#XIp+M%p2mYq=LSw zhWVAroGW^r6ieLL;2e{g5mpdFK=62x zr+R8I)j;cvm~5hkvMkYhi16LXF4T8tQD>+RBJ#b-b|@|TUhP?-$hL_a>%Q&pF8b4; z($Zq}JE~ffpgh30wX$=^$2v|io*{ZANqV*-%ZV&LP1yh<{SV&A`d`X?rDjmrmw+8` zBTiVIF}s-5E*i1L?*#6&4Kb-UH9W0LPR2;+6W*R_bk$E#K`i6ep1x02e(-H^5MBy?yC&rg z@g;h`8rseA4>`t@4zqZ6rkSg^WT4K3%ydDxD|dK*4!OFna-8)^C+pF0n*h~$TT=Sj zI>wfX*>Gv&l?~g*63W11sM(&nr=bpSyQ@N_*u{I4 z$RQv`5%zyhEmsSMj<4P0cnEwQJlMyX*G94%&U2t12G~A%xonsKhn}suexT6SC@7_+ ztz1H&avxuRR@4f62kLegLe;WjMMvnghz_e971Sa(3jKJ;F3yhK1odb<1>EVwxo4*ke`)Vm(Ff4bQ zVBF?xo|9~I6D|wG!nTp1z2F?WqH)lySK>;*MIIrN#b?Gy?dYL5F0d!)&~f~7y_zD_ zqn`?=kN0QFQVRxAT)J`~$S0fY&KY~CLA*EM2Egfuk zBg82D=s5I_zDU34h|1&-bV8@i6!0SPe7cDX{_hSvIe1bX@D&s)im}$A#c{G;&0A3A z3U!(127ArB0N|y*PEteX%0`X=ooW|0WqRnIUa{5wbfQq6HX~-y9lg1_ zBH5>te9O=Lcs!kI+7Cjk5m>a53YHc&t<{Z%f()oP<|_hxnXMh9I4Fseof&1@*p60> z95Y1BpBK;hA(di~tQ2DI@E#F909X-%PeC+iTv~o738i=`t}XxxCQUZaY}Pl!2#lqc zq+_xOTY5?>7t*WIz_7Z+-7C#QheHkNc>O7K2xni9-^q0a zV*fZ9*vD4KNPPvN{{)Lbnxe3kHrUd{R5?ijQxC$Fn82oSo*6;7EkFk0MRasc3=Lmc>LLuRq6Sp9*l7%9ma z@0+FoVG$ z3z0u8-|G5AS+Q8`=~XpAlv(SaslQcVA+mpv7CuYyEG;gEwS&uou7%>!WiNzx$#PK) z9fnWNy)52RI`#0&da%L{B!Qn?hO_gEfShA!_$5-qZ5n05c^*WyVXY0d$-Her}_@}&#Fs)jt27;$aMwR*-jnVRNyqy_qx(QUPj-T z$@unq^6|%x&9o^1iS@3bM( zX}+IrxKven^Z}=YdPyWgl_m>Q%Ngm^lSbpKJ@i``AkOq!T3jny-nLXUuVyNrr*gpNNHtyOz`7SoWW z+7H%^x`!=us}xfjo#63uo2@k6C;LBBwA)vECDuJp6-KjUOE3;lvv1#$!-CSU^Vpvz zXK%3$S!Zw=ZMZNK#5K+tVteZeqJ~_;Pr=MH?<5c(z1e3qcC!K$?@W{g!5o8jdvy|% zR=t7IXphsE!XvYD?le;!JVc8XqhHU9-ut#w2l$WEx_ZHYOL#|w;jB3}E+%OiyR^dY z{*gKRI<4~HQ*$X+L`nC{+5^h}%joWaLlGPnkBRID4u`0XED+(JqnInQ%G+&yNT=L% zLseR9P%pc3&2kv%QQQvZLYhnh>A|9FtFfyHzdMcgKkdzfe77zBF+lF7%z& zi9}rF#gk^!`{!V=PRfbeuYMlUSccQub5c$1C|Fy|0~{dSE51s5V;ut#voC%FM0EY7 zxW@pS@xZlwE!RIJ7ulsEBghbm>m^HKzF&@PptgeHEu84skRU=!6q}sP!iy+?Wj7q7 z;9hm-zHf9*$B#SZ(V39%r=AynAjJ~%W8L!waAC-iA%HUwyqn(w zdXZ%Zp%Ld7g+@#J5;rB*2C)kI=XnK4tdxlD^TFPn1`yg`U@dAq?KQV;zbL7Gozv?l?&>o(}KO%#PJVFU3wC|YN31Gfw>!^0L-D-h| zgrUo()svjy#yO`U?ckvB_2hoeQaIgCdHlXyBxLbU(#BJ`sOi{uI5yY6#z)ff#~7mf z^_t>xG1Ovf&_fH+xB64qcOJr(*QRVzTbyvV^E~k`0H>p7JYDjAy&-v^q2<7tUmB6* zieMCt9zBPia7WF)rl@)iTz)^Gwsl}P<^|p zUyP&vg7qp$wox;PXJq~?f5X`+Ksb}EJoy940UvpLP-nB1OvGrN*kQss+i0(DB&%qL zpvt`hM2S*{*kS@FN3O?1m|{`h2V(3qDD=_9nPH1^#{~d~atsJ`WWRccxi4+75 zQNO~89yEh=lxNUZgKPCY!B|wpKzUNV{x&&}n!D>$v_rk4-}s!r&UE2!Q^5Asy!(Xb zqHahb4d;T9$wCAgaOryjuMDry3HMMAT*3{Bo23# zXkB({Z84Kd<^yq!j}cn4#jBlPqe!)bR#WR+L+`{F@cuVYI}+!7-bIM->f`ir6)3W} zF}86w->yKhwgO!}?SB!*lIeY-eDAU5wU6~+P}F#=-kgCs0!I=zq{M!dZjD%^xVyG)zXI)Q;3ZmHkf)np zXb#OI{;?@_jc}qR@L9=nY2Zazph%N_v1`WMCrg#nwZo0?tS#WXu>=Z!;90Gy(QIj!SGh;{e?U1 z)rBVMls%4u>ABCNhp8oz^6RAJ^r| zR&1HYAx9K5ezm6C)q9Q5c}|u-V-Dv8jS)*L(U-ZinezbAP4UE{SzP>o@EKx*?1o13 z+egeeXLG(Kd0aI0M;(ttt2N^}gVba;rtn^bmUM;4VujRzn*$eQ);;Q(0|BDgPk5TTvU&*Q!ne;} z&GQR3VPXJZ-Tr|oGI1W>d{-=O`L)6bU6A{#lGh$a;{i5^oK+be+*s_ln;Qy?yzwv> zVBlV|>aHXmTI$&Q3&5?jO@s423%Se%KhNnuQw6G7Qu_>Yj`!?6U198t7dLklhfU5n zKiO&@Y=Xzr#XmkVPD3lNiRY0%)Jo z28Mi8LR$YHp9JjMy_KQ-8Z&rhEEQCn$NLS{$Kwg5xpu1|XNwUTEF9Qa6WgIzxi=0$ zvS;PKRF9y`a&JPnWN~TTN04_7AlO77#cUk@#Vkd|kaO_eA)&%TH!>g#oagAKLU~cW z^;Uk2MRvsReGLx3^rGXAqivcm5hiyQG~U6iogTzI3Pg{HeU@;rJ_S4XQq`DlZXYLY z8Xo;h0`XWPmv6QAoCYeDk@i&1*Bmt6s)8!a@tl$ zG$MJR#isU7BH6e6yc5!paLc?T4}5nw@;icuZI$BQ@i_|{+|}qIW`|JL_0>o|1Cc&} z%4V{FR`6q&IQWfumV6T)4r-bwJ3?*S=p}d^KhD?bXuwpgJ~)R9*on&b9a09GSy{IP zpTcgy`~)F*91#WW7z;QrA?c!hoXg!oxqXn}gbY$c4}meF7}|%-C1mFB#sMDBn z<6gRV9|@}N*C9Ydb^0^}rG3Q2$+DS!X`$l0RR#q1M8F1ymkKD*aKQCxM@I>l^7oMd z#3n27gT88_he>vK0b<+i<@9tz>NzKvca%>h1PJYS%re!33O=wi0BDNJt~=2|9i|r< zSfp>z3<}MErRK4nCB-+{T z^O#TUpz`E)vo@SIy(J>C3|)w{lAk^L_D>>H-j`VkXPtGCqZD%*TuJT)2X0(l<~iZM zq9d_d?e45}FOEn?M%ECRNfQ`q#~f@E+saT9luB#NCMU<#Nq+D6@2-;uyW_vO+d!Z_ z!5Y@+|9W(quZ0EcmxplcRW`JNCCVHHtkPz#VltT&Bh=pQYhG>e;*F>%RoYh-5%zRe z@!ol+>T+)$wdU#zwFD`2I<`94p>2P3vM)7KXl_aY(#kX7*qC0;bz)%KEU5ft1r>?j zLPCx2#0kz(M!mOws}1|`YUVVbH*^+%k>}&2Iug+y5+&NylD?aF zGG(VyKMYV@|4TmZs(T}FS>$@(T&Yxp$F@Orm&Tx^rMR6uC}B0ntF6C@$q{OT%c~W^ zTu1P*U`X{&r8e^Z)z;h9wuh73?TMF&)JD1C2nBxUsDWuBG`Ah%O=I&&l@@^m=A&gb z-~f62_nU56c(7uYm*JgFVZ9HIV{CR}=!q~TTrt3zO&Si9yZ@ZH0anCesCG45EpGRv zcgwG&APeYT!P~~TB-T4;QkJfrcR|VJwHz7BsU@*iCnXOPz9by znYOsnqm?6_G$}3~3eJ0%m05#ExjHVLKoKG7HZOu>1X&LccpSKYHrN{OElX>?GC*Gl zpEw4|GuQQK5j=!Z;G!yDE+VH)mAL=iH@a;&SHZmyRRQL)9ni~&^ftOowg8BpFnT|(a~G50M3M$vhdBYeP4so^8uq!F8s!^nQYoZ&{}9wejJb8qxnQMdx_yi ztaivNoVkEoq5#|zM21Um>2nP4Oty@z{TdV^woR>_hW9~5C#(0QEDLD0Ye>*q=yGgU zPjJn)jKVA(#>5eJ%LO{RB<}T0&h4phMLS-p3tYPBVIe(fEZ^%wWp2RyWsgyD=1Gp1 z6OojH>j_B!9q> zGvhkPkR*UkVz+;bwy4a5&v)ewrL%wB6-yvcc$_P5WBu%TQSbhrvk*Zgf<#|SZBzRw zbZ;FbrDjfgBi_7=g?;HENBXDWy{Vg5rwJL|r$; zlpLdQ5xvLclr7M-0+Xk%x~X*`fg&NLP)2K0VnjI_2T`V9@-C5$upk?!6`f)cI?~|Z zG8AWFJ!RmIUs}1eDIjOV1%t>>+O@519MmcLyU1Q!7T4!hPqv-;Q{2)QE@PvzK6Ijs zV(6jt>$s+qP{ptGa?(=xh&JolMQq`a(BIP&d$tyW#Uld)M?dE?xC9=`XN#A&TX-hl z35V@JwpYyt=N~oZ*apZ2Jal0D)W{9(#jKf(KXCinD!A00(M39MP^*8L&Z(J7L!x@} zD9Z^|q5NhGghW+>?~!bIuUy4`6HTXgamZC$r@t5PmaW%IeXo8{$45cSH<7-3(5~7~ z{3Ku*@cL9=6x}_sRGFEPJO2w;G{hiR()rCQa?tHsi0YqLSIMV>BwKcvsZqGNRr6m}R=lPJQt^P`G`a!B#Pju3wyS10cbW3Vz!QApRJ* zuo`TQe5dLh-YkELU?g6@v@}V|EdKG`?$rs$+i7#9D{b07Nrk z_XPeK9ISJS!RQ0b)f1^{qgkE4_UU5LYXFIjMx#!Gk@wg_(Z9fJ3}Juk)y{qP6&LV? zzJGfMI&iiHoO^={O5|UV#Y|m25hl%9uw;D7ttS1}FBcirvQHI0M3`rvYZ54oM;W4% zaF$RZyU3CVqFa1=iQ8hzec`azT|Z%94;=SK)%`Hh1!{+h%|>aE?H#TLXbRgP8Y9lR z&@%Bbe!Qm28aYWfC&)h?I)*);lTYMyH<^zKAbkJOXAU_fg@@!8sUgyLaCS~>^l!M7 zHy=YpAK?z$TYr>+oTdL56)7AHR&XQ$Y+5ayt88Xv+9<@v=x0{dyGTt{pzO2^Nh@tT zFk+3##5g}`&`f*e?kt_(R{|_TOW6^(D-Fn0__S9n$8*2R`=R|jKBKMt z5cg#4PcGrhKZ-qv`g6bfUgnxu+e4;_#2uI?va{5urJON|B9roT2VQTxL)}x$ZLB|* z!}Sh>^!nzi9pbYOM=MDd|K2xWE0J4c6c$7>qjOT8A!0OI>AkLx>xFfkDg`@0czG%R}rm4TtKaQnN1;1*b z$*j9PRR-6j9Xf-7JGAAEeRE~^Av#pPT#rWOX!!S{Kn49O;?+V76SVLLoe#C^-B_fb zyMXaKTN*N?WU6LzyBQM1@m8+=HyC{QFqMq2dRPBsjc zyOQWcRuCKegQyx9YYRN>zcAi7*Yr>a(GHRH<6^9C6e0@Z@I%BB5!%7oedf}xe{ywM zw!zGdq7@&4m3xu-O<1ulN~`N8?n$pR;N_ud&uI9+x%%Tf2%*$V6R$wy?S|=E) zRaO<}GO;w#38o$n=kSnsoUyvz{O`;?!Nrb9%HX-7aM|>xIMp3?^3k!HWaAdUnK zS?4cDO3=U7S_OODmn4yJ(ihLDL9`%{?YgW3#w$YfmlnsQO!7ko`UuT$D;&VGvPz+R z#sCCbrGkXHrroT^8<5!~s#-Zy|IE4T;6B?$zj&Ji&DmSF57el?nciVg>L^buX2dna z%%E_B3JMyIMNvFW2!PKt%wyMx+4GosJ(G+14JatJd+sw$e&>m_X17fcTMa9a^ayHa z^-XHO*&N^#xo)mO1JOxWSbJ%#R#VEqBy`D1|-OshV+7mPAA*0u%btcgTLkgE_pY;tM-U zwV0FuuxLBeF)3|__1pJNEKbDAR65O#DRJ`TAr^H2fQ`{X6Rl8;9N_T)qr7awR6;Y`b z>6YY*`h!m)We0vL-1rR*Ls-kHiY44eogZb~6ph>ieCL4F!u}NiYb?{kUB_vDHi@FH zzS0m~LE=ev?5+C~-& z-InGK{o&}A{M7%0g8FLjz7vuroPYciZ`k=L$oK0>#kMm!8`$IUUE~<{nrQ25`C#R3 z#a9Nypr)>;#d8k}_5;Jue#Q3a4-BTEj}x%Yw(we*R&7JQyxn8mx#mlmSgGt4_^^=g@-cb zybG~-1;bl4kNFXUN_5RXrB;fi0=OG#1H^}pW z%iKBq`Z+ZEMP5Wuh6NNO#RzA|IP3@OSB^sttq)9Mx=DE*wK8Y%{)a^_v%lY$0SS2p zls$9%9eELmQfLG7YoV&_)@Dj?>|jlGA_9auFKp?tjvdShTbM@xQ9jIgS2jy7$~o_d zwR`e=X;}SmJ(e?2B&&svFqpL&d)Rf3e|79n-r2Tbuf)48QfvQzfhn)>#@L?n_zI@5 z!iHG08J7QD?8Jay9--1BBMwqSGL{08m&sCkyNtHk`m7v51-J*TVPr{eRV@WNW9X~PvzN(g?se=nlLFfpP*ttm7-sQB_8>SB!Z8?XJ&)xI?zIUz(BJ1 zCCaYkZ;T_GIVB4s&u)D1&`KKEDg%}|8$$1EZ|`=_@v{|+5~U%&zs!tG)d>iPzj$p3PGG|o;&jJZ^y|EW&?sG{$LaH zs{a(?-?EF<6Q27lqlwNXd5Cs%!i}pg+Zz;c76PJbWb-r5am4;OuU3%?fnvHh%byt= zmz;aPmKwABCn5|p;^=~WgG}od<*(#)sp3V|Oci1X9HZQyxy*^-UHvEmYx;HtHev^s z6F74)4o=Tm8q5=$pE+Vqm?1mbeD3vYwNecHkMShh5jJYq{^9#uiOS|If>3GZZbcT7 zufoCrwW-F=T3T5nh5&)v!`cFm+l(4#UXTQ@0|S$(6Tq;sej}Lfl(*jSF7j1>KfbY- z9@U)z>EU%bt++1m$tLq%oEne8ZZUE}%QFDs4SvRX&_$@qLVD|4v0sP?P72Whs3zTh zwfSck0F)MsFL!~0{JQ!)wuAAk4XTFRaZUbZRW2e`U17y%9G0@`SBNBdAAujcJ6X-ygcB+WTejdt?U4F&?nx8_pJ(s@{zx%rf=r_p=INXb z-Y8?l=D-A}tN4*>61q~|><2-pz-0uVqB&}Q zh7fvLB4E)ZRxI59#@;uMO)?GX0Bx%@W!{Jm0@jx2(P?fjotKNSe3fdB$ZDD~E0(Hv z0cK`6UX4$URYD;AF{tTQhj;a=sGAm z+$wr%QkV42y)-QYfIz&L<7E@m&2MZkGi{b)DA%O=OMzedlE@3{S8XX@_q{OQ_=$&$10nR9z1l3?jcf6IyIF@FQ5f=Tmg$s<^} zS7o-3rM-t7K%cxi1oV*wzgxw@ z7|WfLi7Rcrb3_~mF|va>U-$csP7++@X$#aSaX)D7E>R~NVsc^?v&#yYIzJ5DN8vq3 zNE*QWbBszzq`qs=y72eSN1#3_VV#`W;h(oKg3*L=>_+oL*BSt7sGNfQP|8E6Pf1Pl z%5k*$@LP1QFGwtLC%ofkb#Rk$JCDaLGdEVb3~#zq^gNq7(y#s>5v2A?5U}2(VbJ`d zIR``k`k)Ewq-8M≈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

*4YqUt5FEykS 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..376e0ef034cadb0aedb54992107591449382779c GIT binary patch literal 17136 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 O&kgK1t=P#jF^|7LH4Kyh literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.mq5 new file mode 100644 index 0000000..ac19757 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Smapls/atrstoploss_ind.mq5 @@ -0,0 +1,675 @@ +//+------------------------------------------------------------------+ +//| ATRStopLoss_Ind.mq5 | +//| Rosh Jardine | +//| https://roshjardine.com | +//+------------------------------------------------------------------+ +#property copyright "Rosh Jardine (MQL5/MQL4)" +#property link "https://roshjardine.com" +#property version "1.00" +#property description "Based on https://www.mql5.com/en/forum/349885 , this indicator will draw ATR based stop loss calculation with adjustable multiplier and ATR period." +#property description "This indicator includes helper functions and example to run calculation via function call so the calculation logic can be placed in external include file" +#property indicator_chart_window + +#property indicator_buffers 5 +#property indicator_plots 2 +#property indicator_type1 DRAW_LINE +#property indicator_color1 Orchid +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 +#property indicator_type2 DRAW_LINE +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 +#property indicator_color2 Blue +#property indicator_label1 "Up" +#property indicator_label2 "Dn" + + +//---- input parameters +input int Length=10; //how many look back periods to check the price +input int ATRperiod=10; +input double Kv=2.5; +//---- indicator buffers +double UpBuffer1[]; +double DnBuffer1[]; +double smin[]; +double smax[]; +double trend[]; + +int AtrHandle; +double AtrBfr[1]; +int bars_calculated; +string short_name; + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +int OnInit() + { + bars_calculated = 0; + + short_name="ATRStopLoss_Ind"; + AtrHandle = iATR(_Symbol,_Period,ATRperiod); + if(AtrHandle==INVALID_HANDLE) + { + return(INIT_FAILED); + } + ArrayInitialize(AtrBfr,EMPTY_VALUE); + SetIndexBuffer(0,UpBuffer1); + SetIndexBuffer(1,DnBuffer1); + SetIndexBuffer(2,smin); + SetIndexBuffer(3,smax); + SetIndexBuffer(4,trend); + IndicatorSetInteger(INDICATOR_DIGITS,Digits()); + IndicatorSetString(INDICATOR_SHORTNAME,short_name); + PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,Length); + PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,Length); + PlotIndexSetInteger(0,PLOT_SHIFT,0); + PlotIndexSetInteger(1,PLOT_SHIFT,0); + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) + { + int limit; + if(rates_total<=Length) + return(0); + if(prev_calculated<1) + { + /* + int shift; + ArrayInitialize(UpBuffer1,EMPTY_VALUE); + ArrayInitialize(DnBuffer1,EMPTY_VALUE); + ArrayInitialize(smin,EMPTY_VALUE); + ArrayInitialize(smax,EMPTY_VALUE); + ArrayInitialize(trend,EMPTY_VALUE); + ArraySetAsSeries(UpBuffer1,true); + ArraySetAsSeries(DnBuffer1,true); + ArraySetAsSeries(smin,true); + ArraySetAsSeries(smax,true); + ArraySetAsSeries(trend,true); + + limit = rates_total-Length-1; + + for (shift=limit;shift>=0;shift--) + { + smin[shift] = -100000; smax[shift] = 100000; + for(int i=Length-1;i>=0;i--) + { + int copybuffer = CopyBuffer(AtrHandle,0,shift+i,1,AtrBfr); + if (copybuffer<1) + { + StopIndicator(); + } + smin[shift] = MathMax( smin[shift], iHigh(_Symbol,_Period,shift+i) - Kv*AtrBfr[0]); + smax[shift] = MathMin( smax[shift], iLow(_Symbol,_Period,shift+i) + Kv*AtrBfr[0]); + } + trend[shift]= trend[shift+1]; + if ( iClose(_Symbol,_Period,shift) > smax[shift+1] ) + { + trend[shift] = 1; + } + if ( iClose(_Symbol,_Period,shift) < smin[shift+1] ) + { + trend[shift] = -1; + } + if ( trend[shift] >0 ) + { + if( smin[shift]smax[shift+1] ) smax[shift]=smax[shift+1]; + UpBuffer1[shift] = EMPTY_VALUE; + DnBuffer1[shift] = smax[shift]; + } + } + */ + limit = rates_total-Length-1; + if(!AtrStopFirstRun(limit,UpBuffer1,DnBuffer1,smin,smax,trend,AtrHandle,AtrBfr,Length,_Symbol,_Period,Kv)) + { + StopIndicator(); + } + bars_calculated = limit; + return(rates_total); + } + + + else + { + limit=prev_calculated-Length-1; + + if(limit>bars_calculated) + { + if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,AtrHandle,AtrBfr,Length,_Symbol,_Period,Kv,false)) + { + StopIndicator(); + } + bars_calculated +=1; + } + else + { + if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,AtrHandle,AtrBfr,Length,_Symbol,_Period,Kv,true)) + { + StopIndicator(); + } + } + /* + if (limit>bars_calculated) + { + ArrayResize(UpBuffer1,bars_calculated+1); + ArrayResize(DnBuffer1,bars_calculated+1); + ArrayResize(smin,bars_calculated+1); + ArrayResize(smax,bars_calculated+1); + ArrayResize(trend,bars_calculated+1); + UpBuffer1[0] = DnBuffer1[0]= smin[0] = smax[0] = trend[0] = EMPTY_VALUE; + bars_calculated +=1; + } + for(int j=0;j<=1;j++) + { + smin[j] = -100000; smax[j] = 100000; + for(int k=0;k<=Length-1;k++) + { + int copybuffer = CopyBuffer(AtrHandle,0,j+k,1,AtrBfr); + if (copybuffer<1) + { + StopIndicator(); + + } + smin[j] = MathMax( smin[j], iHigh(_Symbol,_Period,j+k) - Kv*AtrBfr[0]); + smax[j] = MathMin( smax[j], iLow(_Symbol,_Period,j+k) + Kv*AtrBfr[0]); + } + trend[j]= trend[j+1]; + if ( iClose(_Symbol,_Period,j) > smax[j+1] ) trend[j] = 1; + if ( iClose(_Symbol,_Period,j) < smin[j+1] ) trend[j] = -1; + + if ( trend[j] >0 ) + { + if( smin[j]smax[j+1] ) smax[j]=smax[j+1]; + UpBuffer1[j] = EMPTY_VALUE; + DnBuffer1[j] = smax[j]; + } + }*/ + return(rates_total); + } + } + +/************************************ AS HELPERS ************************************/ +bool AtrStopNextRun(int newlimit,double &upbfr[], + double &dnbfr[],double &min[], + double &max[],double &trd[],int &atrhandler, + double &atrbuffer[],int atrlength, + const string symbol,ENUM_TIMEFRAMES tframe, + double multiplier,bool samebar) + { + if(!samebar) + { + ArrayResize(upbfr,newlimit); + ArrayResize(dnbfr,newlimit); + ArrayResize(min,newlimit); + ArrayResize(max,newlimit); + ArrayResize(trd,newlimit); + upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE; + } + else + { + upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE; + } + for(int j=0; j<=1; j++) + { + min[j] = -100000; + max[j] = 100000; + for(int k=0; k<=atrlength-1; k++) + { + int copybuffer = CopyBuffer(atrhandler,0,j+k,1,atrbuffer); + if(copybuffer<1) + { + return(false); + } + min[j] = MathMax(smin[j], iHigh(symbol,tframe,j+k) - multiplier*AtrBfr[0]); + max[j] = MathMin(smax[j], iLow(symbol,tframe,j+k) + multiplier*AtrBfr[0]); + } + trd[j]= trd[j+1]; + if(iClose(symbol,tframe,j) > max[j+1]) + { + trd[j] = 1; + } + if(iClose(symbol,tframe,j) < min[j+1]) + { + trd[j] = -1; + } + if(trd[j] >0) + { + if(min[j]max[j+1]) + { + max[j]=max[j+1]; + } + upbfr[j] = EMPTY_VALUE; + dnbfr[j] = max[j]; + } + } + return(true); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool AtrStopFirstRun(int limit,double &upbfr[], + double &dnbfr[],double &min[], + double &max[],double &trd[],int &atrhandler, + double &atrbuffer[],int atrlength, + const string symbol,ENUM_TIMEFRAMES tframe, + double multiplier + ) + { + ArrayInitialize(upbfr,EMPTY_VALUE); + ArrayInitialize(dnbfr,EMPTY_VALUE); + ArrayInitialize(min,EMPTY_VALUE); + ArrayInitialize(max,EMPTY_VALUE); + ArrayInitialize(trd,EMPTY_VALUE); + ArraySetAsSeries(upbfr,true); + ArraySetAsSeries(dnbfr,true); + ArraySetAsSeries(min,true); + ArraySetAsSeries(max,true); + ArraySetAsSeries(trd,true); + int shift = 0; + for(shift=limit; shift>=0; shift--) + { + min[shift] = -100000; + max[shift] = 100000; + for(int i=atrlength-1; i>=0; i--) + { + int copybuffer = CopyBuffer(atrhandler,0,shift+i,1,atrbuffer); + if(copybuffer<1) + { + return(false); + } + min[shift] = MathMax(min[shift], iHigh(symbol,tframe,shift+i) - multiplier*atrbuffer[0]); + max[shift] = MathMin(max[shift], iLow(symbol,tframe,shift+i) + multiplier*atrbuffer[0]); + } + trd[shift] = trd[shift+1]; + if(iClose(symbol,tframe,shift) > max[shift+1]) + { + trd[shift] = 1; + } + if(iClose(symbol,tframe,shift) < min[shift+1]) + { + trd[shift] = -1; + } + if(trd[shift] >0) + { + if(min[shift]max[shift+1]) + { + max[shift] = max[shift+1]; + } + upbfr[shift] = EMPTY_VALUE; + dnbfr[shift] = max[shift]; + } + } + return(true); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void StopIndicator() + { + IndicatorRelease(AtrHandle); + ChartIndicatorDelete(ChartID(),0,short_name); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + if(AtrHandle!=INVALID_HANDLE) + IndicatorRelease(AtrHandle); + } + + +//--- +//--- MQL4 +//--- + +#ifdef __MQL4__ +#property indicator_buffers 2 +#property indicator_color1 Blue +#property indicator_color2 Red +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 +//---- input parameters +extern int Length=10; +extern int ATRperiod=10; +extern double Kv=2.5; +double UpBuffer1[]; +double DnBuffer1[]; +double smin[]; +double smax[]; +double trend[]; + +double AtrBfr[1]; +int bars_calculated; +string short_name; +int OnInit() + { + bars_calculated = 0; + + short_name="ATRStopLoss_Ind"; + SetIndexStyle(0,DRAW_LINE); + SetIndexStyle(1,DRAW_LINE); + IndicatorBuffers(5); + SetIndexBuffer(0,UpBuffer1); + SetIndexBuffer(1,DnBuffer1); + SetIndexBuffer(2,smin); + SetIndexBuffer(3,smax); + SetIndexBuffer(4,trend); + IndicatorShortName(short_name); + SetIndexLabel(0,"Up"); + SetIndexLabel(1,"Dn"); + SetIndexDrawBegin(0,Length); + SetIndexDrawBegin(1,Length); + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) + { + int limit; + if(rates_total<=Length) + { + return(0); + } + if(prev_calculated<1) + { + /* + int shift; + ArrayInitialize(UpBuffer1,EMPTY_VALUE); + ArrayInitialize(DnBuffer1,EMPTY_VALUE); + ArrayInitialize(smin,EMPTY_VALUE); + ArrayInitialize(smax,EMPTY_VALUE); + ArrayInitialize(trend,EMPTY_VALUE); + ArraySetAsSeries(UpBuffer1,true); + ArraySetAsSeries(DnBuffer1,true); + ArraySetAsSeries(smin,true); + ArraySetAsSeries(smax,true); + ArraySetAsSeries(trend,true); + limit = rates_total-Length-1; + for (shift=limit;shift>=0;shift--) + { + smin[shift] = -100000; + smax[shift] = 100000; + for(int i=Length-1;i>=0;i--) + { + smin[shift] = MathMax( smin[shift], iHigh(_Symbol,_Period,shift+i) - Kv*iATR(Symbol(),Period(),ATRperiod,shift+i)); + smax[shift] = MathMin( smax[shift], iLow(_Symbol,_Period,shift+i) + Kv*iATR(Symbol(),Period(),ATRperiod,shift+i)); + } + trend[shift]= trend[shift+1]; + if ( iClose(_Symbol,_Period,shift) > smax[shift+1] ) + { + trend[shift] = 1; + } + if ( iClose(_Symbol,_Period,shift) < smin[shift+1] ) + { + trend[shift] = -1; + } + if ( trend[shift] >0 ) + { + if( smin[shift]smax[shift+1] ) smax[shift]=smax[shift+1]; + UpBuffer1[shift] = EMPTY_VALUE; + DnBuffer1[shift] = smax[shift]; + } + } + */ + + /*** AS FUNCTION CALL EXAMPLE ***/ + + limit = rates_total-Length-1; + if(!AtrStopFirstRun(limit,UpBuffer1,DnBuffer1,smin,smax,trend,Length,Symbol(),Period(),Kv)) + { + return(0); + } + bars_calculated = limit; + return(rates_total); + } + else + { + limit = prev_calculated-Length-1; + /*** AS FUNCTION CALL EXAMPLE ***/ + if(limit>bars_calculated) + { + if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,Length,Symbol(),Period(),Kv,false)) + { + return(0); + } + } + if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,Length,Symbol(),Period(),Kv,true)) + { + return(0); + } + /* + if (limit>bars_calculated) + { + ArrayResize(UpBuffer1,bars_calculated+1); + ArrayResize(DnBuffer1,bars_calculated+1); + ArrayResize(smin,bars_calculated+1); + ArrayResize(smax,bars_calculated+1); + ArrayResize(trend,bars_calculated+1); + UpBuffer1[0] = DnBuffer1[0]= smin[0] = smax[0] = trend[0] = EMPTY_VALUE; + bars_calculated +=1; + } + for(int j=0;j<=1;j++) + { + smin[j] = -100000; + smax[j] = 100000; + for(int k=0;k<=Length-1;k++) + { + smin[j] = MathMax( smin[j], iHigh(Symbol(),Period(),j+k) - Kv*iATR(Symbol(),Period(),ATRperiod,j+k)); + smax[j] = MathMin( smax[j], iLow(Symbol(),Period(),j+k) + Kv*AtrBfr[0]); + } + trend[j]= trend[j+1]; + if ( iClose(Symbol(),Period(),j) > smax[j+1] ) trend[j] = 1; + if ( iClose(Symbol(),Period(),j) < smin[j+1] ) trend[j] = -1; + + if ( trend[j] >0 ) + { + if( smin[j]smax[j+1] ) smax[j]=smax[j+1]; + UpBuffer1[j] = EMPTY_VALUE; + DnBuffer1[j] = smax[j]; + } + } + */ + return(rates_total); + } + } + +/************************************ AS HELPERS ************************************/ + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool AtrStopFirstRun(int limit,double &upbfr[], + double &dnbfr[],double &min[], + double &max[],double &trd[],int atrlength, + const string symbol,const int tframe, + double multiplier + ) + { + ArrayInitialize(upbfr,EMPTY_VALUE); + ArrayInitialize(dnbfr,EMPTY_VALUE); + ArrayInitialize(min,EMPTY_VALUE); + ArrayInitialize(max,EMPTY_VALUE); + ArrayInitialize(trd,EMPTY_VALUE); + ArraySetAsSeries(upbfr,true); + ArraySetAsSeries(dnbfr,true); + ArraySetAsSeries(min,true); + ArraySetAsSeries(max,true); + ArraySetAsSeries(trd,true); + int shift = 0; + for(shift=limit; shift>=0; shift--) + { + min[shift] = -100000; + max[shift] = 100000; + for(int i=atrlength-1; i>=0; i--) + { + min[shift] = MathMax(min[shift], iHigh(symbol,tframe,shift+i) - multiplier*iATR(symbol,tframe,ATRperiod,shift+1)); + max[shift] = MathMin(max[shift], iLow(symbol,tframe,shift+i) + multiplier*iATR(symbol,tframe,ATRperiod,shift+1)); + } + trd[shift] = trd[shift+1]; + if(iClose(symbol,tframe,shift) > max[shift+1]) + { + trd[shift] = 1; + } + if(iClose(symbol,tframe,shift) < min[shift+1]) + { + trd[shift] = -1; + } + if(trd[shift] >0) + { + if(min[shift]max[shift+1]) + { + max[shift]= max[shift+1]; + } + upbfr[shift] = EMPTY_VALUE; + dnbfr[shift] = max[shift]; + } + } + return(true); + } + + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool AtrStopNextRun(int newlimit,double &upbfr[], + double &dnbfr[],double &min[], + double &max[],double &trd[],int atrlength, + const string symbol,const int tframe, + double multiplier,bool samebar) + { + if(!samebar) + { + ArrayResize(upbfr,newlimit); + ArrayResize(dnbfr,newlimit); + ArrayResize(min,newlimit); + ArrayResize(max,newlimit); + ArrayResize(trd,newlimit); + upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE; + } + else + { + upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE; + } + for(int j=0; j<=1; j++) + { + min[j] = -100000; + max[j] = 100000; + for(int k=0; k<=atrlength-1; k++) + { + min[j] = MathMax(smin[j], iHigh(symbol,tframe,j+k) - multiplier*iATR(symbol,tframe,ATRperiod,j+k)); + max[j] = MathMin(smax[j], iLow(symbol,tframe,j+k) + multiplier*iATR(symbol,tframe,ATRperiod,j+k)); + } + trd[j] = trd[j+1]; + if(iClose(symbol,tframe,j) > max[j+1]) + { + trd[j] = 1; + } + if(iClose(symbol,tframe,j) < min[j+1]) + { + trd[j] = -1; + } + if(trd[j] >0) + { + if(min[j]max[j+1]) + { + max[j] = max[j+1]; + } + upbfr[j] = EMPTY_VALUE; + dnbfr[j] = max[j]; + } + } + return(true); + } +#endif + +//+------------------------------------------------------------------+ diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/candle_time_end_and_spread.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/candle_time_end_and_spread.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..12a0b98743720e50de022d67cb9fa0c26ae3f21a GIT binary patch literal 13682 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%0Anl!itvh^PdmD}b2zf}t43M@JCs$1 z&%RmNVpwxQbGqlXvqw=ZMd!D3fU@P`G1WPqQcZN(nooO2g4t!=oXFRR9s^ERtGY7a zny|m@15~OdCVYWSYGycJ*TmaoZcR%$dcs7eiPGNhp%yQ+EBY2!-Um!U$~0|0mXIML zPm)v!y&w&mF3*vu$i>seXEZ!Fw(;1kCm~D6mG!~cK$AiqYNIt^peymOVrQ`0De$(} zR(uyCsTVUN6~n zJ-!<^%c3h6U02%aj=t*Za~j6zw@kYIvek&~_vqfKB*8O#huA!P_o8R;d+(M78w{J3 zu;`?Pgli8N=nZ;bKeQ+JlQ~v(E-j`1sEWddcyDQKKrR+@Ld3%;X%tqWE7_zkGFEnI zU^Q+>xz5+++FM0f>V`1Y;(E2Fi40g(l8S2G*s6nVs!W)qavERs>y(8Otp1}lHxZLF zoXUv16mP!kj^mt9R03V6Bawl!`{o)TbiUas&0{-aL8UANf)f?hqX2Uk7YZ`o0c(_A zzW6K5FtX@WkZ@;Q<~I9_2uEze037(6{Ec_Snn5L-WkH2qC2=czCq^EU#xakoK^yx> z^I&t;T}dO_89gQ=BB$ybAKA$Q$1B-|EPvby`d93@#Y9taix5a9Pht!#=BfxFTC~VmCFaEdvz%nTvi|z z&j$|wvo;FBMgc$)tna-0H4`Pr)Mu@Mu_L@zSK)kk*weRf)MEUZX&=$4H*aZ(zVC&G zcxt5pjkdLH0jE{!j?1*uph!`r3J3}3rd&|2!t zpt|-TluV3pLxHQr__~=DherTM#g&Z=J6S|bTfy>pb_ljnNa1elzU#clQ zajRI&y0F2&VK6`B8wzshoj&D{Vl!Ovpe03Ac-|~#dymMXCp_(6tqH-UHhjT}Z;{Ir zKLp_fo&WfNxU_5@zQ)g)Bma0ru!gU94=N_|#LAH(Hi?>|@Q=&4lw8&0>o$p$mWZ`3 zcp8E*DPm{^(*2X2?`$cja4f#+Tkz%9Cp`k>`(_2JjOE8H-^~*z_iHivK!k?di}W|ZpQ9ofjP@c1-LU%?-vw1>PE@DHv+4nzk4Bx7fw@HUSm?$+Vy47+PPuDUhBfym=0it`H zT1<~b+RIr@-w>R+?;eL0Ce5Rb7Z{g|H^9Y&tCz!=Fft*OZ&VP-X|@(SHXvK-PB088 zafGC<-3cXF4V2`RLRNMaN8+QXh7nxH0zrEyrC?paM1SDR_l&qlNDn(A1o#efBDhs5 z@86h5ve`!j;4euHMq17&=gY!?@ffsnJTDw-OG{XViwrTsaX*9zeQo3GSPhQCJJu|S z)h;<}g{d%vh3)O*0T|L7Lt7_*XEEXXBTCI^qC{EKSN_sn7|6eu15rF$o1a8wA9~`j z$9Tsf_NPQi-3bt*PmDRcGJq7YwER0M3!i+s&d*K^wg%KP^mV>%LM;3H2Ido@Jx%8h zGyM84QFnF;_>B@dD5cZklQ+^U$&nW?#KuCebh9n0G|Hr-2<;C@fQJJ9T3qyKtGUGq_ z5pT{_xeyt#w3Q3YDRYul@R0Bh`wtJyl$dMIt))rm(n_N%uso;J>{FT+BDz z0WgY6P0dBZJgP*ix1#Yyonz+?VoMFf{ho%f`$LLt!P4{yQ`ws_wA=>kSb4>(R)tf=HmJ@p{Yb?@gZV$|XpTbc`nhFE&XK<2)u9B%nfnXpm`vy39~ z7-K!1IBgzVw_E{#4}1TOqn&6s5+Ike&z#1ZX>k-8VCMIvl;e-10kSWW zA>y)P`{o2XIp)TSCpSeL@$y2ZjN3#G8rvy*(iJ5D8hCJAVE|OYClUKuW0%>W;>o@r z2mnQn(E$D6NFk)QZgIz(d$)A1HAD?#Wmas!LyZ)>zicj@NKEwzzVdGdFqPa}LKNOv z5PG3yG*dL9KGwLTZ{fo@r^c~cf;iadF;4jNWC$QMHmV;!dt5JM3xMPL`xtnyMLwb| zrya1JqC*Qa9D?s!ohZl9CM`v5M2p#}p-$A#SU}5~Si}gVLmoYI#-vPQyb59!O#FyO zRxxjD_u+dn^B0)C>s#!y&gWB_cYA`H-g43&P4qcj^TrQ^qZke^zzA87mXHLu0ow}; zo=b*)f-8aa8at}KbX>1pltaFEt=QnYwhPCD_9@wk!^a@-i6neo=fu);jh_FnNhpwUUmV<+Y1~JPDD~sYiggY?} z#F7JlA|lg<5Y?*Db}<`!>n-_#h8rkX!DxLOkQpoJ&4g$Bf#e@dhstkABeowN31mu@ zn68F7Ye#{LCVEjC{cE-JqtlubK?wh^Z-~Kru{e;mv<|A^oBbn|nM~w7*C0cpKodoV zg~X_RF`A`TyoN+eHA1Z~AMf{Y={^EtF?sxs_XaT9t$;MT`dCGD(2)8^WC?G(trZ$SWhEGsQvuU!jqs zc9SO>`yUc;c&glfK>_;N`u$X6<9QJJMWsS1o7&a9Q|0gzh+Ox?3NqF62R9%yCA6?6 ze$NSW<~RS*eoeWyrepcbzx|#d+g8B--GqsML3h$N>a)u-Skrz|lUnDh&9p=d?vzuwg3wshO9pX564svXYQjiE7+fmxHLo8^Xb4(di3Q}bBA4T$3> zuKuVKm@h(@h2y^>QI#xPI=uv*ETn=n_r6P=HhBQV1=nZTnN4S{u>{|PbuWSdJo!ji zA$sUq47e1SE$Dt|$ZQHUGi)h@7(Gi6efZ8SM%7CEk=4U>J{~JGI@|1*E;C#Xw09P5 zhf(QCK`qF#EHff_M)cwhXap_3dxZ%9@xQbm*%^G9y!SbfIXz!EH;j|SLM-^TxbTKB p;;PE$GP=$(IZ*U4I$@I*NuZEn%W@xyO14;yw>(SV+@@$b=AaZ0aZgRJW_^>rdj>{olm@0J8s1{5R|Y4gm092><}| z-xL6VIJE#R0Q53eIn`!aFvmpkPyQ@J8@eX@CPhKs4~TARVAE?Y9ZCYT|0=WvumLax zFaap0rbg%g=>bKIW=Bj z>D~M&{arNNYyE&~4dw)_O8WGRRf)Lp7V*|#o4^ygIm?h{Y-2KvmAtYP*X4%aT(lXO zC>A^n!Qp(gBQqXXh?Q$re7TH#r*-Fouy4qsY6M92mU2`{=rxvlUz`!mXtj+5;%@rf z_%iH>{<&Mlw;l?wpw?YqTy6yb;Nw!kft%tALOZ1Ss0cASu0p@Xpf?tT5hpXw7%+t4 z5V@Bcv{E|$s|U3%k!6di1Pd43l6MNyH4d&J3e&SqG9N84J6Ev~FNFfKo|hP*oaBlC zi<=6}F-gAS9uIh>vub?Xwr$=Lnz(y)IQ@Vs&!ih6ND+e0 zcp-&7HVXz6cAff*Ne74&@Ws=fpC*kUl4JMc`M>mTWwn;^y9}%(lOlZ&-U+tU14YM} zDUrZXz>P-$W>NQTp3+#|e8Sygz2( zxeNoG<)4D=8yR2FYwMmN0-j~(Rk$L&Q(R8xF{y3NT?KE4;5O--uz@Bl2t3AZQB}JD&2i|0L|(AHCIgJR4z&EiOg=vn_08oUju z_x?d4&8bqL$pLbgW=ScX6bgV}AdxSL$0C*HP?)_RX7ha z=OkT5yZIHm&>aUz0{`yFl;_Y=vu3I+Rkvt1uMG|{G+1`TgR4m1LMZw2(c9|{L)f{qF3X6F1y0rqMc5Ku2UYCK zMu7R;T5U|;T_xF*56T}|VS#STb#Y^x<@ZO>3Ch~vBuii9-Hng?+;f{EYq{J)0T@O; z{ce!5LG4oC4g*>YS~5%Cu-2|-gce76%<|jW;goBa6F#6Az$QFOz*}#<9Ar+g zIMYWf{ZYMVb^(c>H3-$=o0_)E8%&Qv%<56f3$avy6H!S{j!&a$?A*h?xlI!POnu;g zHY7C<5hV1NlF5CWp>p#-llEx_^A%W%R)3$#w*YxTpownOc-FIZomFl~h&zgtRS=?g zMq5&7sLddeW^~_SLmFooh<$yscY2F(!|RP>)@ri*s-brrc4$GysvaAM!3wfz^X?b* z0K?MI$6(2V?~awdXw{RITOrkXM9v28ApdhH|8gJA&P~9hY|Izp*GhRd^zEIfe>hA$ z3S22=#hY}qVpqCN02Cfn7Xy7a3RHE-om`)Jm?YNSNWSt*1Q|9e01LQALkh|GpTKBK7<{VQED{A-CU7o4;}g1ussF%U z-N!DV{2>ye(b}fDXl6jjwhPSA%FsIT1G{Nof>ycpV(wpVi?dOGno7h%UUm(j>Aww0bp{co*UH?T z)_oXc7Cc`zCm6c`&M<&tn`D9NbyVdVlxO4nA#&VA{uZ~#$X)j^DTtWIxe@fk{Pj`O zN|!TkMJLiAd@5auZY$x}a__WzvYIWMg_?~@1kzP&(qhf)fu?QK#^qV4w5W??;PCyq z=f<`4*w@mU3^-mTtQNaGmxE#B)$!I8z5*pYl4J<5qD ze|DA1ta2_m2gC4htS`flDcKNAn2*RZmBA{ZC*VO$q}CFO`lbz=e?Br(}S?3bg z4RW^~Qo(P!mp5R4lgn$WLp8#(idHB6v{U=4540|VV;cC0CcNVLrKC<80JH6hJ@|Th zZJ@UQ#Vn$HbETK7(`=-gmk!$m)nQvM()pAE^#5SH)sRV$e57|qB9A*(g^i0808QGp z$v^h$ZXD?w|M-de0x#@S7>MupAbXzYPm7u-eR&b)vqKFaNr>G*pz+R>P^}6#>n#BI zBGy{YE-Hmv*1)miTMNCy2zi8! zw#B;75)kQN3Uvz|U#sauqqbnnoh!WB?YST=5Aa=+k($>SuoOgF#$7fKP>}zvRSj=v z^xVvYYGBp9R737A2=nqDQ*95&F)Ds_c#`rq8SU*fs#m#~>n+)gT-4bPw2v_vpfx>0}GwJ=#{+C!H*sDEOz7?gk z9gD{s1-~i7M{yVxB0oN8Ag0z9yyI7nxayarnc4*W>Ty00!7E!l<&co{8+g;fwfsdc zY2z>5v3Ik=$=B;XP8mGfck&eaRI;TV3rLZyiG-L9?>=N4MfG(wC-ubb2S9MPI#n$j z&32py8j_mGw_cBHp8xl@+C^G^A%TU2jn%UT92xTGV35`OkxvBA&NB%4c{ybPiT)Lv zv^LIh#tys=%d$yBXgGNWCb@(RaKb5q2`C0F5c%GydL(oBOea)kc1G@lA5O^<6&^-p zKSqX<{Ey49IVP*c?1+lE)t{dv1b3=PS4PI2CwpJ7)d~tyw+$^WVVnKHoN6S^$T@a* zp(GBR@M3{N5Fx{yOMYvF0~p8l_Lz0eNVGz(`yoF+1kk8Y1wqHMA1?SC8ffuuSL{SH zhUpZfvx7!8Fa2m!clSv|f-X3Y1t5y#0K)qoc66O;Ri1tQ^WL$)8>v0d>B`z3lQ<*? ze=)C=^BQGZ+j0nD!HA%z?us6S6aS+kT^vMx0Qgs&;FyKKaM1T8E~cI^1oUbmW!fkRNE@74147P*s>R9@pXh74QI;Jd1uVDhh`q)zrChLb_7mI6 z#_zD77S-*8XV&7l>g3X>kbCxD)8?yjJT}!n`xtD^U59rujT7PL1Va(-m|#nw<_xn> zRH?nuOZ3)npv9sN;hawBo^GTD*MQkRo}^wweWkq!;>fo|jQxwits5l9EMKPvVQ&sZ zxtw+?^vt>RXr&}MA4(lBUhy6JcILoIYw}#6y*C9mrr^Bp%>}Qz37|Q#CygO?ASMG) z))8pm92+fY8yOolRUbXEGss0C`>jad=0aIa(Ai}FwT628WM(fG5ntJP zasKc}GE<}?`6z?U39;SAu<4_5QuZ8;$mzQbXyV@Y?zJj~96n1PegZ;f68e1ZLP1m7 z^Kc)3dUaF7OPv$qoh(gD*l;5iRD5qvA=YrDb&%CHCZS%u8!fhAp_I7rqt`#jIwZX6 z*}eo?frZo6!iFgc`>ftPZ+~Kl<1kntkaK|#Y(Mi;t2^f~I>4_Ui2!fQF%NRDOag~+ z2#jI3WCT^AcJRd#GqA-oeg6+~vdXp+dxEuk>haTOalKOZp;j3D%S92QGko}|Ha$38 zE}dDfoD=*jRUDn-BXVR`SFVB{?x*eYzN$v8bCk~I}H8})L!};@n%|>@k6u(4_{`;tN zTosXVJKXAe?S%Z_?Do%edn!}JijCTrCQ*L)hUdozi*B8$W6r`A#jF_5R#K?%0Ti$P-DhZLfprnkLNFl+7z#em zT`=|>PG&t>?n4bde?048m6y)wn(Ufz2RrI8+-K4C@4v-HJovK?M6DNsl`L}LnJ5Sh z6%z5(ihLeXRuj+DW#k2kBgDDe1$!imay3!$t>{+D?e;>JZ#@&upnEX#Sw zme@`OExjacfQCvObqm(n<4B5@7?klqWC3FGaX`R~U8K@I1qtVYV&EDCYwYff@(2`*s=?6-rA?N@?7IiGb9X5xpjl87y9wL*>k9N7)M9xh$)ph-|mH{t6) zxBM2d;DQ+FtYGrXEpwMmL9g6k>ju=jdABrd+m5x3@M6;7; zgh@d`IU-kV&&-PK9?1umCfocdy~t4#td$VtY=fwKM?|BXf*m61I~&`5;HWXQ#S9kjdrhuoU8b zEW=i+n?D0lp;6)^&C{@B~90C(4w_m4~O@1>%=$Bzq7BjPL7 zc6(e7WnFMS0pD2~Xzo=i4?9_302MIVm(n|CrP^% zLbu9I!aRy$?Kd(HA_zLc?HxN+H?g-|TFhHH#ZI2FNt@*AhHh!HvVM)}&e=0=Z~w&? zSz!-h8Szb7wbq|u(tp(irR%>-|9XpNsf-KSOwc^lXWeJiNUWA7^e2-Y@@sC?EonIBDWKabpF z61piEQ8C8@8K=UdkFpG)=hFu3b>1HPvY<$9QA0)`>ViwuI8|1hNqMX$8M9`-WkH7^*lY;p*4Vi=yjz*D}y zeCgxMRlK!1#?_>C$60e=I$ zeF#X}E=@Ta)D7j~%dVgu7pArY~ck3I#_Prhk0siNi;5AwsUQRPVMKy*UheEHo_`ziLSM#yiXKHZy`7{Dq~G7SJiSVi4}ekOH}F90h7V z=6wC&fV%Iq|BS~j9*%sasAz!2r^3DEkm@k1(E;sBTf>d6?ekVK;5Dy%Fb~+O%A2Et zg*2aSA)wF82cXx~s-O@$K_7a$M7W{~GZPR1*3Fsf8j~{9P)i$SWvXHRP=U~)$;-es zdq1n!wr;cRq^@X9eXZHvm|pySR#{eFVmtOM*AZqk)#YbOX~9_>nGRYg)DEu(NHnfI zH>DIs;E37L$F1l*?Zx-rxUumO35;`c{d&+YyzQ;Za=HKH~Ab{VIOe;roe6=B4@3jEby&YHbRZ$(FT}g znoIp(pQ8O5TdL%QXVHd5> z`L5DMmzV_;5jMMl$(y|zaHvlaW8jxWq&l*3hSDq5%lh5f`^PG9#RihCRGkIo)=v(< zEo9Sh*7($zYJl0M{A@dYOe8Vgx0YTaNU<{`A>9tIgobl$;nz<-wj|8FZ_9QwwJ}Bp z_XP|_^WPfj_E=-Nf6One3?MQK zhZqhRwsmnWj&;v9FV%a?G>aM~AW&k|Q@ILwiz+(phtHQ=LRlrKaxwPg{YZMgIcxO_ zI?)jt$5@Xus1H~GoRei!g_zwDSsLG_W-r;U1Ii!0VHCM|En&(FwDzZWa@YFg41Wjbm86kYFDj`+o z9cSfckgkTXI9y{^Mt_PNk_c1e2?DgM#q&lKDX*P&P-n>9xrBs;RdY3YdBb?2gz1bKG_+I48c{Y=F!Y&(QzP#%GO{mqf0Qj+80 zH!c4~BJDV;@wXL|Giwe|>8udUf4)Cg64B@`r=DOXPtKcYjJx46b;n3YpIDa8bv8(B z^(7Vbd75IYQMQD5DULY+FEX|TSVpCMNhVyIzhU^&Xzg`dEnKn|Q4H4{Ol!*1=bn7| zdHms~`2RQ*zd7+&K*g=eV%iO<=4Vk(N3&9a!-oww(Xv!pmy-fx55;vmkzI9kO4~I{ zA79eT<*EM~^$9k9Cnj_^!q0Sk@R|z{Kv$Yc zg!m*!S&Rj1?y)_f_jjVSf*y|46ruh=v09ClMUVSjF(kZd8J5J*}2$ z>1;lt&gs!3kEu~JV5ej=d`bKVoj2y6MeG?y4FjnPv;WPHV9Ex4p7j@S$iH@o*;DQp z*xhzssZNspvoB}0*8rvp@iG5S*C)J5{40C_!w<33m}gzL)> zb8ZL1D{zVvy;=8l$pjO)8DEW(E@YVCY7vR2tI+y;4_OEWW#7?b{WtAS=h%2PVcFQ# zv4UqyHFB-2wf~h!DW!{J8?x{#?_)bFdKAdeI9(vzvKDF>-H~z0a1gTn$t}>Z)H@o} zcM$J6G{i;nc2J>ni~@cWk+5%}E;(8*rk5D?Cb95#P^J)}dOpw&k@uFYBKC>=LvcO| zX@v&FyQ!+y`MYZSWIcSph#He387Wm+J)JC4jxfZ^BzE_n1=xE}Ji_kPfrtBCHO<;0 zZZzIBGel^+k7Cyvx3pJfQ(Jz2%1rXQ$X0O$-kUw!x0r!>1Y>(-hOvwi>#qDkJ{s`@ zJr)g!&1s%u&JJwB@iG#9T#8eu(~PF*&ma(z31&2lK#(AB>629fZtN=mMO{a4B8TRR zi_9y7p-4}ZHWMb^*S_up4AzL3k(Lg7iW`$DD_wA@>!8#!3DWdHxTY!l zP;m+3*UnGW0&c&LiXGd4*s1l8SN9i7)+^j>x zE3239|Ff=4;`K%O+h;^lsL7dfyZV$=^@B_QxaIJPfh}Qb8@VH}(0tWy`EgxauOZW` zO00814AZvD!GP_aV$^7nbttI1PV4vxb$p$x$y2g#NEF&a*A@if%Ks?i_%cEWdvpH$&b&`8# zCC2G0M7vD)s0r_!@=neDD3`3L4vFI=axa2~NXZ$2_wdU&urr7?{w?p$7v$t84o~iv z8F&>{$}yCguf*5=m+t2gned=1dvU9qV=7)mk&9T?IH*Nwimx*^O+Q$Ayvid~;H@&h-;N z1sa`hXMSY)cXet@aK0)8bGTyy%j?wk^ewI6;+y2`_>Zl}Cdw04wi!tkt%V-gbR zOg$hcJG{89r*`brUDNP#A`Uf@BQ2KY)a-i-4@~E;psh6|R<4 z{8BZ{kBgyly=;jF)B>Sq&#zzhgs4+OqY z7Ya)1*c{?35S{*`F%<<<~{7x|04f;Of1)i>@Avcjw&_g zqR0T*QB1s7;+p(v5Sywfuv*&{QRcfZrbA7x7x#&RPywLT2qpWVwD;pi-P>u7*6rYF zj602=69BmJT1Qmu&I&umn%he3+f{kIqM-)2!%fyw=%bcFrJc^NH1%<}8-K%#YGJG~ zj(78T?zu?$HJPeXo}S?S5G>hGN#CQ-6JXtNS&KRnvLn|yP|(Q>OyI8-*gpn;Dg|9& zdpD}Yq~fGN_WW{XvdnXx+&$37s=s@p`oIGWng*s>hOnu)hbLffBebzc4`C#5FVtv1*$7Oo7 zi7CLGv9L)2?GTLX*IkffhnK*~Ci5#wXYfn`eCxCF#^~*D!DH%YUQjmC8zBU!uZi;0 z@A;mD6)pTW43{fghl^Hqw~xc#{-qe-f@)~SO_aP#yuA9LKKajx;p7{@YN2vey_H0a zCz*KY9GxKBex;1%cR$5Ub*oLAZM5QaSzRk7#tQhpiFAh-c^BR5h-5`+S6?u7#k%c} z7>V$)x@ju}qrA*d3!;p}8=IJ79UD`FLU7@_Z_R_lBL$TUifj!mr+K5OB5~{ZZBqBf zEPqYtRFyMdhxG@vfh~U_KCj}@%uv=9?ZhlQ6S~pK4Q?V}s4{b^+c_hiQeEXI_ zRe7a1U(=eZP7|j5Cj26L!*jR_(>|Ww-9HmskmL}9BpW3h*?J!S7Up2 z0@q#7#`@N#uLIbuTkRd<9rNZ_`0oX78Ykn_a#aUPFh<&Js!w2l2EP7Z(hvfy2S~Sf zH%d*vy$Bpm?)9hf4gQsez()r}$u93+LF7o*GmQ!WXo+s@HCShH$0svLOv&*$rVpsD zNxqUpYTb@?tiHhM>71=7qGZ$zhE7a39KXxYo}H?YRx2rq|wWE zDGOCX{cmhWzrGS^Q*QjOb1=7Ag?$s*Er}q1BR}cCJ~q<$7zcE4JqD3oQL9hFb~R$k zD;F`DdX4$}yd2BsfhAyLVM!fd+R10jB%VJkD_gX{9xG%kYV!@K)*jbe=B%tF= z7HY(UUqk>a^9kGBp4S?Z$VMScfIMqQ=I*%R+u0)n7^pR;etXW(^;tL-c)eClGQz#tfR5&9~vfVOf0A zNXCi@cUPge*I=sD1(_EaSkbo6Qs1erKXR6LOIWq14NOOK z7Hv$5O(TXlq9(5p%C+j{31(0QGNM=UIw`9cFo}G|onDquH8VWP7^O5$iL;_X_Tfr$ zk*-P{#6_;bFTGVFz6LHO3Rf5jANdR$z{*eSvQu>9JFF)3~bTI4X#A8uwd?{UvvcH9t=x&lf8VeR)+bcwPL87U2=6~{UP2-n8* z!&>%N)o9i5s%tgMu3bzBu2!pvhq*TDQR6MPnXb3&33s$LZ^mIGWX$fi>zPR+Bg_9- z5cnp6NqGPx|1vh>bPSjP{C5ILR-bQeQ6;a_1V@wutaI%KyHPq4?ytz4&fm5c8my3A z-gzlSC7|p=f-l*7wwBoplE_iCrvsO${NJFgtD6P(L?wZvkP;ND2Vc-jPv3S6#b&>nb9uUf?sfpS zlS_nnZ3!#uH0WZtANa-u?TV}|Hs&cKpF%)kVBO$R@@A%Iq$jspDf6ai;CIP)&x?7b znl5VGQdMa;g;k3`@FFg^p)+8(ac?Ved$B563T2$Fk}AvLikxCSe8=@AZYYaX+KvF; zT_aPUn9bPtJ(K*0>Erribr5}K+IvpSQEG*7<&tp}VP8y=%1&Jm;e?OYF(1w+!x!g?TRrO z3)?gDn^PA8=7^aVFL`@6_7N2k{aqFc){2vn*4}n~xKM#1wfJH^lUnB%x!Vbq-yDvl zeE9jj$Ax5l?1f0nsUzA%glEUs+v~=tW`a)8413=7B`L=AQT)Wzd(7mnfjL=P4>t^< z{pt~S^&oVFT@PwUSRns`kK9qUz|S!EzN?f_#6c4V;*6dVD}DVi@)Z#k`CAeW(vFpt z(%Evmzf^`LvHWB^m0sf!zTXa$+Zu|Zc>Mmm!-HUZ=mSsBt|#0=Kwty#-S5JzVuni8 z2!Go1AuYo4R{FrweahgehCNKokJIB(ju(6L!AFiNY-7SeZUxOT@<7C_RR}Sz$3YKI3RqO4ahRpyas>J~67xX-KJIMZYch^2-E-12lE(?%qNuGfET*)QM62V#c-{ znv7+)zP~B%$dIf==aEM`B2QiG;j_0cwAwZ{=%F02Z2Z#NQXkSoVA2b=9?ujxRiP$mmSx^-L z{L^Z};L zA{x6y1y4kzJ#{(zOhGnDYU%VgWg-a<*X`<5&`?dZ(IM&zW(OdQ$)=g*6FXiAv*_td-zU$({P#7YkR zAu%2*dM!bWkLhq3P^nwf?Wi>ek5l~QXa}}HyKi&Csh~HHPf?9Pne@pUqgHj081Z>t z;6S?5pY6hextI*PkjF*G{P!u${P~yDHI2+SWRHMCrq-HP-M60*-9oJ*0=BzQ*tT<; z*A6!a?rCoP(XevT#BV`1^b{XO7PzHelj5`R!SQXsWJ{%6V5|OEeAT-Oo8caV%M)(;Q^m6 zCpCZCZE!4kO}SYO8LPp=Y~(9v99`EdByuP&;iJXVZ2`C=fLrnO=np9BoKZ3H4bvwK zU1VyRn-AjUYF8k!m(OO{F`L^PPttnKX-kxuTF#0I9>lt_L_}9^TX`CU7b& zJ2LBo>DXN4>80KpJ!>s!}+n4fj@IDsX+5MDO-;h%hqX+2%%Um zpTWMKvx%By|0Pv$*4~wigTO_el`y;w!IvN9*qAsS@S$}bv1EtGg_#oaOKdV&{8EaL z5Z&oKs9e9Q*Is7^5v%mU*#=^ce%J1ZTh3sXkgOJtI^ml;PNilqIqduNpB?$uV5S=r z_IxVvQVtId>(93!>pNgp&m=0(h^=^)P%IMcHo|ORuo6d}<1|M4mM?nsx*ruv)8?UL zc>m~gv79DrGf+S#dcw3>UXktorTC5CunVdvDJT$x;dE_mZO{Pa@UeY*Mik%mjIi|( z4R!}GTjddfHaFE}D8l@A8)v{(iWBoo7FEp^EZQUKfEz?i6U074)$PA5F#*t0ly|VqwhfU&-> zTva8W8c5Fqg!B>H^h&d{Be~Pi9&b1qJeV(dt)+Ly8b2Xb`1xYyDIqBFwZ?Czo+v4& zvFD6@s&+|X`pdN+7vq^pn)!b8i5-_MkQ5OT-WL!~-upLgVDIc#==E*1wf8a)M{nb6 zjGh@tF!mZChx2N5+lxMb2~qcL9BOTS&W_sxNn2Eq>Mz3uW;h^e|HhyT&ArO{PKR{o zSN4=t$-~`_Di(os^U~5PXS9qo&D+yeV+|JIQJj;qDLIzfO*Z|aPs7?z<&2prXcL!b z+YuH>+kQ@?mn2z`A69>7FIA}(lyxx4E-VMLiWCKXWKnq+1TmxStAALWeG$Li+h~bD z*OTpr@){s?tJWpuMDV0y-#oIgx-(q!nJMg#*ZhHKa*0RJP{5K9XwKYE-_nuHU@dC~ zmYxwHc2#T8zR5rUxxI?&uP+W1wFBsi2t;dU2)NsQ8F%-F1xfa<;ce(|umpk+*Ju$9 zg~ow&A}9gEf~dB1X6yYp^%i(J->(fjFqP|q_8cT|uhJtCLU*EMI5@U9zBO9)9WLsN zF!+V9c8b>QB4 zNU3AindKHICo<>3eVzzX1W-S)It!olbv`1>h_j`PGXgN88}+{oeGxJa6OUQBG_BHt zjOSSr0`nuh245&C9Zbxoj=!66OZr(wOIrEg+B8jh#&ajI`*-#BUQRYggw3k}@N}&o zo_j5DZu{eIiah?*Oqa&x@Hj3fUm^o#uX1P2@v=O(wnoQy)y@}j#P9bf-m-z}9x~BS zakZR=gvhlzI*YP+Qa}>Xyn(r^}i{xd3ePbO8#;b04s}kinUuc>@wS#65SAGs-E#^#=EsF}2gLQ);9Q zijTm{C3qW13-{!VT5myKy5k&od3p`O_#jtuj1Q%90l7RWb-E9Uo&!Hm@>A|Kt(A7W z5TD+ZJz0}?;ATg*<#*XCMGLK-)C^*HM|c{@Cg68~Wgqr@E9-c7h37I7x&VK-IA`hH zm)G(h6mEgeO?icWBp{WFSVPoX}Ei8-@?m!-UxV9(ad$AI} z9i5|u^ zRNojWu0t-imROJj`9m7Ql{WBaS2n@dY3@q+OcqZw7mr=Z;_+9Kcy#5NvDE3Q31^4& ze1)BCK$f(_bJ(H!U9v9JcdTu@CUbY?FZ{ZS_!#HUU=8k#`d9Jm*C9RA(Fdt~tnI%7 zciZ?<0yU`{TFKj&A=Q4&O3N-?53{@J<3s2lhp-~llZ@>ox_R-{=8sc^Xdv{DH(1I3i_0>QhvMj%p(&}<7k-MaqII5!eQBb}` zG+11|#8DN!kAw29mR{m0PVd0Pkt#xISCtn|;~N``M)(U6KmyyHqbVlo;zY||9+$u%?LJJ3Ba z^D0h52H=EKu(IQNSR8FkS4&)K8nr|MM9CmDMqyxFNFjwjhr!o<;8Eq@O zi}BIUZX(=;cM+DIc0{-f?;YcXdR`vcA{+XnB_*jSlMa9aFjZ)|!PKKkHu3o@`Ss!1TbB*9$PR%>=89O;qO+s%Yg8T5>F;-U0 z>}eyJ0c^e3E{8VlBpSX;LiBsm8PLiO_AKsYz7-lhj&uKNXrpIdR|Jcbg>&SY&V=xI znsvC<0DIaNw8**SmC?;)Jo|9J9h$Y>8E~q0#{XPMStz%%Upt0Hvq$F)z6Or=k->WC zz{ytw&wk%tm**zO(GQZAUWZ)#dZHF%&$DvBp0HG`0fJ`GJJ1eJnSzx#d5s`vX26=c z@8-&p)-{9O_lzbON&4~|G;s)N5K0&S|IK>3RDak0()a!Bw1QKSF6=-jKH=GjTMzYj z{&}vaI|YAz3o_b8E%_dNyhUfSgNkx1&iSM1v*6;;e<9$vT-6v$XwnfqMrwk~e2lpYc0;r9D}lwTx8{VjMbs zwAN~=IRX9!V}U2I-4$pwJ1Hq!d*vWmS5@g%lf@3LQ+^ri<`U8(7c~?AnN22#N)NQu&x7_Fe86SXdO#}UWzQ+kO)PuIxr=1vmj4%X z^4kMOyN9va*+*lf9n^>Qwr{&W?c}QmEbIhnY0OI3_&oqmHY&d~>y8q;XEI9Cc5man zdjA3FA*Tx_Vky<6i&Rn`bFr+$v-F>^Pi-tK|12Kz5yC@h%vOkp{4^)vrzz$63E>&X zPgy*EM`ZI#4Lq)zOdZJ!=*yQjBLcfWR>-cG;>oA@GD?iM33pOCq)n8?sVDPrYDHwZ zNK-^h{F0$l?Nd+skxKK}D$a!EU@ec;lfNS*C34D6H!G#l*q^6hJ1toMDvF&a%VHnR zJ2f#5JNMiT?`5z%-a{7QDp=ZQI4036Y;`wI*NnlIXUgXbzG_|BlU9q*6Bbld%l7oj znA6OB<7&!$+O%?Ir;!Ik=_S|Uii}do)`GUCUCD*ZIg?Hh)l2-VN>nSE>U2g<#_7!Z z{c4WX?RwZZ>}sCQ>^h~Mt&gqDG|y*s=ATvx<-sVTv;00`Wdv=L>#S+APZ2-UEKttR zcxIHJt_~!$j|KB_tsfaKcmz~`B}cs z=n12AX4k`hX5})<&j{Vc#;l(e*ICxjEdG$6*|j{Kr6Z>Q>`!^L_VQ;r)A?`BfA1-+ A=Kufz literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/demotradeeventprocessing.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/demotradeeventprocessing.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..6603a40a11afcbfff5e8b036fa7334567ed93cbb GIT binary patch literal 9878 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 + { + //--- we should correct the start date of history to be loaded in the cache + start=curr_start; + PrintFormat("New start limit of the trade history to be loaded: start => %s", + TimeToString(start)); + + //--- now load the trade history for the corrected period again + HistorySelect(start,end); + + //--- correct the number of deals and orders in the history for further comparison + history_orders=HistoryOrdersTotal(); + deals=HistoryDealsTotal(); + } + } +//+------------------------------------------------------------------+ diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/detrended_synthetic_price_dbarsf.mq4 b/MQLTestWorkspace/BKPS/BKP/Smapls/detrended_synthetic_price_dbarsf.mq4 new file mode 100644 index 0000000..0598987 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Smapls/detrended_synthetic_price_dbarsf.mq4 @@ -0,0 +1,247 @@ +//------------------------------------------------------------------ +#property copyright "mladen" +#property link "mladenfx@gmail.com" +#property link "www.forex-station.com" +//------------------------------------------------------------------ +#property indicator_chart_window +#property indicator_buffers 2 +#property indicator_color1 clrLimeGreen +#property indicator_color2 clrOrangeRed +#property indicator_width1 2 +#property indicator_width2 2 +#property strict + +// +// +// +// +// + +enum enPrices +{ + pr_close, // Close + pr_open, // Open + pr_high, // High + pr_low, // Low + pr_median, // Median + pr_typical, // Typical + pr_weighted, // Weighted + pr_average, // Average (high+low+open+close)/4 + pr_medianb, // Average median body (open+close)/2 + pr_tbiased, // Trend biased price + pr_tbiased2, // Trend biased (extreme) price + pr_haclose, // Heiken ashi close + pr_haopen , // Heiken ashi open + pr_hahigh, // Heiken ashi high + pr_halow, // Heiken ashi low + pr_hamedian, // Heiken ashi median + pr_hatypical, // Heiken ashi typical + pr_haweighted, // Heiken ashi weighted + pr_haaverage, // Heiken ashi average + pr_hamedianb, // Heiken ashi median body + pr_hatbiased, // Heiken ashi trend biased price + pr_hatbiased2 // Heiken ashi trend biased (extreme) price +}; +enum enColorOn +{ + chg_onZero, // Change color on zero cross + chg_onOuter, // Change color on levels cross + chg_onOuter2, // Change color on opposite levels cross + chg_onSlope // Change color on slope change +}; +input int DspPeriod = 14; // DSP period +input enPrices Price = pr_median; // DSP price +extern int SignalPeriod = 9; // Signal period +input enColorOn ColorOn = chg_onOuter; // Change color on : + +double val[],histu[],histd[],levelu[],leveld[],state[]; + +//------------------------------------------------------------------ +// +//------------------------------------------------------------------ +// +// +// +// +// + +int OnInit() +{ + IndicatorBuffers(6); + SetIndexBuffer( 0, histu); SetIndexStyle(0,DRAW_HISTOGRAM); + SetIndexBuffer( 1, histd); SetIndexStyle(1,DRAW_HISTOGRAM); + SetIndexBuffer( 2, val); + SetIndexBuffer( 3, levelu); + SetIndexBuffer( 4, leveld); + SetIndexBuffer( 5, state); + IndicatorShortName("DSP bars ("+(string)DspPeriod+")"); + return(0); +} +void OnDeinit(const int reason) { } +//------------------------------------------------------------------ +// +//------------------------------------------------------------------ +// +// +// +// +// + +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) +{ + int counted_bars = prev_calculated; + if(counted_bars < 0) return(-1); + if(counted_bars > 0) counted_bars--; + int limit=MathMin(rates_total-counted_bars,rates_total-1); + + // + // + // + // + // + + double alphas = 2.0/(1.0+SignalPeriod); + double alpham = 2.0/(1.0+DspPeriod); + for(int i=limit; i>=0 && !_StopFlag; i--) + { + double price = getPrice(Price,open,close,high,low,i,rates_total); + val[i] = iEma(price,alpham,i,rates_total,0)-iEma(price,alpham/2.0,i,rates_total,1); + levelu[i] = (i0) ? levelu[i+1]+alphas*(val[i]-levelu[i+1]) : levelu[i+1] : 0; + leveld[i] = (ilevelu[i]) ? 1 : (val[i]levelu[i]) ? 1 : (val[i]0) ? 1 : (val[i]<0) ? -1 : 0; break; + default : state[i] = (ival[i+1]) ? 1 : (val[i]0 && alpha!=-1) + workEma[r][instanceNo] = workEma[r-1][instanceNo]+alpha*(price-workEma[r-1][instanceNo]); + return(workEma[r][instanceNo]); +} + +//------------------------------------------------------------------ +// +//------------------------------------------------------------------ +// +// +// +// +// +// + +#define _priceInstances 1 +#define _priceInstancesSize 4 +double workHa[][_priceInstances*_priceInstancesSize]; +double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int bars, int instanceNo=0) +{ + if (tprice>=pr_haclose) + { + if (ArrayRange(workHa,0)!= bars) ArrayResize(workHa,bars); instanceNo*=_priceInstancesSize; + int r = bars-i-1; + + // + // + // + // + // + + double haOpen; + if (r>0) + haOpen = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0; + else haOpen = (open[i]+close[i])/2; + double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0; + double haHigh = MathMax(high[i], MathMax(haOpen,haClose)); + double haLow = MathMin(low[i] , MathMin(haOpen,haClose)); + + if(haOpen haOpen) + return((haHigh+haClose)/2.0); + else return((haLow+haClose)/2.0); + case pr_hatbiased2: + if (haClose>haOpen) return(haHigh); + if (haCloseopen[i]) + return((high[i]+close[i])/2.0); + else return((low[i]+close[i])/2.0); + case pr_tbiased2: + if (close[i]>open[i]) return(high[i]); + if (close[i]PaysG!hdNG zXb_P9Kse;TjQ^cm!tfWfhB}s8N8Z;jV2>1?_9T)im;ThL^&~goLK(O57ukc{&cZbR zkEJMxJ%|H{Cx{b>C5QzG5X9wQTs9Dve_#b+_{VKQ%t1WLooJ{u6Te-8gw{~IU33c~d7wpsqaqXTuhAY}leWCQ+%+J<;psHg(!6e5<53yMaxN`Lc8)`O?sCOLoTnrVp2RSI2xU@Cm#=>se&VH833OrXn1~&s*{7{-YQvPNN+%tUd%4!}Q-u4^}o>r)jn8=V+jy;4` z&a}J`#9UzB-mz|k;&Yw>oaNR@9`8g@h)`nWm_I09!7wEx$%#R-O&R>WO@A_*?xI)r zWHCA9vei#i2zzvVNJe*E2-+1LV@vvQEne#i3%nX?-m(plZijLaPM~2<`LyH!h>O;} z{VLtGMgKONcYh%zCW~ql(#KB6U5=6{+Z*yUwk`So`cVlD)h&^cn};=Vq~>` zz_LokHQEul2L9RLp~-N0oNK2BV@izH>aFW>)58G~9nJFWq+%MFn%=?K9-4mqbr4ru zKQyRzmvqH@=(3dc8JWk|pi2cBwBZ1)`a(o?X#e~C9~wqy?m3B3N$d+uCt7I$FrLGJ@Cb{D%Vj!&b|UPTS@tMhE0zlZ#;{d6rqd}VgSM28;(>5Aj1q`% z);|(XSP4ZeDPi2D`kexB>x%K!^*wN_pOoh9hIXO7hYbwP9HY%Lc!ua!%o62s6{Sum z=j>sfS>U@F@ z>w}_@VkHW(e>tZi#gZt6P9Ul3^rAFI!cr?`of=b5KdA0Q(G!wCAt49l6JPW9!lbgv z7beTWz-tGy+tY$xFs<_PScbDQdEG7H{*@)@(HN?1+Hbv!EvX#94^PZ>e?&1f>jUxi zL{kjmmi8Yo$S8Y;NCo&O4newz3;!tM!LB`~wrY8$)vlt@W;AfEL<5$|wpC=Bk`g^J zD{cUOEAeK8@C>sgN!^tL(H)?LmLN;6y(s&^t2Tq~ZIj;tFjxW*_EqX4;Hd2gp%Z4q zqrD#n=-TMQ&QM%-RqU%T)l~2c`oaFAct?AN5hyKu$&opnHksK)b;t}m5T1Wl;LU9U zZ~3039zw8si*Q$cwEbRfhyzvf@a)3p1#Q zJIY{rrWH8WN}K}xgX}`Gf+JrUG#tlUrIKi^6gKA zaod?>8}2*(_r?}(_LUZffqFzg6F|IKs9}IzDiqsP=vS%%IVf+*YaF#9l__D$LP$CGQDYltWQoU^`0OZ*&1ZW)}3?`~p#KTsMx0Q;w# zunvL{a_V~5zEM1CHxGWjqPW4N#*Ww4=UdXFA=pNRa8Vw)D^CF$23!c1^$|@%I_8st97fH++U*b7L*0M=7T_y3(O$k%Jqhjzxxpd1xJKlAk7QIH)&;i9}js%zJ(pn9~sM;xe#<_ zbw3{mX=WC<{e0x}6^lrJO73r~dxb4OE*llNS9e=nk!(VhxRlVN0AA+HWkBsmXxNA4 z=`0+cs)fzu5y``Hg)tlb1;36A9Z-(!pn4w$Sku#kniwK7KEebR zV~xTi;^@j(p4QfEW>G;{B^1i0l(m~v2TM=t-z*}%ogCF7#}AHNCf)lW_Ek1x-iUjT z)cq9ZAFAV3PS95&?o_WJnC3O#w5_TK#*`d4(L3RWQF`^K4AHqW|Dvw0Z%WM|c<>q( za2Xijdu>D#;9Jg*KKo*Vq+L*N#b@~2WQwxJaR(j=r{G+q{H1 z$2uFe)l4;WnJmN6pI3ew^Zh|9CaSA!s)0{MDZ$}r!s6L}W}NmI1L71@YXuPyKNEq` z7TY)s^D}su1^*Sf7h-3OdOQS(M4B|FfJGsr9cwwleFJ%U%PJDjL z1I4!dJtIrtSA^=rc&g(wMMcNYIs0*JGyIVozNU@!ivnz*w-OD3C8fH_6H1 z@OIjAfnpe))EU6%GDfMEy{C#?XZvq&JBZ6;)mER&YBS+rXM#KZL;dUM64HjH0G@K! z{IiygrU*kUmK;PjwGv7n#OAb9ri8h$}E`5*yb0@ANJ<2ekTf&dXNB(Ku9 zRLa0_YDA=NxVz^_E+Xtl-VA_j^GV?C8hR5=uD(g0mV#W1=3Y!PG+}XI(iB~|npP~a z;JYW*3xaq53OFsesWm0MWaKYX?s=C5lvpnWzf^HE-Fs#W3PiTn`lOOmy^Yz{K^tDrgfW8iK_xA|%)R{;+8zIoM3^3z1)) zVh~fvSmmJq!YH(Gt@?M zd$R=brX{35pHz*}d3!Cy`f=fAjOz64W<~;eBL-)^3$N5LgIMbh?w*|pgu&Huhr+|z z`R+LF`JWFPHX2I2ovsj$)y`{cv)jhRxxq|21?IkzY9A)6kFg$DX_3*Fd~CE3h=cN< zOg`l2eT;8*N8Rl6x5RNG&SKor)uTbnrP-{Xq>8$wlYzHnwlr_1bVATEbxAHJ$v$Ov z%+xJ9o#El_%$a!CD2in*dl^tMon$xq%fpix%%n+5AZ7&y!6<)snim`uRg>}*#UC^a zCVWPfSxpJkeM{IgURGqbV^a4gpuVY}tG#_-Vh#O%UxG>z8R2CyjRitfU_|{WK8f7)6fW*DdJpK)sSftgc=uH+^=>3x+d1DMGcBYFn z>mQ!5xQe&RmrL>SD8k`V0dx=>ZlVg1=3mi`Vq24;hz7op*}X$n#w8Z3PLW=JMX|IqzagTJ(1D`>tK-VnUW2Q z(d3q0cX69#N}gfk;K^?1xBFbodTx4tXeN?kXe+i5^u(kWQ-!R=p`zlO7_`y^Oafj$VcM0PJUOieh53ao`1rUxt5w<$tKfPqkui$zh(i|l9K)M3 z>ia&L?$jHqU)v3+9O#e!{zP|1!9r?!qE<@Dqd>~4#mW$kWzf5XEhrFf`=)N(H(cva z&vM-%pW&eshw5ovKs{qE^(vbvw?Teup;FpU!$ictWf-E_0dx|cc-3M%f;NJS2CaJS zP%mIoz`ghN$ZdCm;U2%pFUgPdxy`XH0zP<&tR6z_O+7e7`pB<}^>%W$O@AuRiRX4V z4bUUZPuro3Dn^`>5V@91xS|Arq2D-pfVtLyqU#==6c9tYlq%XGdhCZew~=a{`yK*G z-2phKkx9XtQuAsmj~f7MF}K5GX(O$gfXM-n9CdZxShem|C`03u#qk@S`gMewwCge+ z*wvcNpLj-nNmh*rQER;n$T2Q8+q^DF`xV!%f|XjW zj8jDx<%!IhRYnWTv9uW><7UCvaL61Jt-+l)Ls~T@fzI(NCg> z-yJVmYPR67I=w4x^i)qNN5N$y`88(FvM3pv?<^T=Hsa)o9ayrTE|(z1Amjo!O6IS` z;8o5kH7^}wvoh@N9k%wf#}+Gb>$EryA%7%n z^pW`8Rgnm8b0ouUp0#JK%STlCUx$i8YkzCmLhQAnIr?pP6Q7p~gsqCSB;oUBIojqB zolR#Y!M7M~i>yOA6`ULNSZ}MS8c=KOy6=;UeGCN~G zKfpLc_``C~UflH+k0id@R(&E)0xtxu-1{8Q76l|hn<@@qgiVc^ET=AV7awET9AO>v z1-rWj?P^y$^LxEJ_&oz`yDXUmccS-X%_`(}(c--=QZsJg1d*^h?T{W=V1vN;kxBmu zh^5T^U6aI;SV&c3DqCT+LTQ|EvT%aPigzc%4c9({#G+9qNHlAN{ZifFft`v zNxh8;D&nvb>W5m8YK5PIt{9bMV1HbRVYWdMp}nOJ&!a%`v#Dc>BijAMR(CB>=gvb- zvP?ij8OaPRYy6Ji7bpEgwe)`WLt2Oi5CU8(5__4?LQyclgZp*R$d;~3ie8K5pZpdd z%iNx5zqnZ3BzK$JF$)fL&adBmFAPuM=ZY2<7ZkLF`VM$OOW9M#xA$4R$gf2-WTeZ3 zr(tiqH-7NyYJgsaK<8xUsTY($Bn%)1YYG{I&t;9GtI~^NIy;(Y%hh1?c?08~CxWS_ z?eEU7$d&=*Jl-!a3DX4Q^Wx<$!KkDy&;=+()RXVgkr0aw-mVD+(H-@LCoOjl+H zE2f_|3Vm&2S-mPDgrbE8fS4sPT@y3p<0{*X(K|A9gzrdP5sb%mzuQ`q8_)<9SjZI# zx>!Z)MZM)c<7mj6(prr2@dSs-JMq;1b(I5gd#t@oU?wpJqyf=El1M}lE{)us>59Tw zeeFp&hd9Mc2J6ObE&isg1GNFDg0$CLodvPG09FBl%BVq38E_BO3{LqIpx z{{ASa{4CTi;_f$EN94wD<~vHoD&cL{-9@kf%vD7TG#(MK04ZB&XBxtt5Dbw{ekXS5 z*u^VVO^D5>q|MxRY{bvL=~KT57MKY9L94l>-Frwx{NUfzr7Xa5@UW@AcxS9*>L|;$ zal^@NErVdLGXN_0Y`oIRM|{-iy}Thgub?!J%UUbQs>E^!`MrITCAOp zPtb)uB>gZB2&=xiBKF_XLKb|k{WGGI&I@pPi23oFveq#xwGi$*_xSBuoa*@_1YdNlSyZV-!uHHLx|K#9FQH?6r7!nKhRazqYmGp&)yNgpZ!2iu zorjv4F0M;5!~9sEK@Li!0l>Aj2N{n9XZoZ9N~3)m+FB+xyzTF5soDE`?cBJV5=1B9 z3mH@q_8ViPk`?F4Zw9g*bLsxG^O|dg5;d%wyckw1pNeRerv~+Ap+cA9hO~&$2s#F& zA%`FfOQIwthnkOyGd)9MS?#}6w(rx!SmUXgaH*mC{!gfb&m(N#0ow^V{`w5NT6tV& zfLr>Tv(>LJzBP^vrDZB!X4X5$Xyui7M+b**TMt*NhxypX4wx?=1qbNMx;3!)mTBvK zhJf4_X*T&v@zq;4BFATh+gczKSxr8`UH9Iy`{GH&r+fCsO-6zPy^F$DIrb%>M9HJ8 z#hW_Koj+Afukb*1u^ys`hhB#7NvTD+41^qrze3i_=6&&&a~9%x!R{KBmy_M*dl)B} zQ}-QxiDlX%+U7=slf6%4xg&UsYxuE;94GcOo-q~ovQx$Ql0`aXgoI03CS&-@Sb-3o z`Y4znL!lD-RBH88{B1+~O4G9JFW;fA%RQ~A*xdZVeTpT_Qf0)WF9{x05oufiBSc*=jljZ@(Jx9p+JgJwf%7|>rP8` zHT5{H6_I6qisXO>Z~`l9bGay5*qGQR!$mYbjLa zZ_%Wm1uzjm!YN&$hp&DR-MTB+M33%sNY1_ohbFbJw0=CyRpY&&w)?X;+|kx?olru> zk2t?8yIo@+>)#kqz~C1moQwC0p-ds6QY(NLT0i~{ z7J83=i#@oURJPI_aOD3RUCcn-z|wW_t$c0Qn-rP0O{_~%x)@1Q7Zz~!m!^DH%Nc4B zNh>)uKXKZbOuB`6cemdQN{R-7vlBKN#x~r#rP*wp-P{Un0|Voy^n(SmD{@lv5x+t& z0TY`QDzNE+(zfwLj%E7ZWrS`ET&Tm4+-e^7D)EYXJAIGy?NxsO+E%>P%7*$hBbL;( zrB{$^8FpE9gY;sJ^Zc{o2l0^(q?_oOLDY;_;1;?7A0Cwc|sh-1vG zz}v@bp`ANgq>k~0wu=d@IbKLY=h!d;iPL1)2Z)j44y#^B;QQ`@Z+iyMa6yLm&f_g_ za&s~3F|QhIV(c(zalXfZ7yk|ISK>9dxx>uYeKnUa;C33FvnNv3Oh%;-%D<0=`Zz)= znx*}S!15?2Kyy?b_LR~_>2YTvy%oawQ)CsQ{6-Z!0#yhr^50X2Pt6Be0qO!8Hd~_&kjT`Mr%7-^Z>B8w729-aw`UZX1H;gbU@D~LUP09Q zZC3zY;++QVmwo3h5Dl%oSZq-9pq8>4v$#JD3eWB>;FtHV7$eFCUpvipbU|4D|r9T&Q+cXQX-kn8SDnsO{ z2De0F?j^PP?aK8WpGKwCLC0z}+Et{w0 zmAC?w*vmKZaWEW&6qfdE2@dDm6$}Y{T=HKA=5_gFe+Ii~Vzo*}->t;BMMG0@@FsSP z8!^;U$%UjoCYYtQXAM=O5K`szSf4rWoUm>>&oEYHbOT2CHT^VQ@Y9qK(T{5d%bz-D zFgzM@R~ddB>rdrmq`fEDL;dg{KwO|nnhngkdB0Ux;lt9`)uF5-V*oR2#v2Gfs)+`> z%DtM&g%Csb5$eDE(e@^TdH9w>xv%inJH=$j91HBfN9k+>_cAC{H1gU7SjE7zeQ7`U zQRx50p_y9+g+SSK!csj4^#wOw)_>73;l$v~3|=`)gmIS=1(fpRHPDt*HnJDopeS*# zq-eD}c%W&e@1@#5c}8mSQ<9d&&7Rs7*(y5@-62$ZzjF$#A6l-~jr9J^%?LM1x*{=? zAO1#F1)W|Hhv#=ugF`h)BKT38i87Q-d?U0r0vIguNSr%nI#(Jmo^@G1;V9>=<~&ai zT=!+fdR5jak&m^QnRY~w3X%3xPvvYuxq`74x-rH^6FtS8HJ?H+y*@?)X9sp9O>1f4W2v;U~q2tLLr_TTJec=Ic4L)S<=C!I;`LE{N7>6(_o` zaFo$9PJq(wQFVvtUw*K@T8?i3kH9_`>4mTBqQy-?1dCw)No+M}KM;16%yOX)`L(dkBATD1 zd2CJp_ict!_)X8i$s2H#3@RpaRuz?1=-a;6=XU`9`5wK>-4VYuixp1>|(jdbc}J*vG8$6P4c&3MN>`sVO1D&WQt>r}g_w~zGu@L(sAuxWRK^FAYHziFY6 zTP8LI-@`T2V0>rpw$1S+I^hSYfuUwq}Vqo#q!#qk2o-p<}9G zKN9uhi)9>P^0bfvOBq!^u1uqOVm0lmW^&w`Um46ObrBw zYoxvih)EFfB(*ps(wLCaITs9ZNUb{H*~wc>M~< ztZBoBHUJUrP`!Z0!}1{ZqAiIt!O#}7hX90*?ze?SL3IFF1S&Ox5(*<7p$~-6w@W*! zRejdh`2M2%dXyBlQx7Q;NE4qo605*Fk41O1eVym7yrAi_EwhaP=Ae7$%nRco;_6z< zIfqjgqVYfBi?y`o;Ko1~g`E`G+?_k={y`4S{2-JC9E%A?F>=(>y5(J=GFKV%9cO#C%-!j2T~Rjb1@&6VIh>FKh1()8@`Sw5 zeCM=;Mrc{})a$uu)`~Q+PRHsI;4E_Lo~<@xD*M<6&HHO%PQp&yY4!UJ0=+K`^F zs3?-jo5Vuw5L zb0|i&Dlgx2mF?1-QBx$<)Klpgr{Ur= z9Ak4*^yv+?aLZqxKQ++YbS_;F51T+-HIX4B`H76_*t$U|Sa}Pyfl4n*Z@ow-v!dS1 zss={7yt@4k(-io&hPW9bIfLq*ScF7=l=oB-fk!AMf$rJ0eZ1Rp_KvRYrFC|0cE715 z7mEKH(&Al=uR{2KNL_pVjez)f= 0; v--) + { + ulong positionticket = PositionGetTicket(v); + if(PositionSelectByTicket(positionticket)) + { + if(PositionGetDouble(POSITION_SL) != 0) + { + + delta = (SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_SIZE)) * GetPips2Dbl(PositionGetString(POSITION_SYMBOL)); + sl_value = ((MathAbs(PositionGetDouble(POSITION_PRICE_OPEN) - PositionGetDouble(POSITION_SL)) * delta) * PositionGetDouble(POSITION_VOLUME)) * GetMultiplier(PositionGetString(POSITION_SYMBOL)); + sl_value -= PositionGetDouble(POSITION_SWAP); + sl_value = -(sl_value); + total_sl_value += sl_value; + } + } + } + return(NormalizeDouble(total_sl_value, 2)); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +double GetTotalTPValue() + { + double tp_value = 0, total_tp_value = 0, delta; + + for(int v = PositionsTotal() - 1; v >= 0; v--) + { + ulong positionticket = PositionGetTicket(v); + if(PositionSelectByTicket(positionticket)) + { + if(PositionGetDouble(POSITION_TP) != 0) + { + delta = (SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_SIZE)) * GetPips2Dbl(PositionGetString(POSITION_SYMBOL)); + tp_value = ((MathAbs(PositionGetDouble(POSITION_PRICE_OPEN) - PositionGetDouble(POSITION_TP)) * delta) * PositionGetDouble(POSITION_VOLUME)) * GetMultiplier(PositionGetString(POSITION_SYMBOL)); + tp_value -= PositionGetDouble(POSITION_SWAP); + total_tp_value += tp_value; + } + } + } + return(NormalizeDouble(total_tp_value, 2)); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void Display_Info() + { + total = "" + + "SL: $ " + DoubleToString(total_sl, 2) + " " + "TP: $ " + DoubleToString(total_tp, 2); + ObjectSetString(0, label, OBJPROP_TEXT, total); + ChartRedraw(0); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void OnTick() + { + total_sl = GetTotalSLValue(); + total_tp = GetTotalTPValue(); + if((total_sl != prev_total_sl) || (total_tp != prev_total_tp)) + { + Display_Info(); + prev_total_sl = total_sl; + prev_total_tp = total_tp; + } + } +//+------------------------------------------------------------------+ diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/heiken_ashi.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/heiken_ashi.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..7f8994526079979d16ccd3d1ce9260f5c248653e GIT binary patch literal 7278 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Ð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 GRR0&(9?P)+ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/hull_average_2.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/hull_average_2.mq5 new file mode 100644 index 0000000000000000000000000000000000000000..53d85c23c552d457f4e4f793283326367dcb4a8c GIT binary patch literal 12964 zcmd5?Yfl?T6rInN`X5{>AyX3wcKe|Xq@_R}QW_#4N~9 z=I&)?c4x=CKox7X_C99rJ#*hPJOBQ(YF5p?IXJ#FUzo4W&|I1e{GQ@}Y(AQX>Dv2` zxbK;_<_u38X2JZ8-*eM9N9F`=2WA=fZFAqOneXwoj8-2s2Id{wx?>@r^TvEIKY`CV zDEB~r#qvMTXwJK=IJy(y?gIT7a=SE#xIV)jrFm$kcKj!JGcA=-jK;BZtc6hS3uehm%$LRv zEaN5gcnG_BfrGZP13Nmz^&YOba3?Yw;t6HZy~a*yxK^||THHQ*P(CUR?L%4c3}x^h zHq$r1o7b=xx$fG#2Z5gFC6@a(H;8%|FH2gXK3fE4Z=}7AvIhj%^EO zo)6|{SgFRwCM-^Mvy3*+VI8!KO>>aNmu-8!3A&=SDm2%wX?AfHqv}U6dB0(~*rp15lzxiPZ=-wYGWmgn7iI@{0ZQ8FiuFx@F^H z7kZ!kkzuY(Rs$&aml?h}EpL$RiZ_ zUlowcbNLNNA$~rIN~lV&*ci(DO)(}-ZBEL_{*j49^-E_QGZD)GN83N)cpW;)>>^Y^et%(KH5ZUpMX zO`F?@oq}^j#p(CC$*f^W@Ff1)6P#6 z#Y0>9umbY2i4D_IDM23jQTnnX=a?lIIhSE{D9T!_0(U4M*C%}Lu)8bYuYKflO`b77 z%j0ig#e-GA8P+2t--^Y>vb|PyMQ)B~(R2BZRjkeqh%C&u@;?8Z)hPSrpLeq7v+{^w z3M*5|o~PCZ^4ib)RM9@ld@4^V)-K;B^pe<2B=1QsThq(b`#8IBcgHsNYvtH07e#9%8}>7+HPgBiQma&6fENvl`A2>5+Aigj!V!MGg8A z$ZNoV7t`2XzAxI6Pd${W%=}ieSsJUe4evVb^(sTo7fChl#VJXY*~x6YuD)}A>nzI6 zPFLXlS_!tik$qzk$71fiTn_YUX&qH98pI{-Xv{+HTKdT2_{b|Zn%DTI>wGz_Pmy{Y zwMx;ClWBRkv0~yli@akN5+4s&7FJLLi0)=pyD8+3Mpb!-$m96R?7fb>(-DN&3FsO7p!w3L<_nK>p|%bTsc zx;&(PI$BWUEl8j^Q{-CTJL}_qj3C}BF-mx+5UAJJLvRz`c^mby>FDc?>l5TP`>3kX zw1ybZ>uIQ3EUu!Pdc3Rah9ma1LO$UkBc``jp_-1<>9=v|JDcyoJKBh}_l;!8VqDZ1 zyoNb;eq?L#qBsZb)sFNkA9c#6Shc1rOSW+9#G%C9U3vAJ;;s=*Yt7hfGaW;(l9^QS zrDdse!D1`<65{e@2R>D771jowOyjYU#I&kBG_sYiTT$YKD=eO!88zbSl*<9qZF+-x9f1@vy2A zuAY5x zH2lt9ZFl1s{J74`osF#459}_1aDR$EJwrRU&qSZ{`@HTK(P#O6A8tjB-?E9`_oNZ} za}At3o16G|hw-IE1d<=QIF-RL1b)-i@X2; literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/hull_trend.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/hull_trend.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..6b2c25c0be95cb5e1a958eb1c13dcca302b94a45 GIT binary patch literal 18372 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 I;Wbi)BkYc5kN^Mx literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/hull_trend.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/hull_trend.mq5 new file mode 100644 index 0000000000000000000000000000000000000000..f3d6de15cd0057f92c8804ae918ebba6dd641623 GIT binary patch literal 15062 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/relative_moving_average.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/relative_moving_average.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..06c32b61e100749017cf8ed82caa57f945239b47 GIT binary patch literal 10714 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 a|L5XjvyL%y<_!5$_)apA(~{cp?f(EmvVwE~ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/relative_moving_average.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/relative_moving_average.mq5 new file mode 100644 index 0000000000000000000000000000000000000000..da48d8034c8e91e69633c7babb20b26d845b3da9 GIT binary patch literal 7284 zcmd5=ZEqS!5T4JK`X5eIYDj_DN!2fHT!~=RSaM=FxT-44LfD*RR1B1tIBC+qp7eQk zZnJa8av0aC(8=arc4wZMd1iKYKYiSh9jQrU3$B`cEnfl6j(m{h3tTUxC$A-i?mCBOoA~n$uuq+*8PhrZ zojAlr&sSu9Jd`gL$Ag&Mq2th>&=9VQi|lPYxLU6AaR%vQa8zYi3Hy@|iPv>1^h?R-FV9 z(-Dbu+}#aEb?`RD)yMsz!<}xVbqK4^F@Fes)LO~%dNc2lKg6Lj64{58ru+_H9?F5d zl=eoLm^rj`n#sGs(-abE#M-XFL94J+X``G;1MVMq8q$UIP$hc2G9?EM{>lYkXH@OuL9u{$6))Jq-5 zb?WKk?yWpCjH{w5*K-^syXvk&?Bjn6HRA+0Um-vD-F*`{m3fxgGpB=9h8+SUIx`4V zx2^606SI)L%~Yx@v>wPW_;P~!PE6e>>vQY81 zzoxao!y)SS0{`iS6bxVoG0GTD7L(27E5FXb3$7B}Lkz*Rz@lJv@h&Eh{d0;v5qrlX zg8qMy%WjNSZFC12b~XPNHWMQ&Vd~cKV$D}8+sM<2^H=ITrK=PizjPX5)^>&ei_xrrvdA$iIW4RgUM?G2> z)^Rr`-{xrSJNH7&JofQqb7$N12XGlOl%&OW@D!?rKt9yW!I+-X|`p~4NY&R28a zp1K_dPjPsfWM}=1k#RpZfXde>b{avxax|Z-yPwxwi*<&Y$^CnRUv?Qhec&EMyO9U@ zWu0cnLO-%98@njTSrJ>k0M*l-fO&p{&CrtR(c4m!vURFU6vW$+6K|Ug6kHas}my33)Td zv+k|9@&;@C>Z_>297ZNTN4q;6XS0BsuATq6@9sK_xl7~u0C&ec?b(5}kZ~%>Vo=tX zt=D^yMW#|eEzft!Mf-idCWZv|E`X3Z!KX10`o5ZHIX8}%4*!}x+47HX2-y4tV zTkCyBmtIbxWr91N)xB|XU*H{)Dvss8-sXwQ)v;B?O1q+gvzzA&19@ulTHn;r6))$v zO0xVp#q2XDiP5l;T(+j@OSK^ENOs4A^KX#IJ*4+_8Tz|<-y&r^zAMQbdL*0$F@6nT|{oRaf18b#>kK z>%$h;WCsTVN{|8I07C!(1aJfn_}>E0FG-=!HUc3Crv9`<*%$JEYyMZD{-4JGQF}lE z0RNK!0QCRS0RU*=3$*pfuvCL+q;xs?<#?PB<2*p^JUmt`f-rMzR*BQVww$Z9kyQ6ejQ=5a`ELWx03HC- ze{%o-#0anh00FiDb^s&5!6@Pn8zy zZxXz5a%{TvPXnB0DAP8VK=W>l_NaaRXZ^f{@)PDB35-}64n`h23MC=|sz-4_DZZLQ_X~D{#d2cCRsjXIf@EWIKAiRwW_6^J z`rtOndKHxjtYWV6Ho<@G&KsRSpIt90C{v8|P&uXk#NznR`NnNZyUxK4nQ{9kpf2sB zoO|V%TuNp&<@fjomWR2wG#thEe3uY}_Bdaz?2ay@o|*Wf_{SW#HfIno#MVNk3KB}U zG)O=L;F*h^m6%m1m$tDKbT-{2zlGesTXgCL~g(QNJ0;FI5sVDGe}G5Pval znG&J1t3ADsWismKL?R|+Ttq~P@JS4<$PPF@VDmAC3(?~p{;WnmxXNhVBzBH=lCOXwKR`WXjIsz83#~Bima3Tci$4F!1b{{tf8D< zIMKHY2IW=T1DLuB>NPxz+2pQ!*e4iB^VtZm56OzYN@jx|GY1aQN|5?!_7 zT6(reQAP?Af=gRdYn}L2Fj4Epi{D+>L`RxZI1J_jf@B_r;XWk+P*jHT3c)ujF`KXq zV22HN%>Ag;NBXgf!h$tR4xG>T>JBr#;bfXZAoV{z;QncN{d_`BU&37~jqO(>#3fd{ zdq#OJosx!w)`Yn?6b1y*_GohuY-P8ci&&2gRgrols#NYoN_1*Nxs>CYd+oztdB2EPJWW6OIHO{AMm z-MkG?@<2H5hA(ZzzLduQqN8Q{RYs$LkbkL81;LrdQTi5N)gGIqT#HA@sNM&MfyAOb*^a!ITyj<+2K~%m2`aCl4iy&-q}_v;<6yIvG5PtvgR$MltKv=sIOrn}W3f&+pg~Bv zHa6permA#VK1^frm|I4p~0axpN*&LgF~4 z8shgJ^_{oPj;vWweClJvr6jR}m9zz2m59Gg^Q2c8upcHT{ft-5&>0*;!MsdAo zJ<&#&9J({8tO(<^7{}qq_pyU<*&Fih&#gM%geYZuU9S5hZztBh6T#aM1{H4oIM}^> z!1c|(C+v_o#-h3n1AE^LS{;EjbrWCAP8|2jzcPD2znlJm@yvu1axJSGfHc9oaJ;Yt zlaxWMC!NXASYo@#U&Tn*L5zLMOE=yn6>d#O6=H?nHIRJF31MY%AwdVT0kpm({u|2! zTu>V_0<8Mjjo=gh3mbDGroyT&v*W&+GB4g^`4y$;3Zj+PBwh;qljPD`4N}Rtt_RS> z?0MfEBGsqcQEsQz3)rFdWVI&2q4HwreL-1&(x7X%P{G$mW_$uq!sCw=?QUW6Rx7k; z8Hphoz{TRdS%O73G1td?O2NeSG3Gz&VHlN|G39K^RZuR-?!z=sUob-NAEKPJT+QMz zT}gW^%bRZ%W@E#}AyTKK4`C}o7|OSYP)2V8WLEiZR15EQP=pADg|=zcEq@l0Ecklq zzT4(asw`&D417y<7Bmu~up|NFhBIzidVt>GAAR1OQCTv6c_gU2y0i(-Q*Oh8p#lNu zTPS38MP-E*S(im1UMBSjnw%LT*KXP$ePNzlw5!O{aKyd4A*a$g=bFB3jr@CRn%>0w z_2YxiSvg8FHmxvib`&3QRZ(MqyRA`a#!uzBGTvqnWwo$JR8u`$F)a$K-Anv*p)EFV zG_6c=74tbBB4x9XjBxtRu|VPY5EtThV%&5@dhtm5hTAru#duS%NpI#sGt8OW39^o5 z%!PYa2fV+JLvWG6Lxau`;~=Yd(#}e1%etPkRj9#`zKk zhse%H?wuDk_~Y0n%5Q-R10g(;9Q~H1 zNBK|in~u^42p!hXsp=w`b`)fYkwbpe-vXV7-%f9RTt?;4O#Ad(j?7Z-yA@NSoFMIP zzYU%2mZi_syu}3hjb0&Li_8`7^=1 zvtj+SdtXSp!W9-M(8xa7?LdB_<9eNJHmL`x=Kl z&vZ$VOpdbq)S7gvFz(7<(4l_?#zK1tS9u=cdJ1k%bQSP#Sm}Hx^+atQdh81#@ijtR zvYj41hDphI2@c4Lm~tLlVdG^)$EbirHaLe}n3<$(2h|~u^P;DWlVI9-2%cekDZ)*a zy8>tx=zQ=RKP7%E;xRqH;fX}tV6rfgvPS<_c+j?qCy!uVLrqAiz*uE)DG3X_Q`bS@ zaoU^HR!U$`TsgxO`d!!C6K_r)Nse>ZZ4xXZ@`1yz`Tgmvl`>ef6^s~NB=GoLzLW+$ zJ-zof`bTX8*!f)k3yBGmwvRphfCW`^4?NWGH)lAnI-|-mgh;QOhdH9I&SI(<7m#vR zaP(WzU(v?js_FNOOpNX^dd!xEYCv0O*UGtxshgLzqTwJ;**oWO6ww z+tY_wcYUu#h+bqFHChaC6(E>th$RvRz=-;%OKj2sL)N3`|J}96AMzJ8Z66R_(cnE4 zvH2R}%r)E<2{h%NqtX|24vzd?7<{5OgKNn0P&-N5hell_0=K7XB2u0>itbUzsy3nT z{`P-Or{pYFAL#!jrxAlPP*XbZ@X)5_VPGG%coO0RHf}ARq$nv6)(i$*zC_e?p9OS( z+%^)>xliAsH_3VegFe~|UbLnSaCCuCqH3sZlu7H-ww9%tn3kTVtKH?2yR?(8Y|Rtp z?e}qc#^NSaWAV>k+N$^G+?=!mzpzB&wC^fJ#xoK?2U=G|6hVwa3&&BU)f-=^gn7v( z;o{tq50*Ddif~BCPM?>(ggYwK#?d()>0WjQPDbyV-A2vjuq_IMDl;sM&IjGLUe*{= z|5TfSFnp_y3QcW``vCd<^_&N>R2p=N^#D#3)}i(NX+Jo+UPtt%bS6i$?Erv(hAQKH z!MeeI3v?3M-u;qtxvPU4gNq<}euaYB)!O&Op>U~+>B-qU^mYdmYv)2pkU*ev7j{-`M&6@J}#qWJ^bGc27PPc+TDmw?qJyE z9&B3-!|xgY<#Fq4_YJmmMX67;rn)(wK0MrqF4j^|HFSjMop)YV!|8?QZaI2~9@yayCW*Snw? zY^FxCF8M~#f4_WlMHRzzw<0{x6~r^M7ggDVvexrE`T5rjA*zosJz*f<-JHd*R9#Ih%{fq+yiXKS>Sh% zOtRT835gXcr0M~CPcq~zwoWja5#)`_OIkNCR~h5=igJW15%}| zGlGN>POn!yZG@Ehcz_{qxl+db+FWg+*&2;!q81V=x+=Fnwc$lg5;hRzwIm#idYe!7 zO|!K5+*O39Cf<2kXqtrs)ug_WU_}tYf1~|tZ}(t!9W#|8VQR4CbmZ6c-2_nNO0#yQ z!`WtehNLd@VmUJA&l*OZ*~Cooh9pALe__;h<|AJ}iu1=NBM67+7%&;sB=)1;Z%^7t zL;X0^2g%u6ndtwp9~{q(GLq3h|K*ZWMIRHY2~t8+;jRHLjrBf)On~jj&?g5$Dcs@a zY8i1<(DCR5=WuU48v?N{0xbO*Z|Me0xZt)Mxw*(R_xIIpwPK+PJO<=02d1sNm$1*a zd^OreB%;FNz2s|U zJ3lc*gvZ=z5kR(prPgpW-AYcKV12fRK|EZ2_s4sxW533^%VSPrxdJL4Ef^J|;9jm0 zw<3KW@7#kd<5tLA$BOCQBbIB? zP%qcrRshn$E7SbixLVJ8?nAGY7x*`X$I|dY3;(+(`a0w?wfw;V#Pl=X`UhcJ`x(y? z>4vE>c$-bp1Z6K5r+$yuW!USS{xo|_D9f*ehrG{OO~eA1{O?S)H?4zX!y-r~6Zf83 zcCs{fAi=zCO$H3Jg~U?-N~u0ioPh(`9-F~@$X1C#5^*IkH`tXAWNELf_kvYgm8UY2 zSx8R}#nd_yq)R*hHYKR=U;HpI5YeL4cH-F4XdQeuA>69NP4d~vT}MFROCW498J=SY z1k(A3^W3;&w5`U89__u??9Z7=!KAG6Tsuv%6o-$4Cvl7nrc++M6-1Z55C$HB4scjx zdui~9!7z+KugR_HwO-GlXGS%66goxT5{7@Jm1FBiXw+9_3L&n?KwrtvMDFt|r$wk9+46{5+^>yr9Fq^)@yB zGF)k_P{N?ha;Qcgc1}3)3DebX24Gp0ro47T;kD{}iIhgYtPlMJ^z)W7LLs*-CL!@u zvBA(B{xEI0Rnu}nNY-DLhtOfH9ALShaPLCLoIepHsnXN(Oc(Of6!C{*iv^{c{geCX zzg~R|UXUQ$q{W5J*jU(!41}_`k~nM#9@FY7R=hC1tX%r=2;Mx+w4A@m^5SmW@DpA4 z)Xa46Kg)^!O!;x7D1_Gf2^&af4I?e-a6110%R3@)AhvJ1vHGKABc$L^k2x|~S^WN} zD2}(u!?wv(6FFd(Eg6!rPDdBsF{=^*V|R1By%&XQtQ`C%n1&&PD9aH66oZyLy{!-gk^vIMG^Yl~vU zp!q9u7Pi(bDDL7j5amG8m**xdv| zHkFP`;GCb2f5~Ady^@+wCEfPD2!$c2=5O7@JBEaM{xnInCT*B!aju8IkhURkz$yLU zQ7VpHqt8r7pL_&NG^Ha%FRg9eNUd}CsdLM`4)q$k-5kPQSL6MS#V;->TVoHb2yX{) zSCu81sTM!$4l^GtYeIKZR9BoLEa|iiGgtm;yqbpGT{l0)j=rLi4rXxP# zMT+PG$wH~ququ_;6f%#p00>C9^f}t==C9Su`kG}q=$Sj4@v@|3E6leiHl}R*81=4{)-gt7N0bt5v9+Dsm4%&M4j(qW`-G>ZM-CIA-UY zE*!cMl3rhvjAE8WZjR6V%ccwR-=iAcgkLLbP(|Jd(xS`o`QyCaqo ztcy8uvub;SB+X&2E{q0^=ke+;5|wPnBeLGEI){vEiv^r#RN{nVLL=vR05_2!A>Ray zvv!||T{awzEu1uIn?1JsU?ZD}1Y~OO(D(dZ8?VFb$i4|>j#pl*=iSf!aaV5Qj%&n= zQd#$Y%RM3KV+HpRcQi?|?gm1Azylk8oY}Pvd-}0&3A^f8SlRSn4X=3%DS9G#A5PGf z#P@>k4MAKK9e|PD^Ka>Y(fxQjA)e8&vF@#~CXA=hF(a$*x}>mYIN=JJlH=Tp@)G~-0meHR+vLwS$Ueq-4q5HSTqY0a4zRHQ^>p(x&jeNAXV-Dg#(8I!uG ze|s2OvsZtc5JFN;kW{gW6ji!Soc!980MJmZf2J!+_ssACRdi0cP|iN|MiS6jfFg}R810iqa&qz$-d(SPSrefb$71eMHW*X z4;6|M*v>jneKDGHy*B1OOY01wPrCwb=NG(MbGVjnxl@?}4`1g+G?tuqtI`YnoS|3V zpA|i6wn;pMtk7OGUzgg!P=XnW0F|~3hCpIv^~X{WqTv6_u`oN38@1?bP5o449y+6X zEmotGBh)^xO}6^&%MH}wDxn3n)(jKsnY6%X7)4tF8+U)Q6AoxRL*;=XVIvtBYS?C7 zj$d9m(;Km{giFkx^$kd_AJa&uMoa-yUKgUc;S6!;t(p6Eo^V6lhAjf7Du^fTzY-rD zzB245WOO?k{CU!)`uYV!k!0rFgKuB0P%x>H>C%>sS?&0#AW9M@@tA6UlPPIoX-HV9 zSeTrK^#|hi1fMj63|8y9qPvS^2++X_(NynRv6I4wtHvM zZwcLI6icGJ_!4tzUcCf!p)n?*sJEo9)xK1D$I{K zX|TK-zJ7Qy>;~(z@z2+StDt^#rX&ye4V1zsh%*K_#Ry}fCE^94E+b&ba(Bm6yBBL{lJWl z$i|NMZ`M08Vj%DYqDSSOC0v-DJKT-=9<9)Wy)GqK6LJV&K#3C_VPFNe`PFsU(?mTM zRF{SfYfxDS1QLy+T38z^J`)X~m0i#-)R1nxD|GGnYatDGs||33fZo{bOD635Cl6I0 z6I6LV+E|5gt<%OPws+iNp&1D!vbB_)a0 z+u$rr$KhYCyl1xEWg+{HYcm-3;z)~Q`Ooy`Z-RsPK?_1k&)xM&eWkSfjy#4r8}hZb zF;%t-%GPEEx_POg?o1VAivF{O*v4e21R)F(%S`f#E63Ey`M|2IyRnua*+fuRJJ8hFP$dxWDYi=}2q z&IqVqJI!x~U+woaSl{Rl{7P*^C9mMKfsd}=moX$^`sn#9DBA}~#K?v`mx{kqVB2%W zaU?NazBa9JPY0JMVXoXHn?U&XQe>ZTYrwSds%cGQl5|CGq9b`7NG}y=pIub+k!}l7 zWu{QfxIBE6(o6hbx>Kh@zT#EQx%_FXFQ-OeaLQsB?c6ED_)Y|cvp5oPe#kk$Z=df^ zKtFdpq2%< z3o5v%4k+Ulyl@)j|JH-E(;+4#`?*kB{z!#@&7So%EV2Y(C5QgDg+!@ zLuY@Ou+QFzNIvPglbCf%oBe#TcEsP9Gglt+eC6Ojr?cV`UIEajAcVUnOgo=EnW>x-r)vb1ZW3WqWwg?2US z9XZRK-|t-+8=s%BTb(7`Qpoj2+RXixHUZKL6beB4(iLt<8`~b+4xLN+i)u6TS%uiq zI&6q}d23#7L*EEYnrV?q-ZHpE zUl=*RvO*xA%Y`O?V9l4Hiz7Z!hru8IUKF))B8*33B%%r#??;K-1CQOyLnH3bzF%Lp zn4DdDl>|?*KXsC&g3%dw%FnTA=v5aUQhRLjh=CJwDRa>)$RsyzO|??-X`~oTZBd>S64JVsl5!9b!+m|= z$3TZo(oAW=ia1%pN@gbdL7Z>qS#D8M?^NhrRkFBBL_iUpMU5c~j_i3R@#p;~TC0_Q zYiO4X>pr+Vw|OycZ{^FNF7Vbb-U<7YlR&TM8?a(vhCF|{KLHsc#hG&}zBBgtPsH?1 zjRrKe9xgJihCKMX5#KLC6ebrt-F27&^<9skCZ1m6Kx(wq(l6-W&NP_2KtiZTsub;N zbJR+U11^Td%%rt*Km$_LL@IkAS)#)oa&aqGTGA|Jc9Ppwj=(3t8bf*VM!y!;F`-Ua z;}6o72n3C1PUy|sy7U1;M%q01^-B{|t0&iMLWQW>GzXprv%Pa6bav&s_S(bi=YV&1 zBHTBg5xsQ%8^z~bK5gq@=oj#PpaGr%)|DobTSs1wIdROPfjWd~P2qm)L70v$zu{BY zTGA-kS`-BD)S46r*r9V!Yotl&*_0ys*~a@%WjVda5vJ>6>DSr6kaOUnqCj#|G!yI} z-vLo6fh#uZPTsW>Jw(XB^2W%cnkJP(z8q;ZFTh6X&|(^6!JRB8)nvNTxsz+mk5p1? zPQic2R$!4=zyn3$pY`hPZy6mDPzjZ>l-12p62?xjY8Y0{Aj4Sfp0~BIa~5w5xepyX zT+=^fydM~!IsXPM(DvJea*ht6NV>QN!9@-_H<9zi|7cP%z({spL8g(z_G3OEm1SV` zwT|rQq_IjV^URZ|!mQkr>*Cp-f|%hSz?fq&@X;)X;?PwI2m)@;uW$s;LK5!DBu0uI z1yGIk)Mt2hEi&el^h!h>Xw;CYz_LjkPZmQXdP#+if{k3Tp+Qxlzd(f2zp@K6(X&w{ zeOj(a;R(TAU9TKN%xv24-=o7+aDgJA)%q?x4|!P$=)T_PTZ47pPT8*(eaDNd77iGO zn*^;O*_3u0_Tz*7(3mxCSt&W9Q7T|?dSwODwl2^^o>^855U#@{;pHQm_G6T;`J~ZC zLz5QJ1e(10@0u#SRfs-?nL=((CT8|M{zY6ClnMnbKUsG#RREdW#q=eFIY4zrag{Xh zUI?AGX*36&SIZgdG9ye%3yHc6zB2EpOSP;sF{O5LukZ6BfFnkNMo@flva81fBhcByv3>IZ9q@Nn}$JtOjpeFcHRquua9UfpT~` z^cPfqyE}epmU(eF_Lg%>wEAn#HHADK%~9H2X&SK$IXakOgFVbxR>R!Td+e^|Lko51 z9D})ig_rk7*B51C547x5p)6^xU=1B}eZA25Hpdg6dF$+Alg{a)c=!bVtR7PvVY5?* zoA9XC)-Q3@9cbI|Y(D3=JX}JhEuu{3gtSR8#%uF%w-+q#D{qy^0DKGWf0W?7o2|Km z2RGQI*b~X#pcKRHWM4~Z5qtiZis8eR{0&n@y{&<$n89~c)@zZ!D#yx9R*X!Xf)N7v>4#758OD9_%ZCde0 z5!rYK+{Z2m<9_OZJ)RR#x@|aO!15L+roVn*QgE4h4EX*+zCCQ%jmn#0hH@@-g9yD@ zfI>L)WMe@TJ2 znDZgbeHv;YtF10B`vl8vIz0EyEF`GW$;xQi@8PC82=2O}Ivy-Thg_XqWAca+$xvqu z7I1a7Vqg=I?0|2Db`g}FAS{gS#qAnCSLD;>^LW|M=jSOD^UV-`;jCa=jcZ(+9u;i; zXx{M!y?^vi%ob6E$^XC;0hBHKU&i&nv9$}VPC^YGPE6E2gpS!SL(bxrGWHfi5KeyV z3S&clXFIU9D!LPfa_2k3c@MWMS(J>p%+ngxp+@0CzH=+-rTB8Xyk13*9Q~G$ORNBb zc-v#WOAf-{cURMqV#Yt*V*l~`#Ua9OHBR2;MGUeeN(@8Y_HW0`@+CpQUpL5RYNYbl zL;XTWLb(@A?x!t#W;L=MtXmk-a0<^|aEVQ2pU+InIx^Js$s3g}EuO+6=DY5&M-BAL z*uk7eK^JhT==4#Sy4Xhl0skkcsn$c}>`rlz;YLzt8MWYD15s>^HdZSW5`hlBUo(GM z5;RViE;I@9)OirL%#rbfdfFzQubj=<0>Xoc0r$$C*~wh+NpE33Ua{7vXB(ToW}h6- zJDDF-uxqXolrb$@ox6ZS$??$S0w3;?w}wB8g(zlU*Bqqec}Sb<9-Kft%BLe@o!B2V zs`KVKjZ$7m6uzlXM1Sq7)pX9(x>kzmS(~eFYm-kudEC}eX=F!xiW=kS;^Sx>MUTXN z!7*cMe+)6Tpuv}zyHs<*nr=K;lWEzB{N&Q+3d8HGF;r+DFkZ&@VKlxg&8b`L40?BW z#f_60{8z(U0r6*CuFgz0+k)9nusgLjJ8ZV3kk4o1v9Uf<3!ztMrk@PfZ0%j3EY zG`E=T=o6-Hw9(u5-C@E=G6}?)UCE{jw&e+o0m6TJR62JAlE15NX^)Q9bBh~?=)-C9 ot{2YMM66b{zUD|J=@Ny6W(pU{i_FIOK*!~g&Q literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/rma.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/rma.mq5 new file mode 100644 index 0000000000000000000000000000000000000000..da48d8034c8e91e69633c7babb20b26d845b3da9 GIT binary patch literal 7284 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 counted_bars--; + + limit = MathMax(rates_total - counted_bars - Lb, 1); + + + + CopyBuffer(hMAHigh, 0, 0, limit+1, MAHigh); + CopyBuffer(hMALow, 0, 0, limit+1, MALow); + + for(i=limit; i>=0; i--) + { + + Hlv[i]=Hlv[i+1]; + + if (close[rates_total-1-i] > MAHigh[limit-i]) Hlv[i]= 1; + if (close[rates_total-1-i] < MALow[limit-i]) Hlv[i]= -1; + + if(Hlv[i]==-1) + { + ssld[i] = MAHigh[limit-i]; + sslu[i] = MALow[limit-i]; + } + else + { + ssld[i] = MALow[limit-i]; + sslu[i] = MAHigh[limit-i]; + } + + } + +//--- return value of prev_calculated for next call + return(rates_total); + } +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/ssl_channel_chart.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/ssl_channel_chart.mq5 new file mode 100644 index 0000000..9821142 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Smapls/ssl_channel_chart.mq5 @@ -0,0 +1,115 @@ +//+------------------------------------------------------------------+ +//| SSL Channel Chart.mq5 | +//| Copyright 2020, MetaQuotes Software Corp. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2020, MetaQuotes Software Corp." +#property link "https://www.mql5.com" + +//------------------------------------------------------------------ +#property indicator_chart_window +#property indicator_buffers 3 +#property indicator_plots 2 +#property indicator_label1 "Bears" +#property indicator_color1 clrOrange +#property indicator_type1 DRAW_LINE +#property indicator_width1 2 +#property indicator_label2 "Bulls" +#property indicator_color2 clrAqua +#property indicator_type2 DRAW_LINE +#property indicator_width2 2 + + +//------------------------------------------------------------------ + +//---- input parameters +input ENUM_MA_METHOD MA_Method = MODE_SMA; // Method +input int Lb = 10; +//---- buffers + +double ssld[]; +double sslu[]; +double Hlv[]; + +int hMAHigh; +int hMALow; +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + + SetIndexBuffer(0, ssld, INDICATOR_DATA); + SetIndexBuffer(1, sslu, INDICATOR_DATA); + SetIndexBuffer(2, Hlv, INDICATOR_CALCULATIONS); + + hMAHigh = iMA(_Symbol, PERIOD_CURRENT, Lb, 0, MA_Method, PRICE_HIGH); + hMALow = iMA(_Symbol, PERIOD_CURRENT, Lb, 0, MA_Method, PRICE_LOW); + + + if(hMAHigh==INVALID_HANDLE)Print(" Failed to get handle of the iMA indicator"); + if(hMALow==INVALID_HANDLE)Print(" Failed to get handle of the iMA indicator"); + + ArraySetAsSeries(ssld,true); + ArraySetAsSeries(sslu,true); + ArraySetAsSeries(Hlv,true); +//--- + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) + { +//--- + int counted_bars = prev_calculated; + int i,limit; + + double MAHigh[]; + double MALow[]; + + if(counted_bars<0) return(-1); + if(counted_bars>0) counted_bars--; + + limit = MathMax(rates_total - counted_bars - Lb, 1); + + + + CopyBuffer(hMAHigh, 0, 0, limit+1, MAHigh); + CopyBuffer(hMALow, 0, 0, limit+1, MALow); + + for(i=limit; i>=0; i--) + { + + Hlv[i]=Hlv[i+1]; + + if (close[rates_total-1-i] > MAHigh[limit-i]) Hlv[i]= 1; + if (close[rates_total-1-i] < MALow[limit-i]) Hlv[i]= -1; + + if(Hlv[i]==-1) + { + ssld[i] = MAHigh[limit-i]; + sslu[i] = MALow[limit-i]; + } + else + { + ssld[i] = MALow[limit-i]; + sslu[i] = MAHigh[limit-i]; + } + + } + +//--- return value of prev_calculated for next call + return(rates_total); + } +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..af93a95b0a9f6e7b43954ec72589fb6fc513b474 GIT binary patch literal 24624 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 R(eNYpGHLJbt7DF@X1-w8Y=!^; literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.mq5 b/MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.mq5 new file mode 100644 index 0000000..fa68829 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Smapls/tradecontrol_en.mq5 @@ -0,0 +1,505 @@ +//+------------------------------------------------------------------+ +//| TradeControl_en.mq5 | +//| Copyright KlimMalgin | +//| | +//+------------------------------------------------------------------+ +#property copyright "KlimMalgin" +#property link "" +#property version "1.00" + + +datetime start_date = 0; // Date, from which we begin to read history + +int OrdersPrev = 0; // Number of orders at the time of previous OnTrade() call +int PositionsPrev = 0; // Number of positions at the time of previous OnTrade() call +ulong LastOrderTicket = 0; // Ticket of the last processed order + +int _GetLastError=0; // Error code +long state=0; // Order state + +/* + * + * Structure that stores information about positions + * + */ +struct _position +{ + +long type, // Position type + magic; // Magic number for position +datetime time; // Time of position opening + +double volume, // Position volume + priceopen, // Position price + sl, // Stop Loss level for opened position + tp, // Take Profit level for opened position + pricecurrent, // Symbol current price + comission, // Commission + swap, // Accumulated swap + profit; // Current profit + +string symbol, // Symbol, by which the position has been opened + comment; // Comment to position +}; + +int _ExpertPositionsTotal = 0; + +_position PositionList[], // Array that stores info about position + PrevPositionList[]; + + +/* + * + * Structure that stores information about orders + * + */ +struct _orders +{ + +datetime time_setup, // Time of order placement + time_expiration, // Time of order expiration + time_done; // Time of order execution or cancellation + +long type, // Order type + state, // Order state + type_filling, // Type of execution by remainder + type_time, // Order lifetime + ticket; // Order ticket + +long magic, // Id of Expert Advisor, that placed an order + // (intended to ensure that each Expert + // must place it's own unique number) + + position_id; // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + +double volume_initial, // Initial volume on order placement + volume_current, // Unfilled volume + price_open, // Price, specified in the order + sl, // Stop Loss level + tp, // Take Profit level + price_current, // Current price by order symbol + price_stoplimit; // Price of placing Limit order when StopLimit order is triggered + +string symbol, // Symbol, by which the order has been placed + comment; // Comment + +}; + +int _ExpertOrdersTotal = 0; + +_orders OrderList[], // Arrays that store info about orders + PrevOrderList[]; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- +start_date = 0; + +OrdersPrev = OrdersTotal(); +PositionsPrev = PositionsTotal(); + +GetPosition(PrevPositionList); +GetOrders(PrevOrderList); +//--- + return(0); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- + + } +//+------------------------------------------------------------------+ +//| OnTrade function | +//+------------------------------------------------------------------+ +void OnTrade() + { +//--- +GetPosition(PositionList); +GetOrders(OrderList); +datetime dc = TimeCurrent(); +HistorySelect(start_date,dc); + + +Alert("The Trade event occurred"); + +if (OrdersPrev < OrdersTotal()) +{ + OrderGetTicket(OrdersTotal()-1);// Select the last order to work with + _GetLastError=GetLastError(); + Print("Error #",_GetLastError);ResetLastError(); + //-- + if (OrderGetInteger(ORDER_STATE) == ORDER_STATE_STARTED) + { + Alert(OrderGetTicket(OrdersTotal()-1),"Order has arrived for processing"); + LastOrderTicket = OrderGetTicket(OrdersTotal()-1); // Saving the order ticket for further work + } + + + state = OrderGetInteger(ORDER_STATE); + if (state == ORDER_STATE_PLACED) + { + switch(OrderGetInteger(ORDER_TYPE)) + { + case 2: + Alert("Pending order Buy Limit #", OrderGetTicket(OrdersTotal()-1)," accepted!"); + break; + + case 3: + Alert("Pending order Sell Limit #", OrderGetTicket(OrdersTotal()-1)," accepted!"); + break; + + case 4: + Alert("Pending order Buy Stop #", OrderGetTicket(OrdersTotal()-1)," accepted!"); + break; + + case 5: + Alert("Pending order Sell Stop #", OrderGetTicket(OrdersTotal()-1)," accepted!"); + break; + + case 6: + Alert("Pending order Buy Stop Limit #", OrderGetTicket(OrdersTotal()-1)," accepted!"); + break; + + case 7: + Alert("Pending order Sell Stop Limit #", OrderGetTicket(OrdersTotal()-1)," accepted!"); + break; + } + + } + + + +} +else if(OrdersPrev > OrdersTotal()) +{ + state = HistoryOrderGetInteger(LastOrderTicket,ORDER_STATE); + + // If order is not found, generate an error + _GetLastError=GetLastError(); + if (_GetLastError != 0){Alert("Error #",_GetLastError," Order ",LastOrderTicket," is not found!");LastOrderTicket = 0;} + Print("Error #",_GetLastError," state: ",state);ResetLastError(); + + + // If order is fully executed + if (state == ORDER_STATE_FILLED) + { + // Then analyze the last deal + // -- + Alert(LastOrderTicket, "Order executed, going to deal"); + switch(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_ENTRY)) + { + + // Entering the market + case DEAL_ENTRY_IN: + Alert(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_ORDER), + " order invoked deal #",HistoryDealGetTicket(HistoryDealsTotal()-1)); + + switch(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)) + { + case 0: + // If volumes of position and deal are equal, then position has just been opened + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) + && (PositionGetDouble(POSITION_VOLUME) == HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_VOLUME))) + { + Alert("Buy position has been opened on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)); + } + else + // If volumes of position and deal are not equal, then position has been incremented + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) + && (PositionGetDouble(POSITION_VOLUME) > HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_VOLUME))) + { + Alert("Buy position has incremented on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)); + } + break; + + case 1: + // If volumes of position and deal are equal, then position has just been opened + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) + && (PositionGetDouble(POSITION_VOLUME) == HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_VOLUME))) + { + Alert("Sell position has been opened on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)); + } + else + // If volumes of position and deal are not equal, then position has been incremented + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) + && (PositionGetDouble(POSITION_VOLUME) > HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_VOLUME))) + { + Alert("Sell position has incremented on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)); + } + + break; + + default: + Alert("Unprocessed code of type: ", + HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)); + break; + } + break; + + // Âûõîä èç ðûíêà + case DEAL_ENTRY_OUT: + Alert(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_ORDER), + " order invoked deal #",HistoryDealGetTicket(HistoryDealsTotal()-1)); + + switch(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)) + { + case 0: + // If position, we tried to close, is still present, then we have closed only part of it + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) == true) + { + Alert("Part of Sell position has been closed on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL), + " with profit = ", + HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_PROFIT)); + } + else + // If position is not found, then it is fully closed + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) == false) + { + Alert("Sell position has been closed on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL), + " with profit = ", + HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_PROFIT)); + } + break; + + case 1: + // If position, we tried to close, is still present, then we have closed only part of it + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) == true) + { + Alert("Part of Buy position has been closed on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL), + " with profit = ", + HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_PROFIT)); + } + else + // If position is not found, then it is fully closed + if (PositionSelect(HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL)) == false) + { + Alert("Buy position has been closed on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL), + " with profit = ", + HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_PROFIT)); + } + + break; + + default: + Alert("Unprocessed code of type: ", + HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)); + break; + } + break; + + // Reverse + case DEAL_ENTRY_INOUT: + Alert(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_ORDER), + " order invoked deal #",HistoryDealGetTicket(HistoryDealsTotal()-1)); + + switch(HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)) + { + case 0: + Alert("Sell is reversed to Buy on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL), + " resulting profit = ", + HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_PROFIT)); + break; + + case 1: + Alert("Buy is reversed to Sell on pair ", + HistoryDealGetString(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_SYMBOL), + " resulting profit = ", + HistoryDealGetDouble(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_PROFIT)); + break; + + default: + Alert("Unprocessed code of type: ", + HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)); + break; + } + break; + + // Indicates the state record + case DEAL_ENTRY_STATE: + Alert("Indicates the state record. Unprocessed code of direction: ", + HistoryDealGetInteger(HistoryDealGetTicket(HistoryDealsTotal()-1),DEAL_TYPE)); + break; + } + // -- + } + +} + + +if ((PositionsPrev == PositionsTotal()) && (OrdersPrev == OrdersTotal())) +{ + string _alerts = ""; + bool modify = false; + + for (int i=0;i<_ExpertPositionsTotal;i++) + { + if (PrevPositionList[i].sl != PositionList[i].sl) + { + _alerts += "On pair "+PositionList[i].symbol+" Stop Loss changed from "+ PrevPositionList[i].sl +" to "+ PositionList[i].sl +"\n"; + modify = true; + } + if (PrevPositionList[i].tp != PositionList[i].tp) + { + _alerts += "On pair "+PositionList[i].symbol+" Take Profit changed from "+ PrevPositionList[i].tp +" to "+ PositionList[i].tp +"\n"; + modify = true; + } + + } + + for (int i = 0;i<_ExpertOrdersTotal;i++) + { + if (PrevOrderList[i].sl != OrderList[i].sl) + { + _alerts += "Order "+OrderList[i].ticket+" has changed Stop Loss from "+ PrevOrderList[i].sl +" to "+ OrderList[i].sl +"\n"; + modify = true; + } + if (PrevOrderList[i].tp != OrderList[i].tp) + { + _alerts += "Order "+OrderList[i].ticket+" has changed Take Profit from "+ PrevOrderList[i].tp +" to "+ OrderList[i].tp +"\n"; + modify = true; + } + } + + if (modify == true) + { + Alert(_alerts); + modify = false; + } +} + + +GetPosition(PrevPositionList); +GetOrders(PrevOrderList); +OrdersPrev = OrdersTotal(); +PositionsPrev = PositionsTotal(); + +//--- + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- + + } +//+------------------------------------------------------------------+ + + + +void GetPosition(_position &Array[]) + { + int _GetLastError=0,_PositionsTotal=PositionsTotal(); + + int temp_value=(int)MathMax(_PositionsTotal,1); + ArrayResize(Array, temp_value); + + _ExpertPositionsTotal=0; + for(int z=_PositionsTotal-1; z>=0; z--) + { + if(!PositionSelect(PositionGetSymbol(z))) + { + _GetLastError=GetLastError(); + Print("OrderSelect() - Error #",_GetLastError); + continue; + } + else + { + // If the position is found, then put its info to the array + Array[z].type = PositionGetInteger(POSITION_TYPE); + Array[z].time = PositionGetInteger(POSITION_TIME); + Array[z].magic = PositionGetInteger(POSITION_MAGIC); + Array[z].volume = PositionGetDouble(POSITION_VOLUME); + Array[z].priceopen = PositionGetDouble(POSITION_PRICE_OPEN); + Array[z].sl = PositionGetDouble(POSITION_SL); + Array[z].tp = PositionGetDouble(POSITION_TP); + Array[z].pricecurrent = PositionGetDouble(POSITION_PRICE_CURRENT); + Array[z].comission = PositionGetDouble(POSITION_COMMISSION); + Array[z].swap = PositionGetDouble(POSITION_SWAP); + Array[z].profit = PositionGetDouble(POSITION_PROFIT); + Array[z].symbol = PositionGetString(POSITION_SYMBOL); + Array[z].comment = PositionGetString(POSITION_COMMENT); + _ExpertPositionsTotal++; + } + } + + temp_value=(int)MathMax(_ExpertPositionsTotal,1); + ArrayResize(Array,temp_value); + } +//+------------------------------------------------------------------+ + + + +//+------------------------------------------------------------------+ +//| Function GetOrders() | +//+------------------------------------------------------------------+ +void GetOrders(_orders &OrdersList[]) + { + + int _GetLastError=0,_OrdersTotal=OrdersTotal(); + + int temp_value=(int)MathMax(_OrdersTotal,1); + ArrayResize(OrdersList,temp_value); + + _ExpertOrdersTotal=0; + for(int z=_OrdersTotal-1; z>=0; z--) + { + if(!OrderGetTicket(z)) + { + _GetLastError=GetLastError(); + Print("GetOrders() - Error #",_GetLastError); + continue; + } + else + { + OrdersList[z].ticket = OrderGetTicket(z); + OrdersList[z].time_setup = OrderGetInteger(ORDER_TIME_SETUP); + OrdersList[z].time_expiration = OrderGetInteger(ORDER_TIME_EXPIRATION); + OrdersList[z].time_done = OrderGetInteger(ORDER_TIME_DONE); + OrdersList[z].type = OrderGetInteger(ORDER_TYPE); + + OrdersList[z].state = OrderGetInteger(ORDER_STATE); + OrdersList[z].type_filling = OrderGetInteger(ORDER_TYPE_FILLING); + OrdersList[z].type_time = OrderGetInteger(ORDER_TYPE_TIME); + OrdersList[z].magic = OrderGetInteger(ORDER_MAGIC); + OrdersList[z].position_id = OrderGetInteger(ORDER_POSITION_ID); + + OrdersList[z].volume_initial = OrderGetDouble(ORDER_VOLUME_INITIAL); + OrdersList[z].volume_current = OrderGetDouble(ORDER_VOLUME_CURRENT); + OrdersList[z].price_open = OrderGetDouble(ORDER_PRICE_OPEN); + OrdersList[z].sl = OrderGetDouble(ORDER_SL); + OrdersList[z].tp = OrderGetDouble(ORDER_TP); + OrdersList[z].price_current = OrderGetDouble(ORDER_PRICE_CURRENT); + OrdersList[z].price_stoplimit = OrderGetDouble(ORDER_PRICE_STOPLIMIT); + + OrdersList[z].symbol = OrderGetString(ORDER_SYMBOL); + OrdersList[z].comment = OrderGetString(ORDER_COMMENT); + + _ExpertOrdersTotal++; + } + } + + temp_value=(int)MathMax(_ExpertOrdersTotal,1); + ArrayResize(OrdersList,temp_value); + + } +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/Smapls/wma.ex5 b/MQLTestWorkspace/BKPS/BKP/Smapls/wma.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..322c9c7b69e17533e520fe0fc522a7b06fd35398 GIT binary patch literal 12470 zcmd6NLv$uUx9u0(wv&!+J006j$F^KL)F2q*dX?aVV1zD?|mt3DN&Z{sYASN&E+Pg8%^j zdjSBDkpGba$RVSX#yd{BVi*R1QJ}}$*b<2AY?#mJGP052*}#qi3F4E=RcIob{P#X# zfGxld;0|yAm;+1!W&o#ua+v@O07d`@faYH;12F!_82}Uj&i^W%{vpSItkS>O;YB))_*>X{&}?iU#|ZDUmoK> zrwsq*|LZunLg%e8Hdosu%G7-Yl^1Gd+%wDLf00k7bt}5C0=mCkd!}j2CG^VgzdMd} zG6L}hpHuA`R9rbN4D;tCuf0CMUAh1TLq%S*1ei*r7j&hOiMTlW;BuGK-3~T;t{WUa zCl8FuLDK~(TZFW5SPTuCmv;|@XLRwnQ7jYN4lvh_xa`DBgWS(&;3=1ZG}NBGbZE<& z1YcrGr@-Z&#OE2gaPfB)BHk2IA_7yr9#g}uI_qTzH>(hI4iU!5DIHt<@l3vxYSc#n z&a*aVhEtlcT+~tH|A1BkhBU^qkl>#E1#T4%T1Uh}147Jd&;U^YOe$nYpAAgEXZ z>!qJed&+moPl9?aS?soG8;-&R)vJNV|fowz|^ltgYSb5;JrWQ0g!Gmbcp;+k>c&@-EMeTwL z{?m1)_&owsX56F6>KrHmo8IyMw6e!U>LAwE<;2aR^Poi=q9PLaSk2RI`DM?iiSt@^ zchdfYj`rN*>sFPbuqob`0X&QC^>o7Uc0zj){?~5nrryd#jQNVe3FH_Fgrs}4Ud1HI zh05lVT4;6aZTV;dqJ_j=EHQ&&6e!*8k<(A྽#lEAb63x6~F+;}%)|=>s?Gs63 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.ex5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..b043c3cec51f9c40f18f37577950f08b829581c3 GIT binary patch literal 66940 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

06y&-79R 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%0DVvf^t3Ce2J;h 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 z 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

ej(?!qcE`5vxFbHE%0kHdJ7X?PqTuQFK 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Experts/x-saherelm.xea.mq5 b/MQLTestWorkspace/Experts/x-saherelm.xea.mq5 new file mode 100644 index 0000000..381c710 --- /dev/null +++ b/MQLTestWorkspace/Experts/x-saherelm.xea.mq5 @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ---------------------------------------- +// Name: X121EA +// Description: this is an expert controller +// advisors which provides a mechanism for use them ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121EA" +#property strict + +// +// START Definitions ... +// + +// +// Common Library ... +#include "../Classes/x-saherelm.x121.xea.class.mq5" + +// +#define ShortName "X121EA" + +// +// END Definitions ... +// + +// +// START Inputs ... +// + +// +// EA ... +input group "Common"; +input bool xEAEnable = true; // Enable EA +input int xEASlippage = 10; // Slippgae +input ulong xEAMagicNumber = 1604056; // Magic Number + +// +// Signals ... +input group "Signals"; +input bool xEAEnableLongs = true; // Enable Long Trades +input bool xEAEnableShorts = true; // Enable Short Trades + +// +// Risk Management ... +input group "Risk Management"; +input int xEAMaxOpenPositions = 15; // Max Allowed Open Positions +input double xEAMaxAllowedDrawDownFactor = 0.15; // Max Allowed Drawdown Factor + +// +// Alerts ... +input group "Alerts"; +input bool xEAEnableAlerts = true; // Enable Events Alert +input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day +input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month + +// +// END Inputs ... +// + +// +// START Including Providers ... +// + +// +// Logger Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +XSCX121EA *mX121EA; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = ShortName; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + InitEAInstance(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // De Initialize XEA Providers ... + delete mX121EA; +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Prevent Going Forward if user Disable it ... + if (xEAEnable) + { + mX121EA.OnTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + mX121EA.OnTrade(); +} + +// +// Handle Signal Event ... +void OnSignalConditionsRecieved(X121MarketConditions &info) +{ +} + +// +// Handle StopLoss Event ... +void OnStopLossTriggered(const XDeal &deal) +{ +} + +// +// Handle TakeProfit Event ... +void OnTakeProfitTriggered(const XDeal &deal) +{ +} + +// +// Handle Deals Changed Event ... +void OnDealsChangedHandler(int count) +{ +} + +// +// Handle Order Changed Event ... +void OnOrdersChangedHandler(int count) +{ +} + +// +// Handle Position Changed Event ... +void OnPositionsChangedHandler(int count) +{ +} + +// +// Handle Trade State Changed ... +void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) +{ +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + // Validate Args ... + result = + // + xEASlippage > 0 && + xEAMagicNumber > 0 + // + // TODO: add new validations here ... + // + ; + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// Initialize X121EA Class Instances ... +void InitEAInstance() +{ + // + mX121EA = new XSCX121EA( + _Symbol, + _Period, + xEAMagicNumber, + xEASlippage, + OnStopLossTriggered, + OnTakeProfitTriggered, + OnDealsChangedHandler, + OnOrdersChangedHandler, + OnPositionsChangedHandler, + OnTradeStateChangedHandler, + OnSignalConditionsRecieved); +} +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xama.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xama.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..ef90b9ce30da37f5a1d93aaf8b3927d16126e716 GIT binary patch literal 5204 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

p_CHn@DbR!#Ip zuamDP8dvy58%LJtCSL9QpnOt-?ofPls)aG-Ebwu;-Rx3$zw79znUWJZ#xDRGNA0d3@vNHw;MTz0#EH>!9aI>!zVZae-2hQ^_uy+wQC_Bqh(#k zp*ythO#WYXx{TMGp@Mgypl9r>Q)L!J&1szI z>iefNZM!nGD~Zb+qCpus^@8|ztV*{;!*-KDYh2m{npUo@bIUoHfkVMWA5Hx#HSAGm zqK-K`blU0NXOG<9YhHw0uarBlQr};n@ja&N;CI_B-wkG8s4YDtH`!Zgpe=LC@L5sr zqDdfTGk!ckWxIR=mjlkh5=7IGcjvWrXdKK$L}VUJ1PYMRdn9`p06}hBipq3$S#`EM&_}*}PX)+f4kOh%2$AK_T zdr77SZ6K0s^Ibf_owf3)L8RFxyscYZ?vt)>HGxAsmjMlhcq8RLL#s+>FW-a;u2E)K zPpd|Mb490Bse5Hn70)NYNMP7$6PG(Jp#ed*U>Sz&_@SZ%1xo6ItiRw2S=ZW|w;2Vf->mS|U+E zF`}Mh!O>lwG$l6Z- zYj>RcJ|FRIK{JS8ID{?TnU-NvIQ%F=ZqfEtbd5A&=9>t!?>J?Q9i(7+d@qY5>UaSOtWFzR7g?Er|4j68eW==Wqg(z`yo*z zy`>K#a3iS!Q?Xzqo!LLhs}%BMT(y5Q1oO=ZForzl?ZUddLZu2<``~)` z5zvk(rF>)IVk{gOmk&Vaeg?&dpk?|DLyEA9GMgy79mf9#gc#DRI= 2) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xama", + // + // Inputs ... + // + // Makret ... + "", + // + // Length ... + mLength, + // + // Fast EMA Length ... + mFastEMA, + // + // Slow EMA Length ... + mSlowEMA, + // + // Shift ... + mMaShift, + // + // Applied To ... + mAppliedTo, + // + // Presentation ... + "", + // + // Show Line ... + mShowLine + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XAMAInputs GetConfig() + { + // + XAMAInputs result; + + // + result.length = mLength; + result.fastEMA = mFastEMA; + result.slowEMA = mSlowEMA; + result.maShift = mMaShift; + result.appliedTo = mAppliedTo; + result.showLine = mShowLine; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XAMAInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mFastEMA = config.fastEMA; + mSlowEMA = config.slowEMA; + mMaShift = config.maShift; + mAppliedTo = config.appliedTo; + mShowLine = config.showLine; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // VALUE ... + ArraySetAsSeries(valueBuffer, true); + CopyBuffer( + mHandler, + XAMA_LINE, + barIndex, + mLoopbackBars, + valueBuffer); + + // + // STATE ... + ArraySetAsSeries(stateBuffer, true); + CopyBuffer( + mHandler, + XAMA_STATE_LINE, + barIndex, + mLoopbackBars, + stateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XAMAInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XAMAInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + result.value = valueBuffer[barIndex]; + + // + ENUM_XAMA_STATES state = (ENUM_XAMA_STATES)stateBuffer[barIndex]; + ENUM_XAMA_STATES prevState = (ENUM_XAMA_STATES)stateBuffer[barIndex + 1]; + result.state = state; + + // + result.isBullish = state == X_XAMA_BULLISH; + result.isBearish = state == X_XAMA_BEARISH; + result.isNeutural = state == X_XAMA_NEUTURAL; + + // + result.isSwitchedBullish = + state == X_XAMA_BULLISH && prevState != X_XAMA_BULLISH; + result.isSwitchedBearish = + state == X_XAMA_BEARISH && prevState != X_XAMA_BEARISH; + result.isSwitchedNeutural = + state == X_XAMA_NEUTURAL && prevState != X_XAMA_NEUTURAL; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Fast EMA Length ... + int mFastEMA; + // + // Slow EMA Length ... + int mSlowEMA; + // + // Shift ... + int mMaShift; + // + // Applied To ... + ENUM_APPLIED_PRICE mAppliedTo; + // + // Presentation ... + // + // Show Line ... + bool mShowLine; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..7f6fce1dbb09b6ab5ac8007b82dee9adab85e758 GIT binary patch literal 5662 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.mq5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.mq5 new file mode 100644 index 0000000..414a604 --- /dev/null +++ b/MQLTestWorkspace/Helpers/x-saherelm.x121.xcc.helper.class.mq5 @@ -0,0 +1,293 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXCCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +struct XCCInputs +{ + // + // Chart Style ... + color upColor; // Up Color + color downColor; // Down Color + color lineColor; // Line mode and Doji candlestick Color + color bearishColor; // Bullish Color + color bullishColor; // Bearish Color + color volumesColor; // Volumes Color + + // + // Presentation ... + bool showCandles; // Show Candles +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXCCHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Constructor ... + void XSCXCCHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) : XSCBaseHelper(symbol, period) + { + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXCCHelper() + { + } + + // + // START Properties ... + // + + // + // Show Candles ... + bool ShowCandles( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowCandles == show) + { + return true; + } + + // + mShowCandles = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XCC" + GetTagPrefix(); + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) {} + + // + virtual int GetMaxLength() + { + // + int result = -1; + + // + result = 2; + + // + return result; + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + // + // Up Color ... + mUpColor, + // + // Down Color ... + mDownColor, + // + // Line mode and Doji candlestick Color ... + mLineColor, + // + // Bullish Color ... + mBearishColor, + // + // Bearish Color ... + mBullishColor, + // + // Volumes Color ... + mVolumesColor, + // + // Presentation ... + "", + // + // Show Candles ... + mShowCandles + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XCCInputs GetConfig() + { + // + XCCInputs result; + + // + result.upColor = mUpColor; + result.downColor = mDownColor; + result.lineColor = mLineColor; + result.bearishColor = mBearishColor; + result.bullishColor = mBullishColor; + result.volumesColor = mVolumesColor; + result.showCandles = mShowCandles; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XCCInputs &config) + { + // + bool result = false; + + // + mUpColor = config.upColor; + mDownColor = config.downColor; + mLineColor = config.lineColor; + mBearishColor = config.bearishColor; + mBullishColor = config.bullishColor; + mVolumesColor = config.volumesColor; + mShowCandles = config.showCandles; + + // + result = Init(); + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Chart Style ... + // + // Up Color ... + color mUpColor; + // + // Down Color ... + color mDownColor; + // + // Line mode and Doji candlestick Color ... + color mLineColor; + // + // Bullish Color ... + color mBearishColor; + // + // Bearish Color ... + color mBullishColor; + // + // Volumes Color ... + color mVolumesColor; + + // + // Presentation ... + // + // Show Candles ... + bool mShowCandles; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xche.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xche.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..e6c2a36e4151be49463b0c3c32b8c3e64620539a GIT binary patch literal 5566 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 9 && + mLoopback >= 0; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xche", + // + // Inputs ... + // + // Market ... + "", + // + // Length ... + mLength, + // + // Loopback ... + mLoopback, + // + // 1st Multiplier ... + mMultiplier1, + // + // 2nd Multiplier ... + mMultiplier2, + // + // Calculation ... + "", + // + // Up Zone Applied to ... + mUpAppliedTo, + // + // Down Zone Applied to ... + mDownAppliedTo, + // + // Presentation ... + "", + // + // Show 1st Long Exit ... + mShowLongExit1Line, + // + // Show 1st Short Exit ... + mShowShortExit1Line, + // + // Show 2st Long Exit ... + mShowLongExit2Line, + // + // Show 2st Short Exit ... + mShowShortExit2Line + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XCHEInputs GetConfig() + { + // + XCHEInputs result; + + // + result.length = mLength; + result.loopback = mLoopback; + result.multiplier1 = mMultiplier1; + result.multiplier2 = mMultiplier2; + result.upAppliedTo = mUpAppliedTo; + result.downAppliedTo = mDownAppliedTo; + result.showLongExit1Line = mShowLongExit1Line; + result.showShortExit1Line = mShowShortExit1Line; + result.showLongExit2Line = mShowLongExit2Line; + result.showShortExit2Line = mShowShortExit2Line; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XCHEInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mLoopback = config.loopback; + mMultiplier1 = config.multiplier1; + mMultiplier2 = config.multiplier2; + mUpAppliedTo = config.upAppliedTo; + mDownAppliedTo = config.downAppliedTo; + mShowLongExit1Line = config.showLongExit1Line; + mShowShortExit1Line = config.showShortExit1Line; + mShowLongExit2Line = config.showLongExit2Line; + mShowShortExit2Line = config.showShortExit2Line; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // LEVEL 1 .. + + // + // LONG Exit ... + ArraySetAsSeries(longExit1Buffer, true); + CopyBuffer( + mHandler, + XCHE_1ST_LONG_EXIT_LINE, + barIndex, + mLoopbackBars, + longExit1Buffer); + + // + // SHORT Exit ... + ArraySetAsSeries(shortExit1Buffer, true); + CopyBuffer( + mHandler, + XCHE_1ST_SHORT_EXIT_LINE, + barIndex, + mLoopbackBars, + shortExit1Buffer); + + // + // LEVEL 2 .. + + // + // LONG Exit ... + ArraySetAsSeries(longExit2Buffer, true); + CopyBuffer( + mHandler, + XCHE_2ND_LONG_EXIT_LINE, + barIndex, + mLoopbackBars, + longExit2Buffer); + + // + // SHORT Exit ... + ArraySetAsSeries(shortExit2Buffer, true); + CopyBuffer( + mHandler, + XCHE_2ND_SHORT_EXIT_LINE, + barIndex, + mLoopbackBars, + shortExit2Buffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XCHEInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XCHEInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double longExit1 = longExit1Buffer[barIndex]; + double longExit1Prev = longExit1Buffer[barIndex + 1]; + double shortExit1 = shortExit1Buffer[barIndex]; + double shortExit1Prev = shortExit1Buffer[barIndex + 1]; + + // + double longExit2 = longExit2Buffer[barIndex]; + double longExit2Prev = longExit2Buffer[barIndex + 1]; + double shortExit2 = shortExit2Buffer[barIndex]; + double shortExit2Prev = shortExit2Buffer[barIndex + 1]; + + // + result.longExit1 = longExit1; + result.shortExit1 = shortExit1; + result.longExit2 = longExit2; + result.shortExit2 = shortExit2; + + // + result.isLongExit1Start = + longExit1 != EMPTY_VALUE && + longExit1Prev == EMPTY_VALUE; + + // + result.isShortExit1Start = + shortExit1 != EMPTY_VALUE && + shortExit1Prev == EMPTY_VALUE; + + // + result.isLongExit2Start = + longExit2 != EMPTY_VALUE && + longExit2Prev == EMPTY_VALUE; + + // + result.isShortExit2Start = + shortExit2 != EMPTY_VALUE && + shortExit2Prev == EMPTY_VALUE; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Loopback ... + int mLoopback; + // + // 1st Multiplier ... + double mMultiplier1; + // + // 2nd Multiplier ... + double mMultiplier2; + // + // Calculation ... + // + // Up Zone Applied to ... + ENUM_APPLIED_PRICE mUpAppliedTo; + // + // Down Zone Applied to ... + ENUM_APPLIED_PRICE mDownAppliedTo; + // + // Presentation ... + // + // Show 1st Long Exit ... + bool mShowLongExit1Line; + // + // Show 1st Short Exit ... + bool mShowShortExit1Line; + // + // Show 2st Long Exit ... + bool mShowLongExit2Line; + // + // Show 2st Short Exit ... + bool mShowShortExit2Line; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xct.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xct.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..9e720442ec1aab46631aa3f977f209f67fd74a9e GIT binary patch literal 6052 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 J#~iIx{tFd|s|Nr8 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xhk.helper.class.mq5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xhk.helper.class.mq5 new file mode 100644 index 0000000..ff6bdd2 --- /dev/null +++ b/MQLTestWorkspace/Helpers/x-saherelm.x121.xhk.helper.class.mq5 @@ -0,0 +1,427 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXHKHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XHKInputs +{ + // + // Presentation ... + bool drawCandles; // Draw Hiken Ashi Candle + bool drawCandleLines; // Show HikenAshi Lines +}; + +// +// Index of Lines ... +enum ENUM_XHK_BUFFERS +{ + // + // Main Requirements ... + XHK_OPEN_LINE = 0, + XHK_HIGH_LINE = 1, + XHK_LOW_LINE = 2, + XHK_CLOSE_LINE = 3, +}; + +// +// Retrieve Info Model ... +struct XHKInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double open; + double high; + double low; + double close; + + // + // Conditions ... + + // + // Detect Candle is Bullish or not ... + bool isBullish; + + // + // Detect Candle is Bearish or not ... + bool isBearish; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXHKHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double openBuffer[]; + double highBuffer[]; + double lowBuffer[]; + double closeBuffer[]; + + // + // Constructor ... + void XSCXHKHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + // + // Indicator Properties ... + // + // Presentation ... + // + // Draw Hiken Ashi Candle ... + ) : XSCBaseHelper(symbol, period) + { + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXHKHelper() + { + } + + // + // START Properties ... + // + + // + // Draw Candles ... + bool DrawCandles( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mDrawCandles == show) + { + return true; + } + + // + mDrawCandles = show; + result = Init(); + + // + return result; + } + + // + // Show HikenAshi Lines ... + bool DrawCandleLines( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mDrawCandleLines == show) + { + return true; + } + + // + mDrawCandleLines = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XHK" + GetTagPrefix(); + } + + // + virtual int GetMaxLength() + { + // + int result = -1; + + // + result = 2; + + // + return result; + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xhk", + // + // Inputs ... + // + // Presentation ... + "", + // + // Draw Hiken Ashi Candle ... + mDrawCandles, + // + // Show HikenAshi Lines ... + mDrawCandleLines + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XHKInputs GetConfig() + { + // + XHKInputs result; + + // + result.drawCandles = mDrawCandles; + result.drawCandleLines = mDrawCandleLines; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XHKInputs &config) + { + // + bool result = false; + + // + mDrawCandles = config.drawCandles; + mDrawCandleLines = config.drawCandleLines; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // OPEN ... + ArraySetAsSeries(openBuffer, true); + CopyBuffer( + mHandler, + XHK_OPEN_LINE, + barIndex, + mLoopbackBars, + openBuffer); + + // + // HIGH ... + ArraySetAsSeries(highBuffer, true); + CopyBuffer( + mHandler, + XHK_HIGH_LINE, + barIndex, + mLoopbackBars, + highBuffer); + + // + // LOW ... + ArraySetAsSeries(lowBuffer, true); + CopyBuffer( + mHandler, + XHK_LOW_LINE, + barIndex, + mLoopbackBars, + lowBuffer); + + // + // CLOSE ... + ArraySetAsSeries(closeBuffer, true); + CopyBuffer( + mHandler, + XHK_CLOSE_LINE, + barIndex, + mLoopbackBars, + closeBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XHKInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XHKInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double open = openBuffer[barIndex]; + double high = highBuffer[barIndex]; + double low = lowBuffer[barIndex]; + double close = closeBuffer[barIndex]; + + // + result.open = open; + result.high = high; + result.low = low; + result.close = close; + + // + result.isBullish = open < close; + result.isBearish = open >= close; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Presentation ... + // + // Draw Hiken Ashi Candle ... + bool mDrawCandles; + // + // Show HikenAshi Lines ... + bool mDrawCandleLines; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..fd2a79462483d63c08e8f3d7ffd23ef9a41a8110 GIT binary patch literal 5920 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.mq5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.mq5 new file mode 100644 index 0000000..63de5c3 --- /dev/null +++ b/MQLTestWorkspace/Helpers/x-saherelm.x121.xhull.helper.class.mq5 @@ -0,0 +1,530 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXHULLHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XHULLInputs +{ + // + // Market ... + int length; // Length + double divisor; // Divisor (Speed) + + // + // Calculation ... + ENUM_APPLIED_PRICE upAppliedTo; // Up Zone Applied to + ENUM_APPLIED_PRICE downAppliedTo; // Down Zone Applied to + + // + // Presentation ... + bool showUpZone; // Show Up Zone + bool showDownZone; // Show Down Zone +}; + +// +// Index of Lines ... +enum ENUM_XHULL_BUFFERS +{ + // + // Main Requirements ... + XHULL_UP_ZONE_LINE = 0, + XHULL_UP_ZONE_STATE_LINE = 1, + XHULL_DOWN_ZONE_LINE = 2, + XHULL_DOWN_ZONE_STATE_LINE = 3, +}; + +// +// Hull States ... +enum XHULL_ZONE_STATES +{ + XHULL_STATE_NEUTURAL = 0, + XHULL_STATE_BULLISH = 1, + XHULL_STATE_BEARISH = 2 +}; + +// +// Retrieve Info Model ... +struct XHULLInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double up; + XHULL_ZONE_STATES upState; + double down; + XHULL_ZONE_STATES downState; + + // + // Conditions ... + + // + bool isUpBullish; + bool isUpNeutural; + bool isUpBearish; + + // + bool isUpSwitchedToBullish; + bool isUpSwitchedToBearish; + bool isUpSwitchedToNeutural; + + // + bool isDownBullish; + bool isDownBearish; + bool isDownNeutural; + + // + bool isDownSwitchedToBullish; + bool isDownSwitchedToBearish; + bool isDownSwitchedToNeutural; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXHULLHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double upBuffer[]; + double upStateBuffer[]; + double downBuffer[]; + double downStateBuffer[]; + + // + // Constructor ... + void XSCXHULLHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) : XSCBaseHelper(symbol, period) + { + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXHULLHelper() + { + } + + // + // START Properties ... + // + + // + // Show Up Zone ... + bool ShowUpZone( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowUpZone == show) + { + return true; + } + + // + mShowUpZone = show; + result = Init(); + + // + return result; + } + + // + // Show Down Zone ... + bool ShowDownZone( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowDownZone == show) + { + return true; + } + + // + mShowDownZone = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XHULL" + GetTagPrefix(); + } + + // + virtual int GetMaxLength() + { + // + int result = -1; + // + result = mLength; + + // + return result; + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Inputs ... + // + result = + mLength >= 9 && + mDivisor >= 0.5; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xhull", + // + // Inputs ... + // + // Market ... + "", + // + // Length ... + mLength, + // + // Divisor (Speed) ... + mDivisor, + // + // Calculation ... + "", + // + // Up Zone Applied to ... + mUpAppliedTo, + // + // Down Zone Applied to ... + mDownAppliedTo, + // + // Presentation ... + "", + // + // Show Up Zone ... + mShowUpZone, + // + // Show Down Zone ... + mShowDownZone + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XHULLInputs GetConfig() + { + // + XHULLInputs result; + + // + result.length = mLength; + result.divisor = mDivisor; + result.upAppliedTo = mUpAppliedTo; + result.downAppliedTo = mDownAppliedTo; + result.showUpZone = mShowUpZone; + result.showDownZone = mShowDownZone; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XHULLInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mDivisor = config.divisor; + mUpAppliedTo = config.upAppliedTo; + mDownAppliedTo = config.downAppliedTo; + mShowUpZone = config.showUpZone; + mShowDownZone = config.showDownZone; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // UP ... + ArraySetAsSeries(upBuffer, true); + CopyBuffer( + mHandler, + XHULL_UP_ZONE_LINE, + barIndex, + mLoopbackBars, + upBuffer); + + // + // UP State ... + ArraySetAsSeries(upStateBuffer, true); + CopyBuffer( + mHandler, + XHULL_UP_ZONE_STATE_LINE, + barIndex, + mLoopbackBars, + upStateBuffer); + + // + // DOWN ... + ArraySetAsSeries(downBuffer, true); + CopyBuffer( + mHandler, + XHULL_DOWN_ZONE_LINE, + barIndex, + mLoopbackBars, + downBuffer); + + // + // DOWN State ... + ArraySetAsSeries(downStateBuffer, true); + CopyBuffer( + mHandler, + XHULL_DOWN_ZONE_STATE_LINE, + barIndex, + mLoopbackBars, + downStateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XHULLInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XHULLInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double up = upBuffer[barIndex]; + XHULL_ZONE_STATES upState = (XHULL_ZONE_STATES)upStateBuffer[barIndex]; + XHULL_ZONE_STATES upStatePrev = (XHULL_ZONE_STATES)upStateBuffer[barIndex + 1]; + + // + double down = downBuffer[barIndex]; + XHULL_ZONE_STATES downState = (XHULL_ZONE_STATES)downStateBuffer[barIndex]; + XHULL_ZONE_STATES downStatePrev = (XHULL_ZONE_STATES)downStateBuffer[barIndex + 1]; + + // + result.up = up; + result.upState = upState; + result.down = down; + result.downState = downState; + + // + result.isUpBullish = upState = XHULL_STATE_BULLISH; + result.isUpBearish = upState = XHULL_STATE_BEARISH; + result.isUpNeutural = upState = XHULL_STATE_NEUTURAL; + + // + result.isUpSwitchedToBullish = upState == XHULL_STATE_BULLISH && + upStatePrev != XHULL_STATE_BULLISH; + result.isUpSwitchedToBearish = upState == XHULL_STATE_BEARISH && + upStatePrev != XHULL_STATE_BEARISH; + result.isUpSwitchedToNeutural = upState == XHULL_STATE_NEUTURAL && + upStatePrev != XHULL_STATE_NEUTURAL; + + // + result.isDownBullish = downState = XHULL_STATE_BULLISH; + result.isDownBearish = downState = XHULL_STATE_BEARISH; + result.isDownNeutural = downState = XHULL_STATE_NEUTURAL; + + // + result.isDownSwitchedToBullish = downState == XHULL_STATE_BULLISH && + downStatePrev != XHULL_STATE_BULLISH; + result.isDownSwitchedToBearish = downState == XHULL_STATE_BEARISH && + downStatePrev != XHULL_STATE_BEARISH; + result.isDownSwitchedToNeutural = downState == XHULL_STATE_NEUTURAL && + downStatePrev != XHULL_STATE_NEUTURAL; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Divisor (Speed) ... + double mDivisor; + // + // Calculation ... + // + // Up Zone Applied to ... + ENUM_APPLIED_PRICE mUpAppliedTo; + // + // Down Zone Applied to ... + ENUM_APPLIED_PRICE mDownAppliedTo; + // + // Presentation ... + // + // Show Up Zone ... + bool mShowUpZone; + // + // Show Down Zone ... + bool mShowDownZone; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..c7831226bc7d6279531490666a1acc66b85c1d8f GIT binary patch literal 5824 zcmdT^Wl$W<|M-8x3Mj`JfeJ_A=Dn&zzF8zKOm+lgR`=4s*sxk$oIV62(tk?e zMwij{pS^MbH-I}J0N@F50N4TS0p0)_03U$o#rXjoFZmmQ#S3fmQda;t16*Dh6@c!` zDEGp-zO4SI^8XqCDE5B20WW|UfcwS#{$*S*^MC8M`Im04m;3qut@J;4i5I~2(rupq zT>L+tC1mGkV_b7M6zv zU~OZpjB$Y$wJ4s$`GD~;)gc`X)&H$AtR}Wt!<7=fnlUVHYpYJXR|{b^Vi2}d@lTaH5kuM-2_Nf9Xyc^Lm>5l z9xnu^9kfeZ1fEKy2fW`(2qA~GA3*J>q!&3rl503g>^XBDoYQoZ;%&h`m)VCkJjM8y zeQLsrlYXdyjs7X|kLx?t&X(VeG5ze>HLQH#BF4tYlZkDY>O3j`d6rc71)SPr{4@;r zjgx)>tq_S$c115_{5zV1ITeb_q~&-r+GC>C$$Po3P$YFX86mNOETku$U|eHw#Lc&m zGRk}%?p*j~Z8wM=+&~kyq zoK|*BT2@VrHOL({-{QT#iCP&Ik%P;95T#n)8tv}o#pj$~mB)ow9dz-2#oLSv=_3(( za%Fhd@Wc$u5@;?(GeAt?a+=`xmzfg951MK5a+3`DEI+|ZKdCSuiX7XIgh4!ui=)>W z@OpKom?ozpqs18wvY*3+gp5}duPvkT(% zj?YhN^bvZ$#ib^5_}}o=z1j9Ji)GsCsnK!THE6jR`1@;biJ=FOl2dAJW^r4j_iQ9L zZh%pWf}38koZ{2$z7P&|Vn*w9mi#Ij9Z4F$WpuWlt_-!m9e$j2Cn_7c*X+Rh4&SG) z*Giw9N1=%xuuR(|eqyG!>8iSdeTa8YWkx0L-7dBopk?Fj{hs?bDzaYbWHJ=vB>oUm zoi`{j0gQmyk~QzA_s|Ab)PU$yS}cN~(!bO~qZ2U1bX97@=7%BuLO7HO8yd=;9SE@9 zX0uz9;{Hk*E1l>ma=00BN3spqZd28nywTk>FMgqkvbhfthri_N&?BA`BS{d`HkDl0 z`0FoWWD?<|3nB7WU$*Sm+4l=gHYp2`M1MCdyRHHyw(LdmaCq+UEc162#)W=v@@ngm zPKH8_A&kzUd4=Z@sBlWHp{?Xj18vw_yNQeB&rpj{PVXDaG-D-yIdd5{H%Lsm4&rOE zLlzD=W_?v>Q)boV*G;%Ak9cS{^Frr#&(tyD#F&!bUTr%}Y_GVjT451*6DU0=wCN&` zOVc3CVIIF-O|35Nm^~w)`$!Kl+44zcQiGlImwC1>)kWsFU9ttZKo$>g&~958UoFa> z*LF*`HE86@CzaMUosq&Y`l&`nD}y9%UsKGfNtSg>ju~rWk3s^m9Wrv%&uFhQvTkyF-JM!B3n;F8<4ATS@e<38lVdM*&U$&PyF=~3450$pfE>3@hp^~uJJRre39gy1k zExc42zsUEg*54)8gRKIIiYS=(3JopI3>u-*U#|H<)P!dG^iz~|BG=24Xq5I0- z?y-jTsPXwen+_$32ujl-U@$W0hi=XkmI~wq*!|iYoTJ64IW%qp_4;qcEI1)iepDIC zl(|#uW;a5#Zk8xN+=7r&GY&^!b*Z_AD*-@ZUzExj)4+I(nXu{9zotw2C&D{}KN;O% zP0qzHCl(+tD$WSe{w%iDv2FBo6J_+t)?$_n+Yy655MX6-Vy#J*W=g4=8`;oz

F z=TD+}W^Gge<2~qmoDP0X$xG`DWW9S&Jw$M~*vm{Vrw(({ZCjq9*`1zYq6J^#FS*ou zZ{X2Rx2*A;MywiNpI`M6Yhiafg-6Kow;W1jdoM%%^gVCgV}i+#{7Oho_P@lUxg1=aoQ>osyq^0b zC=Yq}Mdy#->?55?5e{R~6n^Yp#T-L~ppoV3bYgbyTZeKKtoX@+@0W?PD}r#JEGqqN zGc#oOGS;=TTA#Ta4!Jzq06gZko1}yNu2}wcJ@l|ozo=h(CR8}&VdfOMWNpS&em<3J zi@TKF4^zIdHQt9;xV>@+n=gf7USnKuzVfQ>$z(he$)_}T{4$1~x)yfMWEd26Ht7;5 z`zmfW$v}5C23-whHLxQt6=;vizr}#kKN0zu0JlZ;JcTCc$)8E1hlXy4@zc#c6!x?M zcdX>IQX!)>E^Te|LOjH~$YbUub~8wX{okhO;XbCO0dYFz3&N|M4S{{d;~(@HauXJ| zg}Mmygp~xs^j~RMZcHK5vYEQIKd(A?rtQMfJ~r0ds+X?ta8^0RNk13geM|XOJIWFN zp}{>;xE)igB4qKG)HXU?E<;2dFnQ>&0?ng)$wB70_(f|id(Um|F-AvaT zu-H*OzN5%4_$z>tLNWr&;D75CP2i$NCsIESEcj#beb(rvI~yHVvCxJeR%n_`OHs!P z*ArV&w5mc*X+9^W5Z~uba#8?|ibBxQMMH7+tNI`^+|_F#(&3Iuv%yWOqsBkc34N)vz%bOgITi~ufTF*pTZd&K zu{M5My!CYv(6+g%-8PI?(W${E)L^n6583p(T}_-Amd>>-kFR)2wST~w(`3oPjj$=Y zzNHX!X$fCI%iY^N&Of>(+%IJ(U!6PmvXbzFb@aG$sbguC4gNW&=-n82`NY&eutl?Q z1LY;Ufzn!R=8Z-R{KVM2sthf18IZy;OJ9b-S+9f3Gin0HavHv{Uqw5d_~mTxM#4LK z&#-ty4ex*wP#!n^M})^%U!5oYA@z!U&mpOn;BGwC`2ID1*>aq(!|=vU{m1~ z1G#>h;2S@8deKWlE`i}SnBtmf@x%X z7gE@DOI_E517l`p{-*owXkyX|h@~`}nst{ODJj%Fa$&2^K%V95m0P)ogVmQm7ae}3 z3CKhx=mdQIc62qFcy|S!HYZ6Cp8l*7*g&-Xol!Vj!@(!BOFz%*)QeCukjF;QBPr0+awhMK~z(Q zO1gBM&LiH*=?)-NzfaLGL8PrDbm^0SAC8Fy0VfK`N@pI4blOq2Y*Y_NaXr z1ys`-Fo8XqPff;FC(7i6_AXCqijKgzp-oyl_zrYubIq+BseqKevRSkh{%m}sj(mdl zhCKn=72!v6>T7LYR#znDS3fzE^{21SbKQa$;W^$yib`}(U(Ix0cB8p z$6rxCg6B)#>uD~`WTo`UTbkG+{GIlFQTQ9xV8a-f!y7jWj<8!JivQ>wdv zp7yQ=z=@9G99AqXqSQtD;e+%uV0M-}%9h?LA1)69$U5)WSF^tU6j(L|lySojiACd@ z%7rVf#T}8JC}bhKfG;QVNe|_P>pC|n6L}}?94^~|XBt|oBbgw)Ike5x@1&7@ku_yFW z8gB)`>2UG;u?_H_0DgrAL*EWnvf_vaVpqL>Fw>sf1`cNIch}-aR|?q>5`@Y?K~1Jc z8r(})P7_0SA%{=9foG$+Dkxs5!F6Qp3u9M(*E=$({+4Y#T$0DPs<63Fe6$|#veu^l zWOm75RE@v=#sZlWzCEzMx*E|a%(>;WO(fO9z`mDSN9SR*H9QGYn>ZPd*5lA;-7B%x z#2{^x6#n))%F6s|bJ4LrQw-{r4o1jAwe(vUe{d_&)WM=ZwH(Nh_apS4qAsRBE*H$@ zKB@f?@B`n#bsPV)8eLMGPIf$LV^**r;EWDvMl_R)hr!qBm7H5%_a4Ga8U@m*nQSgz zf#MX)Za&3}*yA`;Hq>cCcoWs!o;MP|xBjMSFdDXqyatkVH8|-m#3?ZUz@!urz;{IQNs{cJVlb|R`S8?69$1~ zi!b{2Iz6JL}Zk!MXKgqQD@zdz8KXyc1+ev-#Jw!X`xtb)Uby@-6dA+?TS@t6S;`yEyFoQ{HR@# zk}~-{l!BJlt?~Xap-lN+GxVpFkF`E*t%9bm#R_zeICh%j*oY+*6ND=GyP|O{QbnR~ zWRtBZOx%vw@VVBMN0m%%P2wwYkrrmvkOGpOSl-hC{hw3X>w4DnRjiCg{DMXNtZa

fy*EZF_T!tpPK?4xrDu=dZXReT?e@GzOf4`9*+WN{kHT6R>FYfvD zOqpc#A-cScbr59Ri9D1o0d_h)W75Yfid%}A?+%+aODubL2XNZn{!3(yL>@}Sy{}kJ z0__*DxBt*Vs#JZAzXK_KUqUOoG}2UCLDQAfc|V2OC!TFE*-6cUj(>EZB@(>Ewp=hv zYErsS{yKLAQNg!#k;Xc7@Jp&RbEZ(2-tsw{@bmX0T=$>pZX7a%%sdrhHjO~#2fp9f zH>cCaq5U%TT7BmQb(!yr?jssl=ZOiezEWqCkRbc{DWhq3R#>VA&lE?WLKFY4p4GO# z!?M(G0y>QH7W782GW8r|DdceFPdnaschipbIb%(C+g*}Dps#oB+Y8wP?V6|Y9jHhf zELZP%zX>jNfBbDTuo`kPmdvtF0oBXwuBJ8V9edR)x=rei25f@Bz}07Z_m&g0Uh3tc zACAdO^{cr&6Gm5Ustp4vm`M3J3}H7sd04ycCc|TqxlbsUt9ns~O>$Meb7UC`3>&g| wg`emX_z^v1cshkjJi!)-H@`;b-|A^&j7J@063qX0xLzI*Kp&}k*EiqrU$R0bR{#J2 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.mq5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.mq5 new file mode 100644 index 0000000..ec79b08 --- /dev/null +++ b/MQLTestWorkspace/Helpers/x-saherelm.x121.xich.helper.class.mq5 @@ -0,0 +1,965 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXICHHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// Inputs ... +struct XICHInputs +{ + // + // TENKANSEN ... + // Tenkan Sen ... + int tenkanSenLength; // Length + ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode; // Calculation Mode + + // + // KIJUNSEN ... + // Kijun Sen ... + int kijunSenLength; // Length + ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode; // Calculation Mode + + // + // SENKOUSPANB ... + // Senkou Span B ... + int senkouSpanBLength; // Length + ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode; // Calculation Mode + + // + // CHIKOUSPAN ... + // Chikou Span ... + ENUM_APPLIED_PRICE chikuoSpanAppliedTo; // Price Type + + // + // Presentation ... + bool showTenkanSen; // Show Tenkan Sen + bool showKijunSen; // Show Kijun Sen + bool showKijunSenPlus; // Show Kijun Sen + + bool showKijunSenNegative; // Show Kijun Sen - + bool showChikouSpan; // Show Chikou Span + bool showSenkouSpanA; // Show Senkou Span A + bool showSenkouSpanB; // Show Senkou Span B + bool showKumo; // Show Kumo + bool shiftKumo; // Shift Kumo to Future +}; + +// +// Index of Lines ... +enum ENUM_XICH_BUFFERS +{ + // + // Main Requirements ... + XICH_TEANKANSEN_LINE = 0, + XICH_KIJUNSEN_LINE = 1, + XICH_CHIKOUSPAN_LINE = 4, + XICH_SENKOUSPANA_LINE = 5, + XICH_SENKOUSPANB_LINE = 6, +}; + +// +// Retrieve Info Model ... +struct XICHInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double tenkanSen; + double kijunSen; + double chikouSpan; + double senkouSpanA; + double senkouSpanB; + double senkouSpanAFuture; + double senkouSpanBFuture; + + // + // Conditions ... + + // + bool isTenkanSenOverKijunSen; + bool isTenkanSenUnderKijunSen; + bool isTenkanSenCrossedOverKijunSen; + bool isTenkanSenCrossedUnderKijunSen; + + // + bool isKumoBullish; + bool isKumoBearish; + bool isFutureKumoBullish; + bool isFutureKumoBearish; + bool isKumoSwitchedToBullish; + bool isKumoSwitchedToBearish; + bool isFutureKumoSwitchedToBullish; + bool isFutureKumoSwitchedToBearish; + + // + bool isTenkanSenOverSenkouSpanA; + bool isTenkanSenUnderSenkouSpanA; + bool isTenkanSenOverFutureSenkouSpanA; + bool isTenkanSenUnderFutureSenkouSpanA; + bool isTenkanSenCrossedOverSenkouSpanA; + bool isTenkanSenCrossedUnderSenkouSpanA; + bool isTenkanSenCrossedOverFutureSenkouSpanA; + bool isTenkanSenCrossedUnderFutureSenkouSpanA; + + // + bool isTenkanSenOverSenkouSpanB; + bool isTenkanSenUnderSenkouSpanB; + bool isTenkanSenOverFutureSenkouSpanB; + bool isTenkanSenUnderFutureSenkouSpanB; + bool isTenkanSenCrossedOverSenkouSpanB; + bool isTenkanSenCrossedUnderSenkouSpanB; + bool isTenkanSenCrossedOverFutureSenkouSpanB; + bool isTenkanSenCrossedUnderFutureSenkouSpanB; + + // + bool isKijunSenOverSenkouSpanA; + bool isKijunSenUnderSenkouSpanA; + bool isKijunSenOverFutureSenkouSpanA; + bool isKijunSenUnderFutureSenkouSpanA; + bool isKijunSenCrossedOverSenkouSpanA; + bool isKijunSenCrossedUnderSenkouSpanA; + bool isKijunSenCrossedOverFutureSenkouSpanA; + bool isKijunSenCrossedUnderFutureSenkouSpanA; + + // + bool isKijunSenOverSenkouSpanB; + bool isKijunSenUnderSenkouSpanB; + bool isKijunSenOverFutureSenkouSpanB; + bool isKijunSenUnderFutureSenkouSpanB; + bool isKijunSenCrossedOverSenkouSpanB; + bool isKijunSenCrossedUnderSenkouSpanB; + bool isKijunSenCrossedOverFutureSenkouSpanB; + bool isKijunSenCrossedUnderFutureSenkouSpanB; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXICHHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double tenkanSenBuffer[]; + double kijunSenBuffer[]; + double chikouSpanBuffer[]; + double senkouSpanABuffer[]; + double senkouSpanBBuffer[]; + + // + // Constructor ... + void XSCXICHHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) : XSCBaseHelper(symbol, period) + { + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXICHHelper() + { + } + + // + // START Properties ... + // + + // + // Show Tenkan Sen ... + bool ShowTenkanSen( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowTenkanSen == show) + { + return true; + } + + // + mShowTenkanSen = show; + result = Init(); + + // + return result; + } + + // + // Show Kijun Sen ... + bool ShowKijunSen( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowKijunSen == show) + { + return true; + } + + // + mShowKijunSen = show; + result = Init(); + + // + return result; + } + + // + // Show Chikou Span ... + bool ShowChikouSpan( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowChikouSpan == show) + { + return true; + } + + // + mShowChikouSpan = show; + result = Init(); + + // + return result; + } + + // + // Show Senkou Span A ... + bool ShowSenkouSpanA( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowSenkouSpanA == show) + { + return true; + } + + // + mShowSenkouSpanA = show; + result = Init(); + + // + return result; + } + + // + // Show Senkou Span B ... + bool ShowSenkouSpanB( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowSenkouSpanB == show) + { + return true; + } + + // + mShowSenkouSpanB = show; + result = Init(); + + // + return result; + } + + // + // Show Kumo ... + bool ShowKumo( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowKumo == show) + { + return true; + } + + // + mShowKumo = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XICH" + GetTagPrefix(); + } + + // + virtual int GetMaxLength() + { + // + int result = -1; + // + result = MathMax(result, mTenkanSenLength); + result = MathMax(result, mKijunSenLength); + result = MathMax(result, mSenkouSpanBLength); + + // + return result; + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Inputs ... + // + result = + (mTenkanSenLength > 2 && + mKijunSenLength > mTenkanSenLength && + mSenkouSpanBLength > mKijunSenLength); + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xich", + // + // Inputs ... + // + // TENKANSEN ... + "", + // + // Length ... + mTenkanSenLength, + // + // Calculation Mode ... + mTenkanSenMode, + // + // KIJUNSEN ... + "", + // + // Length ... + mKijunSenLength, + // + // Calculation Mode ... + mKijunSenMode, + // + // SENKOUSPANA ... + "", + // + // Length ... + mSenkouSpanBLength, + // + // Calculation Mode ... + mSenkouSpanBMode, + // + // CHIKOUSPAN ... + "", + // + // Price Type ... + mChikuoSpanAppliedTo, + // + // PRESENTATION ... + "", + // + // Show Tenkan Sen ... + mShowTenkanSen, + // + // Show Kijun Sen ... + mShowKijunSen, + // + // Show Kijun Sen + ... + mShowKijunSenPlus, + // + // Show Kijun Sen - ... + mShowKijunSenNegative, + // + // Show Chikou Span ... + mShowChikouSpan, + // + // Show Senkou Span A ... + mShowSenkouSpanA, + // + // Show Senkou Span B ... + mShowSenkouSpanB, + // + // Show Kumo ... + mShowKumo, + // + // Shift Kumo to Future ... + mShiftKumo + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XICHInputs GetConfig() + { + // + XICHInputs result; + + // + result.tenkanSenLength = mTenkanSenLength; + result.tenkanSenMode = mTenkanSenMode; + result.kijunSenLength = mKijunSenLength; + result.kijunSenMode = mKijunSenMode; + result.senkouSpanBLength = mSenkouSpanBLength; + result.senkouSpanBMode = mSenkouSpanBMode; + result.chikuoSpanAppliedTo = mChikuoSpanAppliedTo; + result.showTenkanSen = mShowTenkanSen; + result.showKijunSen = mShowKijunSen; + result.showKijunSenPlus = mShowKijunSenPlus; + result.showKijunSenNegative = mShowKijunSenNegative; + result.showChikouSpan = mShowChikouSpan; + result.showSenkouSpanA = mShowSenkouSpanA; + result.showSenkouSpanB = mShowSenkouSpanB; + result.showKumo = mShowKumo; + result.shiftKumo = mShiftKumo; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XICHInputs &config) + { + // + bool result = false; + + // + mTenkanSenLength = config.tenkanSenLength; + mTenkanSenMode = config.tenkanSenMode; + mKijunSenLength = config.kijunSenLength; + mKijunSenMode = config.kijunSenMode; + mSenkouSpanBLength = config.senkouSpanBLength; + mSenkouSpanBMode = config.senkouSpanBMode; + mChikuoSpanAppliedTo = config.chikuoSpanAppliedTo; + mShowTenkanSen = config.showTenkanSen; + mShowKijunSen = config.showKijunSen; + mShowKijunSenPlus = config.showKijunSenPlus; + mShowKijunSenNegative = config.showKijunSenNegative; + mShowChikouSpan = config.showChikouSpan; + mShowSenkouSpanA = config.showSenkouSpanA; + mShowSenkouSpanB = config.showSenkouSpanB; + mShowKumo = config.showKumo; + mShiftKumo = config.shiftKumo; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // Since Ichimoku Has Some Issues ... + mLoopbackBars = 52; + + // + // TENKANSEN ... + ArraySetAsSeries(tenkanSenBuffer, true); + CopyBuffer( + mHandler, + XICH_TEANKANSEN_LINE, + barIndex, + mLoopbackBars, + tenkanSenBuffer); + + // + // KIJUNSEN ... + ArraySetAsSeries(kijunSenBuffer, true); + CopyBuffer( + mHandler, + XICH_KIJUNSEN_LINE, + barIndex, + mLoopbackBars, + kijunSenBuffer); + + // + // CHIKOUSPAN ... + ArraySetAsSeries(chikouSpanBuffer, true); + CopyBuffer( + mHandler, + XICH_CHIKOUSPAN_LINE, + barIndex + mKijunSenLength + 1, + mLoopbackBars, + chikouSpanBuffer); + + // + // SENKOUSPANA ... + ArraySetAsSeries(senkouSpanABuffer, true); + CopyBuffer( + mHandler, + XICH_SENKOUSPANA_LINE, + -1 * (barIndex + mKijunSenLength), + mLoopbackBars, + senkouSpanABuffer); + + // + // SENKOUSPANB ... + ArraySetAsSeries(senkouSpanBBuffer, true); + CopyBuffer( + mHandler, + XICH_SENKOUSPANB_LINE, + -1 * (barIndex + mKijunSenLength), + mLoopbackBars, + senkouSpanBBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XICHInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XICHInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double tenkanSen = tenkanSenBuffer[barIndex]; + double tenkanSenPrev = tenkanSenBuffer[barIndex + 1]; + + // + double kijunSen = kijunSenBuffer[barIndex]; + double kijunSenPrev = kijunSenBuffer[barIndex + 1]; + + // + double chikouSpan = chikouSpanBuffer[barIndex + mKijunSenLength]; + double chikouSpanPrev = chikouSpanBuffer[barIndex + mKijunSenLength + 1]; + + // + double senkouSpanA = senkouSpanABuffer[barIndex + mKijunSenLength]; + double senkouSpanAPrev = senkouSpanABuffer[barIndex + mKijunSenLength + 1]; + + // + double senkouSpanB = senkouSpanBBuffer[barIndex + mKijunSenLength]; + double senkouSpanBPrev = senkouSpanBBuffer[barIndex + mKijunSenLength + 1]; + + // + double senkouSpanAFuture = senkouSpanABuffer[barIndex]; + double senkouSpanAFuturePrev = senkouSpanABuffer[barIndex + 1]; + + // + double senkouSpanBFuture = senkouSpanBBuffer[barIndex]; + double senkouSpanBFuturePrev = senkouSpanBBuffer[barIndex + 1]; + + // + bool isTenkanSenOverKijunSen = + tenkanSen > kijunSen; + bool isTenkanSenUnderKijunSen = + tenkanSen < kijunSen; + bool isTenkanSenCrossedOverKijunSen = + tenkanSen > kijunSen && + tenkanSenPrev <= kijunSenPrev; + bool isTenkanSenCrossedUnderKijunSen = + tenkanSen < kijunSen && + tenkanSenPrev >= kijunSenPrev; + + // + bool isKumoBullish = + senkouSpanA > senkouSpanB; + bool isKumoBearish = + senkouSpanA < senkouSpanB; + bool isFutureKumoBullish = + senkouSpanAFuture > senkouSpanBFuture; + bool isFutureKumoBearish = + senkouSpanAFuture < senkouSpanBFuture; + bool isKumoSwitchedToBullish = + senkouSpanA > senkouSpanB && + senkouSpanAPrev <= senkouSpanBPrev; + bool isKumoSwitchedToBearish = + senkouSpanA < senkouSpanB && + senkouSpanAPrev >= senkouSpanBPrev; + bool isFutureKumoSwitchedToBullish = + senkouSpanAFuture > senkouSpanBFuture && + senkouSpanAFuturePrev <= senkouSpanBFuturePrev; + bool isFutureKumoSwitchedToBearish = + senkouSpanAFuture < senkouSpanBFuture && + senkouSpanAFuturePrev >= senkouSpanBFuturePrev; + + // + bool isTenkanSenOverSenkouSpanA = + tenkanSen > senkouSpanA; + bool isTenkanSenUnderSenkouSpanA = + tenkanSen < senkouSpanA; + bool isTenkanSenOverFutureSenkouSpanA = + tenkanSen > senkouSpanAFuture; + bool isTenkanSenUnderFutureSenkouSpanA = + tenkanSen < senkouSpanAFuture; + bool isTenkanSenCrossedOverSenkouSpanA = + tenkanSen > senkouSpanA && + tenkanSenPrev <= senkouSpanAPrev; + bool isTenkanSenCrossedUnderSenkouSpanA = + tenkanSen < senkouSpanA && + tenkanSenPrev >= senkouSpanAPrev; + bool isTenkanSenCrossedOverFutureSenkouSpanA = + tenkanSen > senkouSpanAFuture && + tenkanSenPrev <= senkouSpanAFuturePrev; + bool isTenkanSenCrossedUnderFutureSenkouSpanA = + tenkanSen < senkouSpanAFuture && + tenkanSenPrev >= senkouSpanAFuturePrev; + + // + bool isTenkanSenOverSenkouSpanB = + tenkanSen > senkouSpanB; + bool isTenkanSenUnderSenkouSpanB = + tenkanSen < senkouSpanB; + bool isTenkanSenOverFutureSenkouSpanB = + tenkanSen > senkouSpanBFuture; + bool isTenkanSenUnderFutureSenkouSpanB = + tenkanSen < senkouSpanBFuture; + bool isTenkanSenCrossedOverSenkouSpanB = + tenkanSen > senkouSpanB && + tenkanSenPrev <= senkouSpanBPrev; + bool isTenkanSenCrossedUnderSenkouSpanB = + tenkanSen < senkouSpanB && + tenkanSenPrev >= senkouSpanBPrev; + bool isTenkanSenCrossedOverFutureSenkouSpanB = + tenkanSen > senkouSpanBFuture && + tenkanSenPrev <= senkouSpanBFuturePrev; + bool isTenkanSenCrossedUnderFutureSenkouSpanB = + tenkanSen < senkouSpanBFuture && + tenkanSenPrev >= senkouSpanBFuturePrev; + + // + bool isKijunSenOverSenkouSpanA = + kijunSen > senkouSpanA; + bool isKijunSenUnderSenkouSpanA = + kijunSen < senkouSpanA; + bool isKijunSenOverFutureSenkouSpanA = + kijunSen > senkouSpanAFuture; + bool isKijunSenUnderFutureSenkouSpanA = + kijunSen < senkouSpanAFuture; + bool isKijunSenCrossedOverSenkouSpanA = + kijunSen > senkouSpanA && + kijunSenPrev <= senkouSpanAPrev; + bool isKijunSenCrossedUnderSenkouSpanA = + kijunSen < senkouSpanA && + kijunSenPrev >= senkouSpanAPrev; + bool isKijunSenCrossedOverFutureSenkouSpanA = + kijunSen > senkouSpanAFuture && + kijunSenPrev <= senkouSpanAFuturePrev; + bool isKijunSenCrossedUnderFutureSenkouSpanA = + kijunSen < senkouSpanAFuture && + kijunSenPrev >= senkouSpanAFuturePrev; + + // + bool isKijunSenOverSenkouSpanB = + kijunSen > senkouSpanB; + bool isKijunSenUnderSenkouSpanB = + kijunSen < senkouSpanB; + bool isKijunSenOverFutureSenkouSpanB = + kijunSen > senkouSpanBFuture; + bool isKijunSenUnderFutureSenkouSpanB = + kijunSen < senkouSpanBFuture; + bool isKijunSenCrossedOverSenkouSpanB = + kijunSen > senkouSpanB && + kijunSenPrev <= senkouSpanB; + bool isKijunSenCrossedUnderSenkouSpanB = + kijunSen < senkouSpanB && + kijunSenPrev >= senkouSpanB; + bool isKijunSenCrossedOverFutureSenkouSpanB = + kijunSen > senkouSpanBFuture && + kijunSenPrev <= senkouSpanBFuturePrev; + bool isKijunSenCrossedUnderFutureSenkouSpanB = + kijunSen < senkouSpanBFuture && + kijunSenPrev >= senkouSpanBFuturePrev; + + // + result.tenkanSen = tenkanSen; + result.kijunSen = kijunSen; + result.chikouSpan = chikouSpan; + result.senkouSpanA = senkouSpanA; + result.senkouSpanB = senkouSpanB; + result.senkouSpanAFuture = senkouSpanAFuture; + result.senkouSpanBFuture = senkouSpanBFuture; + + // + result.isTenkanSenOverKijunSen = isTenkanSenOverKijunSen; + result.isTenkanSenUnderKijunSen = isTenkanSenUnderKijunSen; + result.isTenkanSenCrossedOverKijunSen = isTenkanSenCrossedOverKijunSen; + result.isTenkanSenCrossedUnderKijunSen = isTenkanSenCrossedUnderKijunSen; + + // + result.isKumoBullish = isKumoBullish; + result.isKumoBearish = isKumoBearish; + result.isFutureKumoBullish = isFutureKumoBullish; + result.isFutureKumoBearish = isFutureKumoBearish; + result.isKumoSwitchedToBullish = isKumoSwitchedToBullish; + result.isKumoSwitchedToBearish = isKumoSwitchedToBearish; + result.isFutureKumoSwitchedToBullish = isFutureKumoSwitchedToBullish; + result.isFutureKumoSwitchedToBearish = isFutureKumoSwitchedToBearish; + + // + result.isTenkanSenOverSenkouSpanA = isTenkanSenOverSenkouSpanA; + result.isTenkanSenUnderSenkouSpanA = isTenkanSenUnderSenkouSpanA; + result.isTenkanSenOverFutureSenkouSpanA = isTenkanSenOverFutureSenkouSpanA; + result.isTenkanSenUnderFutureSenkouSpanA = isTenkanSenUnderFutureSenkouSpanA; + result.isTenkanSenCrossedOverSenkouSpanA = isTenkanSenCrossedOverSenkouSpanA; + result.isTenkanSenCrossedUnderSenkouSpanA = isTenkanSenCrossedUnderSenkouSpanA; + result.isTenkanSenCrossedOverFutureSenkouSpanA = isTenkanSenCrossedOverFutureSenkouSpanA; + result.isTenkanSenCrossedUnderFutureSenkouSpanA = isTenkanSenCrossedUnderFutureSenkouSpanA; + + // + result.isTenkanSenOverSenkouSpanB = isTenkanSenOverSenkouSpanB; + result.isTenkanSenUnderSenkouSpanB = isTenkanSenUnderSenkouSpanB; + result.isTenkanSenOverFutureSenkouSpanB = isTenkanSenOverFutureSenkouSpanB; + result.isTenkanSenUnderFutureSenkouSpanB = isTenkanSenUnderFutureSenkouSpanB; + result.isTenkanSenCrossedOverSenkouSpanB = isTenkanSenCrossedOverSenkouSpanB; + result.isTenkanSenCrossedUnderSenkouSpanB = isTenkanSenCrossedUnderSenkouSpanB; + result.isTenkanSenCrossedOverFutureSenkouSpanB = isTenkanSenCrossedOverFutureSenkouSpanB; + result.isTenkanSenCrossedUnderFutureSenkouSpanB = isTenkanSenCrossedUnderFutureSenkouSpanB; + + // + result.isKijunSenOverSenkouSpanA = isKijunSenOverSenkouSpanA; + result.isKijunSenUnderSenkouSpanA = isKijunSenUnderSenkouSpanA; + result.isKijunSenOverFutureSenkouSpanA = isKijunSenOverFutureSenkouSpanA; + result.isKijunSenUnderFutureSenkouSpanA = isKijunSenUnderFutureSenkouSpanA; + result.isKijunSenCrossedOverSenkouSpanA = isKijunSenCrossedOverSenkouSpanA; + result.isKijunSenCrossedUnderSenkouSpanA = isKijunSenCrossedUnderSenkouSpanA; + result.isKijunSenCrossedOverFutureSenkouSpanA = isKijunSenCrossedOverFutureSenkouSpanA; + result.isKijunSenCrossedUnderFutureSenkouSpanA = isKijunSenCrossedUnderFutureSenkouSpanA; + + // + result.isKijunSenOverSenkouSpanB = isKijunSenOverSenkouSpanB; + result.isKijunSenUnderSenkouSpanB = isKijunSenUnderSenkouSpanB; + result.isKijunSenOverFutureSenkouSpanB = isKijunSenOverFutureSenkouSpanB; + result.isKijunSenUnderFutureSenkouSpanB = isKijunSenUnderFutureSenkouSpanB; + result.isKijunSenCrossedOverSenkouSpanB = isKijunSenCrossedOverSenkouSpanB; + result.isKijunSenCrossedUnderSenkouSpanB = isKijunSenCrossedUnderSenkouSpanB; + result.isKijunSenCrossedOverFutureSenkouSpanB = isKijunSenCrossedOverFutureSenkouSpanB; + result.isKijunSenCrossedUnderFutureSenkouSpanB = isKijunSenCrossedUnderFutureSenkouSpanB; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // TENKANSEN ... + // + // Length ... + int mTenkanSenLength; + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE mTenkanSenMode; + // + // KIJUNSEN ... + // + // Length ... + int mKijunSenLength; + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE mKijunSenMode; + // + // SENKOUSPANB ... + // + // Length ... + int mSenkouSpanBLength; + // + // Calculation Mode ... + ENUM_X_ICHIMOKU_CALCULATION_MODE mSenkouSpanBMode; + // + // CHIKOUSPAN ... + // + // Price Type ... + ENUM_APPLIED_PRICE mChikuoSpanAppliedTo; + // + // Presentation ... + // + // Show Tenkan Sen ... + bool mShowTenkanSen; + // + // Show Kijun Sen ... + bool mShowKijunSen; + // + // Show Kijun Sen + ... + bool mShowKijunSenPlus; + // + // Show Kijun Sen - ... + bool mShowKijunSenNegative; + // + // Show Chikou Span ... + bool mShowChikouSpan; + // + // Show Senkou Span A ... + bool mShowSenkouSpanA; + // + // Show Senkou Span B ... + bool mShowSenkouSpanB; + // + // Show Kumo ... + bool mShowKumo; + // + // Shift Kumo to Future ... + bool mShiftKumo; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xmrb.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xmrb.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..5ca9f84e63d79e65dcb8eff4359520bd10e08e36 GIT binary patch literal 6520 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 2 && + mFast2Length > mFast1Length && + mFast3Length > mFast2Length && + mFast4Length > mFast3Length && + mFast5Length > mFast4Length && + mSlow1Length > mFast1Length && + mSlow2Length > mFast2Length && + mSlow3Length > mFast3Length && + mSlow4Length > mFast4Length && + mSlow5Length > mFast5Length && + mSlow2Length > mSlow1Length && + mSlow3Length > mSlow2Length && + mSlow4Length > mSlow3Length && + mSlow5Length > mSlow4Length + // + ) + // + ; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xmrb", + // + // Inputs ... + // + // Ribbon 1 ... + "", + mFast1Length, + mSlow1Length, + // + // Ribbon 2 ... + "", + mFast2Length, + mSlow2Length, + // + // Ribbon 3 ... + "", + mFast3Length, + mSlow3Length, + // + // Ribbon 4 ... + "", + mFast4Length, + mSlow4Length, + // + // Ribbon 5 ... + "", + mFast5Length, + mSlow5Length, + // + // Calculation ... + "", + // + // Mode ... + mRibbonMode, + // + // Applied To ... + mRibbonAppliedTo, + // + // Presentation ... + "", + // + // Show Fast ... + mShowFastMa, + // + // Show Slow ... + mShowSlowMa, + // + // Show Ribbon ... + mShowRibbon + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XMRBInputs GetConfig() + { + // + XMRBInputs result; + + // + result.fast1Length = mFast1Length; + result.slow1Length = mSlow1Length; + result.fast2Length = mFast2Length; + result.slow2Length = mSlow2Length; + result.fast3Length = mFast3Length; + result.slow3Length = mSlow3Length; + result.fast4Length = mFast4Length; + result.slow4Length = mSlow4Length; + result.fast5Length = mFast5Length; + result.slow5Length = mSlow5Length; + result.ribbonMode = mRibbonMode; + result.ribbonAppliedTo = mRibbonAppliedTo; + result.showFastMa = mShowFastMa; + result.showSlowMa = mShowSlowMa; + result.showRibbon = mShowRibbon; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XMRBInputs &config) + { + // + bool result = false; + + // + mFast1Length = config.fast1Length; + mSlow1Length = config.slow1Length; + mFast2Length = config.fast2Length; + mSlow2Length = config.slow2Length; + mFast3Length = config.fast3Length; + mSlow3Length = config.slow3Length; + mFast4Length = config.fast4Length; + mSlow4Length = config.slow4Length; + mFast5Length = config.fast5Length; + mSlow5Length = config.slow5Length; + mRibbonMode = config.ribbonMode; + mRibbonAppliedTo = config.ribbonAppliedTo; + mShowFastMa = config.showFastMa; + mShowSlowMa = config.showSlowMa; + mShowRibbon = config.showRibbon; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // FAST ... + ArraySetAsSeries(fastBuffer, true); + CopyBuffer( + mHandler, + XMRB_FAST_LINE, + barIndex, + mLoopbackBars, + fastBuffer); + + // + // SLOW ... + ArraySetAsSeries(slowBuffer, true); + CopyBuffer( + mHandler, + XMRB_SLOW_LINE, + barIndex, + mLoopbackBars, + slowBuffer); + + // + // RIBBON 1 ... + + // + // FAST ... + ArraySetAsSeries(fastR1Buffer, true); + CopyBuffer( + mHandler, + XMRB_R1_FAST_LINE, + barIndex, + mLoopbackBars, + fastR1Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR1Buffer, true); + CopyBuffer( + mHandler, + XMRB_R1_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR1Buffer); + + // + // RIBBON 2 ... + + // + // FAST ... + ArraySetAsSeries(fastR2Buffer, true); + CopyBuffer( + mHandler, + XMRB_R2_FAST_LINE, + barIndex, + mLoopbackBars, + fastR2Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR2Buffer, true); + CopyBuffer( + mHandler, + XMRB_R2_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR2Buffer); + + // + // RIBBON 3 ... + + // + // FAST ... + ArraySetAsSeries(fastR3Buffer, true); + CopyBuffer( + mHandler, + XMRB_R3_FAST_LINE, + barIndex, + mLoopbackBars, + fastR3Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR3Buffer, true); + CopyBuffer( + mHandler, + XMRB_R3_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR3Buffer); + + // + // RIBBON 4 ... + + // + // FAST ... + ArraySetAsSeries(fastR4Buffer, true); + CopyBuffer( + mHandler, + XMRB_R4_FAST_LINE, + barIndex, + mLoopbackBars, + fastR4Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR4Buffer, true); + CopyBuffer( + mHandler, + XMRB_R4_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR4Buffer); + + // + // RIBBON 5 ... + + // + // FAST ... + ArraySetAsSeries(fastR5Buffer, true); + CopyBuffer( + mHandler, + XMRB_R5_FAST_LINE, + barIndex, + mLoopbackBars, + fastR5Buffer); + + // + // SLOW ... + ArraySetAsSeries(slowR5Buffer, true); + CopyBuffer( + mHandler, + XMRB_R5_SLOW_LINE, + barIndex, + mLoopbackBars, + slowR5Buffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XMRBInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XMRBInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double fast = fastBuffer[barIndex]; + double fastPrev = fastBuffer[barIndex + 1]; + double slow = slowBuffer[barIndex]; + double slowPrev = slowBuffer[barIndex + 1]; + double fastR1 = fastR1Buffer[barIndex]; + double fastR1Prev = fastR1Buffer[barIndex + 1]; + double slowR1 = slowR1Buffer[barIndex]; + double slowR1Prev = slowR1Buffer[barIndex + 1]; + double fastR2 = fastR2Buffer[barIndex]; + double fastR2Prev = fastR2Buffer[barIndex + 1]; + double slowR2 = slowR2Buffer[barIndex]; + double slowR2Prev = slowR2Buffer[barIndex + 1]; + double fastR3 = fastR3Buffer[barIndex]; + double fastR3Prev = fastR3Buffer[barIndex + 1]; + double slowR3 = slowR3Buffer[barIndex]; + double slowR3Prev = slowR3Buffer[barIndex + 1]; + double fastR4 = fastR4Buffer[barIndex]; + double fastR4Prev = fastR4Buffer[barIndex + 1]; + double slowR4 = slowR4Buffer[barIndex]; + double slowR4Prev = slowR4Buffer[barIndex + 1]; + double fastR5 = fastR5Buffer[barIndex]; + double fastR5Prev = fastR5Buffer[barIndex + 1]; + double slowR5 = slowR5Buffer[barIndex]; + double slowR5Prev = slowR5Buffer[barIndex + 1]; + + // + result.fast = fast; + result.slow = slow; + result.fastR1 = fastR1; + result.slowR1 = slowR1; + result.fastR2 = fastR2; + result.slowR2 = slowR2; + result.fastR3 = fastR3; + result.slowR3 = slowR3; + result.fastR4 = fastR4; + result.slowR4 = slowR4; + result.fastR5 = fastR5; + result.slowR5 = slowR5; + + // + result.isFastOverSlow = + fast > slow; + result.isFastCrossedOverSlow = + fast > slow && fastPrev <= slowPrev; + result.isFastUnderSlow = + fast < slow; + result.isFastCrossedUnderSlow = + fast < slow && fastPrev >= slowPrev; + + // + result.isR1FastOverSlow = + fastR1 > slowR1; + result.isR1FastCrossedOverSlow = + fastR1 > slowR1 && fastR1Prev <= slowR1Prev; + result.isR1FastUnderSlow = + fastR1 < slowR1; + result.isR1FastCrossedUnderSlow = + fastR1 < slowR1 && fastR1Prev >= slowR1Prev; + + // + result.isR2FastOverSlow = + fastR2 > slowR2; + result.isR2FastCrossedOverSlow = + fastR2 > slowR2 && fastR2Prev <= slowR2Prev; + result.isR2FastUnderSlow = + fastR2 < slowR2; + result.isR2FastCrossedUnderSlow = + fastR2 < slowR2 && fastR2Prev >= slowR2Prev; + + // + result.isR3FastOverSlow = + fastR3 > slowR3; + result.isR3FastCrossedOverSlow = + fastR3 > slowR3 && fastR3Prev <= slowR3Prev; + result.isR3FastUnderSlow = + fastR3 < slowR3; + result.isR3FastCrossedUnderSlow = + fastR3 < slowR3 && fastR3Prev >= slowR3Prev; + + // + result.isR4FastOverSlow = + fastR4 > slowR4; + result.isR4FastCrossedOverSlow = + fastR4 > slowR4 && fastR4Prev <= slowR4Prev; + result.isR4FastUnderSlow = + fastR4 < slowR4; + result.isR4FastCrossedUnderSlow = + fastR4 < slowR4 && fastR4Prev >= slowR4Prev; + + // + result.isR5FastOverSlow = + fastR5 > slowR5; + result.isR5FastCrossedOverSlow = + fastR5 > slowR5 && fastR5Prev <= slowR5Prev; + result.isR5FastUnderSlow = + fastR5 < slowR5; + result.isR5FastCrossedUnderSlow = + fastR5 < slowR5 && fastR5Prev >= slowR5Prev; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Ribbon 1 ... + int mFast1Length; + int mSlow1Length; + // + // Ribbon 2 ... + int mFast2Length; + int mSlow2Length; + // + // Ribbon 3 ... + int mFast3Length; + int mSlow3Length; + // + // Ribbon 4 ... + int mFast4Length; + int mSlow4Length; + // + // Ribbon 5 ... + int mFast5Length; + int mSlow5Length; + // + // Calculation ... + // + // Mode ... + ENUM_MA_METHOD mRibbonMode; + // + // Applied To ... + ENUM_APPLIED_PRICE mRibbonAppliedTo; + // + // Presentation ... + // + // Show Fast ... + bool mShowFastMa; + // + // Show Slow ... + bool mShowSlowMa; + // + // Show Ribbon ... + bool mShowRibbon; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xpv.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xpv.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..51d7a2da6ec7c3788825104cce18ae38ec2375c6 GIT binary patch literal 5900 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 2 && + mMediumLength > mShortLength && + mLongLength > mMediumLength && + mHindLength > mLongLength) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xpv", + // + // Inputs ... + // + // Market ... + "", + // + // Short Length ... + mShortLength, + // + // Medium Length + mMediumLength, + // + // Long Length ... + mLongLength, + // + // Hind Length ... + mHindLength, + // + // Fibio 1st Level ... + mFiboLevel1, + // + // Fibio 2st Level ... + mFiboLevel2, + // + // Fibio 3rd Level ... + mFiboLevel3, + // + // Detection Mode ... + "", + // + // Highest High Calculation Method ... + mHHMode, + // + // Lowest Low Calculation Method ... + mLLMode, + // + // Presentations ... + "", + // + // Show Peaks and Vales ... + mShowPeaksAndVales, + // + // Show Levels ... + mShowLevels, + // + // Show Fibo 1st Level ... + mShowFibo1Levels, + // + // Show Fibo 2nd Level ... + mShowFibo2Levels, + // + // Show Fibo 3rd Level ... + mShowFibo3Levels + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XPVInputs GetConfig() + { + // + XPVInputs result; + + // + result.shortLength = mShortLength; + result.mediumLength = mMediumLength; + result.longLength = mLongLength; + result.hindLength = mHindLength; + result.fiboLevel1 = mFiboLevel1; + result.fiboLevel2 = mFiboLevel2; + result.fiboLevel3 = mFiboLevel3; + result.hhMode = mHHMode; + result.llMode = mLLMode; + result.showPeaksAndVales = mShowPeaksAndVales; + result.showLevels = mShowLevels; + result.showFibo1Levels = mShowFibo1Levels; + result.showFibo2Levels = mShowFibo2Levels; + result.showFibo3Levels = mShowFibo3Levels; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XPVInputs &config) + { + // + bool result = false; + + // + mShortLength = config.shortLength; + mMediumLength = config.mediumLength; + mLongLength = config.longLength; + mHindLength = config.hindLength; + mFiboLevel1 = config.fiboLevel1; + mFiboLevel2 = config.fiboLevel2; + mFiboLevel3 = config.fiboLevel3; + mHHMode = config.hhMode; + mLLMode = config.llMode; + mShowPeaksAndVales = config.showPeaksAndVales; + mShowLevels = config.showLevels; + mShowFibo1Levels = config.showFibo1Levels; + mShowFibo2Levels = config.showFibo2Levels; + mShowFibo3Levels = config.showFibo3Levels; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + CopyBuffer( + mHandler, + XPV_PEAKS_LINE, + barIndex, + mLoopbackBars, + peaksBuffer); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + CopyBuffer( + mHandler, + XPV_VALES_LINE, + barIndex, + mLoopbackBars, + valesBuffer); + + // + // FIBBO LEVELS ... + + // + // LEVEL 1 ... + ArraySetAsSeries(fl1Buffer, true); + CopyBuffer( + mHandler, + XPV_FL1_LINE, + barIndex, + mLoopbackBars, + fl1Buffer); + + // + // LEVEL 2 ... + ArraySetAsSeries(fl2Buffer, true); + CopyBuffer( + mHandler, + XPV_FL2_LINE, + barIndex, + mLoopbackBars, + fl2Buffer); + + // + // LEVEL 3 ... + ArraySetAsSeries(fl3Buffer, true); + CopyBuffer( + mHandler, + XPV_FL3_LINE, + barIndex, + mLoopbackBars, + fl3Buffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XPVInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XPVInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + result.peak = peaksBuffer[barIndex]; + result.vale = valesBuffer[barIndex]; + result.fl1 = fl1Buffer[barIndex]; + result.fl2 = fl2Buffer[barIndex]; + result.fl3 = fl3Buffer[barIndex]; + + // + result.isNewPeak = + peaksBuffer[barIndex] != peaksBuffer[barIndex + 1]; + result.isNewVale = + valesBuffer[barIndex] != valesBuffer[barIndex + 1]; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Short Length ... + int mShortLength; + // + // Medium Length + int mMediumLength; + // + // Long Length ... + int mLongLength; + // + // Hind Length ... + int mHindLength; + // + // Fibio 1st Level ... + double mFiboLevel1; + // + // Fibio 2st Level ... + double mFiboLevel2; + // + // Fibio 3rd Level ... + double mFiboLevel3; + // + // Detection Mode ... + // + // Highest High Calculation Method ... + ENUM_SERIESMODE mHHMode; + // + // Lowest Low Calculation Method ... + ENUM_SERIESMODE mLLMode; + // + // Presentations ... + // + // Show Peaks and Vales ... + bool mShowPeaksAndVales; + // + // Show Levels ... + bool mShowLevels; + // + // Show Fibo 1st Level ... + bool mShowFibo1Levels; + // + // Show Fibo 2nd Level ... + bool mShowFibo2Levels; + // + // Show Fibo 3rd Level ... + bool mShowFibo3Levels; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..f008b684882e51bf45fb25f70b0773e0ce40d6a4 GIT binary patch literal 6168 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 aBxLrpO#`4`4P&JOQo>GACd&@pru;AY`m`wk literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.mq5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.mq5 new file mode 100644 index 0000000..53631dc --- /dev/null +++ b/MQLTestWorkspace/Helpers/x-saherelm.x121.xsslc.helper.class.mq5 @@ -0,0 +1,473 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXSSLCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Inputs ... +struct XSSLCInputs +{ + // + // Market ... + int length; // Length + + // + // Calculation ... + ENUM_MA_METHOD method; // Method + ENUM_APPLIED_PRICE upAppliedTo; // Up Applied To + ENUM_APPLIED_PRICE downAppliedTo; // Down Applied To + + // + // Presentation ... + bool showUp; // Show Up + bool showDown; // Show Down +}; + +// +// Index of Lines ... +enum ENUM_XSSLC_BUFFERS +{ + // + // Main Requirements ... + XSSLC_UP_LINE = 0, + XSSLC_DOWN_LINE = 1, +}; + +// +// Retrieve Info Model ... +struct XSSLCInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double up; + double down; + + // + // Conditions ... + + // + // Detect Trend is Bullish or not ... + bool isBullish; + + // + // Detect Trend is Switched to Bullish Or not ... + bool isSwitchedBullish; + + // + // Detect Trend is Bearish or not ... + bool isBearish; + + // + // Detect Trend is Switched to Bearish Or not ... + bool isSwitchedBearish; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXSSLCHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double upBuffer[]; + double downBuffer[]; + + // + // Constructor ... + void XSCXSSLCHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) : XSCBaseHelper(symbol, period) + { + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXSSLCHelper() + { + } + + // + // START Properties ... + // + + // + // Show Up ... + bool ShowUp( + bool show // Show or Hide Line + ) + { + // + bool result = false; + + // + if (mShowUp == show) + { + return true; + } + + // + mShowUp = show; + result = Init(); + + // + return result; + } + + // + // Show Down ... + bool ShowDown( + bool show // Show or Hide Line + ) + { + // + bool result = false; + + // + if (mShowDown == show) + { + return true; + } + + // + mShowDown = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XSSLC" + GetTagPrefix(); + } + + // + virtual int GetMaxLength() + { + // + int result = -1; + + // + result = mLength; + + // + return result; + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Args ... + result = + // + (mLength >= 2) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xsslc", + // + // Inputs ... + // + // Market ... + "", + // + // Length ... + mLength, + // + // Calculation ... + "", + // + // Method ... + mMethod, + // + // Up Applied To ... + mUpAppliedTo, + // + // Down Applied To ... + mDownAppliedTo, + // + // Presentation ... + "", + // + // Show Up ... + mShowUp, + // + // Show Down ... + mShowDown + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XSSLCInputs GetConfig() + { + // + XSSLCInputs result; + + // + result.length = mLength; + result.method = mMethod; + result.upAppliedTo = mUpAppliedTo; + result.downAppliedTo = mDownAppliedTo; + result.showUp = mShowUp; + result.showDown = mShowDown; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XSSLCInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mMethod = config.method; + mUpAppliedTo = config.upAppliedTo; + mDownAppliedTo = config.downAppliedTo; + mShowUp = config.showUp; + mShowDown = config.showDown; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // UP ... + ArraySetAsSeries(upBuffer, true); + CopyBuffer( + mHandler, + XSSLC_UP_LINE, + barIndex, + mLoopbackBars, + upBuffer); + + // + // DOWN ... + ArraySetAsSeries(downBuffer, true); + CopyBuffer( + mHandler, + XSSLC_DOWN_LINE, + barIndex, + mLoopbackBars, + downBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XSSLCInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XSSLCInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double up = upBuffer[barIndex]; + double upPrev = upBuffer[barIndex + 1]; + double down = downBuffer[barIndex]; + double downPrev = downBuffer[barIndex + 1]; + + // + result.up = up; + result.down = down; + + // + result.isBullish = up > down; + result.isBearish = up < down; + + // + result.isSwitchedBullish = + up > down && + upPrev <= downPrev; + result.isSwitchedBearish = + up < down && + upPrev >= downPrev; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Length ... + int mLength; + // + // Calculation ... + // + // Method ... + ENUM_MA_METHOD mMethod; + // + // Up Applied To ... + ENUM_APPLIED_PRICE mUpAppliedTo; + // + // Down Applied To ... + ENUM_APPLIED_PRICE mDownAppliedTo; + // + // Presentation ... + // + // Show Up ... + bool mShowUp; + // + // Show Down ... + bool mShowDown; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xtm.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xtm.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..ffd3df00c8556758eac022c644696f083f480645 GIT binary patch literal 6902 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 l0Tn~CE8WC*8!jo= 2) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xtm", + // + // Inputs ... + // + // Makret ... + "", + // + // Length ... + mLength, + // + // Shift ... + mShift, + // + // Calculations ... + "", + // + // Method ... + mMethod, + // + // Applied To ... + mAppliedTo, + // + // Presentation ... + "", + // + // Show Line ... + mShowLine + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XTMInputs GetConfig() + { + // + XTMInputs result; + + // + result.length = mLength; + result.shift = mShift; + result.method = mMethod; + result.appliedTo = mAppliedTo; + result.showLine = mShowLine; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XTMInputs &config) + { + // + bool result = false; + + // + mLength = config.length; + mShift = config.shift; + mMethod = config.method; + mAppliedTo = config.appliedTo; + mShowLine = config.showLine; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // VALUE ... + ArraySetAsSeries(valueBuffer, true); + CopyBuffer( + mHandler, + XTM_LINE, + barIndex, + mLoopbackBars, + valueBuffer); + + // + // STATE ... + ArraySetAsSeries(stateBuffer, true); + CopyBuffer( + mHandler, + XTM_STATE_LINE, + barIndex, + mLoopbackBars, + stateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XTMInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XTMInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + result.value = valueBuffer[barIndex]; + + // + ENUM_XTM_STATES state = (ENUM_XTM_STATES)stateBuffer[barIndex]; + ENUM_XTM_STATES prevState = (ENUM_XTM_STATES)stateBuffer[barIndex + 1]; + result.state = state; + + // + result.isBullish = state == X_XTM_BULLISH; + result.isBearish = state == X_XTM_BEARISH; + result.isNeutural = state == X_XTM_NEUTURAL; + + // + result.isSwitchedBullish = + state == X_XTM_BULLISH && prevState != X_XTM_BULLISH; + result.isSwitchedBearish = + state == X_XTM_BEARISH && prevState != X_XTM_BEARISH; + result.isSwitchedNeutural = + state == X_XTM_NEUTURAL && prevState != X_XTM_NEUTURAL; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Makret ... + // + // Length ... + int mLength; + // + // Shift ... + int mShift; + + // + // Calculations ... + // + // Method ... + ENUM_MA_METHOD mMethod; + // + // Applied To ... + ENUM_APPLIED_PRICE mAppliedTo; + + // + // Presentation ... + // + // Show Line ... + bool mShowLine; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.ex5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..9e613de34a7df9daae1199357ae33fea68e599e9 GIT binary patch literal 5598 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 bz+zQ@iSop9zUP2Lj&tsOUG#f&>+AmlMGcf$ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 b/MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 new file mode 100644 index 0000000..5aa9c24 --- /dev/null +++ b/MQLTestWorkspace/Helpers/x-saherelm.x121.xtrnd.helper.class.mq5 @@ -0,0 +1,1074 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXTRNDHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// Inputs ... +struct XTRNDInputs +{ + // + // Makret ... + int cycleLength; // Cycle Length to Check + int numberOfVerifications; // Number of Verifications + + // + // Calculation ... + ENUM_SERIESMODE hhMode; // Detect Up + ENUM_SERIESMODE llMode; // Detect Low + + // + // Cycles ... + + // + // Level 1 ... + ENUM_X_PERIOD_METHOD l1Method; // How to Find Period + ENUM_TIMEFRAMES l1Period; // Time Period + + // + // Level 2 ... + ENUM_X_PERIOD_METHOD l2Method; // How to Find Period + ENUM_TIMEFRAMES l2Period; // Time Period + + // + // Level 3 ... + ENUM_X_PERIOD_METHOD l3Method; // How to Find Period + ENUM_TIMEFRAMES l3Period; // Time Period + + // + // Presentation ... + bool showConsolidations; // Show Consolidations + bool showTrend; // Show Trend + bool showL1Trend; // Show Cycle 1 Trend + bool showL2Trend; // Show Cycle 2 Trend + bool showL3Trend; // Show Cycle 3 Trend +}; + +// +// Index of Lines ... +enum ENUM_XTRND_BUFFERS +{ + // + // Main Requirements ... + XTRND_UP_LINE = 0, + XTRND_UP_STATE_LINE = 16, + XTRND_DOWN_LINE = 2, + XTRND_DOWN_STATE_LINE = 17, + // + // LEVEL 1 ... + XTRND_L1_UP_LINE = 4, + XTRND_L1_UP_STATE_LINE = 18, + XTRND_L1_DOWN_LINE = 6, + XTRND_L1_DOWN_STATE_LINE = 19, + // + // LEVEL 2 ... + XTRND_L2_UP_LINE = 8, + XTRND_L2_UP_STATE_LINE = 20, + XTRND_L2_DOWN_LINE = 10, + XTRND_L2_DOWN_STATE_LINE = 21, + // + // LEVEL 3 ... + XTRND_L3_UP_LINE = 12, + XTRND_L3_UP_STATE_LINE = 22, + XTRND_L3_DOWN_LINE = 14, + XTRND_L3_DOWN_STATE_LINE = 23, +}; + +// +enum ENUM_XTRND_STATES +{ + XTRND_STATE_BULLISH = 1, + XTRND_STATE_BEARISH = 2, + XTRND_STATE_CONSOLIDATION = 0, +}; + +// +// Retrieve Info Model ... +struct XTRNDInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Values ... + double hh; + ENUM_XTRND_STATES hhState; + double ll; + double llState; + double l1hh; + ENUM_XTRND_STATES l1hhState; + double l1ll; + ENUM_XTRND_STATES l1llState; + double l2hh; + ENUM_XTRND_STATES l2hhState; + double l2ll; + ENUM_XTRND_STATES l2llState; + double l3hh; + ENUM_XTRND_STATES l3hhState; + double l3ll; + ENUM_XTRND_STATES l3llState; + + // + // Conditions ... + // + bool isTrendBullish; + bool isTrendSwitchedToBullish; + bool isTrendBearish; + bool isTrendSwitchedToBearish; + bool isTrendConsolidation; + bool isTrendSwitchedToConsolidation; + + // + bool isL1TrendBullish; + bool isL1TrendSwitchedToBullish; + bool isL1TrendBearish; + bool isL1TrendSwitchedToBearish; + bool isL1TrendConsolidation; + bool isL1TrendSwitchedToConsolidation; + + // + bool isL2TrendBullish; + bool isL2TrendSwitchedToBullish; + bool isL2TrendBearish; + bool isL2TrendSwitchedToBearish; + bool isL2TrendConsolidation; + bool isL2TrendSwitchedToConsolidation; + + // + bool isL3TrendBullish; + bool isL3TrendSwitchedToBullish; + bool isL3TrendBearish; + bool isL3TrendSwitchedToBearish; + bool isL3TrendConsolidation; + bool isL3TrendSwitchedToConsolidation; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXTRNDHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double hhBuffer[]; + double hhStateBuffer[]; + double llBuffer[]; + double llStateBuffer[]; + double l1hhBuffer[]; + double l1hhStateBuffer[]; + double l1llBuffer[]; + double l1llStateBuffer[]; + double l2hhBuffer[]; + double l2hhStateBuffer[]; + double l2llBuffer[]; + double l2llStateBuffer[]; + double l3hhBuffer[]; + double l3hhStateBuffer[]; + double l3llBuffer[]; + double l3llStateBuffer[]; + + // + // Constructor ... + void XSCXTRNDHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) : XSCBaseHelper(symbol, period) + { + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCXTRNDHelper() + { + } + + // + // START Properties ... + // + + // + // Show Trend ... + bool ShowTrend( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowTrend == show) + { + return true; + } + + // + mShowTrend = show; + result = Init(); + + // + return result; + } + + // + // Show Cycle 1 Trend ... + bool ShowL1Trends( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowL1Trends == show) + { + return true; + } + + // + mShowL1Trends = show; + result = Init(); + + // + return result; + } + + // + // Show Cycle 2 Trend ... + bool ShowL2Trends( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowL2Trends == show) + { + return true; + } + + // + mShowL2Trends = show; + result = Init(); + + // + return result; + } + + // + // Show Cycle 3 Trend ... + bool ShowL3Trends( + bool show // Show or Hide + ) + { + // + bool result = false; + + // + if (mShowL3Trends == show) + { + return true; + } + + // + mShowL3Trends = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XTRND" + GetTagPrefix(); + } + + // + virtual int GetMaxLength() + { + // + int result = -1; + + // + result = MathMax( + mCycleLength, + mNumberOfVerifications); + + // + return result; + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Inputs ... + // + // + result = + // + (mCycleLength > 0 && + mNumberOfVerifications > 0) + // + ; + if (!result) + { + return result; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xtrnd", + // + // Inputs ... + // + // Market ... + "", + // + // Cycle Length to Check ... + mCycleLength, + // + // Number of Verifications ... + mNumberOfVerifications, + // + // Calculations ... + "", + // + // Detect Up ... + mHHMode, + // + // Detect Low ... + mLLMode, + // + // Cycles ... + "", + // + // LEVEL 1 ... + "", + // + // How to Find Period ... + mLLMethod, + // + // Time Period ... + mL1Period, + // + // LEVEL 2 ... + "", + // + // How to Find Period ... + mL2Method, + // + // Time Period ... + mL2Period, + // + // LEVEL 3 ... + "", + // + // How to Find Period ... + mL3Method, + // + // Time Period ... + mL3Period, + // + // Presentation ... + "", + // + // Show Consolidations ... + mShowConsolidations, + // + // Show Trend ... + mShowTrend, + // + // Show Cycle 1 Trend ... + mShowL1Trends, + // + // Show Cycle 2 Trend ... + mShowL2Trends, + // + // Show Cycle 3 Trend ... + mShowL3Trends + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Retrieve Current Config ... + XTRNDInputs GetConfig() + { + // + XTRNDInputs result; + + // + result.cycleLength = mCycleLength; + result.numberOfVerifications = mNumberOfVerifications; + result.hhMode = mHHMode; + result.llMode = mLLMode; + result.l1Method = mLLMethod; + result.l1Period = mL1Period; + result.l2Method = mL2Method; + result.l2Period = mL2Period; + result.l3Method = mL3Method; + result.l3Period = mL3Period; + result.showConsolidations = mShowConsolidations; + result.showTrend = mShowTrend; + result.showL1Trend = mShowL1Trends; + result.showL2Trend = mShowL2Trends; + result.showL3Trend = mShowL3Trends; + + // + return result; + } + + // + // Set Config ... + bool SetConfig(XTRNDInputs &config) + { + // + bool result = false; + + // + mCycleLength = config.cycleLength; + mNumberOfVerifications = config.numberOfVerifications; + mHHMode = config.hhMode; + mLLMode = config.llMode; + mLLMethod = config.l1Method; + mL1Period = config.l1Period; + mL2Method = config.l2Method; + mL2Period = config.l2Period; + mL3Method = config.l3Method; + mL3Period = config.l3Period; + mShowConsolidations = config.showConsolidations; + mShowTrend = config.showTrend; + mShowL1Trends = config.showL1Trend; + mShowL2Trends = config.showL2Trend; + mShowL3Trends = config.showL3Trend; + + // + result = Init(); + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ) + { + // + // HH ... + ArraySetAsSeries(hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_UP_LINE, + barIndex, + mLoopbackBars, + hhBuffer); + + // + // HH State ... + ArraySetAsSeries(hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_UP_STATE_LINE, + barIndex, + mLoopbackBars, + hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(llBuffer, true); + CopyBuffer( + mHandler, + XTRND_DOWN_LINE, + barIndex, + mLoopbackBars, + llBuffer); + + // + // LL State ... + ArraySetAsSeries(llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + llStateBuffer); + + // + // CYCLES ... + + // + // LEVEL 1 ... + + // + // HH ... + ArraySetAsSeries(l1hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_UP_LINE, + barIndex, + mLoopbackBars, + l1hhBuffer); + + // + // HH State ... + ArraySetAsSeries(l1hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_UP_STATE_LINE, + barIndex, + mLoopbackBars, + l1hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(l1llBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_DOWN_LINE, + barIndex, + mLoopbackBars, + l1llBuffer); + + // + // LL State ... + ArraySetAsSeries(l1llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L1_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + l1llStateBuffer); + + // + // LEVEL 2 ... + + // + // HH ... + ArraySetAsSeries(l2hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_UP_LINE, + barIndex, + mLoopbackBars, + l2hhBuffer); + + // + // HH State ... + ArraySetAsSeries(l2hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_UP_STATE_LINE, + barIndex, + mLoopbackBars, + l2hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(l2llBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_DOWN_LINE, + barIndex, + mLoopbackBars, + l2llBuffer); + + // + // LL State ... + ArraySetAsSeries(l2llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L2_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + l2llStateBuffer); + + // + // LEVEL 3 ... + + // + // HH ... + ArraySetAsSeries(l3hhBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_UP_LINE, + barIndex, + mLoopbackBars, + l3hhBuffer); + + // + // HH State ... + ArraySetAsSeries(l3hhStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_UP_STATE_LINE, + barIndex, + mLoopbackBars, + l3hhStateBuffer); + + // + // LL ... + ArraySetAsSeries(l3llBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_DOWN_LINE, + barIndex, + mLoopbackBars, + l3llBuffer); + + // + // LL State ... + ArraySetAsSeries(l3llStateBuffer, true); + CopyBuffer( + mHandler, + XTRND_L3_DOWN_STATE_LINE, + barIndex, + mLoopbackBars, + l3llStateBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XTRNDInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XTRNDInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + barIndex--; + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime; + result.barIndex = barIndex; + + // + double hh = hhBuffer[barIndex]; + ENUM_XTRND_STATES hhState = (ENUM_XTRND_STATES)hhStateBuffer[barIndex]; + ENUM_XTRND_STATES hhStatePrev = (ENUM_XTRND_STATES)hhStateBuffer[barIndex + 1]; + + // + double ll = llBuffer[barIndex]; + ENUM_XTRND_STATES llState = (ENUM_XTRND_STATES)llStateBuffer[barIndex]; + ENUM_XTRND_STATES llStatePrev = (ENUM_XTRND_STATES)llStateBuffer[barIndex + 1]; + + // + double l1hh = l1hhBuffer[barIndex]; + ENUM_XTRND_STATES l1hhState = (ENUM_XTRND_STATES)l1hhStateBuffer[barIndex]; + ENUM_XTRND_STATES l1hhStatePrev = (ENUM_XTRND_STATES)l1hhStateBuffer[barIndex + 1]; + + // + double l1ll = l1llBuffer[barIndex]; + ENUM_XTRND_STATES l1llState = (ENUM_XTRND_STATES)l1llStateBuffer[barIndex]; + ENUM_XTRND_STATES l1llStatePrev = (ENUM_XTRND_STATES)l1llStateBuffer[barIndex + 1]; + + // + double l2hh = l2hhBuffer[barIndex]; + ENUM_XTRND_STATES l2hhState = (ENUM_XTRND_STATES)l2hhStateBuffer[barIndex]; + ENUM_XTRND_STATES l2hhStatePrev = (ENUM_XTRND_STATES)l2hhStateBuffer[barIndex + 1]; + + // + double l2ll = l2llBuffer[barIndex]; + ENUM_XTRND_STATES l2llState = (ENUM_XTRND_STATES)l2llStateBuffer[barIndex]; + ENUM_XTRND_STATES l2llStatePrev = (ENUM_XTRND_STATES)l2llStateBuffer[barIndex + 1]; + + // + double l3hh = l3hhBuffer[barIndex]; + ENUM_XTRND_STATES l3hhState = (ENUM_XTRND_STATES)l3hhStateBuffer[barIndex]; + ENUM_XTRND_STATES l3hhStatePrev = (ENUM_XTRND_STATES)l3hhStateBuffer[barIndex + 1]; + + // + double l3ll = l3llBuffer[barIndex]; + ENUM_XTRND_STATES l3llState = (ENUM_XTRND_STATES)l3llStateBuffer[barIndex]; + ENUM_XTRND_STATES l3llStatePrev = (ENUM_XTRND_STATES)l3llStateBuffer[barIndex + 1]; + + // + bool isTrendBullish = + hhState == XTRND_STATE_BULLISH && + llState == XTRND_STATE_BULLISH; + bool isPrevTrendBullish = + hhStatePrev == XTRND_STATE_BULLISH && + llStatePrev == XTRND_STATE_BULLISH; + bool isTrendBearish = + hhState == XTRND_STATE_BEARISH && + llState == XTRND_STATE_BEARISH; + bool isPrevTrendBearish = + hhStatePrev == XTRND_STATE_BEARISH && + llStatePrev == XTRND_STATE_BEARISH; + bool isTrendConsolidation = + hhState == XTRND_STATE_CONSOLIDATION && + llState == XTRND_STATE_CONSOLIDATION; + bool isPrevTrendConsolidation = + hhStatePrev == XTRND_STATE_CONSOLIDATION && + llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isTrendSwitchedToBullish = + isTrendBullish && + !isPrevTrendBullish; + bool isTrendSwitchedToBearish = + isTrendBearish && + !isPrevTrendBearish; + bool isTrendSwitchedToConsolidation = + isTrendConsolidation && + !isPrevTrendConsolidation; + + // + bool isL1TrendBullish = + l1hhState == XTRND_STATE_BULLISH && + l1llState == XTRND_STATE_BULLISH; + bool isL1PrevTrendBullish = + l1hhStatePrev == XTRND_STATE_BULLISH && + l1llStatePrev == XTRND_STATE_BULLISH; + bool isL1TrendBearish = + l1hhState == XTRND_STATE_BEARISH && + l1llState == XTRND_STATE_BEARISH; + bool isL1PrevTrendBearish = + l1hhStatePrev == XTRND_STATE_BEARISH && + l1llStatePrev == XTRND_STATE_BEARISH; + bool isL1TrendConsolidation = + l1hhState == XTRND_STATE_CONSOLIDATION && + l1llState == XTRND_STATE_CONSOLIDATION; + bool isL1PrevTrendConsolidation = + l1hhStatePrev == XTRND_STATE_CONSOLIDATION && + l1llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isL1TrendSwitchedToBullish = + isL1TrendBullish && + !isL1PrevTrendBullish; + bool isL1TrendSwitchedToBearish = + isL1TrendBearish && + !isL1PrevTrendBearish; + bool isL1TrendSwitchedToConsolidation = + isL1TrendConsolidation && + !isL1PrevTrendConsolidation; + + // + bool isL2TrendBullish = + l2hhState == XTRND_STATE_BULLISH && + l2llState == XTRND_STATE_BULLISH; + bool isL2PrevTrendBullish = + l2hhStatePrev == XTRND_STATE_BULLISH && + l2llStatePrev == XTRND_STATE_BULLISH; + bool isL2TrendBearish = + l2hhState == XTRND_STATE_BEARISH && + l2llState == XTRND_STATE_BEARISH; + bool isL2PrevTrendBearish = + l2hhStatePrev == XTRND_STATE_BEARISH && + l2llStatePrev == XTRND_STATE_BEARISH; + bool isL2TrendConsolidation = + l2hhState == XTRND_STATE_CONSOLIDATION && + l2llState == XTRND_STATE_CONSOLIDATION; + bool isL2PrevTrendConsolidation = + l2hhStatePrev == XTRND_STATE_CONSOLIDATION && + l2llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isL2TrendSwitchedToBullish = + isL2TrendBullish && + !isL2PrevTrendBullish; + bool isL2TrendSwitchedToBearish = + isL2TrendBearish && + !isL2PrevTrendBearish; + bool isL2TrendSwitchedToConsolidation = + isL2TrendConsolidation && + !isL2PrevTrendConsolidation; + + // + bool isL3TrendBullish = + l3hhState == XTRND_STATE_BULLISH && + l3llState == XTRND_STATE_BULLISH; + bool isL3PrevTrendBullish = + l3hhStatePrev == XTRND_STATE_BULLISH && + l3llStatePrev == XTRND_STATE_BULLISH; + bool isL3TrendBearish = + l3hhState == XTRND_STATE_BEARISH && + l3llState == XTRND_STATE_BEARISH; + bool isL3PrevTrendBearish = + l3hhStatePrev == XTRND_STATE_BEARISH && + l3llStatePrev == XTRND_STATE_BEARISH; + bool isL3TrendConsolidation = + l3hhState == XTRND_STATE_CONSOLIDATION && + l3llState == XTRND_STATE_CONSOLIDATION; + bool isL3PrevTrendConsolidation = + l3hhStatePrev == XTRND_STATE_CONSOLIDATION && + l3llStatePrev == XTRND_STATE_CONSOLIDATION; + + // + bool isL3TrendSwitchedToBullish = + isL3TrendBullish && + !isL3PrevTrendBullish; + bool isL3TrendSwitchedToBearish = + isL3TrendBearish && + !isL3PrevTrendBearish; + bool isL3TrendSwitchedToConsolidation = + isL3TrendConsolidation && + !isL3PrevTrendConsolidation; + + // + result.hh = hh; + result.hhState = hhState; + result.ll = ll; + result.llState = llState; + result.l1hh = l1hh; + result.l1hhState = l1hhState; + result.l1ll = l1ll; + result.l1llState = l1llState; + result.l2hh = l2hh; + result.l2hhState = l2hhState; + result.l2ll = l2ll; + result.l2llState = l2llState; + result.l3hh = l3hh; + result.l3hhState = l3hhState; + result.l3ll = l3ll; + result.l3llState = l3llState; + + // + result.isTrendBullish = isTrendBullish; + result.isTrendBearish = isTrendBearish; + result.isTrendConsolidation = isTrendConsolidation; + + // + result.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + result.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + result.isTrendSwitchedToConsolidation = isTrendSwitchedToConsolidation; + + // + result.isL1TrendBullish = isL1TrendBullish; + result.isL1TrendBearish = isL1TrendBearish; + result.isL1TrendConsolidation = isL1TrendConsolidation; + + // + result.isL1TrendSwitchedToBullish = isL1TrendSwitchedToBullish; + result.isL1TrendSwitchedToBearish = isL1TrendSwitchedToBearish; + result.isL1TrendSwitchedToConsolidation = isL1TrendSwitchedToConsolidation; + + // + result.isL2TrendBullish = isL2TrendBullish; + result.isL2TrendBearish = isL2TrendBearish; + result.isL2TrendConsolidation = isL2TrendConsolidation; + + // + result.isL2TrendSwitchedToBullish = isL2TrendSwitchedToBullish; + result.isL2TrendSwitchedToBearish = isL2TrendSwitchedToBearish; + result.isL2TrendSwitchedToConsolidation = isL2TrendSwitchedToConsolidation; + + // + result.isL3TrendBullish = isL3TrendBullish; + result.isL3TrendBearish = isL3TrendBearish; + result.isL3TrendConsolidation = isL3TrendConsolidation; + + // + result.isL3TrendSwitchedToBullish = isL3TrendSwitchedToBullish; + result.isL3TrendSwitchedToBearish = isL3TrendSwitchedToBearish; + result.isL3TrendSwitchedToConsolidation = isL3TrendSwitchedToConsolidation; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Cycle Length to Check ... + int mCycleLength; + // + // Number of Verifications ... + int mNumberOfVerifications; + // + // Calculations ... + // + // Detect Up ... + ENUM_SERIESMODE mHHMode; + // + // Detect Low ... + ENUM_SERIESMODE mLLMode; + // + // Cycles ... + // + // LEVEL 1 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD mLLMethod; + // + // Time Period ... + ENUM_TIMEFRAMES mL1Period; + // + // LEVEL 2 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD mL2Method; + // + // Time Period ... + ENUM_TIMEFRAMES mL2Period; + // + // LEVEL 3 ... + // + // How to Find Period ... + ENUM_X_PERIOD_METHOD mL3Method; + // + // Time Period ... + ENUM_TIMEFRAMES mL3Period; + // + // Presentation ... + // + // Show Consolidations ... + bool mShowConsolidations; + // + // Show Trend ... + bool mShowTrend; + // + // Show Cycle 1 Trend ... + bool mShowL1Trends; + // + // Show Cycle 2 Trend ... + bool mShowL2Trends; + // + // Show Cycle 3 Trend ... + bool mShowL3Trends; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xama.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xama.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..ba4ccbba5c2cb6c5fac6cfddad6f9671e7659a93 GIT binary patch literal 10504 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 rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = length; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showLine ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showLine); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..fb182bf37c5d7daa2e16a2c876b5188550443055 GIT binary patch literal 10770 zcmdUTV~{Q|v*tUtZQHhO+qP{RXKdS^Gqyc*#x~B_#-49$cdPFGasO|pl1g_csXX23 zbSh$+Y@kkn5=22z03iSX1ULc({1;m2;TH0$HCk-6Osi3rHI(@;%6|;`e;52;{{O7w z4G94JrwRi8HUEvC#D1Ik%9K(E>$c$66I3z>Nas1kg7#X&NZ%SLIIK7;u}vxdRV6e3 z&omK$1HcjB1#kvf0W1KP0M~!pWd<<*t1JN8e|;5z(Lbr#KfM^h7GU>JA_Y+W*NXg; z+5a2;AI<;I^dH2o|197F;07@KD=z;Jui5{`OaIR<|9>O=pS{Bbp#SG>#{YTH|Ddfj z8xlE_;?dP}Bf&lfIrL-|k2n5dS2Qg1&-Jl-j?&cXY8dpef9B)yjc-B2n@7Ra+Z-eZ zE_pqhny+~>4D?AzrFxSo37-%M8>2u$t56p%DL50&LnWNDC7u7s$cWBNMtrf%`?>IF zc=x_vnhhAt9V1{6&;An$7HSR7{HtURh(9CV%hhLneA{}Ydkfd1aEuUKm0u&Ik~<{% zHpiWsSKnYryE+85pLnQhVulau?Fu-mM?T@OuZ5(+N*Oi#23kIjU=%D!vNE9&gEHw_)S!Tv6p!O#PEuN~v{l=3ddc2QprhPQ70h{X zKmww^t&GVp2qo$kZnA(PQtiJcm85Yut&G2k5AI+E$RBJ74C0;1)y8KxYx)8%iPp#v zNFrmle)o@$NO`0|@tO8XV!~;2j8pJ)N>=JFZWUR%>{;(U<@M2uNdn=(C?C6j4SAw70#&{ZxBnuPy`25o#Pkc!g^BC8P#e6oaU|-JRu@8czqB$NXTNX_Z%}{ua>D;Ns3<|v`7K}#f`+=WkPFZm%9i!V}gLV zm{|+gxtfX%$6Ia)wXzoW!x1BT1xhA2SAH`86hEtxkaU?ZlH9&!P&nTW#W3|nlV0ua zJ>9=HM@=sb&0UyxmN#|JarL46I7ib%EhAK%hUi)%SunpXOW0lBi_yUuG)^tmI?rqhsPG`Z)Zpf=^2^nTd6<)5dsmU*a=|Vu;858g_ z!a+Y_6B0|*Dfnw0p!HhYbR>(2@1XjIJsFFt5Dl7dpxm){8z6oIfb)E;~F zo$Pt`)uW?4ZllbOQvd1-TG#rnj*xGbjW;@iyzcuzk`z6=l2x>1Dp+PFYh_iKWMIZR zMq1&!K`5i<3%&JWr2hpeHmoyT9CX`ZFMH8W&A?{ zr=eP05PaTKSRblF@$VvV*;>7#b;LM+ISFOVdt@eEiJ{;87{7Q^uA}+Y%9$?R}VV^;-WL=GV@N66fu$h=s&Hz5!Ld!*xwBwssdgrz`;R zlOu}b`V9ruhx3(l)##Or-&X3|F*dqNGB2dI31h7SwC(UF_=)zs2_6u-N#8Dj;}nXi zv6f%JJ28WPR+@K!_lPnSvuO(Xbb@LOB-m$WfJ3;!WvK!B%rD$ff#~bx!HQow<7po3 zxt|H@p8F^<>YpeJPOO#@cq3f|~ zq?Q38QL+lbn;HO2ba@hu`kg`Ql>Nm*Xe|z99A$>>$h!U8CS%tT;eOYTHvu@Mix1cE z=`ptGpn(~rz>Ati)4|$BRZ~!fqo8Dc?jlwe7u2n3i7E;o@ZruW(=8-fyZ^!ZkdG&5 zNp`##%_Y1+|CV2EH;s+nz>sX57B?;u)di`ZMcDzB7xuIVvO+@5)8|~R0;}w84Y{!8 zc=8wt1e?>odzy&YL}_wBFg&eOGVweTRWVkDz2#Pl+* zJ>O`NWE=qJ%w^FffsG~e0)jXt(s%OMcQy#^NXqW;#}^SMUKA*nt6q*8?%}m~ey*r> z!MDdE8v+;4*)OSM)ab-sDJI!%4<|QdC62MBG_XoO?`eDAZ!a{6`0z?|@W91;5iQ2ysPCI!v5pb9_`omXhBSqAfgS14C?W2n%bd5RpiPnER+ zcP@R)Uz|J?7%!tl+i@CD-WCl0ZU|ui-VKUOAmFv90O%|``X+dXt^7n&x@(0dEz!bY zuj>{aK@V#XKJ;I7L=N(8&2sx%0lu=zZ8uv6-?s!}G~zn5A7G4b5zqy^v%`&SKYZOt zO0$CfC_tW4;~E$fL7JKaNMsf-J$#51IfvGT{0k)?`)GiH9FGAC_92N8UBY;X(pVt< zI|2L3Hhrl|PhnipUg+tkqEwZt+v-M#>pju2?OlGBTKt*sZ@|36Kt>Nl5ec0y>#Js9 zzDZKA-5&npLsOZ_y+(!QA>oJvww^3KO3hM`@XE(Gj^pmup-Z^38W519>!RmJvL&Ki z;bpdl4_D*`Cl!xGi^Q)rr;3WAqV&gzcgy;G@IO;|6S|V}>)1LH&MEQ@irl(U$=NXM_7sdEezg-$jT^gMS z7mw=}n(^myCh*M&@i6Q=uSkKL4JfL1e+x@28Zyi(*OOt=XJXrwXYNGevrRc_dwA0D z<3*Evr>M&)I_-KK>)MZ0*ridCrFu_|3% zWxu$P{(L$VBP}-!VYJyM!??Uv?tL6on2Aw0JPqvoP{}~1Js4&9<__M81H<=7h{*}@ z>I#zuFNpMGpjV#0Z?uW9vUT~`^&8BjFtKJo_Cy-lv z>I(5}0jxG5IJBnM1}k=qrpRdG?Dv|=4nSP3^=aJ5@E>>df(avM4trY2ro5sp?4BrU zKKk9#^-`q1=PxF?8MhoHXjoP9@r8|9rkw9DLmK!hv$TjH?JPLDb<3K9L#`cj4iabW zYBYei5REz zmpXPM;stYI)@5Hn|sJ5Vx9PK7RB+`fR3V%m#Oq3#GPH0r@Cps`qAtCUrlo7L9o>)T5c4chv7MQ$9> zS1GV)tl2*%qw9s_qHi4oVk|>_Dq2k9MadO{=#BR7gg*P&L$-adnLS zP-hu!g#>I911&qg-2VYd`DFgOM6(egWG|44i z4*1M_SFb~AjOU(|)&gHC9pK2#9wE~Q*Vq{F9ug?rJO{_9we*L(9#}mF!P)UtGI!iV zTyI3W-qDS&ai;x%>NXiXdV44);;-C`{KPHN+*amG-RCU+(h;V>9YkQ!(Cmd4&i0uP za6MA96aESEM1$ddWUMu%FXBYm&E0e>gXuUkC}6nl!l$5~9QkQp2w!9sszn$7z@Us#PeA6#7?No6xqoojVxb(eh$rnU-z`~IFCHq1U>f0!U3m&;UfEz++ z{Qlz(HtJPniXrm&RuZV6M>je{*Pep`M5MR+Qs!ladrrg+myJoDyxs?9Stqxt8(p02 zUbrvt!|Wd&LbGNz2A53(yN_P=+-dzFFdH8nX46@(Mo5?4$)r4G5C(KSp{}r`#mz#T zk$rqF=NojogRYTvOr;gI`RKr<>3OmF0)KeGfV{g9h_KTGsZbveRa^WuDkFxwk?)jQ zhB8rlgz}%p(k!6)Hd$b zO3VPc;_!(6G6JbEvG&bwt#`M-{j;v@yR)^`mjG^X+%$`2y7gmYs7ha7!k9(X-8PB; z6iS3`8apMgnmxBWQM@xY^NTgV@llHaboJP_gvu!W&xgZVQcLfRnBd=Li_|fOFPEky0V4M1gHA8H!fDA{?cFI4aeolW9x;een}2iNk-~w z8EnekRz`W#BKNS!(h5aWtvVsKRftW(GZD(!GnYKHu^J!8h$wC3ave-?HB`JcBwBde z4A$_gw|Q!EWz;vE!Iy}b({fIHql4U(%w!%H;I#2iOG1O?(?(8I$SMpVTe0_F=wsu5 zP~XkmJk~D)&|ssthb}RW)**&S)`Z`ZL?pFU&6%yI_coA zZxC#MRjs=eJ$VLAr`RqWX6^@P@hK2@eCs|V>HH`{G|wvMCgAakBjw9?j9y53a^9E5 z3Kt09ljg558JL8NYb41mIL$ZGXcTYB_uGTUe>8@Ct3V`P59G&Gt(VGd7eN7V2+m3T z&gQKO3UVhqMMYfqf|ME#Q17e4c3N5$VQ+A!n791|W9V@}tLCS--qqW8=oxvX-8yAm zt9c~ETkBfqEqZR>JLmDDx1}Ou0YDhLoBX(X(Mo0T4XV(kbse=@^cZ+ZAd*OrD7>{b zP8>8DU{U+1E`&kO%gHs>-52>Z`GS5Gk^FP(Q-WeB`~o*~fsme!(N*!NN$4XKdM?uZ zZR=PCinp{UM&Ds4J%$pAlUANp;Qd-2q&?YiCaw`A0_duT2erBI(7sdOVCJ(a_mz|6f0$mt{EY)E}ZhvB~u8wlAAmWsgOr5!#m zi~g-nqg!eDh<}Kfk4eE(v8MCL#$-Jdug}ei2sLm|9wS_=!0v{fLmKH_`elX1cd7fn zk2nB9)?zv>o!yDGSn?ZUhakK!oJ_>(1FW8@wnxEfLx4QpP#h|qcFN>}t@U2cES(*h zk2ZPMw5jz6)FLe#=#|l_<>&CM0w|qBOmMQu6@dvhNB-0F%=Vqj8(iV9*bniA>1?XF zZ*Eg0_?sqZ=Y|Nc_T?7ORENmN5zqLaBKb1e&$(x8pmgY;FkP>su*?N7cVnZ?;De{t zxO!9;{s^Z7fE+uP39$fgksUZ$ z_#U>`p;`GSZPnm$hshfO-ghQK({~5H01lR0s!Pk?UeYvK9X_pC6?XJ9hf*6tYia)B zA_+F1HQh^3?(ATZU`?{g7`)>b>T6fm&qEiDKk3EkNVd=ro!cac9Fx1tTQc9QDMwDk zqa~J(k6k5qDld06LAHZzVpDt$sK2b3u})A46JX6AIi4Pz&0ce^kHL>w(btED8k5#n zV6$|%obkln(sqnwu9>dRJz5gqz-FK9LiRug>pTN184nZ!pgYxXw4i{c4PmL(fRi1R zKg7a9LA9znjuVj1*`vuI>0r$dsWW<6qju}XE$!o^dWx+N-7EM;)X(B?4KD6?j+#>6 z>)U$r1uwe0UTG^WHT)?m`|zN#g|>IujKISJl|XuE#TZY`lZz^7MD}^cMVX|jE@*RR zTaFr@s%%gRuJj@goOn9&e&s69D~>U5ly+c_?hXZvWY&(Z#@xAf-SUS3o8p8a+8I%1 zU^f#?+r~i_o|{!aozF!qS-KagN3x$0+t(U_S1B?Dw}96Fc4qt}6ds@C6?9l0{HUcQ zEgAx9q7E+JE<0pUcM-JGY*?AnE7ts3Z0;pdfI-pBT_fNhPwjB6k7xthmIRPxs;%9_ z=VQ)4DKQ2k+D@cDBy?{u_xnB%vgJ6=)mi82jiP~mou@96&?6hUud^HUK#8yg#_81! zDto;krP)@!ulS6o>a7L%tmA(z*jjG=eh=)GKFX`QF!jj zGW$p=2d_JDF1L{pSV}-lG#%&>NCFQV54}c%HIgIgzYiH*QLg+PHkj_FMCr4xvSgug z-4|@(ZV_#-0@ZhvfPjUGW$dfdB|2%G#Cq+_)S4Nq?$gxeezY}78cb^L_NOixc?&;q z7vr^acJ3eu4`fH};6HXxO1)m&AN+vY)5jM6`YTBlWaW}dU3|oIw=|pU3E3n4i>PZW z=?;7HTvL5*fQ98sS*K$|^iFM`3y)W91B@G%pT3GkTqgdbd(B;k!yPjwZwA1PeBIximP&yA0w~Y6eJMLmZJV%@QFPr z04(89LS8`5)B`FF`HacT;EvT^q0kss#4N+SS+V zOKQTC!_%QeQju5Fnd}FL+I;)3;#DHMrpGIsx?_VohQ72?Z{sBd`>7|Kev60)))8Ef$l`@9^;$WuZ)HkWq@NPTj!V&ETjSI|c; zL*Og)!V89rJy4RUw_goKddKHylmhaA&iAkE_mjTqS%00EM`sF{j{m`g`wE+mJDgm4 zjsX=D@lS>J+ocs3c=W1X!iG+}j|ZmCS?@I_9Mmi=y$iv6xjnjzU4+9n|jf zpe`!~nVDIB;Rb4a*x!%VdJ*P;JOkjdrp#E((c{v18gVyaG2Bz?z1wo9wP`{~B+W{p z0Pjr-mj6({;8&>g=kfRFW7%P4&m$8kE7 zx}$IkP7s=8D3)j0K!R^%l%plA!=gwETH z5W!%_c_~h6SP*L}-I*{IPEPG}_-v^1(@mB5>8tZR%1K}P(%o*}uG!$g88;ZCb1_Ot zrg_+Via$ktnYc&qrj3zCEVUUz-akt>W8PzsAr6rr=MwLuYWDT2yaWZxF^*FmXP~0w zT39%=zVcjWiFk5xqMH{Cc0|q?pd~E;dEcDT{;5ivztz zVncqehZNIGc{W!xliN!~*6DH}5y#NCYRia8HBs8m8@~e4L=dcnHGpi^5tGS>w3D!n zR)e;EPr_Jv;_BD0EfNxfzpKP-$Z>P~nV6u#PhvgxvyM1Flh2GShrUNo#^qe3i#oNH z8ojsijFj~E!1$b$cF_Pgt&ac>aVCZhDoyidiOpy@m8wlw;h~?!t)bY6Z#0@EWJQBP zGg0DIyejQP7>)3^fkEmrky9*zbCz{V@S#s6Sk=XeX0$}RPI7UUq^X5J&(+q7Rp%By zr4C`4YL}x;I%1%esRQr6Z4JS7|1-QO&I}cTNO(bn-AVgyot&};TNeRxwdL&=FDF5L z$lGBsu|@_@0`rXs^uO(oX`oql{`X-+5CInM1=E!v|{L zoJ=$_U>UwiMcGm&?)qZB<>`f$j4nW*1aQ?1nUGzjBF`tG#|0apIz`vJ^+kLAp2HfstdrrJ;%)M#?& zV_Qh$XS+qhv@80O2qwjlk+r1>CZilTXiK^Kv~>)NoE#q7;ir>+S(%c^%-loZMatnW zxFg2jQv7=T8NR$W6UN>D{+dV+7bMlpXpFS~o&V}34{{pyB)FFo(_@&Gogv?4WNM=! z7CdI`FIZZs3LWz(jbWDv8Y0o8%hgb#>VCB8?4$q!SNze2@{er5#t%MJH$ko0dF42) z%TqLcdt0c*k0I`yjPz1oUfCtXa~VGk%@RQu_y_hE8uRMRn{DV`*Q64k_kCI!wj$90 z%04nrvoVbNmnY)S_L#Ao0P!ZPQ&c~3l5e6{PHo&7e7|e@?0ysM)#dZ>LtW7*3Y9;b z`4};iHdt+X=9PL^YUkRJ>xwDwKw$o1)(AJ<##(74VG!S~t<6(kz53nQVG=b)@LflK zgl)|AiGVgcaBk{d=Y*b=;&}J;C$q>Q`Vo(*6{d4f4EXJCRSFcHj=-x@R@2`W(*O8B z@6z|BNU~z# zZ=fgoSZ64earx+DIM$AQ>d&^%v{p1Zz@FzQx^#Z+aAM(-KeE{Fg(_KeyOaQVUgSvJ ztnaeq0Br*Bp?ZnxC8lG>VZkGv&>rqrI*3Cwpht#@E+T$)e*HH8zIezv4arYwPU~Fl z&RF<&{~+Ke`l-)uUeq0J``z@=slSv}KQq^+hnva|oeozRb-o~oS6~8T{M;uo@{5CC zBFyt0zSI`?!)JzGL>jt93EG?S@5HdxXXe~$^=9;Jk9%!d14oFPRT8#fNcQ!`IzU*G zuBs?+m4OpfAh(!(ol8*vi~o!^>;o(0^d9vFSnI=n1GVY(zxBsE{N^2H z)u+K#DfM4S*=Dv$``4G@a)AO}gqUd5ot+a}2lf+x8yi%E4{;uCJ~d~J=F9LsUTQAa zyvQG2TfOAJQIYD!(;!Vl@HAydi)(|Lz8pA9bQ{*I(@NY59MBy5!3o08Se^o$;TEFu zxYX$%My`?DDI?@zD~;N~msdhn2!G+}FsJCdUEkVQae_fJ`Nl?*-FLR0bUNFGVPR3V zb4^ieGD$J!3NJsf{b;%TNth-{1HaRAe7G8VW}^E$v?A0-uH$$GW5$GOao!F!eYNGbeyn>XYj4p|f9_O6 zcVpLZdqP>zRsI56CY_%m2;*zpW6R*nIL{w?Iy*dqK`F~#lYE=UB8deD%) z6GZotGH(iQH&HcqfJIxR4TPptaE*A88vaB*RhT2oe7GE=* z^9^xlsYp7ET!c3tTJCYgZrwDgT_N7hNgI{_SZ!M|mow){2n}a6$pA$!$9W;Ym4dbQ z!c#=rp?7-HoJRjk=G)urKlvX=pKRGqTN_0FoQ+zFR@6wmXwz+u28%K~!f@^Qsr~vi z;%$t>5U8OQz}r@sV6QoIH{0Yf4@ZXRd@y}D)n`!4*KR`~d~eV=QkGNpcrdf?&n{D- zfr;>$QzZMiv(J_XvJFfG+eh4Bc~vuokaiNfN=lL!IK}(jQ{u0V%qeG*=i{o|89Kp4t8pQy)1k6Tup*h(e4X<0^t1T zbi;dGb1|G-56*jfZ=h`e;p^-(Q^~x`nS~mot;Yi4?NhM>{}qpyVuNog1ajxH$i>9PuD8KhDBY;wKlt1urdHV5yIB2y7yDtZW{=HaB% z(oQD5TfjiO`;R{f1=M={Ka7S00!;Wn-=mD)ifPC0f$}cuf)DEWWmq9aCvtP9kV%R9 zLhIbmm1LxKo}PhY&flbM>Z7UW*v&9uwV#V;R94bV;+e?J2>2U zub|~O)!v4IDeXsbo&AA^I(&lEOrqWHWdqyhC%GobBwILn_}FaBdjuSQC$qdIo(?YM zpOe|pnVz1gKNN;Zdb{ViBGRW7^o)dLjx`k5#6Re+7F~u|&h=wJIS<6+3Oz*#hNP4v z9ciD9+(%^d`;12rI+x!yIYs6*&Eg1>GYr1ifu(HKR)-z!zb@2b{=I+Hz#S3`eJ-04 zyT&>BULkHL9>k#aTBTtty55lHhL0h3cTs0*Q?>`mGLCG1l{|n~=doy3jAyN^(M`U@*)~41{M!413popLP7O z`IJ9Lbl#Ux={dBUG#$wI+79xS`ydR9n%F3R#h^gLSbN9m8TZgdh&aj9vW2DIhBJP3 zcA2+jjprgqJ+qj6F94pz*7{L5550Dk|Bu4xFa``FyQ6X{i#6HpJKl|>5WV_y_ihKd zXY3`MTwbh44CUUFG|*s2nYiq8US!O!WbM+MmubKO+6>`t*AH~8?5(zzztK3=YBUFX zz7;hykG~n((L$f)s>|whq|L!k!lm?)Y(-ir*xk9YL%?30&y@jP?&z#v@C;O_y&ex) rR&Vyd{Nr>oWDLh4c=A1g1J+O>u`9|2b5S*zdKbWBqEp|L2K2uGsh6+R literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..7389725 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xcc.mq5 @@ -0,0 +1,454 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: X121_CC +// Description: Candle Styles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_CC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_CC" + +// +// Holds an SnapShot of Charts Configuration ... +struct XChartStyle +{ + // + // chart's ID ... + long chartId; + // + // chart's mode ... + ENUM_CHART_MODE mode; + // + // show bid line ... + bool showBidLine; + // + // show ask line ... + bool showAskLine; + // + // show grids on chart ... + bool showGrid; + // + // show volumes ... + bool showVolumes; + // + // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ... + bool showTradeLevels; + // + // chart autoscroll ... + bool autoScroll; + // + // chart quick navigation state ... + bool quickNavigation; + // + // chart's foreground color ... + color foreGroundColor; + // + // chart's background color ... + color backGroundColor; + // + // Up Color ... + color upColor; + // + // Down Color ... + color downColor; + // + // Bullish color ... + color bullishColor; + // + // Bearish color ... + color bearishColor; + // + // grid color ... + color gridColor; + // + // bid line color ... + color bidLineColor; + // + // ask line color ... + color askLineColor; + // + // line mode and doji candlestick color ... + color lineColor; + // + // Color of stop order levels (Stop Loss and Take Profit) ... + color stopColor; + // + // volumes color ... + color volumesColor; +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Chart Style"; +input color upColor = clrLime; // Up Color +input color downColor = clrRed; // Down Color +input color lineColor = clrLime; // Line mode and Doji candlestick Color +input color bearishColor = clrRed; // Bullish Color +input color bullishColor = clrLime; // Bearish Color +input color volumesColor = clrGreen; // Volumes Color + +// +input group "Presentation"; +input bool showCandles = true; // Show Candles + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XChartStyle chartStyle; +XChartStyle clearStyle; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Apply Chart Style ... + ApplyCustomChartStyle(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// Apply Custom Chart Style ... +void ApplyCustomChartStyle() +{ + // + // Read Current Chart Config and Store it ... + ReadChartStyle(); + + // + // After Reading Current Chart Style ... + // we have to Save Configs and Change Styles ... + clearStyle = chartStyle; + + // + clearStyle.upColor = CLR_NONE; + clearStyle.downColor = CLR_NONE; + clearStyle.lineColor = CLR_NONE; + clearStyle.bullishColor = CLR_NONE; + clearStyle.bearishColor = CLR_NONE; + + // + // Decide to Show or not Candles based on User Input ... + if (showCandles) + { + SetChartStyle(chartStyle); + } + else + { + SetChartStyle(clearStyle); + } +} + +// +// Read Previous Chart Style ... +void ReadChartStyle() +{ + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + chartStyle.chartId = chartId; + + // + // Retrieve Chart Mode ... + chartStyle.mode = (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); + + // + chartStyle.showBidLine = (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); + chartStyle.showAskLine = (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); + chartStyle.showGrid = (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); + chartStyle.showVolumes = (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); + chartStyle.showTradeLevels = (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); + chartStyle.autoScroll = (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); + chartStyle.quickNavigation = (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); + + // + chartStyle.foreGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); + chartStyle.backGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); + chartStyle.upColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); + chartStyle.downColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); + chartStyle.bullishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); + chartStyle.bearishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); + chartStyle.gridColor = (color)ChartGetInteger(chartId, CHART_COLOR_GRID); + chartStyle.bidLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_BID); + chartStyle.askLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_ASK); + chartStyle.stopColor = (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); + chartStyle.lineColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); + chartStyle.volumesColor = (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); + + // + chartStyle.upColor = upColor; + chartStyle.downColor = downColor; + chartStyle.lineColor = lineColor; + chartStyle.bearishColor = bearishColor; + chartStyle.bullishColor = bullishColor; + chartStyle.volumesColor = volumesColor; +} + +// +// Set Chart Style ... +void SetChartStyle( + XChartStyle &mChartStyle // Chart Style to Apply +) +{ + // + ApplyChartStyle( + mChartStyle.chartId, + mChartStyle.mode, + mChartStyle.showBidLine, + mChartStyle.showAskLine, + mChartStyle.showGrid, + mChartStyle.showVolumes, + mChartStyle.showTradeLevels, + mChartStyle.autoScroll, + mChartStyle.quickNavigation, + mChartStyle.foreGroundColor, + mChartStyle.backGroundColor, + mChartStyle.upColor, + mChartStyle.downColor, + mChartStyle.bullishColor, + mChartStyle.bearishColor, + mChartStyle.gridColor, + mChartStyle.bidLineColor, + mChartStyle.askLineColor, + mChartStyle.lineColor, + mChartStyle.stopColor, + mChartStyle.volumesColor); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xche.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xche.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..3960a6fb476d8a2d6290608d3eb7f012ef311140 GIT binary patch literal 17704 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 9 && + loopback >= 0; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(length, loopback); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + uint arrowCode = 159; + + // + // LEVEL 1 ... + + // + // Long Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE longExit1DrawType = showLongExit1Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE longExit1StartDrawType = showLongExit1Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(longExit1BufferIndex, longExit1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit1BufferIndex, PLOT_SHOW_DATA, showLongExit1Line); + PlotIndexSetInteger(longExit1BufferIndex, PLOT_DRAW_TYPE, longExit1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(longExit1StartBufferIndex, longExit1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_DRAW_TYPE, longExit1StartDrawType); + + // + // Short Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE shortExit1DrawType = showShortExit1Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE shortExit1StartDrawType = showShortExit1Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(shortExit1BufferIndex, shortExit1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit1BufferIndex, PLOT_SHOW_DATA, showShortExit1Line); + PlotIndexSetInteger(shortExit1BufferIndex, PLOT_DRAW_TYPE, shortExit1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(shortExit1StartBufferIndex, shortExit1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_DRAW_TYPE, shortExit1StartDrawType); + + // + // LEVEL 2 ... + + // + // Long Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE longExit2DrawType = showLongExit2Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE longExit2StartDrawType = showLongExit2Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(longExit2BufferIndex, longExit2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit2BufferIndex, PLOT_SHOW_DATA, showLongExit2Line); + PlotIndexSetInteger(longExit2BufferIndex, PLOT_DRAW_TYPE, longExit2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(longExit2StartBufferIndex, longExit2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_DRAW_TYPE, longExit2StartDrawType); + + // + // Short Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE shortExit2DrawType = showShortExit2Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE shortExit2StartDrawType = showShortExit2Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(shortExit2BufferIndex, shortExit2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit2BufferIndex, PLOT_SHOW_DATA, showShortExit2Line); + PlotIndexSetInteger(shortExit2BufferIndex, PLOT_DRAW_TYPE, shortExit2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(shortExit2StartBufferIndex, shortExit2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_DRAW_TYPE, shortExit2StartDrawType); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int prevCalculated, // Previous Calculated + int ratesTotal, // Total Rates + const double &open[], // Rates Open ... + const double &high[], // Rates High ... + const double &low[], // Rates Low ... + const double &close[] // Rates Close ... +) +{ + // + // Cleanup Buffers ... + longExit1Buffer[bar_index] = longExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index] = shortExit1StartBuffer[bar_index] = EMPTY_VALUE; + longExit2Buffer[bar_index] = longExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index] = shortExit2StartBuffer[bar_index] = EMPTY_VALUE; + + // + int start = MathMax(bar_index - loopback, 0); + + // + // Calculate ATR Value ... + double atrValue = 0; + for (int k = 1; k <= length && (bar_index - k - 1) >= 0; k++) + { + // + atrValue += MathMax(high[bar_index - k], close[MathMax(bar_index - k - 1, 0)]) - + MathMin(low[bar_index - k], close[MathMax(bar_index - k - 1, 0)]); + } + atrValue /= (double)length; + + // + // Retrieve Highest High and Lowest Lows ... + double loopbackMax = high[ArrayMaximum(high, start, loopback)]; + double loopbackMin = low[ArrayMinimum(low, start, loopback)]; + + // + // Fill Multi Dimesional Working Array ... + work[bar_index][hi1Idx] = loopbackMax - multiplier1 * atrValue; + work[bar_index][lo1Idx] = loopbackMin + multiplier1 * atrValue; + work[bar_index][hi2Idx] = loopbackMax - multiplier2 * atrValue; + work[bar_index][lo2Idx] = loopbackMin + multiplier2 * atrValue; + work[bar_index][trend1Idx] = (bar_index > 0) ? work[bar_index - 1][trend1Idx] : 0; + work[bar_index][trend2Idx] = (bar_index > 0) ? work[bar_index - 1][trend2Idx] : 0; + + // + if (bar_index > 0) + { + // + // Calculate Trends ... + if (close[bar_index] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][trend1Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][trend1Idx] = -1; + } + + // + if (close[bar_index] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][trend2Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][trend2Idx] = -1; + } + + // + // Calculate Exit Values ... + + // + // Exit 1 ... + + // + // Long ... + if (multiplier1 > 0 && work[bar_index][trend1Idx] == 1) + { + // + if (work[bar_index][hi1Idx] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][hi1Idx] = work[bar_index - 1][hi1Idx]; + } + + // + longExit1Buffer[bar_index] = work[bar_index][hi1Idx]; + + // + if (longExit1Buffer[bar_index - 1] == EMPTY_VALUE) + { + longExit1StartBuffer[bar_index] = longExit1Buffer[bar_index]; + } + } + + // + // Short ... + if (multiplier1 > 0 && work[bar_index][trend1Idx] == -1) + { + // + if (work[bar_index][lo1Idx] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][lo1Idx] = work[bar_index - 1][lo1Idx]; + } + + // + shortExit1Buffer[bar_index] = work[bar_index][lo1Idx]; + + // + if (shortExit1Buffer[bar_index - 1] == EMPTY_VALUE) + { + shortExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index]; + } + } + + // + // Exit 2 ... + + // + // Long ... + if (multiplier2 > 0 && work[bar_index][trend2Idx] == 1) + { + if (work[bar_index][hi2Idx] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][hi2Idx] = work[bar_index - 1][hi2Idx]; + } + + // + longExit2Buffer[bar_index] = work[bar_index][hi2Idx]; + + // + if (longExit2Buffer[bar_index - 1] == EMPTY_VALUE) + { + longExit2StartBuffer[bar_index] = longExit2Buffer[bar_index]; + } + } + + // + // Short ... + if (multiplier2 > 0 && work[bar_index][trend2Idx] == -1) + { + // + if (work[bar_index][lo2Idx] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][lo2Idx] = work[bar_index - 1][lo2Idx]; + } + + // + shortExit2Buffer[bar_index] = work[bar_index][lo2Idx]; + + // + if (shortExit2Buffer[bar_index - 1] == EMPTY_VALUE) + { + shortExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index]; + } + } + } +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xct.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xct.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..8c752b54b44c2dcfe9cbd7cd1588d24e17cec8ab GIT binary patch literal 13694 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 F{{mmIj!OUl literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xct.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..72f2a26 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,264 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121_XCT +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XCT Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121_XCT" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showCandleTime = true; // Show Candle Time + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (showCandleTime) + { + CreateIndicatorObject(); + } + else + { + ObjectDelete(0, ShortName); + } + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Delete Object ... + ObjectDelete(0, ShortName); + + // + Comment(""); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + ArraySetAsSeries(time, true); + + // + if (!showCandleTime) + { + return rates_total; + } + + // + XCandleRemains remainTime; + GetCandleRemainsTime( + remainTime, + _Symbol, + _Period, + 0); + + // + string msg = ToString( + remainTime, + "", + "", + "", + "", + "", + ":", + true); + + // + long mSpread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); + + // + string _sp = ""; + if (mSpread < 10) + _sp = ".."; + else if (mSpread < 100) + _sp = "."; + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + " Next Bar in: " + msg; + + // + ObjectSetInteger(0, ShortName, OBJPROP_COLOR, clr); + ObjectSetString(0, ShortName, OBJPROP_TEXT, objText); + ObjectSetInteger(0, ShortName, OBJPROP_FONTSIZE, 10); + ObjectSetString(0, ShortName, OBJPROP_FONT, "Courier"); + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +void CreateIndicatorObject() +{ + // + if (!showCandleTime) + { + return; + } + + // + ObjectCreate(0, ShortName, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, ShortName, OBJPROP_CORNER, corner); + ObjectSetInteger(0, ShortName, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, ShortName, OBJPROP_YDISTANCE, 2); + + // + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + ObjectSetInteger(0, ShortName, OBJPROP_ANCHOR, Anchor); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..7b21716b84e794774c8a8f5789fec0c23153e151 GIT binary patch literal 11108 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.mq5 new file mode 100644 index 0000000..4d80fb3 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xhk.mq5 @@ -0,0 +1,486 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// -------------------------------------------- +// Name: X121_HK +// Description: Hiken Ashi ... +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XHK Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_XHK" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Presentation"; +input bool drawCandles = true; // Draw Hiken Ashi Candle +input bool drawCandleLines = false; // Show HikenAshi Lines + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 13 +#property indicator_plots 5 + +// +// PLOTTED Buffers ... + +// +// Open ... +#define openBufferIndex 0 +double openBuffer[]; + +// +// High ... +#define highBufferIndex 1 +double highBuffer[]; + +// +// Low ... +#define lowBufferIndex 2 +double lowBuffer[]; + +// +// Close ... +#define closeBufferIndex 3 +double closeBuffer[]; + +// +// Candle Color ... +#define candleColorBufferIndex 4 +double candleColorBuffer[]; + +// +#define candlesBufferIndex 0 + +// +#property indicator_label1 "X121_XHK Open;X121_XHK High;X121_XHK Low;X121_XHK Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 clrAqua, clrMagenta, CLR_NONE + +// +#define openHKBufferIndex 5 +#define openHKColorBufferIndex 6 +double openHKBuffer[]; +double openHKColorBuffer[]; + +// +#define openHKBufferPlotIndex 1 +#property indicator_label2 "X121_XHK O" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 clrAqua, clrMagenta, clrLightGray +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +#define highHKBufferIndex 7 +#define highHKColorBufferIndex 8 +double highHKBuffer[]; +double highHKColorBuffer[]; + +// +#define highHKBufferPlotIndex 2 +#property indicator_label3 "X121_XHK H" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 clrAqua, clrMagenta, clrLightGray +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define lowHKBufferIndex 9 +#define lowHKColorBufferIndex 10 +double lowHKBuffer[]; +double lowHKColorBuffer[]; + +// +#define lowHKBufferPlotIndex 3 +#property indicator_label4 "X121_XHK L" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 clrAqua, clrMagenta, clrLightGray +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define closeHKBufferIndex 11 +#define closeHKColorBufferIndex 12 +double closeHKBuffer[]; +double closeHKColorBuffer[]; + +// +#define closeHKBufferPlotIndex 4 +#property indicator_label5 "X121_XHK C" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 clrAqua, clrMagenta, clrLightGray +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i, prev_calculated, rates_total, open, high, close, low); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Candles Color ... + ArraySetAsSeries(candleColorBuffer, true); + SetIndexBuffer(candleColorBufferIndex, candleColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(candlesBufferIndex, PLOT_EMPTY_VALUE, 0.0); + + // + PlotIndexSetInteger(candlesBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(candleColorBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + PlotIndexSetInteger(openBufferIndex, PLOT_SHOW_DATA, false); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + PlotIndexSetInteger(highBufferIndex, PLOT_SHOW_DATA, false); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + PlotIndexSetInteger(closeBufferIndex, PLOT_SHOW_DATA, false); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open HK ... + ENUM_DRAW_TYPE openDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(openHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(openHKBufferPlotIndex, PLOT_DRAW_TYPE, openDrawType); + + // + ArraySetAsSeries(openHKColorBuffer, true); + SetIndexBuffer(openHKColorBufferIndex, openHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // High HK ... + ENUM_DRAW_TYPE highDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(highHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(highHKBufferPlotIndex, PLOT_DRAW_TYPE, highDrawType); + + // + ArraySetAsSeries(highHKColorBuffer, true); + SetIndexBuffer(highHKColorBufferIndex, highHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Low HK ... + ENUM_DRAW_TYPE lowDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(lowHKBufferPlotIndex, PLOT_DRAW_TYPE, lowDrawType); + + // + ArraySetAsSeries(lowHKColorBuffer, true); + SetIndexBuffer(lowHKColorBufferIndex, lowHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Close HK ... + ENUM_DRAW_TYPE closeDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(closeHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(closeHKBufferPlotIndex, PLOT_DRAW_TYPE, closeDrawType); + + // + ArraySetAsSeries(closeHKColorBuffer, true); + SetIndexBuffer(closeHKColorBufferIndex, closeHKColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[]) +{ + // + double mPrevHKOpenValue; + double mPrevHKCloseValue; + + // + if (ArraySize(open) <= bar_index + 1) + { + // + mPrevHKOpenValue = 0; + mPrevHKCloseValue = 0; + } + else + { + // + mPrevHKOpenValue = openBuffer[bar_index + 1]; + mPrevHKCloseValue = closeBuffer[bar_index + 1]; + } + + // + double mHKOpenValue = (mPrevHKOpenValue + mPrevHKCloseValue) / 2; + double mHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double mHKHighValue = MathMax(high[bar_index], MathMax(mHKOpenValue, mHKCloseValue)); + double mHKLowValue = MathMin(low[bar_index], MathMin(mHKOpenValue, mHKCloseValue)); + + // + openBuffer[bar_index] = mHKOpenValue; + highBuffer[bar_index] = mHKHighValue; + lowBuffer[bar_index] = mHKLowValue; + closeBuffer[bar_index] = mHKCloseValue; + + // + double candleColorValue = + mHKOpenValue < mHKCloseValue ? 0 : 1; + + // + candleColorBuffer[bar_index] = drawCandles ? candleColorValue : 2; + + // + openHKBuffer[bar_index] = mHKOpenValue; + openHKColorBuffer[bar_index] = candleColorValue; + + // + highHKBuffer[bar_index] = mHKHighValue; + highHKColorBuffer[bar_index] = candleColorValue; + + // + lowHKBuffer[bar_index] = mHKLowValue; + lowHKColorBuffer[bar_index] = candleColorValue; + + // + closeHKBuffer[bar_index] = mHKCloseValue; + closeHKColorBuffer[bar_index] = candleColorValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..b4cc7431a9b95652342b0c007cfc2b496116953e GIT binary patch literal 18034 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.mq5 new file mode 100644 index 0000000..dbfc3e1 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xhull.mq5 @@ -0,0 +1,602 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121_XHULL +// Description: Hull Trend Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XHULL Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121_XHULL" + +// +struct XHullData +{ + // + double value; + double value3; + + // + double wsum1; + double wsum2; + double wsum3; + + // + double lsum1; + double lsum2; + double lsum3; +}; + +// +// END Constants ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START XSCHULL Class Definition ... +// + +// +// a Class For Hull Calculations ... +class XSCHull +{ + // +public: + // + // Constructor ... + XSCHull() : mFullPeriod(1), mHalfPeriod(1), mSqrtPeriod(1), mArraySize(-1) + { + // + // These are a way above to assign Private variables at Construct time ... + } + + // + // Deconstructor ... + ~XSCHull() + { + ArrayFree(mData); + } + + // + // Initial Hull ... + bool Init( + int mPeriod, + double mDivisor) + { + // + bool result = false; + + // + mFullPeriod = (int)(mPeriod > 1 ? mPeriod : 1); + mHalfPeriod = (int)(mFullPeriod > 1 ? mFullPeriod / (mDivisor > 1 ? mDivisor : 1) : 1); + mSqrtPeriod = (int)MathSqrt(mFullPeriod); + + // + mArraySize = -1; + mWeight1 = mWeight2 = mWeight3 = 1; + + // + result = true; + + // + return result; + } + + // + // CalCulate Specific Value ... + double Calculate( + double value, + int i, + int bars) + { + // + double result = 0; + + // + if (mArraySize < bars) + { + // + mArraySize = ArrayResize(mData, bars + 500); + if (mArraySize < bars) + return result; + } + + // + mData[i].value = value; + if (i > mFullPeriod) + { + // + mData[i].wsum1 = mData[i - 1].wsum1 + value * mHalfPeriod - mData[i - 1].lsum1; + mData[i].lsum1 = mData[i - 1].lsum1 + value - mData[i - mHalfPeriod].value; + mData[i].wsum2 = mData[i - 1].wsum2 + value * mFullPeriod - mData[i - 1].lsum2; + mData[i].lsum2 = mData[i - 1].lsum2 + value - mData[i - mFullPeriod].value; + } + else + { + // + mData[i].wsum1 = mData[i].wsum2 = + mData[i].lsum1 = mData[i].lsum2 = mWeight1 = mWeight2 = 0; + for (int k = 0, w1 = mHalfPeriod, w2 = mFullPeriod; w2 > 0 && i >= k; k++, w1--, w2--) + { + // + if (w1 > 0) + { + // + mData[i].wsum1 += mData[i - k].value * w1; + mData[i].lsum1 += mData[i - k].value; + mWeight1 += w1; + } + + // + mData[i].wsum2 += mData[i - k].value * w2; + mData[i].lsum2 += mData[i - k].value; + mWeight2 += w2; + } + } + + // + mData[i].value3 = 2.0 * mData[i].wsum1 / mWeight1 - mData[i].wsum2 / mWeight2; + + // + if (i > mSqrtPeriod) + { + // + mData[i].wsum3 = mData[i - 1].wsum3 + mData[i].value3 * mSqrtPeriod - mData[i - 1].lsum3; + mData[i].lsum3 = mData[i - 1].lsum3 + mData[i].value3 - mData[i - mSqrtPeriod].value3; + } + else + { + // + mData[i].wsum3 = + mData[i].lsum3 = mWeight3 = 0; + + // + for (int k = 0, w3 = mSqrtPeriod; w3 > 0 && i >= k; k++, w3--) + { + // + mData[i].wsum3 += mData[i - k].value3 * w3; + mData[i].lsum3 += mData[i - k].value3; + mWeight3 += w3; + } + } + + // + result = mData[i].wsum3 / mWeight3; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + int mFullPeriod; + int mHalfPeriod; + int mSqrtPeriod; + int mArraySize; + double mWeight1; + double mWeight2; + double mWeight3; + + // + XHullData mData[]; +}; + +// +// END XSCHULL Class Definition ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 72; // Length +input double divisor = 2.0; // Divisor (Speed) + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Zone Applied to +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Zone Applied to + +// +input group "Presentation"; +input bool showUpZone = true; // Show Up Zone +input bool showDownZone = true; // Show Down Zone + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// UP Zone ... + +// +#define upZoneBufferIndex 0 +#define upZoneColorBufferIndex 1 + +// +double upZoneBuffer[]; +double upZoneColorBuffer[]; + +// +#property indicator_label1 "X121_XHULL Up" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLightGray, clrAqua, clrMagenta +#property indicator_width1 1 + +// +// DOWN Zone ... + +// +#define downZoneBufferIndex 2 +#define downZoneColorBufferIndex 3 + +// +double downZoneBuffer[]; +double downZoneColorBuffer[]; + +// +#property indicator_label2 "X121_XHULL Down" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 clrLightGray, clrAqua, clrMagenta +#property indicator_width2 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XSCHull *mUpZHull; +XSCHull *mDownZHull; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Make an Instance of Hull Class ... + + // + mUpZHull = new XSCHull(); + mUpZHull.Init( + length, + divisor); + + // + mDownZHull = new XSCHull(); + mDownZHull.Init( + length, + divisor); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + delete mUpZHull; + delete mDownZHull; +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // this counts Available Bars ... + int limit; + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + double upPrice = getPrice( + upAppliedTo, + open, high, low, close, i); + + // + double downPrice = getPrice( + downAppliedTo, + open, high, low, close, i); + + // + CalculateBuffers( + i, + rates_total, + upPrice, + downPrice); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + length >= 9 && + divisor >= 0.5; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = length; + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // UP Zone ... + + // + // Draw Type ... + ENUM_DRAW_TYPE upZoneDrawType = showUpZone ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(upZoneBufferIndex, upZoneBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upZoneBufferIndex, PLOT_SHOW_DATA, showUpZone); + PlotIndexSetInteger(upZoneBufferIndex, PLOT_DRAW_TYPE, upZoneDrawType); + + // + // Color Buffer ... + SetIndexBuffer(upZoneColorBufferIndex, upZoneColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DOWN Zone ... + + // + // Draw Type ... + ENUM_DRAW_TYPE downZoneDrawType = showDownZone ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(downZoneBufferIndex, downZoneBuffer, INDICATOR_DATA); + PlotIndexSetInteger(downZoneBufferIndex - 1, PLOT_SHOW_DATA, showDownZone); + PlotIndexSetInteger(downZoneBufferIndex - 1, PLOT_DRAW_TYPE, downZoneDrawType); + + // + // Color Buffer ... + SetIndexBuffer(downZoneColorBufferIndex, downZoneColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int ratesTotal, // Total Rates + double upPrice, // Up Price ... + double downPrice // Down Price ... +) +{ + // + double upValue = mUpZHull.Calculate( + upPrice, + bar_index, + ratesTotal); + upZoneBuffer[bar_index] = upValue; + double upColorIDX = (bar_index > 0) + ? (upZoneBuffer[bar_index] > upZoneBuffer[bar_index - 1]) + ? 1 + : (upZoneBuffer[bar_index] < upZoneBuffer[bar_index - 1]) + ? 2 + : upZoneColorBuffer[bar_index - 1] + : 0; + upZoneColorBuffer[bar_index] = upColorIDX; + + // + double downValue = mDownZHull.Calculate( + downPrice, + bar_index, + ratesTotal); + downZoneBuffer[bar_index] = downValue; + double downColorIDX = (bar_index > 0) + ? (downZoneBuffer[bar_index] > downZoneBuffer[bar_index - 1]) + ? 1 + : (downZoneBuffer[bar_index] < downZoneBuffer[bar_index - 1]) + ? 2 + : downZoneColorBuffer[bar_index - 1] + : 0; + downZoneColorBuffer[bar_index] = downColorIDX; +} + +// +// END Functions ... +// + +// +// TEMPLATE Function ... + +template +double getPrice(ENUM_APPLIED_PRICE tprice, T &open[], T &high[], T &low[], T &close[], int i) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xich.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xich.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..e0e91b2e0a3fbf3de712fbbff2534637e15db10c GIT binary patch literal 19182 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 D(ca}c literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xich.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xich.mq5 new file mode 100644 index 0000000..5493ba2 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xich.mq5 @@ -0,0 +1,743 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121_XICH +// Description: Ichimoku Kinko Hyo ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XICH Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_XICH" + +// +// Ichimoku Golden Numbers ... +enum ENUM_X_ICHIMOKU_GOLDEN_NUMBERS +{ + X_ICH_BASE = 9, + X_ICH_GOLDEN = 17, + X_ICH_CYCLE = 26, + X_ICH_PERIOD = 35, + X_ICH_STAR = 45, + X_ICH_MED = 52, + X_ICH_LONG = 63, + X_ICH_FULL = 72 +}; + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// ICHIMOKU Kinko Hyo ... + +// +// TENKANSEN ... +input group "Tenkan Sen"; +input int tenkanSenLength = 9; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// KIJUNSEN ... +input group "Kijun Sen"; +input int kijunSenLength = 26; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// SENKOUSPANB ... +input group "Senkou Span B"; +input int senkouSpanBLength = 52; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// CHIKOUSPAN ... +input group "Chikou Span"; +input ENUM_APPLIED_PRICE chikuoSpanAppliedTo = PRICE_CLOSE; // Price Type + +// +input group "Presentation"; +input bool showTenkanSen = true; // Show Tenkan Sen +input bool showKijunSen = true; // Show Kijun Sen +input bool showKijunSenPlus = false; // Show Kijun Sen + +input bool showKijunSenNegative = false; // Show Kijun Sen - +input bool showChikouSpan = true; // Show Chikou Span +input bool showSenkouSpanA = true; // Show Senkou Span A +input bool showSenkouSpanB = true; // Show Senkou Span B +input bool showKumo = true; // Show Kumo +input bool shiftKumo = true; // Shift Kumo to Future + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 8 + +// +// PLOTTED Buffers ... + +// +// ICHIMOKU ... + +// +// TENKANSEN ... + +// +#define tenkanSenBufferIndex 0 +double tenkanSenBuffer[]; + +// +#property indicator_label1 "X121_XICH TK" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// KIJUNSEN ... + +// +#define kijunSenBufferIndex 1 +double kijunSenBuffer[]; + +// +#property indicator_label2 "X121_XICH KJ" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrDodgerBlue +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define kijunSenPlusBufferIndex 2 +double kijunSenPlusBuffer[]; + +// +#property indicator_label3 "X121_XICH KJ+" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrMediumTurquoise +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define kijunSenNegativeBufferIndex 3 +double kijunSenNegativeBuffer[]; + +// +#property indicator_label4 "X121_XICH KJ-" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrDarkSeaGreen +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// CHIKOUSPAN ... + +// +#define chikouSpanBufferIndex 4 +double chikouSpanBuffer[]; + +// +#property indicator_label5 "X121_XICH CS" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrDarkGreen +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +#define senkouABufferIndex 5 +double senkouABuffer[]; + +// +#property indicator_label6 "X121_XICH SSA" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrLightGray +#property indicator_style6 STYLE_DASHDOTDOT +#property indicator_width6 1 + +// +#define senkouBBufferIndex 6 +double senkouBBuffer[]; + +// +#property indicator_label7 "X121_XICH SSB" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrLightGray +#property indicator_style7 STYLE_DASHDOTDOT +#property indicator_width7 1 + +// +// KUMO ... + +// +// SENKOUSPANA ... + +// +#define senkouSpanABufferIndex 7 +double senkouSpanABuffer[]; + +// +// SENKOUSPANB ... + +// +#define senkouSpanBBufferIndex 8 +double senkouSpanBBuffer[]; + +// +// KUMOCLOUD ... + +// +#define kumoBufferIndex 7 + +// +#property indicator_label8 "X121_XICH Kumo" +#property indicator_type8 DRAW_FILLING +#property indicator_color8 clrAqua, clrMagenta +#property indicator_style8 STYLE_SOLID +#property indicator_width8 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +ENUM_SERIESMODE mTenkanSenTopMode = NULL; +ENUM_SERIESMODE mTenkanSenBottomMode = NULL; + +// +ENUM_SERIESMODE mKijunSenTopMode = NULL; +ENUM_SERIESMODE mKijunSenBottomMode = NULL; + +// +ENUM_SERIESMODE mSenkouSpanBTopMode = NULL; +ENUM_SERIESMODE mSenkouSpanBBottomMode = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (tenkanSenLength > 2 && + kijunSenLength > tenkanSenLength && + senkouSpanBLength > kijunSenLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ichimoku ... + result = MathMax(result, tenkanSenLength); + result = MathMax(result, kijunSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // ICHIMOKU ... + + // + // TENKANSEN ... + + // + ENUM_DRAW_TYPE tenkanSenDrawType = showTenkanSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tenkanSenBuffer, true); + SetIndexBuffer(tenkanSenBufferIndex, tenkanSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_SHOW_DATA, showTenkanSen); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_TYPE, tenkanSenDrawType); + + // + // KIJUNSEN ... + + // + ENUM_DRAW_TYPE kijunSenDrawType = showKijunSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenBuffer, true); + SetIndexBuffer(kijunSenBufferIndex, kijunSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_SHOW_DATA, showKijunSen); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_TYPE, kijunSenDrawType); + + // + // KIJUNSEN Plus ... + + // + ENUM_DRAW_TYPE kijunSenPlusDrawType = showKijunSenPlus ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenPlusBuffer, true); + SetIndexBuffer(kijunSenPlusBufferIndex, kijunSenPlusBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_SHIFT, kijunSenLength); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_DRAW_TYPE, kijunSenPlusDrawType); + + // + // KIJUNSEN Negative ... + + // + ENUM_DRAW_TYPE kijunSenNegativeDrawType = showKijunSenNegative ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenNegativeBuffer, true); + SetIndexBuffer(kijunSenNegativeBufferIndex, kijunSenNegativeBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_DRAW_TYPE, kijunSenNegativeDrawType); + + // + // CHIKOUSPAN ... + + // + ENUM_DRAW_TYPE chikouSpanDrawType = showChikouSpan ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(chikouSpanBuffer, true); + SetIndexBuffer(chikouSpanBufferIndex, chikouSpanBuffer, INDICATOR_DATA); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHOW_DATA, showChikouSpan); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_TYPE, chikouSpanDrawType); + + // + // SENKOUSPAN A and B ... + int shiftSize = shiftKumo ? kijunSenLength : 0; + + // + // SENKOUSPANA ... + ENUM_DRAW_TYPE senkouSpanADrawType = showSenkouSpanA ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(senkouABuffer, true); + SetIndexBuffer(senkouABufferIndex, senkouABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouABufferIndex, PLOT_SHOW_DATA, showSenkouSpanA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_DRAW_TYPE, senkouSpanADrawType); + + // + // SENKOUSPANB ... + ENUM_DRAW_TYPE senkouSpanBDrawType = showSenkouSpanB ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(senkouBBuffer, true); + SetIndexBuffer(senkouBBufferIndex, senkouBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_SHOW_DATA, showSenkouSpanB); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_DRAW_TYPE, senkouSpanBDrawType); + + // + // KUMO ... + + // + // SENKOUSPANA ... + ArraySetAsSeries(senkouSpanABuffer, true); + SetIndexBuffer(senkouSpanABufferIndex, senkouSpanABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // SENKOUSPANB ... + ArraySetAsSeries(senkouSpanBBuffer, true); + SetIndexBuffer(senkouSpanBBufferIndex, senkouSpanBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // KUMO ... + + // + ENUM_DRAW_TYPE kumoDrawType = showKumo ? DRAW_FILLING : DRAW_NONE; + + // + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kumoBufferIndex, PLOT_DRAW_TYPE, kumoDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // ICHIMOKU ... + + // + double topValue; + double bottomValue; + + // + // TENKANSEN ... + + // + // Extract Tenkan Sen Top/Bottom Calculation Mode based on User Input ... + if (mTenkanSenTopMode == NULL || mTenkanSenBottomMode == NULL) + { + // + switch (tenkanSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mTenkanSenTopMode = MODE_HIGH; + mTenkanSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mTenkanSenTopMode = MODE_OPEN; + mTenkanSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mTenkanSenTopMode, + tenkanSenLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mTenkanSenBottomMode, + tenkanSenLength, + bar_index); + + // + double tenkanSenValue = (topValue + bottomValue) / 2; + tenkanSenBuffer[bar_index] = tenkanSenValue; + + // + // KIJUNSEN ... + + // + // Extract Kijun Sen Top/Bottom Calculation Mode based on User Input ... + if (mKijunSenTopMode == NULL || mKijunSenBottomMode == NULL) + { + // + switch (kijunSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mKijunSenTopMode = MODE_HIGH; + mKijunSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mKijunSenTopMode = MODE_OPEN; + mKijunSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mKijunSenTopMode, + kijunSenLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mKijunSenBottomMode, + kijunSenLength, + bar_index); + + // + double kijunSenValue = (topValue + bottomValue) / 2; + kijunSenBuffer[bar_index] = kijunSenValue; + + // + kijunSenPlusBuffer[bar_index] = kijunSenValue; + kijunSenNegativeBuffer[bar_index] = kijunSenValue; + + // + // CHIKOUSPAN ... + double chikouSpanValue = GetAppliedPrice( + bar_index, + chikuoSpanAppliedTo); + chikouSpanBuffer[bar_index] = chikouSpanValue; + + // + // KUMO ... + + // + // SENKOUSPANA ... + double senkouSpanAValue = (tenkanSenValue + kijunSenValue) / 2; + senkouABuffer[bar_index] = senkouSpanAValue; + senkouSpanABuffer[bar_index] = senkouSpanAValue; + + // + // SENKOUSPANB ... + + // + // Extract Senkou Span B Top/Bottom Calculation Mode based on User Input ... + if (mSenkouSpanBTopMode == NULL || mSenkouSpanBBottomMode == NULL) + { + // + switch (senkouSpanBMode) + { + // + case X_XICH_HH_LL_MODE: + // + mSenkouSpanBTopMode = MODE_HIGH; + mSenkouSpanBBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mSenkouSpanBTopMode = MODE_OPEN; + mSenkouSpanBBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mSenkouSpanBTopMode, + senkouSpanBLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mSenkouSpanBBottomMode, + senkouSpanBLength, + bar_index); + + // + double senkouSpanBValue = (topValue + bottomValue) / 2; + senkouBBuffer[bar_index] = senkouSpanBValue; + senkouSpanBBuffer[bar_index] = senkouSpanBValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xmrb.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xmrb.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..c4bbb9b01d9b62e72305ac90e222fd0766797285 GIT binary patch literal 20740 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 W rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + // + int copiedFast1Mas = CopyBuffer(fast1MaHandler, 0, 0, limit, fast1Buffer); + int copiedFast2Mas = CopyBuffer(fast2MaHandler, 0, 0, limit, fast2Buffer); + int copiedFast3Mas = CopyBuffer(fast3MaHandler, 0, 0, limit, fast3Buffer); + int copiedFast4Mas = CopyBuffer(fast4MaHandler, 0, 0, limit, fast4Buffer); + int copiedFast5Mas = CopyBuffer(fast5MaHandler, 0, 0, limit, fast5Buffer); + // + int copiedSlow1Mas = CopyBuffer(slow1MaHandler, 0, 0, limit, slow1Buffer); + int copiedSlow2Mas = CopyBuffer(slow2MaHandler, 0, 0, limit, slow2Buffer); + int copiedSlow3Mas = CopyBuffer(slow3MaHandler, 0, 0, limit, slow3Buffer); + int copiedSlow4Mas = CopyBuffer(slow4MaHandler, 0, 0, limit, slow4Buffer); + int copiedSlow5Mas = CopyBuffer(slow5MaHandler, 0, 0, limit, slow5Buffer); + if ( + copiedFast1Mas <= 0 || + copiedFast2Mas <= 0 || + copiedFast3Mas <= 0 || + copiedFast4Mas <= 0 || + copiedFast5Mas <= 0 || + copiedSlow1Mas <= 0 || + copiedSlow2Mas <= 0 || + copiedSlow3Mas <= 0 || + copiedSlow4Mas <= 0 || + copiedSlow5Mas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (fast1Length > 2 && + fast2Length > fast1Length && + fast3Length > fast2Length && + fast4Length > fast3Length && + fast5Length > fast4Length && + slow1Length > fast1Length && + slow2Length > fast2Length && + slow3Length > fast3Length && + slow4Length > fast4Length && + slow5Length > fast5Length && + slow2Length > slow1Length && + slow3Length > slow2Length && + slow4Length > slow3Length && + slow5Length > slow4Length + // + ) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ma ... + + // + result = MathMax(fast1Length, fast2Length); + result = MathMax(result, fast3Length); + result = MathMax(result, fast4Length); + result = MathMax(result, fast5Length); + + // + result = MathMax(result, slow1Length); + result = MathMax(result, slow2Length); + result = MathMax(result, slow3Length); + result = MathMax(result, slow4Length); + result = MathMax(result, slow5Length); + + // + return result; +} + +// +// Initialize Ma Handlers ... +bool InitializeMas() +{ + // + bool result = false; + + // + fast1MaHandler = iMA( + _Symbol, + _Period, + fast1Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast2MaHandler = iMA( + _Symbol, + _Period, + fast2Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast3MaHandler = iMA( + _Symbol, + _Period, + fast3Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast4MaHandler = iMA( + _Symbol, + _Period, + fast4Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast5MaHandler = iMA( + _Symbol, + _Period, + fast5Length, + 0, + ribbonMode, + ribbonAppliedTo); + + // + slow1MaHandler = iMA( + _Symbol, + _Period, + slow1Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow2MaHandler = iMA( + _Symbol, + _Period, + slow2Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow3MaHandler = iMA( + _Symbol, + _Period, + slow3Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow4MaHandler = iMA( + _Symbol, + _Period, + slow4Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow5MaHandler = iMA( + _Symbol, + _Period, + slow5Length, + 0, + ribbonMode, + ribbonAppliedTo); + + // + result = + fast1MaHandler != INVALID_HANDLE && + fast2MaHandler != INVALID_HANDLE && + fast3MaHandler != INVALID_HANDLE && + fast4MaHandler != INVALID_HANDLE && + fast5MaHandler != INVALID_HANDLE && + slow1MaHandler != INVALID_HANDLE && + slow2MaHandler != INVALID_HANDLE && + slow3MaHandler != INVALID_HANDLE && + slow4MaHandler != INVALID_HANDLE && + slow5MaHandler != INVALID_HANDLE; + + // + if (!result) + { + // + string message = "Error Initializing Handlers ..."; + Print(message); + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // FAST ... + ENUM_DRAW_TYPE fastDrawType = showFastMa ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(fastMaBuffer, true); + SetIndexBuffer(fastMaBufferIndex, fastMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_SHOW_DATA, showFastMa); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_TYPE, fastDrawType); + + // + // SLOW ... + ENUM_DRAW_TYPE slowDrawType = showSlowMa ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(slowMaBuffer, true); + SetIndexBuffer(slowMaBufferIndex, slowMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_SHOW_DATA, showSlowMa); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_TYPE, slowDrawType); + + // + // DATA ... + ENUM_DRAW_TYPE ribbonDrawType = showRibbon ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fast1Buffer, true); + SetIndexBuffer(fast1BufferIndex, fast1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast1BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast1BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast2Buffer, true); + SetIndexBuffer(fast2BufferIndex, fast2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast2BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast2BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast3Buffer, true); + SetIndexBuffer(fast3BufferIndex, fast3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast3BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast3BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast4Buffer, true); + SetIndexBuffer(fast4BufferIndex, fast4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast4BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast4BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast4BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast5Buffer, true); + SetIndexBuffer(fast5BufferIndex, fast5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast5BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast5BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast5BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow1Buffer, true); + SetIndexBuffer(slow1BufferIndex, slow1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow1BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow1BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow2Buffer, true); + SetIndexBuffer(slow2BufferIndex, slow2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow2BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow2BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow3Buffer, true); + SetIndexBuffer(slow3BufferIndex, slow3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow3BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow3BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow4Buffer, true); + SetIndexBuffer(slow4BufferIndex, slow4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow4BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow4BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow4BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow5Buffer, true); + SetIndexBuffer(slow5BufferIndex, slow5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow5BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow5BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow5BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Retireve Values ... + + // + double fast1Value = fast1Buffer[bar_index]; + double fast2Value = fast2Buffer[bar_index]; + double fast3Value = fast3Buffer[bar_index]; + double fast4Value = fast4Buffer[bar_index]; + double fast5Value = fast5Buffer[bar_index]; + + // + double slow1Value = slow1Buffer[bar_index]; + double slow2Value = slow2Buffer[bar_index]; + double slow3Value = slow3Buffer[bar_index]; + double slow4Value = slow4Buffer[bar_index]; + double slow5Value = slow5Buffer[bar_index]; + + // + double fastValue = (fast1Value + fast2Value + fast3Value + fast4Value + fast5Value) / 5; + fastMaBuffer[bar_index] = fastValue; + + // + double slowValue = (slow1Value + slow2Value + slow3Value + slow4Value + slow5Value) / 5; + slowMaBuffer[bar_index] = slowValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xpv.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xpv.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..878e0fec9e70724b9339f5b401229ac32acb249d GIT binary patch literal 23320 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 y-|JC6i5KZv6|u&ko}%ja7Zrf rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (shortLength > 2 && + mediumLength > shortLength && + longLength > mediumLength && + hindLength > longLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax(shortLength, mediumLength); + result = MathMax(result, longLength); + result = MathMax(result, hindLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RANGE ... + + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, 225); + // PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW_SHIFT, -20); + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, 225); + // PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW_SHIFT, 20); + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // SUPPORT and RESISTANCE ... + // + + // + // RESISTANCE ... + ArraySetAsSeries(rBuffer, true); + SetIndexBuffer(rBufferIndex, rBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(rBufferIndex, PLOT_SHOW_DATA, false); + + // + // RESISTANCE Color ... + ArraySetAsSeries(rColorBuffer, true); + SetIndexBuffer(rColorBufferIndex, rColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SUPPORT ... + ArraySetAsSeries(sBuffer, true); + SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // SUPPORT Color ... + ArraySetAsSeries(sColorBuffer, true); + SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX); + + // + // FIBBO Levels ... + + // + // LEVEL 1 ... + + // + // BULLISH ... + ArraySetAsSeries(fl1Buffer, true); + SetIndexBuffer(fl1BufferIndex, fl1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl1BufferIndex, PLOT_SHOW_DATA, showFibo1Levels); + + // + // BULLISH Color ... + ArraySetAsSeries(fl1ColorBuffer, true); + SetIndexBuffer(fl1ColorBufferIndex, fl1ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 2 ... + + // + // BULLISH ... + ArraySetAsSeries(fl2Buffer, true); + SetIndexBuffer(fl2BufferIndex, fl2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl2BufferIndex, PLOT_SHOW_DATA, showFibo2Levels); + + // + // BULLISH Color ... + ArraySetAsSeries(fl2ColorBuffer, true); + SetIndexBuffer(fl2ColorBufferIndex, fl2ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 3 ... + + // + // BULLISH ... + ArraySetAsSeries(fl3Buffer, true); + SetIndexBuffer(fl3BufferIndex, fl3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl3BufferIndex, PLOT_SHOW_DATA, showFibo3Levels); + + // + // BULLISH Color ... + ArraySetAsSeries(fl3ColorBuffer, true); + SetIndexBuffer(fl3ColorBufferIndex, fl3ColorBuffer, INDICATOR_COLOR_INDEX); + + // + ENUM_DRAW_TYPE zoneDrawType = showLevels ? DRAW_LINE : DRAW_NONE; + + // + // SHORT Buffers ... + + // + // HIGH ... + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // MEDIUM Buffer ... + + // + // HIGH ... + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LONG Buffer ... + + // + // HIGH ... + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // HIND Buffer ... + + // + // HIGH ... + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate ... + + // + double rColorIDX = 1; + double sColorIDX = 1; + + // + // SHORT ... + + // + // HIGH ... + int sHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + shortLength, + bar_index); + double sHHValue = GetAppliedPrice( + sHHIndex, + hhMode); + + // + sHHBuffer[bar_index] = sHHValue; + + // + // LOW ... + int sLLIndex = iLowest( + _Symbol, + _Period, + llMode, + shortLength, + bar_index); + double sLLValue = GetAppliedPrice( + sLLIndex, + llMode); + + // + sLLBuffer[bar_index] = sLLValue; + + // + // MEDIUM ... + + // + // HIGH ... + int mHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + mediumLength, + bar_index); + double mHHValue = GetAppliedPrice( + mHHIndex, + hhMode); + + // + mHHBuffer[bar_index] = mHHValue; + + // + // LOW ... + int mLLIndex = iLowest( + _Symbol, + _Period, + llMode, + mediumLength, + bar_index); + double mLLValue = GetAppliedPrice( + mLLIndex, + llMode); + + // + mLLBuffer[bar_index] = mLLValue; + + // + // LONG ... + + // + // HIGH ... + int lHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + longLength, + bar_index); + double lHHValue = GetAppliedPrice( + lHHIndex, + hhMode); + + // + lHHBuffer[bar_index] = lHHValue; + + // + // LOW ... + int lLLIndex = iLowest( + _Symbol, + _Period, + llMode, + longLength, + bar_index); + double lLLValue = GetAppliedPrice( + lLLIndex, + llMode); + + // + lLLBuffer[bar_index] = lLLValue; + + // + // HIND ... + + // + // HIGH ... + int hHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + hindLength, + bar_index); + double hHHValue = GetAppliedPrice( + hHHIndex, + hhMode); + + // + hHHBuffer[bar_index] = hHHValue; + + // + // LOW ... + int hLLIndex = iLowest( + _Symbol, + _Period, + llMode, + hindLength, + bar_index); + double hLLValue = GetAppliedPrice( + hLLIndex, + llMode); + + // + hLLBuffer[bar_index] = hLLValue; + + // + // RESISTANCE SUPPORT ... + + // + // RESISTANCE ... + double rValue = (sHHValue + mHHValue + lHHValue + hHHValue) / 4; + rBuffer[bar_index] = rValue; + + // + // SUPPORT ... + double sValue = (sLLValue + mLLValue + lLLValue + hLLValue) / 4; + sBuffer[bar_index] = sValue; + + // + // PEAKS and VALES ... + + // + // PEAKS ... + bool isPeak = rValue == hHHValue && + hHHValue == lHHValue && + lHHValue == mHHValue && + mHHValue == sHHValue; + // + if (isPeak && lastPeak != rValue) + { + // + if (showPeaksAndVales) + { + rColorIDX = 0; + } + + // + lastPeak = rValue; + peaksBuffer[bar_index] = lastPeak; + } + else + { + peaksBuffer[bar_index] = lastPeak; + } + + // + // VALES ... + bool isVale = sValue == hLLValue && + hLLValue == lLLValue && + lLLValue == mLLValue && + mLLValue == sLLValue; + + // + if (isVale && lastVale != sValue) + { + // + if (showPeaksAndVales) + { + sColorIDX = 0; + } + + // + lastVale = sValue; + valesBuffer[bar_index] = lastVale; + } + else + { + valesBuffer[bar_index] = lastVale; + } + + // + // Set Default Colors ... + + // + rColorBuffer[bar_index] = rColorIDX; + sColorBuffer[bar_index] = sColorIDX; + + // + // Calculate Fibonacci ... + double upPrice = peaksBuffer[bar_index]; + double downPrice = valesBuffer[bar_index]; + + // + // Level 1 ... + + // + // Bullish ... + double fibLevel1BullishValue = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel1, + 1); + fl1Buffer[bar_index] = fibLevel1BullishValue; + double fl1BullColorIdx = showFibo1Levels ? 1 : 0; + fl1ColorBuffer[bar_index] = fl1BullColorIdx; + + // // + // // Bearish ... + // double fibLevel1BearishValue = GetFibonacciLevel( + // upPrice, + // downPrice, + // fiboLevel1, + // 0); + // fl1BearBuffer[bar_index] = fibLevel1BearishValue; + // double fl1BearColorIdx = showFibo1Levels ? 1 : 0; + // fl1BearColorBuffer[bar_index] = fl1BearColorIdx; + + // + // Level 2 ... + + // + // Bullish ... + double fibLevel2BullishValue = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel2, + 1); + fl2Buffer[bar_index] = fibLevel2BullishValue; + double fl2BullColorIdx = showFibo2Levels ? 1 : 0; + fl2ColorBuffer[bar_index] = fl2BullColorIdx; + + // // + // // Bearish ... + // double fibLevel2BearishValue = GetFibonacciLevel( + // upPrice, + // downPrice, + // fiboLevel2, + // 0); + // fl2BearBuffer[bar_index] = fibLevel2BearishValue; + // double fl2BearColorIdx = showFibo2Levels ? 1 : 0; + // fl2BearColorBuffer[bar_index] = fl2BearColorIdx; + + // + // Level 3 ... + + // + // Bullish ... + double fibLevel3BullishValue = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel3, + 1); + fl3Buffer[bar_index] = fibLevel3BullishValue; + double fl3BullColorIdx = showFibo3Levels ? 1 : 0; + fl3ColorBuffer[bar_index] = fl3BullColorIdx; + + // // + // // Bearish ... + // double fibLevel3BearishValue = GetFibonacciLevel( + // upPrice, + // downPrice, + // fiboLevel3, + // 0); + // fl3BearBuffer[bar_index] = fibLevel3BearishValue; + // double fl3BearColorIdx = showFibo3Levels ? 1 : 0; + // fl3BearColorBuffer[bar_index] = fl3BearColorIdx; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..0a292c2e78aa61d0b25ecb0e638f183ea2a66a07 GIT binary patch literal 13690 zcmdVAbC4!Mw>S8-ZJX1!ZQHiHpSEqgdz#a>ZQHhOV;VEfo%h>&H}-C9eE)x0kyVxF zoXDv2%Y({{Bd)~`?gS`C76Jzl0{|d^V{pL#XnV)0RlcKq?-}aWD6(pd`2U0XZ$RK z5sNK?{95gY#ed{Q0S*91fEU0SU=6SYSOHxBeJ%@t>0f6B(EWQ?1sMOMn*ZaA18f0y z|0vP`wSRZfe>D4l(*NQ7pWObVvFkqsTmU=(#($T~|D&(@|I(M?A1?oAYxuuk9cBQ- zztv{?-wXY3xc=(S7P;i&5D|u~urMfLxB%8>yG2-2e!P}}XhG+}(S9XR$G0(McNvL; zB)gRI{ejmJPmLwbOLai3e$nyN35?i_B@HlH)^oL(J0ph+2p)HqI{##YoYiwr! zL|r{4d0wP}Bc!$v809UQl%`S7T+(UQ}+Vc@>Ukr_?7IthdOw_bXv3q zB2u~rQO0aZyatFQJgVDGSF6v7bI6h=CXY@T01K?PI^}F|C9v|+c!HMVM#sTJUbRCu zIza;$T}I%9FQxhosZS6o`NBvFlPt(jnTb8%;ZYSwc7cEUD|6=+c@D3a-n{gJ&9i)+ zMmKQ@oXuJYH1!AbW3nL!A_&w_6ZE{l18Af#H`jQ6EKT5YVi;C6JJ0QfWP)GsY1LNs8P(Bo`8%&qBWu?Fn+o6a|EN2KN7Pk z^a5rGl?T&@Nrv#2HoWS{r3b;58SU;8pc7*E|6{~9gB@~gN(T)>D2WkY+lbPAUb?Zn2lW6HP^q8H1iX0sU3%#@pS(1+Ok}1# z5P-XI8f+ol-Y}~4A@NrnK5QC}#7)!eTpTi1PN4pdOqW2pzXx{Iv1%u^?NCq@_$|K4 z$Re~SFcrZQjxnRnWoG2^csnQ%Q{jOpL9U)DY^8WmZkry_>9vlC$9lh`m0d^YMx^KB zRk#_qQV*)GHuAWtp@<|1M{wM`GCSGWq9uE=CP?FYpg~VW>5ga%7SI(!nB_yUIy0Os z`Rg37L4Ldzkf}UZ74R`N4rn-&58eFPUL0fcN$MXoc(rsqLs64R_N;iwu!Ik(C}1xQ zb~EE@&!wblD%jX~Ve-6{h(J@!&%S#Kt1vn$(G5A}Q~S&&9{BmHemd!UtpsH)LS0yn zI=}kkuXJr8cfO*hfet3VtcXiNms4D#4dW%K_w`W>3ZPM=-f~T9CW_;tB2Fi&W2TU+ z9F@E}1NGYt2Bpos4{A<&=!| zV`aVun7yS1>`i9JO4QK~dZcxT#)8XY}3`FS%6InCo%G?!Jn+b5Hbb|h1R`2T%4HIg3tQ&|K`lQ2v_lo=ZiTV4! ztLva-wVY?uO;Mv#yo;PWII)Ui>ykz~Vfvgq?%naHib4I44=F7*0F2l;OQOZLi!mSD zsR_Ci@8^^=4dAeK0?zdhQ+J{J`yVKxRFYmLb+jzi7yA7eI5k_$UYeZkwczsHMLsAo z>R?p^_zkpYuWN{m@tw{_-S3U>o@V*sl&BX-Yc-kl1H{Z0M&_oE&!_dMakI*?#XvRa z&IefKkNfnT+~w^u5I;JekOo)@vn=ZqXLb1+UeWM)o4N$j{PVY6rC~`IE^*Q}bVQi% za7`0TXu2+5*00YW7k6l7iIs??){8B?CYu}Aa8!ZlGlvM~ms>AkevyIlv_z8QG z6eHpFL<}&UR7H@Y%#M{Hq(*N^q(nzQ(NS?L^BpMkLF&BYq#cQbr3d{SJQu&Jygo-cec@{+NAJh*+`K`@7BlCt*T(sz}zM7K!w zjx0~m{uGsx7~n)BiKdQOpPWO6TRcaj$c+ktPu z?@GICeng(}aXQOuY@mEn81`}dV=PvGu8jR16C!))nm)?oD7550#Q|!sOI2097+qlO zS}2%rTg8JN0#mUh>l?T~IpW_EDJv9BM>nHk7_Xa`1um-+r`(G%%xQ#*Y^{M04ve8e z4WInk$bzSRr;NvM`*P5sQ_~Vz+WHSAgQjbPk-xn6LzB9BKmV>9Z+H+d?IlDX8+oG} zspqUWK0ysJwX@9hMEDi4q@hqRgijk2avB*riO*bqjc;~|lP3p6g*x`&0$QLdV^8iu zrN*FOLDN?%EV}szkq(x##@{vg{9VIo8?L8wKryL`i0iV4pr>pR83ygQMlg)qsM z@&)aj>ac>znZyx6GAG5kE1*Y9&mG&+*x;aFQ21lAv-pp=Ava!l;(Vy7 zgFkZ>sb9hwAG|ww;tb3T&DC1+HuNHG;{@FsGGGd0xDtP1b%r+Y#j0KRb#UvyeQB~KWg?4B7JNO73juLl%PqW!^mse{vdZXiQbXgc4v{sy zX&M!ZB$17-B3-`QEO;rTS>321g5_FaE}~ZoKwq|aQIj0A{2>VET*AEM7Iwiueo9;t5o z;mH(O?Xxz)<{1}D_?s0;6(x!#V*tG;0DoJ#4#y&;bLl-OZZ*J0wjTOy{-AUMqCNl# zBtS$Sw9d_8eNY)a!9OyZn(0jJma-?!1qrpj?00$Yz6)~a1v|t(*LmHDaz>S7K_vt& zkg-tco5lH4eZRNZPQIn?(gV@($CP>*0!ESiZPUD#U%euKe`nRNx zU@UW{KlFf|lkuL0>}ci4bXP6>U?2;!;XAQu4-f_PS29YkX3jeN)$**Q)ZXyEV2#gY2UtL+gQ%*0Qu_7nHAH`(F6r)NY zzo;X45y=gh-B~Sn6yUv3as37A8c8i@Xmv*Or7)2Q32ZoJc-n*hlBJMEq-`)0AnLSeX{@R4g+x@@8My%+=)Mn0+QC7-uq0N06F% z!QN5j+e)4an}G4gE8*SDDCPmGwV~iI0@o&1@yWL_nXr)wZD(=!dpc3-(AMs`F zqvLIL{v|jENOrN*pXlmwll1o*eo?~5w)hQOzewxYJy*C6cc?>}#U`ZeMRMZ^4X*|# zA4XnMRDm!p&83zPA}@{nAU%2U#WqJ;{-@^ZYfKNJOY07!SoI`WI&r5Ji&l#4Bpq^> zuC+m|Xz@u7B#b4mFd)B1;dSoJ*uW2I+GHQ;eG(y=l=veihrUrK2Kyhd?a=xP(}+!d~|;^-m}UCh|N}wDlmH7ixP72*EKm+ zz+4l+)Jkdjp1o~ZPx|L=l%B9CIWxdUtbKa|3(Np?;?EA__P2XEHy3Zrm6pYtOxMn} zbbKE+=O|{y?4MWQ*BsY+xhfQR34I}nPg915nrEzOj=P3p^dd(T<34ph$5ttHhNGUs z2{FoLL-b)tp{A&9(w^*nAmj0%)FLK#>s9$u63uE}?rzJbCXF$z1$y0mG_{=;-37ha zDXqCIfwcbuBBX%uT%JAO@kB#|z?iyCL*iT-iK!JA|H=@-6nLN=XpLdNmIGfwN0I~S z;2YtaU(}bT&*C9G=%_3^o(syH9WU|?^pl_cCZ?9=i}xLUR+i*>mB6h!-pmJ#Ps%!q zn>Z<0@GZwBPE(+&JA|MPI&5V&`w9_1_C(50HNYe=cjGv!$w3-y^>JvvVsSH2q|E1@ zT6qEG%H**qdFJ^NN6uvXtGsS#{BakAPCVdBZ$z5%O4aSl8kwhcd&~80mM_k-S9&U; zB$9j$SqwLM`K2_`k+mpYeUKncccolxkz&#_zYlk0aPd5rcRE~8x=p-je%;#dSdCE6 z;OH}T(&x{d-O^gA&zMjTi&xM`6UcBv*v`*h7JSiq4Vs3gVNjp)?T|y$dAW0qV0+#| ztjX=F>ciF3g=s@_;ch)1>Tg1)Br%9urXllXK4C&+WPs0bfd_Q#uY_^Sn<~-FnM~|$ zjq)^0=&ZaqR}tUPjBzWe3DzPD@Lkt5)-z{}NzbLF&8w)`CQa2Ev+Kh{zr}^oDP;r^ zq(M*(cI5yt&fK}(qvFXm>@8Wi4}^AY7B*T{reQl3_bAkKc?R%>l<&C^sa;VsPlrEh zrLfH`$w+dG`i*HcC6`5R(m&=Xu@J)=jxiwfc(Ysz?aAK#+c!0P9tcXR{k=)*L0?CI zIY$%>m-MM}C-dd8XPC02iHl3K?N4*)gqPe$xorJVd0=qs_1vnq72h1m|T3)6DN z-x^v7Z)lgE%x$5FbP361b+`b(zweKb~1K2Dtzzu`i}{k`Pl zaWEc3ON~E-TS$lU< zY$rARCEOT6Q9nzDu3X-`oF4|#<=#1l|6p4w3_9|NiIkuNy6a8vD%YrL@zhmF{*XXs zgp<@B{gqD-Hw;5RCLZN1f$G#Gwj4+p-Hc{4sG#Dl&#JYas>$~nvfzunQAk7sa==?k z0iWgNjx+qbE-o4a((Xn5HQI#2j1xWEpy`ZrH86d?B1kc>bazPa)b7_&6Mj^S~p2|W=oFL@|++FBKIp*%#yV|v>Fz3K z8yj)P#TF^ZEr&b$9rDuH5vaye|NDEmI?lF_Zd6Gd)U4x@z`|_cRWIypQK>4e4iUU8 zJi=OP?h&_mr`j@H!AiC#_EXev@l}TVv4x+L^PmW^qYub^p%R=Jx#scIRdds-Pp>&J zZ0mAx=D&<1AY0XF9Rm``&W&{q(Q`RcB*h4TSHl=~!UklLGbyuUl#(HBDs`UCLv_93 zZaYvArn2&@RNGn}KpffA#nlrKFB)O^yfAIC`if?`iWXOc$T@IDYw0)|BTK$f`OsN$ zi!@9Ve5)tF?-(`{tCk2Fvy99199FRjsSQoG#5j$sQR6ZM|Mgqj1HPa2t%eX@=zABIU|&)mk1S(0~QZsM`e=4?!nCcn3MOJ_SQ>4#C~VPCKzeeF~&^>JAM zjb{C|mWS+v7sj2lZntz*KW&UZFBvpXb|7}M`_Zy~sDLglpE{H_Hgn$p{62m4mIZJJ zr!!QtS>IR^<$@wCh~csZpU)|l9^ghK=~~m0C9=T?+>j?8hI>!1g+BBZq%=M02{Cx{+4(k+x=sfQmFMI?0I!U~g05IEG^$uS;|v zPiPS6u3PQLuk$s-<(kB{QSG!nB1Zo;0i0 z3%h;(Y9%_oa?oluZN-8bkjjLg`JGVWY3#aofwhGCFYr&LZL~;Axb|z73hyLzP!U7n2r!HF9cVCjvcX_sA5Wz82VOTLPLXfbw)v^;~syun1ZWg%TC-_ch`FUapcF1C-;3519Ho&^l7C&;-FP>YjLe;3M|;uHg2{}5@` z0rewXL}X$QLrDUhLJ_Mmo{Cf+8gQOLx5lL{PJ?!PXbk7T|8P33DL}$kA37QG%nT?E z(VbOH`IqJ&D)~Rj<>!|pBoH7#o`YL=oa2x&6bTER`Mx38ai~-Tj~P-qYBYM2<%(Uu zVYiY>lY8rg&ga#eR!}ff58KpiD~m8_e$Fj%UkP6h=%0r~CWeYJu_GiFC7P{*P080E z5Bs7^;KL)xfc^NvQoG8Aa2GAbit*HGw0sID0@Szc6;Aj6=}V~sOwJj#j)yf6!PWDf z6OS-l5&LRKLelkT!D+xl%@ZaGYPxA_r~c>{EyV9+PKGbDIH)Fv6M4nTGF{f{25~yM zonSJ`v97!mS{-|tA(?>4E6KynimCqK&YPB0gB$ec4l%G8-Cdc6)QAkvM-Ri z^V}BRt>nT{0%11f&m<)NSlB}_=_1+VeH}(Un4dja z#a(K>F&GbYR=RD5N#ewdf#LUT32l8P5=*d*-2YMWf{(ivs2!MJQOgz%@yn(()B2+> zAV}-az#)l{1D{KjMJmNhh&@C*#YE44M z$!C4W_t0hIkbf$^Hu5AzfSy7I@8uPc z91=4>y$zP+iK-}PS=_IxKZ|C>2dG*to%$cCsssrlf|M|BPw#tiY6obMVOhmPv%UH1seRBRhhSFOQ)Pc~TxmZK(&AVe2*zd+cVpD4D z&jWPx`LP@7hA}aJSvKnnLrM~X1aK(x<>ERhv2x5O9W2@IN$j%ei@yl8kDc5Z(3}QF zZX$NnJ=^?7orJHeU}U@B-;%Hhn36GW!EGjaBJ+@99^fU%u$2;z55cC8e+XA-0S|ew z`1E{v>Bw|pkuJO}w730ot(NYFuoDG}lwIOHQ49vhV2C_NmlP{XvkXcK-H)K)%r7%N zj?%+NH@`WgASe)dxASbOZm#hLC7!YO<8VB^M;8QM7QLg9h7mYpjya_C4+1r)cJkbX z94F`yTcdsnhpX}lU(hk68;Ad0lERC5*YAmtRHm@Gh4q{{z}mha7j@j#4tMuBXkq~; z`?5s|m2-2z_5?Xeo>!%JPLVNi9$3=t?oF|Uu~mN>|R5JV$Gy z{e?F~yF#j!uasdbRT-H*T$_`AkT5<0tf9(na(X&o+Lh5-c=PY{Id4*?@f5# zX~%h8vJ8M&JHJt}EhhtnW-d}(Z6-cbQ)*$S*4P4u{qn3sz}u8-CS?7*S-uu5f250CwjRnFVtiK{WnsiKk9zjo6cN{Kqy0NFOs9Qe z&G3^gl%x)Sn?yIaVeK{5nV@6I_)+7S=}s-}~m3eVLJ@!kxXB^iHQ zun-9jZ9c7df?+OeD$C-{1VRd{ZcxFF@K#-uph~8|yMh^l^mC5BjM^LSPKpkTV3fwf zhTitg(FR1Twy=*;^mw8K1Cg{@qf#CKNy6U({`OYv613n`1VdkXOIo$@)hN#@27<1A z5C&9CmjirsA-7k)zp_v<6;Ck+|rs)qs zmA_`!sDrMpGa$8(WBB8F3b*8$y_}xX#fN6#e&8VHRoUghl`c445*vIJh4{Fsa|ySj zU%HkQ@mSkaPDgC9CJMbxqu}($G%|Ms&tvw~zG|M5-mNHda$+Mx$FU<`nFJ>qn*t%f zEgfYW4~ecWMr46YC!FfhikZvjcV;R8#vr<#-KVbQt7m1YZ~fw~iE^MS`6B19nttng z7@AA-87IYQ^*?59lj!l$A4yV*)C_RIEJSA8abqoJml4zJfI)Z=DR^z!EcDk1If zbb3jvxUz$;en(Wa$VDd!ODYec9`X_;*wvet{Kp^@KO3y&1C_aSGY+8aM->nmR~TrV ze8k4f_GSf7>w_{iblfNWrPe5kQy>UnW!im{FSi3!fZmT5~+AT>Ox5HgqRg|4F~uW`aECLXZp7?yFwh!o+$wbOg=}o%xqe{gf>RVZKpO9 zAz+CA#-*PQTml8MW%(q5D#`60#!jfy_Y;!JA##XUFz^~mD;Q-Y{nG8=E7m5Fshh!pJ? zhiNPk=v{av2^3NNSDHc`UME=Xl#b#|I)n7AmlX1+P+A&GW|n& zzFzaC3GL$1SGdSOS?v`5gFl^Z=MT<|k&pNG153#p?RImUko_O()zmf?ze`8(q}92L zR;<(=A%PJZl4cbSobtaYO!GW>Ry5ZoI4k^F!KLgOu#!B;Gj?7kY)Pxbd$YZ5V% zs~65gQ91gzE*ABY?~q}l%X}@XaA$v(;ad?iBnT<;0vquO-U+Lqt7PFUV$s7#AybCc zCjCLsO(|GCJJy^~R2-a~6om1~cvflj6G?OBb!HEEHLD9uh>+;zinMu{-E zB~=8*w{)grkUbd|5RlI(XtPbZ)cZ*kj(6k9&4;_LFgt&S=T{eE%{?iXY&Yf^0 zld_~b8SuDCy?#3|ADuXM0MQ-GMtJ#-@Co)*_Rt$cOzH+w3(3|(>>)%;RCZ;Kk#(*{ zN9Zm@h&tKc2{&%<^y3=yb?4i{i@P2TzW;a zi>Ol^<;qC6&58R8{h`I4VI*fV@WAIiy=qholSwj{sEbF+)3!0*352B(izcF1hQGHt zy>p%iDRQ7)hwv(54$FC5X&VAV3zz}5d-|LR>TXYCGA`bbLBsE*wX zEX~tC0c{Et2z!_{f9p1~_ZwqY6nzJrK}4J=uc1Op_UgtsnBnwL>oZ3z z3eEtdfwG_lEFbupjz*q2>6ScKeRq@Be1;rl%&g8G+AkgujC9WN+ zh{OW#zdZc3@EuNL@+PmUY%9~K3_f=&|88-DiX1CKTmNMe{-Uh;hri^LS5a#n1#;}n zMEL$MFg91{L2Y68`3W0O?snN6PxcluJGJOFGH=6Lq zN1>`7LfPOT0n3{impy^2dl-wVEtb0bYcD$4g1N0eYTesoiltY9Q(%?ZTxNGz)}cK5 zgCMvnC3-zsI9ECeTqT5<@+X59a zy}Tt8Y_iZ&<702b|H_+LgY%&dQFAcUy))pvJDV&1p$RqIu@g3SKL;Xq+jPjY2IF)= zyzSlXN7WxQK7VO}8+d{-$F@NhQd`;iT}^$ik948gqTIe3`-Pt1c2orTVi@zk+~=yO zE`e>2b#44M$p7&_Kl`&=s^XJ_-ts~?HDmF*Q!j@GgWw6LC$<}{Nf&11wD?20(dbJ5 z7|I(ZRHye7#sKyxiCWGG1UpjAzC@op;}W7d^+Lo`s^917tz%BO%Hs-Co*G*hxzDp& z@TF`~$E_UTu&>>ZAK(e}iPw(xNgrODqTZNGF(`TB4alWc!z31IH#Svet{gV3@Hn5A z)Y3Qw@=hJbhooB)?Z!l3l8uq(74~0?O^S|7sZah^!4lE5Vb^XW4MGRoT^S)B>lGfm zFq%VI2p~Tjdgi=H9lS3$$-yGikTC9>75{|mYIvAaM7i-eUT%K(5c-szg+VY|{b8WL zR2@&B)oe4f9z?WtsQMTGhYmfs;4t6Jtid4LvV=VMj@^b&%Eds9-4Bp&U}n>7po$=^ z#fxRxQH)L72*MotsG|g2;&{bplupUISs*zaMjpz!(B+f0o?5Xur#D$a(LG3`g_3l% z{}n?f_5F#>sZDSj_Fe@QN#tkn9e(@UsvI7EDj3P$dHI3S?f=HhiB71cfBJh(*cIwi z@ETe3J9OCZTnB6*zm-IZK3>&D5~>K?QldnN2B2g=h#TzCCtl(!yZir>e-&q?X1uj_ zuI|gs4v}m5k~%iWqpsI;mI!pw6KVg;{wefyu?fGf%ftr|ERczanLn^`z1)>Zupzv- z1~RM#j@~t@&5Bb=XBk_-;s?}5SIqndN9S!>Qt`a)H0Oxw!SkVySTp}_Afg?Y;$ATh zIEBn>Gh-dDg^#ZX(>nXz>`+3+WXi*=6xg_1O3?{=ng2RkH~H)t)pab4D5$ih>)uv^ z?aT0??lS2B13vH|vuqjP{gQ2J^4o}orhxi|SIlQz{;vkX68kJlvNZIL@Lh*U5bd72 z^R^M?SLg)J9NB^NBI%W^ZGi=+@`y?r(>|tYPik)z!E}6{^rHspTSDiffZu2keU6W8 z^WTi^Mvm>?CH?XFIXUSUWF&n)5~ts^G-s`LVF$$KsOc3IooG;Dql0-dbF0>_T7!>a zK0P+^D}JCN?-uJpf`n{&vsJKjcSDK%e72%R^jHha)o+`k)A;#-mP>-$3W7_9QTJ`? zlb$#&@};Cg>O~xKBuIXO!uqgHpXbjW*?gA$UxilcxJo*QHAv+U%uXHT9O=XFZ*BV) z64zS)>@RqaT&;@A+Pu-V`oTHCbVd=2Hl14TCvV_F%M#UmyxowX@{TeVC!E$v3V0P< zYQSH0btR(-mBQerYT86&xqk0nWsrUPhY8x3EEznyKC9_9QdB+O{#kKZipwyD?j*j& zyq{U&vO(`Nu~bcnJl^AlSA9Vp?QXknHbtNrkLs1{@~=w|0qpDe$C8k1bUFQrB`?h0p( z5gb1_l6kLQAf9!&d#53AC;i-rYJ&L{L7Bd;>Q9Z7V5;D)Q&*1CCN_XYg@znA1Tb!s z9v`lzA1lIrfDi4JBy>g|!pLq#@d!4pJjrSJ5vD>}nDZ~|47cUXjyN5o%BL;fk-ERq z->S%-Aj)f;*CbIo;vKXO7n!)0OI7(mh~~C&ykQ%+7@w12Zpp^>w_ctj^owJNvZTyV z=>Y4W_!(sWm6w8*-2^g0f&6BdlaAZG=Qpj{y#zSv>&wRItWj-4WhkPn(}-Pr6tk*7 z<=Uth6CJ|ti9U3Rh0qt?TCa!5YSNX}=)84?^(1X0U^k;F9J`%-S_GGJY&GuJ zh27=mc{tk%-MhSe!?U;nk zy9ab#uyLH5Do5^e8?x3mMd1yFX@F$TZ-B5vOU5)iD7qFPN8h?1S*4v6GB;4Oc7fD)uJu9t8JVSbJBy}XHdL9V}g$u$$8c$I10p> z_GNA9jy9m`{d{fSF&!$px5ms0+9gx1q_i>-}IBa1iYa&Ky?h9qw)8h zFQY>7;_e`w!NVE#>YMO|eXZr9*iBV*J{%90JFhMyJfACR)P;*aR*sp6CLrGQ%Wm7M^ru$*Ol`{1G84B~ z5u$Wu>rJqr)a-6(@WI)&#gJXjlT%}DmwDHrU!?7-`1&o=9+=FdN1Nl8{7duC3UpE8 z05LNz@q;qhY1)>&3+_8nfYpQW809vKmkfIap5aCmlHPd!VNId3V-W2!9z|OCd>xxe z*Fd(>doc?XC>hEkJIN`&1}A|nd0_Rm{YLU{rHH%gRz5$nBayk~oHu#D9v*D;VUM(H zk6?>==&Yorz~ZZ))w1wO_L$2}o8qp@^=_%wn1l^y!=%+|`%Hv!Er%(13pr48Iy4wj z?}8ms_k#->S)4*Y#MHm31V5P+?OEDJMs+$uopH{s3B{{Vr!xJra?U}94Ywebol2w zyNd$BM=2Zd*jZXEmjC4+({!vp8C(djOZ~M2Q2tQH|M)*7TF>c!?|*O<uj+sN3BKd}Yhd>duX-_@-fO!pd>tLwPTV~A(t=x7|JwZL(UQ~w;%l8xgr zC{tWUpW&)hy=7_J`OWw+fr+6X-gKcRM}0kUYAW@Xv$0zAq2P;$1`-X{J`?=fwXSGC zDh9ud%Zrzz$+fmC!qqWD_eYe3o$nTNT>81pcJ_TzZRE;8Jf1laePaZnOZ;;qKVY-t z449xP>tH0s6B_VaJA$-MY^@hbzZymO7a_N>|M>JkYPG8yQG*jB+_GlYxDzdE{24<8 z6-jjaUOKk10G2{)g!8FZHs-(c7w~Pui@o@oUMmzW)5SsfE61QW06CUCjMbn>w%f## z(A(S#)k9x2PA5e5IYcIRg3|(oYgO$@SGs8kQ5KskV!i4=hj`h-2218;UO%z3mqD;o zdCI@BUY9EPy(6x>2cR9x&iNKFK?802kT*DP8oG`{(s)=^l@@Kto)v*Z(rXvCt1J9byddTz0GD6* z9K;~2_Od(#tT?PfcH7KD3oOGVyf*W7K5`MS+h+{_wU6Q!YDnB=_Bb|pw2=IKP_~2h zXOH1n$hP{;+ReF*-=|yMq2nV23;cHq2h)lKRjN_>5BUF>^*#x}yHiY7E{$P< RyETyqo8xW}M249b{9lRgJ$V2C literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.mq5 new file mode 100644 index 0000000..e682067 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xsslc.mq5 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ---------------------------------------------------- +// Name: X121_XSSLC +// Description: SSL Channel Indicator +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XSSLC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_XSSLC" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 36; // Length + +// +input group "Calculation"; +input ENUM_MA_METHOD method = MODE_SMA; // Method +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Applied To +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Applied To + +// +input group "Presentation"; +input bool showUp = true; // Show Up +input bool showDown = true; // Show Down + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 5 +#property indicator_plots 2 + +// +// PLOTTED Buffers ... + +// +#define upBufferIndex 0 +double upBuffer[]; + +// +#property indicator_label1 "X121_XSSLC Up" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#define downBufferIndex 1 +double downBuffer[]; + +// +#property indicator_label2 "X121_XSSLC Down" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// DATA Buffers ... + +// +#define upMaBufferIndex 2 +double upMaBuffer[]; + +// +#define downMaBufferIndex 3 +double downMaBuffer[]; + +// +#define kpiBufferIndex 4 +double kpiBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int upHandler = INVALID_HANDLE; +int downHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initialize Requierd Handlers ... + upHandler = iMA( + _Symbol, + _Period, + length, + 0, + method, + upAppliedTo); + downHandler = iMA( + _Symbol, + _Period, + length, + 0, + method, + downAppliedTo); + if (upHandler == INVALID_HANDLE || downHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + Print(msg); + + // + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Release Indicators ... + IndicatorRelease(upHandler); + IndicatorRelease(downHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int upCalculatedBars = BarsCalculated(upHandler); + int downCalculatedBars = BarsCalculated(downHandler); + if (upCalculatedBars < maxLength || + downCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedUps = CopyBuffer(upHandler, 0, 0, limit, upMaBuffer); + int copiedDowns = CopyBuffer(downHandler, 0, 0, limit, downMaBuffer); + if (copiedUps <= 0 || + copiedDowns <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i, limit, rates_total, prev_calculated, close); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (length > 2) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(result, length); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // UP ... + + // + ENUM_DRAW_TYPE upDrawType = showUp ? DRAW_LINE : DRAW_NONE; + + + ArraySetAsSeries(upBuffer, true); + SetIndexBuffer(upBufferIndex, upBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(upBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(upBufferIndex, PLOT_DRAW_TYPE, upDrawType); + + // + // DOWN ... + + // + ENUM_DRAW_TYPE downDrawType = showDown ? DRAW_LINE : DRAW_NONE; + + + ArraySetAsSeries(downBuffer, true); + SetIndexBuffer(downBufferIndex, downBuffer, INDICATOR_DATA); + PlotIndexSetInteger(downBufferIndex, PLOT_SHOW_DATA, showDown); + PlotIndexSetInteger(downBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(downBufferIndex, PLOT_DRAW_TYPE, downDrawType); + + // + // DATA Buffers ... + + // + // UP MA ... + ArraySetAsSeries(upMaBuffer, true); + SetIndexBuffer(upMaBufferIndex, upMaBuffer, INDICATOR_CALCULATIONS); + + // + // DOWN MA ... + ArraySetAsSeries(downMaBuffer, true); + SetIndexBuffer(downMaBufferIndex, downMaBuffer, INDICATOR_CALCULATIONS); + + // + // KPI ... + ArraySetAsSeries(kpiBuffer, true); + SetIndexBuffer(kpiBufferIndex, kpiBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int limit, + int ratesTotal, + int prevCalculated, + const double &close[]) +{ + // + double upMaValue = upMaBuffer[bar_index]; + double downMaValue = downMaBuffer[bar_index]; + + // + double closeValue = close[bar_index]; + + // + double kpiValue; + if (closeValue > upMaValue) { + kpiValue = 1; + } else if (closeValue < downMaValue) { + kpiValue = -1; + } else { + kpiValue = kpiBuffer[bar_index + 1]; + } + + // + kpiBuffer[bar_index] = kpiValue; + + // + double upValue = kpiValue < 0 ? downMaValue : upMaValue; + upBuffer[bar_index] = upValue; + + // + double downValue = kpiValue < 0 ? upMaValue : downMaValue; + downBuffer[bar_index] = downValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..f8abd494d297e9143f184aecfd88d88140a5dca4 GIT binary patch literal 11030 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.mq5 new file mode 100644 index 0000000..c483d3b --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xtm.mq5 @@ -0,0 +1,354 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121_XTM +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XTM Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "X121_XTM" + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 0, + X_XTM_BEARISH = 2, + X_XTM_NEUTURAL = 1, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int length = 35; // Length +input int shift = 0; // Shift + +// +input group "Calculations"; +input ENUM_MA_METHOD method = MODE_SMA; // Method +input ENUM_APPLIED_PRICE appliedTo = PRICE_LOW; // Applied To + +// +input group "Presentation"; +input bool showLine = true; // Show Line + +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 2 +#property indicator_plots 2 + +// +// maBuffer ... +#define maBufferIndex 0 +double maBuffer[]; + +#define maColorBufferIndex 1 +double maColorBuffer[]; + +// +#property indicator_label1 "X121_XTM" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int maHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initializing MA Handler ... + maHandler = iMA( + _Symbol, + _Period, + length, + shift, + method, + appliedTo); + if (maHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Ma Handler ..."; + Print(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(maHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = length; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showLine ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showLine); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..90048300c39bc712fd62bd6e00362e03450c5c1e GIT binary patch literal 36482 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

m$>gBN5R1IPx-4lf>S@8%p)%c5uO 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тa>uz>&GXwu%0M-4D91K>mqE-XP`E7b-P6j?w_fAFkd_E93t z-q?`96GzY-m*-xHbhMB)+2ag(T)pS=E>|yjYD_gxsnvPoV#PxccP`#LV5Mw~B&t?! z>1&b>_-A+4iXq>X6+*nBSK@`+cpS`YoPI!Gzl!vPD4K^tfw?{_lom(hg>URgRe%g9 zzpZYmir1`QDGf=|VE}?QBq?%kDmlxNj(KTN{rwClUURiKXl%-QcCIxCWRi{7o4X{a z{26>;X}w=*@4$@ZRN7dY_pA{1a=CH?M-HaU7A96)Qf305voeuXJcZ?Uyh z{L6`+$SR3A#F8~VxR>+bVA1I2*kXfMn~;00us+A5Fuoo_EAig5hYZUQr%3uCwsTWR z2V}QvSEM;0VUBxSEy8_eu#IA~b1{2vT|Ki@pzU>W*#+wmtDAiRS1@KTruY*C5!O^N3Z7ZzPZy!CMJ7mw&ba1k>(e_SlVZIcp?t-@ z3c+S}wBo566E(fZtxhIYyJiarzgR=WRs;zx3N? z@9GzNB4WW>nt>&O9)@1?ftgEn6+=P~rX&L?IG;--N@f;~+4C|hlCospOm;OXc27)pS4fB{Y4a zk+w-IR&}LjMM`1Y^swBF8O$k30xe^@g*MAe# zen`;|-Ergpymh9=r~|59aA+bTBMc?JCw9Beup*-xL4E9$z$sC%h$+PKv)aw{q6>FPVf`s+@5 zbtzq-&Co$4g#;rDo;vgUEga3lcoxS~=OJG+kKJo0lBqqBLr^qtQ>?J78Kd{}K1oHm zYT1sBG1NueA^96L%|Kh7WQ!qU32Yk&I&-ZuX2V+8mF@Zdvb%SJNqJU& z(He5wNcrj(5pZ6|MVSl%JQ~avR~9y9RNx=P+vgi~9O;(iTJ$S99G*bx%~G`ZBQ9RG z8&kU2Eg4IvRo%AZ?%l!QQ<1s#rL1O^^MswG+qBC#*Us0E1r5Sw^^Twwrnn+k59a$` zW17k45bF<%t=4fYv=nTWT0$ufXYM%qO#cXNAAX5o12sK+`!9&Q_t(;7gGiWXBF!DW zrX!vP3YW92X@Ldl?Ebgt;oHsZ2kS^epH=g*Wh)B|c8 z>N3~OA_G|(1OKy8t?mGD&+aY$f&w975MUq`HQxn(b^p~;W`1+m=?u;Wt3Ia_toXoH z$-aA{ea!`ZZrMUIRQdA_jV-2{K?ET#kA6U&($#}qwm9?nkBJfbEwww;phqzx2usT}6R zvhHr`)gm<|JN^#DGV(;Nh@TF<`H;WpD8QdEXVf6)w7&`q$YfR4(|>vMx~$~^V~w)f zczXO2T_fLCi$}WKouJ$d)9;#y)^TG4^533NoUd#D*eNTFaNiz?i6M{d+ieE@NAG>X<^uaqlP!v%x+IOPlB_&|8Q^K=RY*+x#aA+!5E=bJecd(M z`>48drVt<7&LS_lse=x75enwGA8u?qdM5Z}@(9M{33XA)o2x^&qI2j4?vt1;`tA$1 z>P|=_AzO)P6}*z~s<7p;iCk|2&-txi6L3BB7&&Tn6iKJg4f0*);vgWM* z%-Ww`&R#_!R%qh(dDT-cBKV`xc6szryIOcdbOg^sJ;V##wo@YrCUVb0gUa?EFWqUR z%YylELaH1ng_6xLS zt<0cPVl_gDl!3v8e|`n>pnARJH~)r-ij#EL`)B?AQa96@Rz6~rM(7QZro+VNY^9Fl8-As~!}Kk`?c8uM z{1(jy#jF8CM*Le1%|y2PN>*#N(Yt21ubQl&H8eRjhj|?Mu~O}o7l+T1?S%10uwu_iFl;<=g12opnmbZfq*$cI z(+a0!KHd#G)l9B(=#l~)bI_V$0aUXZ@wwy*N?kU5I0D=Lsi0}i@CEmh2Ll?y5Oi}e zrq4hh(=y@rO~!RV`ep*?nX&U45gk$l=eJcbIai+8C7pFk5zRx%-_fLK58oA=jbVF4 zTHY*JxlebImr>}RuR%*C_uZ?}kt>K*NbkK|FNc@`MFvsMk9?b^j52{o=N0(;{v_K` zd4L{w$*}8Pgp~y}cG?+M?vU(oh=fk0Ig7@^5~>nkZMwSraEr}ZRm~+?4Z2G8&_p_y ztWjVoQ@JMx7K9#DTn(o#PCJdZ|Y%omgq%={c^Pi)P~ zgV%yh42Tl=DLT$_6j$tik%+So0y-!tb*)fno9z}a)Im~K+qfzl-?ni6`I&Gr0)H7q zDAH=XG5#*wEQlu`lR^VqDyn+KP}ZGDw$w^GwjbnKp0F+>Grp|?wJdiUx8C^2F7Vw$&&2acn=e+^b`S~o@(*hL zq9qVc-+`x|(I>nbAhh&j+;%Wtdy8)RE{Q*4ZvAKtHbb=NK%sGpMeMM3u!q0-l8{4o zO~9!$HybhH=U5?*Y>vR4-sJE?fX3>Uu9&wTqDunL37< z_`2*gX11rExhJ<+TS|AlY|f>zTbv#ikRU%a>_cz`(6$BjeiWe@;WIFcPoboOklY@Fy)Kx(Llkr7YR?{8!4rb?HR%U4$T61 z@0w(iYTi@JaUfpt-gL?x3ld(v)=IpC-64Kg(unJ3Dk>^{$XLwzwboE`4R$wc znX}(y_@NaI@&Hukg2P$3i+5{v15=cOA~Sw<51sy`&ok&g_6#0-qwuWSBUTA+{}Jln zPR!d)4etGDVY;=ud;qMgQA|S;>v*Cv2*M~8sMMqhC(kHf4kA+VVun8B;9SasTI2*N zPe%@!h>yh2^{=3v|H-U2l7d#mBkOs*PGjJnt3%;Vp0?J{_epQ?xO+Xq+-(KHCyM_# zGoAkv9cgzTB{PuTIf!r0?C@8bV>9jqsIzaum7iOwPg1HaRZlGfsbj&*o?6x`GV||# z?`_zmOOv@V9F|B`p=yqlb^wx4FF2UwSq76~_Gb);uofo9qY2%Eh(HjG^~C-Jgc-_5 zv2&}taDpjZ38MsxFxJ}o^8oG`dI*uKSYi1dW-Et%{S$vs;~}eQmV>U9Hf+sv3U?Xq zh@#dIu@={#4Sx(3j?$FvoxOu6O~9eKFJ@kMl=fS=L*+0j1ZEU0VgYuAc@vu{1KQ_l zW14TtXNpmrd7syGcHH$c77r`FNT(5eS@Issi3*@tel8uX&+TNh@f(XY1!rIp5+JvA zZlO45vU&S7-P|21C&?3R(Yx_iQb@@28m3f};KvwkzVXK5ak$5g+WnH!O%L@FX}|oE z*{9;r?&ONPFQqfoI<3s#IM;y{tRo3%Y<8(XiiMXN!vnIlLp+>5snX1t!WLz;)3K5= zIf5tRi^3zzbC4z& zi#kvpY2PX=ruQ0QHSX4fnx3Oy2{nP&9sGr4>`~b23{@M#3W<#|zWpAS`k>2$S8zrB z<4rnvBGWA_zwN>0*R*!6)6=?V;iW<->r+!f>lmOH-)d@P4V=}ES1!FzbQ%-3sc-Q{ zq|IX$&A8FyfDh*vvi3x20dWBh9zARHlH9Pum>GS7cF7o$8dJoxdQH|Vx$b^z+o75f zdY$3@XXj@&Lnin+l}sJRxCu=}v&5}XehmkmO9a~L^K&BPM}l$b;Ry8WrH)I^`3YWw zD03552qHOd=|L2t&2Nf1^UE$udyotiS;cf;1jd3gLw>?h1_%&n17Mcq>i9oZ z$5gC@KJ~4D@)C?VA;N0~OrzlKBfgY>LpBm=e!d%#$jz07-zthk z2;%Ixtzr|>vzsL4RoYrctcpE!>u~wK6nL#0j%?9fj$qtJ`NCWKb?Ce#j(Fy4;W4LT zbY0|>Wm%eI`h&#K5`1bJ`!N-R;2QR^eQRV@R+)b1$R$2z+PG+RNFWKV{T)R-73N;u zODE<1dVBb_f>F8 z!Ec&@VeZv4)kwRs-bjV7DrY7Ioz5eMUaQe5cSzK!Z4ofRqTl8li97!+QV@X(x?1;n zawx^O#(O(_WGu*sk$pk8wz|%wXUs!v2k^e_&u*KWHR_qYc@rB7v(a~J`Q}Y{46zTC z8&#w^&hz5*yb>5!hPF`m%#Xcq&kIGPuwym6H4Jj<^FYEGWM`bm=QZB(!~v}!GblG= zLK~-9G=iYw5ca5Awed`9iZm9Bi$24CVziD}b4r9%qNSAyM2>=XVSc~sc7sW|XZA&X z&vniga1~7QvS29)xoVQE-_*G5l);h#XxqcwX7(;(pl4y zFFsiX$^8H(%SlHu8HOYR)b=XMjDuynisvUK+MsDj%5?@M8<)jcr2&H!@u=p*%y?$d z1!)_CuD*-iLztB6+DfnUZWDy`4nV05zb&7SEm|D9>Hv{{)doPv0loa9=!W>xPJ%qG z2yS(03>=vz&TcIgnwX4c!v#*6v}Y5#*vYm1WV%J)ev+Bu;_yp%VFxHC^fvOjMLZ(E z@fjv1PRvL}w@Xjxc^)h|E<}@wn*$sE>8Om`(`!RDP4O7{$?+5&rsfyTzy)4SrDEA#KWP~;+Eog(R>V-Wz&S6O&=Gb;tGe8&#G59j(`Ruiy>=lz* zM(!fch<2_<$PptA3NUYGT znX?_}l96s!4s|nV{n!6S_!GPL4s+8bhy8UOQ4|pWGZ+5#g9F=7i=BxJ#O^9+L+RtC*Lc7E-FqK=5L!#j=*&+1&nZWKG zjZ?G*HHzCRy&J+I=<9ZX!`jBU6ZvL{H$`D#1`?`_>wV{jd!KhWF%h_V1>zzC&_2LG zf$d3knOCvGDl+t&vB5ezv*S;9_r{l;ig;h+69@hq|8j6^Ez_m;mKDoP8O7;o*9d{u zsF^jpmZf6`?9i3$*ZW_7W4?5^FOaktes5+Gs|Yl`^bVF>8&A72n{tIta!2 zgJ|DNuN|c5@+i~1+^woB1pmuastDM-2FrLV6NWaYzDr-`5@MbVVe{M!RGUWasH)m^ z%urjFdVdiYFTh(H#{5=P4r49wfB?6L7h=D&VX)2WwUU7u#?&?1nul-WZYV3LKnkH( zUTb<=GZVVhCX!?JTRx1&V;LD)HGm2W}vV z%sLegQ>eW*b0p~_nn!TMzkAu_nn)Se^f!idCLnUOpTflV&x>S;@)COxz!OPm|kzF411mByE)US&U5m{%k-ll)X?ftnF zT~MR{-F})*OXv&0?76NF_$uNSRjxWj%@>h*FYMAWK0OyiwT|IO{dgS<)Whs$CwdfMY=$lTibxWJzXsVZD+q@KWPR<31idFDXT_}|QtG*u zsH%~5ekFUX0s?NHZC4V(J}BxW?&S|Iwm0|-$K3c=@T$g#sX$Sklzi{Jiw2FI-3SIJY4$8UKHD4>7Vo! zCsm|=zFkz2@$dGlTN-`+j>7r({LFEtlnBZ{YvL#|N0vCrz5ov#zeiu7& z#ln}HMpft|B+y)?`syX`KJ{Yxv`oi;qi6p4zxw(-=v18EM*sb52vG@zOnglesK(oG z;9806bPx-~gRgyo`G4ZC#;+OL*%+&pXFS#><~V`Si8@7x@uYbc8*C+vl^)<+k3UN+ z)pUnk?|C2Z_Uf)=^WTr!x&8I-kR0Tu`4YZh+GBLl?Pn+X4n2+RaU`q*Q-0=RI&1(R z`-Yma3do1LQl9>?CwK~*et*xTJ+TOjf2VSuP)D;uz~8CvS8h0E`4Po&c{7i$bq`!a z<4#_~>dYTHqW+zK#`5@czF}o{xr%WDa0rvbhnTWS5I|tu_VA?^om*2$d!pngxI=09 zVXMv*`10pPeLR%3XWlDDIR+Od@}NjUZ3R4^iC>Uu8V4Wo|{DklRpe@TOWnlAbOkoS(?b#?I{VC*!u zZ99#v#iUd)@BwdOB4>z=#!{(iWRFzTDNOxf)H zQ)A7b)(fPSg$=P5V?TsbN{9@XxmXB7OC&OP30aVhA*hg6*}Z2mccUQx^<4c?-{?S} zuu25O^|lU{BsJ$YHd)nCp`dr@3@(1qTHJ!B0f%chZ+z>G+EiX7?}mqr$Azu^fTUQ$7fZ4_{xVKM)bA2F_`u%|rxDGBDV#G^jfTHX)MnbZl2s77RkXx z*u*XNdweP+cEOhE1{G{fqBm1Bf)O+dMfamLYt$H@V0rR${eM-(@pxOv&qV$aC2C3g z>ZZiWJ^U@WS+GeX&2zxS`eHf6nTh{$pk~)9eWSbwmH^nM^bL`{WzTYA6@8a`-*ts9 zX{E*btIG3U7-w6<)~GbiIhK;Di(MFQVJ!-hE{Y6M@`8w|Djp0MhU#Xx)())Oy>iZk z8PPRAV zYVVsTvFYpjUlqF#%u_SjMQi0sm3FewLniW7$@u*#-{|YBea#?x_>xvOGLox6N?D$t z-s)*2*7J>moxd&;t$nUPQ1U$A;(0r&jGBy`Or|Kz!1L7D;XF%Yn!Uwnl7klJoRC;t zEcrnAADi6S8>{h`tj*Tr-)OX%{X zurDw{0zbn@4KhCXR*<9U!3!S_MgVz1ZInWoOrRqGQdmK!?)Ht8a;5frlxlG*I)i8I z+#P+eMFO$_+UR?%b)W5fgLqQ@M4*DzYO+BhJ=OD$A*u@@J>$t<0{I;oca zK2(;Gyq|Zw=vj}1!5k)>g(I?joyVqkdcIl1~y zSo5V)ATd=H5b2M4B0bD`SQb3bO)M$ID;)2L8mQp3tfAQad#uK=OnH8Z1eJ_|pQjipfsYnof zQ#c}L5lH~-KzS3nj}p&4)&Ee*Rxzg`7Wj1k?rbI{L*- zQjECSk2*`Cl>&x)mPk1(Oxj%1yZCMDb4E4u?hBYHT=(b%?|*IRV~vGss*oeBW4ICl zPPT1sW8j#q%v@!>eDp$}oLH4W?6(e@nPNH@h53f~E_LJ`Mv%~Tr+_b*W2w$j#`Kg3 z@!=i5f=JQsWi=hBGQQB&tLPqO5^^(i&tt^GcOwmK0O|>bYvyIc?;;I5UQd9LS=1o>NUvh)on1NTa`EQ5Jzsm!mo)7(8~o)~!dR)Bfq~+`DgCC;A-rQBUxO zdX^C7cvHHPtZtH+W;pV&>oiyBenZ;Q9!^LiLjC3kQssxvOgYz(hE73T z+84$5*nZzrR$ajPFXwK#_3=1TU+ljaG&UI-oW(J#S5y7N)J|*s4uO&IU=IACLv+DPSdls4(PW(;P0zy^|g zPx|Nm5EDk1%-FlIrQGYg-35BuuhH?Rh=ijQvg1wj(IPEskzV>|njaNj#wZRW&d;wc zKgx5t2gOAs-tHwMC%)=PA-&VVO3ir_mgT{n%REx_dQrZgTu^sm7T2CPAc+zj?Ra*k zG3DqpR-#NSm`p)`9kfJO{^VbB>agi^VOpX?>_!#aFJhW9-pz1Z(2=dYA<4QO$X&8w zI{mO_xF_KI4PmWdA5(3uoC!S4tQSZ5%9q|Tk+H%&9#CT{uBLPqS?V?!!Wg+jEbBZ+ zn7{nwvm;}ph`gZsSk}cDp=QQe7U#k#PTJXp2#9Je3+MIcM0L2qimMpDGzWd^KhPYy(n zZ~cuS=e)Cy*V`E?au|(sDA-tdGvrOxxi5x_SYRwj@-4bdZCq{zPxRV%wf+-p2J@Dc zoJ_mJC7r4IngSC!H2y-!F&@aVb`^j5*KqQu{xFbW*ftlcDKgl4RA=eK(P*0hgLR9Y zInrzdvBws}HKMv4Q8pSNZwX4lja*aiX*4RD&d4Y5a!2;4P-J3git~CaYu>stme>Nd zafaQWia)qP?N#>2p4#bV)3`%n!B$`d}f+2k>8{iQbp=-I}e+feT!2}f@;(U%?A=%0{njl64YTMjjlZ|v#_>yHlnK|^R?HiiKd zHh6SAEWp7i&OAS-KrK(a9TJP1`pUNYc#32F2iFr};R~heWrcL-WQ85L#{Oj?!J9F! ziycej1aPS(cT>V*H|rLr)V!o=@0tM+WF+01kudbnSoiDNE^jz8`(S*{5!0v!R>KT@ zIlURGd6VaQ+})k;=7BGo9XZ5!=L^2uWuN%xERdK!F+N!`Q07i!ecfdCqA)K@XyqpJ`01?*OGdvm1b#&fgU`7PTd_jq^ZwgfY z`AQT>u+Hy1GA4Bcc)Hn6H-PuAx}cPy-)wkY=pL8{*Dh-{0mDAv|a@K z{bFMh#8B^}CwX*b(Lk=M2?lHghF_k1R>+jk%N*86LK}p#%4a2HL@QsCVqETz@HPq@ z&z7L|ZJW22*@1 zGuaB#v6MHB)TGQ^)kX{v2HGW&3ykw2hS~0~{y^ElY4(T9910;ZG{L-kGtpH3+4NRK zM5nBSEcQtxnQ_$T{GQw9b}VAR5%u2qQu9Y+u^7vKI~o4L!^&u0v;cW&EPJ+`N`CsoI@rTL zb~m0-H}G|!-$TL>)(4$0&_|Y|nk#GQ_^hm;@4HrVN@A+C9C7`fA%K4{>gn31@F1i) zvo<1YN0DtD@;bwQ0q7s;^$v2T{LrAx!*Ffri)AE5xlR2zN+F1ixaBu%fq?nX=`)ul zD@ZfgIuZ|x1C3|IhJTACP&D)4RraaBWaAd4KGyoCR_Wqd(D!`JL0iu$#(55k%GZYC1)vzAG(xV@IMetPA3&{m&l(?*zPF`PBw&-FLR z3d9r_t|267l+Db^eRpBxgH>#7WQKbuw_om+6|EHi`Z&S8)66&6!i>ma2Hbx7qXe-3 z^-j?v0dA<5D1TshFlU+;O-Z7x{JK`+fZUEs^|3P=ZZ2PlA{E7AWeNtg1VTc2O8LXc zMw75*aD6*JINBc1U;RIR@u!1;=1P#m;_gP>cNxii84$4UHiaOH22T$kW@*!vT^>C- z^q_?w_Gx@b-vdH`)mJq1{I+3Ye&VK{mQnyof}Ro#JR{?Ng? z>1@e~j~1|F0rll(z}V1C`Xzr`wf*ZmCx4%gB>tTjEzmKpwC<<=F+cFG+_q&H-=q_X zy~)1q80OLIL@-y_`5vPU-__ch&xlAQ0|8x8G@=`snwy=kiV%P}ODD?*ULRpZ+-v@| zKT~k~r^R=cvv(3iRN%BL-(jS69zOKV<$M!ANmI&4rwt>U7e2RgR`(Ie&-I@{I6IXk zM*?4YO<~KYR?s|r#}Hy3i@>Xxa|VfFhf}HV_K$z|tkiD4K8!XHgIK3!WTPR-?wmbQ zlIx;Sy>F8xHWpcNGB6}NVV}9gM8cn_hY~L5<|e0Sv&3Kz@R2?Fs1f1ZpcJ9Bx{3+X z=@>bT0JC&0=X;ZLE^QihMQJzuhd)xPAK`3+818X|2d*(P$5*8bWY;N96*F!tJ(EL( zF(i`X^d-$fwZkf^wN$=sPp+scv!5uCPatA)YY@WoaK?C&-22Wz2I>zzBuH2FG_`pn zT0U&4HJhQFwfsoOLJ|cXOhuwIHNPj(jKI*(xHrh2G0Lg_0+!aAhJN#G)tN-AsM4l|=3<-%|8mwTV{M^FmGWve~J52Cmm zy2PBbVN67JRU^Ldn*oE3JaWTN-o;QCcJ8y@%1%VlXk0e`WU(b!gXnq|gFhbOhOJ+I zO6mO(iQdn)4(+$*v~aT*q^6>)q$MWZSc1zJ{Kos0>zv}X?N!nWeXVe29dE{yt2g=) z%&=<3h2celt23D@2r)|z^FGpujv^HDgT3$~He#jdC zdUa*u{nyYs6|dgz*AocZ>Xk*!DXcB7J(n%Y98(jVW3Y+lRbL_AFAp}t$=%y~c^OiK z{EY|LTNV)+6qXB5i@6;qN0c9>D4Eq*XVP1UlMz&|W+(K0xaF8HW92>HjdVKtL_=Fb zDwYTDUttV0#?|`YY)JUm_sk^_PK1omj%M+q*EJQbnnznGWrzz#q}z}t=bxpJ@p{LgiU z-0uOVve~-?>hv}9s=>fA1gpgEq>Vzzo_8+jBuaXlkizuuMIC1K#y*#XM5SCjkQ5kZj?O3qpY7nZ7_ zPQFw*45CQg5UJc`v*lpZ1y9)Hd6A{>a;to*`E23~@{)W2{Q0FyC&zon_sfbmWS%*| ze~oY!`SkzR+#^H0#7CrZBSNPsm~Q^LivaTJHw!LJIb}$@D+uZ$6_6>6reu?hrA^gF)2e92OaiC zg>(RWeCiMBS8lF_%W!G^@U6S2P9YCkluz;wBoAAej@qky<*=KEho&Q>Qe#j1DO}Be zW&+NoK&)9=j#_6BU&g#=SYB` z2ZZxaup4dTmWJVspA60yqi~;n)s$t$hZ_#ct$A9YV!xMua9G^Vm>&4cUp>CCPxQMO zSPM|U7O7mcP2n(n57yG90{E}MAUqIx^rpX{^hA|5a@5gwSy zIJGJ-s|Z=wI`#%hiMhd=74nrE55YX)&HWFl(pjlL^J*@XVK*H5NWNcl91?6czEK*@ z`Gf?kv7vo<&$Z9e!|&f9I+Q}gn&z7OC!DMO0)WO{v<@oCs>AhXocZ`18; zXW<>=dyFD{h+??W0RHzty@I*VbLg(~-EXK8;J;-A=9Y6X0v|u^^%5|!oFB&LBkhtA zldrIHNcn~W{O6cwb>krFw~z^YyU+Yd-zC0|6k*6&7U5>se2p(BL0-*vu(;lG`BFuz zVMe#qIbPZAYLE-$Op2h{UaF-s{lAlmo@*8-PT7@P{TLK#bs7; zeVEJzq~x%y^=5xhsPl6}(t|jdKM*2{zuq+WUZ^oV%O&M!Q=>b)Edl;le$qfxoVs@0 z4>6+j3yWh+_@aGqG#jk)bsdG{;IA;GfBmtf~ub zUt6~2dzzF@x28UBw~8y(VEjek-%ej(0saftWqDYRo8VW=kP-oiK5b{`P66C zE3JI>oGIjmNBTQ|Q3!$pLb#nIR`8<$`5y&;-E4}<0&2xB-poDJ8gs5tw-+Tq{vrUj z9Mb6<2GXO4L$N8iVpJ<*9UrLEOEjnfFhzSK>M0Q+SwPzY& z|D)iu^lLTfUF_zl?8X9~FUOGG0{%YP%8^^iz%Ts%c$ud1sefM1!!*hO{O_cNg$vZq zcuXtnC$;=3OH%k^3*?mfsRC^--N`5u2CBnU2hAOgKQ&q7Gn<_Dg*A!+k!L)sjT{dH zm*SvJ5l;7qSex9{kh_1%)*D&1R$&+#c5ltPET82d9k@8pI~OoPXM_Lxuj-ut=AR?@ z;~N|-!T>x7S72aqinio4YJ~>Stk$sanRLp4F6NdbKQvsyD>TYroK3I}1rbz4K$9Cc zOh^!DKjj&z>Q+eOMPjdk#wy0{qa4BXSd%c@m-(MFcuXV!{2x$8rREL9B-jYsA`bS% z{gNhw!{%zhw4D^AE8d)XjVA#3{aj(bPCwf^9V`7&RQvblvm#nk=k*|$4VR;`p!uvJ zdJ@(rl_~`?D42GuqY420O9seR!B+q=%B{4z9Yxv)s%izzy;OYNpfggvb}CR+ps%qr zm|b>cEmFHDRWDS+b;D?E1xQV1)dX)cZ6k$Rq_5hCeq*U3sa}t+vhe>Re?^z@G{(8r z$YVSuSN%ZV<0+jU0dMlGyai)l>-#vBk?i$)OL<)F^SFzOP3hly?6TQs$p@5QMiZ(; z>Xju+3>WKP=ces^@KPUq+yhSgL5Gu@TWi|MKB$RIbycKk>fc*+Z0>9)K$Y%3_d!gy zxqKZ)!IGBpUDn%H-LT+Sleau8eVWYOu)G9;vh*Y1`7ehkwv~dJl!nbsmZt-;;eI*V z7Gh9~N(fO}@gW`O9(0F?_0e>!EyP;;1L1)Dg>;1d@AU@(Wid?jQx?srwoC#L^4^p|Wq}E!fBSmR;lWBXeJ1SXvMflS>o6P@#xEV3KQkMc8Zm+i7o?ak^ zc(;+^t0~i4VHEqz;=29B-NWcK)U|LDkm6w=1 z^5gC_oyB@FJS*+GCS$w{npbklmFA~UE19T4eE>1GtNlQY?c>n zqE$TD>=URd4)8AB9wrL%wS9vD+ed|)V$%6KW)RVlqeTU~E6QI97yK>;KQCRKw=(U$9k{GBCRZQ5y&Y^9KK!|D)Y0S<=3gS}<^tS;_{?zYJli&-K?3 zaQ{H86@yvCh!Zny@Af?3Kee7HiUlgF^~T{4K6}u%WjaYLG4imR#?d-A=Xcq}>(lWk zM%z`BgbI<555YZ*<$XCmQCv{tynBoQ54gF&&8WmD_qlf&ID%y6|0PfqK4`-?1Zwsv_A`Hi^I|u-boo`zqdllX z-0l)T>cuWJ`8bu_X^;0lT@Ig9@)qcme?OvuuGu)yl8a%q57AKJPIJQh_xt4TSKpF2 zH%MOPQxV6)TP;H5X^yRQ{V;x1+>k`i3VN8%OzDsW@409QdVfwmM}QG_0m7{=dKcI_ zvS07HU=ds*S7BSWo0;gJ^Ph3H z-%S~P-ynOmK=_`);55A_9Fux%M&+>SwzbjhE7?Ixw+n~t_i6-uGN?WH*bXYCyL&KA zh}3qU!o=5xz^sXt3k@@UCTxdNN88u;wgxNcGazUPnC`j*+aLG>AS0no4cAOdzrNvw zIZfN;=wM_XF6k^<4=UY_ZnIDTkNs-=(+yPXB-};)75tdNG@S%ebFV#&oUYDFQSsA% zN`QF~7gR570ZCr2V^mv&DE&5sXV+`vLmWwuV1#)93{wCvkdz6^C^UdBPE;IZG5sTcYFz)GX9`vRR<2=!?P zM>rhN7t@?6Ey$7AJVu6*hLWFR#)p}98YIWN%7a8n>IOcl!mOmlvp`--S(mMub8Yh6 zpZOzFORtT$`=PoyEce2}kziljSEG2?dvH--rG2W@)-t;yT37)7<{SLYeI<8KHX2Of zZ1Sl;{A4&BTm#_G?|a1M$z@@0OawYPnKNKsu8Bfyx3P>Z0HSxg`(M$5+m~$=3b5 z|2zDBaEF2MOqf3jXQvncT2(rXH_s0V(GgXQf6s-+HE!5AyK2078!pWIcE5m#g^oQb ztaM0|{&XZ)@-FtJ zeHx~iQuYu24UQcrBXBbY`rU?!dwe8bq+9M)oP-oMHm=)q-EfQ0u;6fBACrH-pFM*p z$sX&}S%#6=Y3e;)k;LAt5;T24!Hd2-d!-Q;JcqzIT@&xjTsb&0{gP61FQWBYC76_^ zhG=rFvDJ#7>TmwtD{1|@$h9ia4)FY&JnTNeZphbScc4SPjvWD8s6Js7Wg^rvn1!um6Jbv!6*-ON(v^$) zD{J-e)6e;1Zt+}Gr=Y&V3%bsx3bi^|r{gfBluS65&4>?tik#Goe|7$;f6^#aIyq84 zASv*`b%MT5G?RfFMAz2anE9bL_K*VjAL@~JH!VPay(aqL8@3l7yU|x04{jV{eJ;pNL0@1Z9!d=zFGZ!J^0b5kpEtf3)3qY>IWZFhb_kGrUDB zP{Dxu>A&*D*RhNN`X{9EQF+(p?uj_xtk18{x=PVI&GpYOD~sXhAhsweXg15EthI}V zT6}}VR86x*Fml~~`Va#%jfH%vUi;Kvarr$fYa^t=Pi>ULE$P}=1s%Qs_|LipZx!*U z{tbtkhNlF!*vGSN@Tq^BTx)*%FM0VG>pXz`byQeT>vDp=r&b8Xr~mKNrs{tG*ia3A zKFaX^2HgB%9>L!W$e;5?QOCRCUwLeyA2i!!b6inxmThRBOU#!7{m=a2V%#mUfC`fH zo7vP!DWLm#L=w8_;SV}U~#jBD2CA!)wQ;HNnl=$D_@}#=W2lLeLxa(1m>t zOGBRIG{FC*-hrl+0-icfA`crwf>{~J!~$DQOqP@MID36zW@0-o#5$Z&bTOe_GG+-d zMcB5yX6>7`&*8lO>Xx?KU;6IsMtw8=SO0-O?BYsQBEcVp4@x*BR9N+|J(BUl@qB}v zyOW_@e%&WRft|U5g~k&^fmnrNcq9i2eS-d*e{bMhQslYmTV-=&M=dLK*6|+KaC-pc zeS4iHttjM}zzLgl6Xi|@!Z;eN zBjE|jJV;m#X<}1f6ISji?^` zgiKU$4Gfur^r2UctuOJyyDuVyt&{E}q6s}A1vgiu;C5@uHpIUk3?Yuc8FkZW7 z)8O${Q^+p~GUzD;bnEq51W3v_K$u2u7GIGM@kCno++QWsi(mh@{BE&G#1Dpak8INLehZ|;6+gxRwyIJOpnuwLZjAU)_CjtE%YB1#ASveX?vo?}dKAyfTtgy?U&nMxv z{LKH7EK|D70A(n{!~e_wTgOq|nga5l79K#K`8Sh^fB0+IqwkM7G-A>@hX)DOa!tA> zB_*zP$kgt+^d;NkyI(c8N=OQn9_KLc9rALWsg_HB4NN;UXleY%hPx&r^2CrH-X!JL z`gYnS+2}h271pMUsDhC{)oZXd=w+v6I`b)A(ZT2WXZ_k@ig;LGC5>fdERC?Csj5UX zDi_)+tOmuXza10_PsruY!?@FupLu2U>Ho-M3!tZV@>yHxUEaVN!De2Tk)KZl5pbcr z=PCT{|D22|`xO-HYesJRIa4eXQCSJhq6Y!=7u%O#lO;lEcz3%v(d{Q8{D-3=9QMzZ zLyJ+$%#y^X`)rb3@QiRI2GzSs%Ds=&O;gu5U%^#2Ze1S^#2{EZ%4v%7{ zC2A&PN=Y)`u4LKXAQEDJ`VI2~bQ93O5LaH}2&j_+%T}Y*TeclmVQuo#u$M%E*UmlM z9*NOeL||tX$^hWM%yNHR@}b`f2iX5d{hQliL!cVqe<)BFNeh~t22DrYwEwi{*D$OP z=Q`dEwmBV#V!^?$tEdu8&a=1075CkKC>3-XX9u8uc!Xs{0STtdrJ^QV`x<~KD|8YD8^+DsG6MVXnu)D#GM!`(R!Z5 z&}^8`Gow&tb&BVLOCEpwk{etv1EEK?k&(+5hZ`Hhb7Uiq1dA-soy~kZz#pZ6`nmr( zQJ_=G0r_9v=DY3~KIGRy-Em9eub~;^zapvx0s8O!?@*H__%_M?0quo$!273`vHg6$ z^8r(BcfX~vH&ResfA3yKj+0%zL(+ZcI(+N|>3A;1Mw*J$6IH)YXzST${}9ziWI9BT zilpGB4zJ!>q?^SGbXzU9N1B4wRPt~BO%f>{RUM%J3o|3p_#|)KbjG##CbjceP7+X! z%9ki^m*#oZ^#SrPR%OtVX@LIQ(U6(d4gmiaY3^PsE1F;%ah}lsc?^)yip0}Ses=*G(b1{V>zHO<_Cu&PIR*8Ts`+Pm1wwTaPyD^pyxe3oQp;tDagyYWYM^Dnul285Tm2~QDCfRsHANC*rN@HfT zdPvPCv?qK~{F^`L)tk2BRnBdwv8)XN2l$_daJrxU&o=D8`)~X8*Hu>n1Lf1UCwI=s z=|x46NZ8320$jp*GW5zC9A1L`8)AttU-D>F*`HEn*F^0ux@Y+-y4NyGl%@ajSCU-j zcG~#o7VC~q0ZV}S8!6_8*H9(H_&5KaE`<+eNP@=T5x;T~DV<<;@FlJj+rTCeCa39V z_t_T);m4t^W$rtTJ4F0P3hs+f{og#&DmWxC^lNS;vP$3X!ur_r33W1$_+&cRz49r} zpua+nJ#5zRh0Oo**GH_IpZEhYJudr>PVYFip!+j__uG`rI~$Nca7*O`!k#z)!$oR! zfSj%-HPAl$aw>H0+v>JkRSEDPh0Vnwmgh_2RGP3v%q+ZtW!*Pv-=!m|2!Sl zg|J}&{C9?y532$oGUZGa<@_y^PDLdG!r3g(1WQ)>Y;&R#@R9GRV?yF8)q5BPeAGDp zeMXjNg=-~m_)|r(t#`)~0)YNgZ|*<_wqW07f<591O9+$Ty?z?w;#JS`S3c|A$D4ub zA}eyf)cyR-A7cC0LFm=j zM-w`Zk&y1wuUL`>zZdof;uu%jOqVtj)n@y6+BDFJkpuK^B|ZFN_5k@S-|7P?4?zC! zeeB=!As(qN=g&B0QfY7MzY(4ft9w~7Ge}8&=AV$BDE*3N^fhVR)mI@h=M700CaZr$k`p@Loe{;# z6J|nowTj(PYah_4PmZOr^Y+l3ZcJta^mpAkl~4T752QTHXS|1!jzB!7RH=3#1C2!J zNcD)kqpAHk&>in_$oKq-zYQPK3Ll}b)e}sgc*@7x1MPDD^-t_qwc0?L$3xYMVid~x z%Gvc%(p^t~{q0}Ew_>bRl5bxtXMO+MeD4zow$1aHx+-)tz`0)4?xKp)@3hyL zl6QL~Zy1I+Dg>7$f_9$8Xsyq{5yX)Bs2m16BH49qBNu<1qvh@UO$-^aQ-jdgPx0c*KmQixYDvO ztQ)kb5PM|E5W?Ih2L8N;Rkg(E+3(;n+C`qMBA)0zvINJrd*fGvTDTgO+Oyar`~u}2 zyNkfgc6p5ZLqT}`C*RHZ*A$vNbcl)4KaJ-g;{>JMM~}sUfcZOrRWPYg3EG2pGXEcUpVOV_?P_9yM(w)3k1-KtpzU=PR)?XJ0V!oSs-=mHM&K zP*=Oa?HoLOrRf)vheHHSOSCap9}y5;K;8Fj>UZd}+|MR&Tou!sL*6^MZ;~F+s^TU1 zhbf56KM3sWHau9s6odxx8{jjF)Ck|v&Yy2D?9H>X>&^lEJ2vZpdney=%6DfkrR$G?zxc{Wd|1dFA?7nzc0Zre^L$iog9At7hg~!GSsI zwe!g{A))E_m-`>+EuA^cNzg;-`ncg0!K6Qv(tUv7d)*2}?7jZ(zhGtRQWl9&3zCrE z`Oti7n}k%5>zk}EN-r>^*Es>i_0%(tNy_Mw6<3HSdS?CQD1N#>!lFc1cM}Fpkp?Fk z&WE72k3?}u@DaIV~fpSHvGHk46je@w?Rl>qtHG1-23Yq;^$VR+o3G>YEBO@RYP{1+#)5m1#|e@W{pUX_J@M{>5u;p_tJmTZ;h@?V(oT>D ziA0>(>zi$W6-cC)Tm)yapRY59>&i<|Av&l@$EgO{=$4Z|{UrqVI|n@mMy3-~ z?$~m=&V~5$7fifEM%gxG8YFzvYT^a#81AGkPgOg*!VVq*!S6WE+e}r;0g)zc6l; zSZ9WEf5k;KvnSCJanOU{zv!1{bi1kVVZ$H**%!D&gmO*b2Iabs4Uwu9GBLD*R`eBD z@!CZ-=eg&!x80B#Y1DA(SBobd5x_h@opWiY{x5%^IPvFw z9iMyy%JA*JSUa~82SG=VrNU&EKOvq`6d79w@GUQHFBL?#r#2PxfTNCPet4?KOZE>4 zWa~^ucm|;0IDs}!J9U>2ZD$4PkY#*bu~Q*a_j%RsE;+w8gHZZT`L$DCq13~pt4NW` zt)b|hA%8UDb*o>5Ij(IfZ8F=e+Wniihp3G6$m)=%wTiI{k^k%Z_v@0l?2~d_*Xx92 zpNrM2GQ^5q-OG2Uxut7Q&d>CDhwk(0wMBoMp%`5|-bomR=w7?Aj=pU4t$PIAL9Rf% zbtXNDnI+d{r#V?isp_SNThA+}@$ABe9MmZD#!?RlML|KaElJ9Tc;tmHn z%+zzRc@{SJIx_oan7ZHP{PX-$=eIcf!h_(_mlDxo6XRb$@%0@nkULm3p<*gj zZ+Oel-@(x>PQakDbuf%+XTAD=YwN$3UX$VPCG>ix? zCxmu2#BCx|b$3Hc>ZyH^kvvD{csiXCIx{%KL4+BdAxTa420%pqCr5+4*tcHv$mn zfB6qIUyxk%pOqQO_?J<*vT8WXjsrSTnHg5q)9fi_$(cvg#md<*oruN{OQ&^&{B8YP z3TtC1+*hRk>CY!ZVFhb1L9)>o8;IVt6cUDebzvS;`XO8^%FoI_e7-+WdT9iCjB!_Y z7AQ!yh(PpMg8W24)(hD#x=Yl_c7eGVWOF+kci{|)%KUy(t}kU&&@ zWbp=Trfw2y1GXmcTYuY$_(3lo;|sP?1t}`T)-2{7XF~eHRg6gL-VsD7@qNm1 z0o>edgt}uxjxpL`4*-7*lPfs8u`^1n1v*eKK-oG=u5Q-PeFZ_}-(FAav4;IS|Nr*? zrOis`X4AeHC$xK&2<<8~{?|X)I)~lwg&3-?AufDc2)Bnz&qzic4Jxxie493FVD+~u zh~hg*7U514=1kRKaam8mqBomj#KQP}NeU|r`^>ss3;mLYQMd!!pS`4OU=8uppnPsgCTf~Psi&<^TlU=mcvDfLs zR?O;)EniQNg7_SmIgffH?3)#xPU=X5ssM?t9Bz@AZ}fR`yjF){B%}_5+z3Pi&)8^O zXqSA8t!6ywBCXLL|NNf<5g)}p%9NH;TdhdLe45!(2DN^HoI{KzJAs&h=jzUZK!E=u zR^aus(fEJ-AM`eXANSL*?mK6T18_>k3lkuk4e;Y};pMtFZjcm&Mr&&O8yi4Hzx^Hu z>I+exY(KdH)=2o9Kg)ZaixR}hx8=8Rp#VFN3;1@z(E56TkMPqDakv?$y90Tx_DK^h zrG7`bDmzKhx-4uc%(u>z`mTn&S?nEhGjbl^C)jQFhJ!5(c82!_qs?3$kNY}AQIOwI z$>&gKdW%k011WhOgAJH)Sa*T`IN3>kPi?Wv%sfF~-2WQ|YZjH04#<5dJ}P#s{2Tp2 zs+-ytR}I7-CHQ~|c2^J5NImXs+l4V~ZrPbsb5gd1YfeIEg7Z&p){|D;9v-N-WB(1* zFwcOIH#&YFv|;fpqFP5;3dUD2Z4OCw9j9xhl?4tFBgmXNA{toq8Rad~+ejbTi*MTn z4!W7D3a)B+e2FX;W`O%A*8X3`UzW&;d9m075d}^#pkp@G+@20u37l84Qmom$eDQj8 zUW;ictOkFm36SQFslg?|f#?s*+-S>KhrJ_o;gs@TAnsHg+8UrEl-qq$zV0t)cGyEs z^>^-0f0%B_8C6a#Bq8gkwD=W>ZK~9nqXRxJwxmkGcZ{(83uLUk9>4T%CD<7%D>WVQ zw_lY7>eIYY3uCZZNtn<Jqr}&?+S}auwIB$cL`33b=ypFYI zHyC8J5K>pMSU~YdwU=m56J1mfRF*3&Op|maedWm5GiV(2fF6Shk#VCHUl{k&T{Jen zRzdAhgAN+ucJv{P)!|RKpP54Emt07+Cgh5_XC<{KId*8WAN|DcHzbLq6G4~4 z0Zp;D2opJkgDIVoteM5D zj?6&xp2kN)vlT{G6W=nhr+Kax73eGG-qvy$yC+t{Fs%P?=Rde;KzaYucai^Pr*oHT ze>=5$O~dyGo6lZ(_`d9XeDLlA&zqG3mM-s~6m}tXK?NJ*sp6Aqa$j%BU%L9~_RK?k z+n>HJY5B3HZ3V-<{5_E>FP{bU#TX<@HmqpEexL^gO!l zW2KJU`nfYZ5{~6hYx=`|pmu+O$o~tPC+@#^+JA=S;O(zjeebr_Z2I;h^_V|w{q=#| zn6sPIA}SN5wpa&-|0y;XXx-%Z+jIjTo2IJfouDIUf&*G2mMlnZdQn~@51fCyGNS!2 zX*hN2^`~nM?nmwv=i0V^#+1ij=07~}^>)|pV*B%Je&?SIOAuE6_sZrc4^PolGj`Ko zU7c>5?K0!?S;MNl1M441q&R%C$tk)WaCAp#<^Jd%jl*7#pE=vidG!AE1iOv5&$hih z*v7AMqj104jGE1}HwWFZ3Ojl0*CQ#d+dOfM;PF>^?!;*GWtr!ld#C7l^2tTkiDsMC z2Z|W}-5ROX`t-miXHMNOUyPWU#4_gV2x_x5Ot#r;QXEqGJE0)dz4MwsO`P(k-D?xW|VBkrXAmR|8~Wsm{O z-6?&c*ShvKI0v0wdGr3;no6e`HrY!#%z@*ddpe^wUTTSOIWynA+OgRb3#+TJ)@#kLn^Y>X!>Pr= O`OjSa@~cx{uLJ;r+na#^ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.mq5 new file mode 100644 index 0000000..a5d92fc --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.x121.xtrnd.mq5 @@ -0,0 +1,1253 @@ +///////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// -------------------------------------------------- +// Name: X121_XTRND +// Description: Market Trend Detector ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XTRND Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_XTRND" + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int cycleLength = 2; // Cycle Length to Check +input int numberOfVerifications = 2; // Number of Verifications + +// +input group "Calculation"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Detect Up +input ENUM_SERIESMODE llMode = MODE_LOW; // Detect Low + +// +input group "Cycles"; + +// +input group "Level 1"; +input ENUM_X_PERIOD_METHOD l1Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l1Period = NULL; // Time Period + +// +input group "Level 2"; +input ENUM_X_PERIOD_METHOD l2Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l2Period = NULL; // Time Period + +// +input group "Level 3"; +input ENUM_X_PERIOD_METHOD l3Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l3Period = NULL; // Time Period + +// +input group "Presentation"; +input bool showConsolidations = false; // Show Consolidations +input bool showTrend = true; // Show Trend +input bool showL1Trend = false; // Show Cycle 1 Trend +input bool showL2Trend = false; // Show Cycle 2 Trend +input bool showL3Trend = false; // Show Cycle 3 Trend + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 24 +#property indicator_plots 16 + +// +// Higher High ... +#define hhBufferIndex 0 +#define hhPlotBufferIndex 0 +double hhBuffer[]; + +#define hhColorBufferIndex 1 +double hhColorBuffer[]; + +// +#property indicator_label1 "X121_XTRND U" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// Lower Low ... +#define llBufferIndex 2 +#define llPlotBufferIndex 1 +double llBuffer[]; + +#define llColorBufferIndex 3 +double llColorBuffer[]; + +// +#property indicator_label2 "X121_XTRND D" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// CYCLE 1 ... + +// +// Higher High ... +#define l1hhBufferIndex 4 +#define l1hhPlotBufferIndex 2 +double l1hhBuffer[]; + +#define l1hhColorBufferIndex 5 +double l1hhColorBuffer[]; + +// +#property indicator_label3 "X121_XTRND C1 U" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +// Lower Low ... +#define l1llBufferIndex 6 +#define l1llPlotBufferIndex 3 +double l1llBuffer[]; + +#define l1llColorBufferIndex 7 +double l1llColorBuffer[]; + +// +#property indicator_label4 "X121_XTRND C1 D" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// CYCLE 2 ... + +// +// Higher High ... +#define l2hhBufferIndex 8 +#define l2hhPlotBufferIndex 4 +double l2hhBuffer[]; + +#define l2hhColorBufferIndex 9 +double l2hhColorBuffer[]; + +// +#property indicator_label5 "X121_XTRND C2 U" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// Lower Low ... +#define l2llBufferIndex 10 +#define l2llPlotBufferIndex 5 +double l2llBuffer[]; + +#define l2llColorBufferIndex 11 +double l2llColorBuffer[]; + +// +#property indicator_label6 "X121_XTRND C2 D" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +// CYCLE 3 ... + +// +// Higher High... +#define l3hhBufferIndex 12 +#define l3hhPlotBufferIndex 6 +double l3hhBuffer[]; + +#define l3hhColorBufferIndex 13 +double l3hhColorBuffer[]; + +// +#property indicator_label7 "X121_XTRND C3 U" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +// Lower Low ... +#define l3llBufferIndex 14 +#define l3llPlotBufferIndex 7 +double l3llBuffer[]; + +#define l3llColorBufferIndex 15 +double l3llColorBuffer[]; + +// +#property indicator_label8 "X121_XTRND C3 D" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// DATA Buffers ... + +#define hhStateBufferIndex 16 +#define llStateBufferIndex 17 +double hhStateBuffer[]; +double llStateBuffer[]; + +#define l1HHStateBufferIndex 18 +#define l1LLStateBufferIndex 19 +double l1HHStateBuffer[]; +double l1LLStateBuffer[]; + +#define l2HHStateBufferIndex 20 +#define l2LLStateBufferIndex 21 +double l2HHStateBuffer[]; +double l2LLStateBuffer[]; + +#define l3HHStateBufferIndex 22 +#define l3LLStateBufferIndex 23 +double l3HHStateBuffer[]; +double l3LLStateBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int currentPeriodSecconds = 0; + +// +// CYCLE 1 ... +int mL1Candles; +int mL1PeriodSecconds = 0; +int mLastL1StartBarIndex = 0; +datetime mLastL1StartTime = NULL; +ENUM_TIMEFRAMES mL1Period = NULL; + +// +// CYCLE 2 ... +int mL2Candles; +int mL2PeriodSecconds = 0; +int mLastL2StartBarIndex = 0; +datetime mLastL2StartTime = NULL; +ENUM_TIMEFRAMES mL2Period = NULL; + +// +// CYCLE 3 ... +int mL3Candles; +int mL3PeriodSecconds = 0; +int mLastL3StartBarIndex = 0; +datetime mLastL3StartTime = NULL; +ENUM_TIMEFRAMES mL3Period = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initial Periods ... + InitialCycles(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (cycleLength > 0 && + numberOfVerifications > 0) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax( + cycleLength, + numberOfVerifications); + + // + return result; +} + +// +// Initial Multi Time Frame Cycles Periods ... +void InitialCycles() +{ + // + // Calculate Current Period Secconds ... + currentPeriodSecconds = PeriodSeconds(_Period); + + // + // Nearest ... + // Calculate Cycle 1 Requirements ... + if (mL1Period == NULL) + { + // + if (l1Method == X_PERIOD_AUTO) + { + mL1Period = GetNearestTimeFrame(_Period); + } + else + { + mL1Period = l1Period; + } + + // + mL1PeriodSecconds = PeriodSeconds(mL1Period); + + // + mL1Candles = mL1PeriodSecconds / currentPeriodSecconds; + } + + // + // Mediest ... + // Calculate Cycle 2 Requirements ... + if (mL2Period == NULL) + { + // + if (l2Method == X_PERIOD_AUTO) + { + mL2Period = GetMediestTimeFrame(_Period); + } + else + { + mL2Period = l2Period; + } + + // + mL2PeriodSecconds = PeriodSeconds(mL2Period); + + // + mL2Candles = mL2PeriodSecconds / currentPeriodSecconds; + } + + // + // Farest ... + // Calculate Cycle 3 Requirements ... + if (mL3Period == NULL) + { + // + if (l3Method == X_PERIOD_AUTO) + { + mL3Period = GetFarestTimeFrame(_Period); + } + else + { + mL3Period = l3Period; + } + + // + mL3PeriodSecconds = PeriodSeconds(mL3Period); + + // + mL3Candles = mL3PeriodSecconds / currentPeriodSecconds; + } +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(hhBuffer, true); + SetIndexBuffer(hhBufferIndex, hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(hhColorBuffer, true); + SetIndexBuffer(hhColorBufferIndex, hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(llBuffer, true); + SetIndexBuffer(llBufferIndex, llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(llPlotBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(llColorBuffer, true); + SetIndexBuffer(llColorBufferIndex, llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // CYCLES ... + + // + // NEAREST ... + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l1hhBuffer, true); + SetIndexBuffer(l1hhBufferIndex, l1hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l1hhPlotBufferIndex, PLOT_SHOW_DATA, showL1Trend); + PlotIndexSetInteger(l1hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l1hhColorBuffer, true); + SetIndexBuffer(l1hhColorBufferIndex, l1hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l1llBuffer, true); + SetIndexBuffer(l1llBufferIndex, l1llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l1llPlotBufferIndex, PLOT_SHOW_DATA, showL1Trend); + PlotIndexSetInteger(l1llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l1llColorBuffer, true); + SetIndexBuffer(l1llColorBufferIndex, l1llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIEST ... + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l2hhBuffer, true); + SetIndexBuffer(l2hhBufferIndex, l2hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l2hhPlotBufferIndex, PLOT_SHOW_DATA, showL2Trend); + PlotIndexSetInteger(l2hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l2hhColorBuffer, true); + SetIndexBuffer(l2hhColorBufferIndex, l2hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l2llBuffer, true); + SetIndexBuffer(l2llBufferIndex, l2llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l2llPlotBufferIndex, PLOT_SHOW_DATA, showL2Trend); + PlotIndexSetInteger(l2llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l2llColorBuffer, true); + SetIndexBuffer(l2llColorBufferIndex, l2llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // FAREST ... + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l3hhBuffer, true); + SetIndexBuffer(l3hhBufferIndex, l3hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l3hhPlotBufferIndex, PLOT_SHOW_DATA, showL3Trend); + PlotIndexSetInteger(l3hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l3hhColorBuffer, true); + SetIndexBuffer(l3hhColorBufferIndex, l3hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l3llBuffer, true); + SetIndexBuffer(l3llBufferIndex, l3llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l3llPlotBufferIndex, PLOT_SHOW_DATA, showL3Trend); + PlotIndexSetInteger(l3llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l3llColorBuffer, true); + SetIndexBuffer(l3llColorBufferIndex, l3llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DATA Buffers ... + ArraySetAsSeries(hhStateBuffer, true); + SetIndexBuffer(hhStateBufferIndex, hhStateBuffer, INDICATOR_CALCULATIONS); + + ArraySetAsSeries(llStateBuffer, true); + SetIndexBuffer(llStateBufferIndex, llStateBuffer, INDICATOR_CALCULATIONS); + + // + // LEVEL 1 ... + ArraySetAsSeries(l1HHStateBuffer, true); + SetIndexBuffer(l1HHStateBufferIndex, l1HHStateBuffer, INDICATOR_CALCULATIONS); + + ArraySetAsSeries(l1LLStateBuffer, true); + SetIndexBuffer(l1LLStateBufferIndex, l1LLStateBuffer, INDICATOR_CALCULATIONS); + + // + // LEVEL 2 ... + ArraySetAsSeries(l2HHStateBuffer, true); + SetIndexBuffer(l2HHStateBufferIndex, l2HHStateBuffer, INDICATOR_CALCULATIONS); + + ArraySetAsSeries(l2LLStateBuffer, true); + SetIndexBuffer(l2LLStateBufferIndex, l2LLStateBuffer, INDICATOR_CALCULATIONS); + + // + // LEVEL 3 ... + ArraySetAsSeries(l3HHStateBuffer, true); + SetIndexBuffer(l3HHStateBufferIndex, l3HHStateBuffer, INDICATOR_CALCULATIONS); + + ArraySetAsSeries(l3LLStateBuffer, true); + SetIndexBuffer(l3LLStateBufferIndex, l3LLStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // HIGHER Highs ... + double hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + cycleLength, + bar_index); + + // + hhBuffer[bar_index] = hh; + + // + // LOWER Lows ... + double ll = GetLowestLow( + _Symbol, + _Period, + llMode, + cycleLength, + bar_index); + + // + llBuffer[bar_index] = ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double hhColorIDX = showConsolidations && showTrend ? 1 : 0; + double llColorIDX = showConsolidations && showTrend ? 1 : 0; + hhColorBuffer[bar_index] = hhColorIDX; + llColorBuffer[bar_index] = llColorIDX; + + // + // Calculate Cycle Changes ... + + // + int cycleCLength = cycleLength * numberOfVerifications; + bool isCycleCLengthPassed = MathAbs(ArraySize(hhBuffer) - bar_index) > cycleCLength + 1; + + // + if (isCycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + cycleCLength; i++) + { + // + double iHH = hhBuffer[i]; + double iLL = llBuffer[i]; + + // + if (hh < iHH) + { + isHighsestHighUp = false; + } + else if (hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (ll < iLL) + { + isLowestLowUp = false; + } + else if (ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + hhColorIDX = 2; + llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + hhColorIDX = 3; + llColorIDX = 3; + } + } + + // + if (showTrend) + { + // + hhColorBuffer[bar_index] = hhColorIDX; + llColorBuffer[bar_index] = llColorIDX; + } + + // + hhColorIDX = + hhColorIDX == 0 || hhColorIDX == 1 + ? 0 + : hhColorIDX - 1; + llColorIDX = + llColorIDX == 0 || llColorIDX == 1 + ? 0 + : llColorIDX - 1; + + // + hhStateBuffer[bar_index] = hhColorIDX; + llStateBuffer[bar_index] = llColorIDX; + + // + // CYCLE 1 ... + + // + int l1cycleLength = cycleLength * mL1Candles; + + // + // HIGHER Highs ... + double l1hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + l1cycleLength, + bar_index); + + // + l1hhBuffer[bar_index] = l1hh; + + // + // LOWER Lows ... + double l1ll = GetLowestLow( + _Symbol, + _Period, + llMode, + l1cycleLength, + bar_index); + + // + l1llBuffer[bar_index] = l1ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double l1hhColorIDX = showConsolidations && showL1Trend ? 1 : 0; + double l1llColorIDX = showConsolidations && showL1Trend ? 1 : 0; + l1hhColorBuffer[bar_index] = l1hhColorIDX; + l1llColorBuffer[bar_index] = l1llColorIDX; + + // + // Calculate Cycle Changes ... + + // + int l1cycleCLength = l1cycleLength * numberOfVerifications; + bool isl1CycleCLengthPassed = MathAbs(ArraySize(l1hhBuffer) - bar_index) > l1cycleCLength + 1; + + // + if (isl1CycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + l1cycleCLength; i++) + { + // + double iHH = l1hhBuffer[i]; + double iLL = l1llBuffer[i]; + + // + if (l1hh < iHH) + { + isHighsestHighUp = false; + } + else if (l1hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (l1ll < iLL) + { + isLowestLowUp = false; + } + else if (l1ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + l1hhColorIDX = 2; + l1llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + l1hhColorIDX = 3; + l1llColorIDX = 3; + } + } + + // + if (showL1Trend) + { + // + l1hhColorBuffer[bar_index] = l1hhColorIDX; + l1llColorBuffer[bar_index] = l1llColorIDX; + } + + // + l1hhColorIDX = + l1hhColorIDX == 0 || l1hhColorIDX == 1 + ? 0 + : l1hhColorIDX - 1; + l1llColorIDX = + l1llColorIDX == 0 || l1llColorIDX == 1 + ? 0 + : l1llColorIDX - 1; + + // + l1HHStateBuffer[bar_index] = l1hhColorIDX; + l1LLStateBuffer[bar_index] = l1llColorIDX; + + + // + // CYCLE 2 ... + + // + int l2cycleLength = cycleLength * mL2Candles; + + // + // HIGHER Highs ... + double l2hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + l2cycleLength, + bar_index); + + // + l2hhBuffer[bar_index] = l2hh; + + // + // LOWER Lows ... + double l2ll = GetLowestLow( + _Symbol, + _Period, + llMode, + l2cycleLength, + bar_index); + + // + l2llBuffer[bar_index] = l2ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double l2hhColorIDX = showConsolidations && showL2Trend ? 1 : 0; + double l2llColorIDX = showConsolidations && showL2Trend ? 1 : 0; + l2hhColorBuffer[bar_index] = l2hhColorIDX; + l2llColorBuffer[bar_index] = l2llColorIDX; + + // + // Calculate Cycle Changes ... + + // + int l2cycleCLength = l2cycleLength * numberOfVerifications; + bool isl2CycleCLengthPassed = MathAbs(ArraySize(l2hhBuffer) - bar_index) > l2cycleCLength + 1; + + // + if (isl2CycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + l2cycleCLength; i++) + { + // + double iHH = l2hhBuffer[i]; + double iLL = l2llBuffer[i]; + + // + if (l2hh < iHH) + { + isHighsestHighUp = false; + } + else if (l2hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (l2ll < iLL) + { + isLowestLowUp = false; + } + else if (l2ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + l2hhColorIDX = 2; + l2llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + l2hhColorIDX = 3; + l2llColorIDX = 3; + } + } + + // + if (showL2Trend) + { + // + l2hhColorBuffer[bar_index] = l2hhColorIDX; + l2llColorBuffer[bar_index] = l2llColorIDX; + } + + // + l2hhColorIDX = + l2hhColorIDX == 0 || l2hhColorIDX == 1 + ? 0 + : l2hhColorIDX - 1; + l2llColorIDX = + l2llColorIDX == 0 || l2llColorIDX == 1 + ? 0 + : l2llColorIDX - 1; + + // + l2HHStateBuffer[bar_index] = l2hhColorIDX; + l2LLStateBuffer[bar_index] = l2llColorIDX; + + // + // CYCLE 3 ... + + // + int l3cycleLength = cycleLength * mL3Candles; + + // + // HIGHER Highs ... + double l3hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + l3cycleLength, + bar_index); + + // + l3hhBuffer[bar_index] = l3hh; + + // + // LOWER Lows ... + double l3ll = GetLowestLow( + _Symbol, + _Period, + llMode, + l3cycleLength, + bar_index); + + // + l3llBuffer[bar_index] = l3ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double l3hhColorIDX = showConsolidations && showL3Trend ? 1 : 0; + double l3llColorIDX = showConsolidations && showL3Trend ? 1 : 0; + l3hhColorBuffer[bar_index] = l3hhColorIDX; + l3llColorBuffer[bar_index] = l3llColorIDX; + + // + // Calculate Cycle Changes ... + + // + int l3cycleCLength = l3cycleLength * numberOfVerifications; + bool isl3CycleCLengthPassed = MathAbs(ArraySize(l3hhBuffer) - bar_index) > l3cycleCLength + 1; + + // + if (isl3CycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + l3cycleCLength; i++) + { + // + double iHH = l3hhBuffer[i]; + double iLL = l3llBuffer[i]; + + // + if (l3hh < iHH) + { + isHighsestHighUp = false; + } + else if (l3hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (l3ll < iLL) + { + isLowestLowUp = false; + } + else if (l3ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + l3hhColorIDX = 2; + l3llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + l3hhColorIDX = 3; + l3llColorIDX = 3; + } + } + + // + if (showL3Trend) + { + // + l3hhColorBuffer[bar_index] = l3hhColorIDX; + l3llColorBuffer[bar_index] = l3llColorIDX; + } + + // + l3hhColorIDX = + l3hhColorIDX == 0 || l3hhColorIDX == 1 + ? 0 + : l3hhColorIDX - 1; + l3llColorIDX = + l3llColorIDX == 0 || l3llColorIDX == 1 + ? 0 + : l3llColorIDX - 1; + + // + l3HHStateBuffer[bar_index] = l3hhColorIDX; + l3LLStateBuffer[bar_index] = l3llColorIDX; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/Indicators/x-saherelm.xchnl.ex5 b/MQLTestWorkspace/Indicators/x-saherelm.xchnl.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..0ed21471b8a92df38f2012583cbb37927c4cef08 GIT binary patch literal 24258 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 KSCvDmf&YJkD)Y<$ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Indicators/x-saherelm.xchnl.mq5 b/MQLTestWorkspace/Indicators/x-saherelm.xchnl.mq5 new file mode 100644 index 0000000..c850540 --- /dev/null +++ b/MQLTestWorkspace/Indicators/x-saherelm.xchnl.mq5 @@ -0,0 +1,775 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121_XCHNL +// Description: XCHL Channel Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XCHNL Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121_XCHNL" + +// +// END Constants ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START XSCHULL Class Definition ... +// + +// +// END XSCHULL Class Definition ... +// + +// +// START Inputs ... +// + +// +input group "Makret Cycles"; +input int shortLength = 9; // Short Length +input int mediumLength = 17; // Medium Length +input int longLength = 26; // Long Length +input int hindLength = 35; // Hind Length + +// +input group "Trend"; +input int numOfShoulder = 10; // Number of Shoulders for Swings + +// +input group "Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; +input bool showTrend = false; // Show Trend +input bool showSRs = false; // Show Support and Resistance + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +// PEKSANDVALES ... + +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 0 + +#define sHHBufferIndex 0 +#define sLLBufferIndex 1 +#define mHHBufferIndex 2 +#define mLLBufferIndex 3 +#define lHHBufferIndex 4 +#define lLLBufferIndex 5 +#define hHHBufferIndex 6 +#define hLLBufferIndex 7 + +double sHHBuffer[]; +double sLLBuffer[]; +double mHHBuffer[]; +double mLLBuffer[]; +double lHHBuffer[]; +double lLLBuffer[]; +double hHHBuffer[]; +double hLLBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Make an Instance of Hull Class ... + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + RemoveDraws(drawPrefix); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // this counts Available Bars ... + int limit; + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + // + // Validate Peaks and Vales ... + (shortLength > 2 && + mediumLength > shortLength && + longLength > mediumLength && + hindLength > longLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax(shortLength, mediumLength); + result = MathMax(result, longLength); + result = MathMax(result, hindLength); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_CALCULATIONS); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate ... + + // + // SHORT ... + + // + // HIGH ... + int sHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + shortLength, + bar_index); + double sHHValue = GetAppliedPrice( + sHHIndex, + hhMode); + + // + sHHBuffer[bar_index] = sHHValue; + + // + // LOW ... + int sLLIndex = iLowest( + _Symbol, + _Period, + llMode, + shortLength, + bar_index); + double sLLValue = GetAppliedPrice( + sLLIndex, + llMode); + + // + sLLBuffer[bar_index] = sLLValue; + + // + // MEDIUM ... + + // + // HIGH ... + int mHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + mediumLength, + bar_index); + double mHHValue = GetAppliedPrice( + mHHIndex, + hhMode); + + // + mHHBuffer[bar_index] = mHHValue; + + // + // LOW ... + int mLLIndex = iLowest( + _Symbol, + _Period, + llMode, + mediumLength, + bar_index); + double mLLValue = GetAppliedPrice( + mLLIndex, + llMode); + + // + mLLBuffer[bar_index] = mLLValue; + + // + // LONG ... + + // + // HIGH ... + int lHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + longLength, + bar_index); + double lHHValue = GetAppliedPrice( + lHHIndex, + hhMode); + + // + lHHBuffer[bar_index] = lHHValue; + + // + // LOW ... + int lLLIndex = iLowest( + _Symbol, + _Period, + llMode, + longLength, + bar_index); + double lLLValue = GetAppliedPrice( + lLLIndex, + llMode); + + // + lLLBuffer[bar_index] = lLLValue; + + // + // HIND ... + + // + // HIGH ... + int hHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + hindLength, + bar_index); + double hHHValue = GetAppliedPrice( + hHHIndex, + hhMode); + + // + hHHBuffer[bar_index] = hHHValue; + + // + // LOW ... + int hLLIndex = iLowest( + _Symbol, + _Period, + llMode, + hindLength, + bar_index); + double hLLValue = GetAppliedPrice( + hLLIndex, + llMode); + + // + hLLBuffer[bar_index] = hLLValue; + + // + // Find Swings ... + + // + // High ... + int hSwing1 = FindSwing( + _Symbol, + _Period, + MODE_HIGH, + numOfShoulder, + bar_index + 1); + + int hSwing2 = FindSwing( + _Symbol, + _Period, + MODE_HIGH, + numOfShoulder, + hSwing1 + 1); + + // + // High ... + int hSwing3 = FindSwing( + _Symbol, + _Period, + MODE_HIGH, + numOfShoulder, + hSwing2 + 1); + + // int hSwing4 = FindSwing( + // _Symbol, + // _Period, + // MODE_HIGH, + // numOfShoulder, + // hSwing3 + 1); + + // + // Low ... + int lSwing1 = FindSwing( + _Symbol, + _Period, + MODE_LOW, + numOfShoulder, + bar_index + 1); + + int lSwing2 = FindSwing( + _Symbol, + _Period, + MODE_LOW, + numOfShoulder, + lSwing1 + 1); + + int lSwing3 = FindSwing( + _Symbol, + _Period, + MODE_LOW, + numOfShoulder, + lSwing2 + 1); + + // int lSwing4 = FindSwing( + // _Symbol, + // _Period, + // MODE_LOW, + // numOfShoulder, + // lSwing3 + 1); + + // + if (bar_index < 50) + { + + // + bool isStrongResistance = + // + hHHBuffer[bar_index + 1] == hHHBuffer[bar_index + 2] && + hHHBuffer[bar_index + 2] == hHHBuffer[bar_index + 3] && + // + lHHBuffer[bar_index + 1] == lHHBuffer[bar_index + 2] && + lHHBuffer[bar_index + 2] == lHHBuffer[bar_index + 3] && + // + mHHBuffer[bar_index + 1] == mHHBuffer[bar_index + 2] && + mHHBuffer[bar_index + 2] == mHHBuffer[bar_index + 3] && + // + sHHBuffer[bar_index + 1] == sHHBuffer[bar_index + 2] && + sHHBuffer[bar_index + 2] == sHHBuffer[bar_index + 3] + // + ; + + // + bool isStrongSupport = + // + hLLBuffer[bar_index + 1] == hLLBuffer[bar_index + 2] && + hLLBuffer[bar_index + 2] == hLLBuffer[bar_index + 3] && + // + lLLBuffer[bar_index + 1] == lLLBuffer[bar_index + 2] && + lLLBuffer[bar_index + 2] == lLLBuffer[bar_index + 3] && + // + mLLBuffer[bar_index + 1] == mLLBuffer[bar_index + 2] && + mLLBuffer[bar_index + 2] == mLLBuffer[bar_index + 3] && + // + sLLBuffer[bar_index + 1] == sLLBuffer[bar_index + 2] && + sLLBuffer[bar_index + 2] == sLLBuffer[bar_index + 3] + // + ; + + // + if (isStrongResistance && showSRs) + { + // + DrawSupportResistance( + "R", + clrRed, + sHHBuffer[bar_index + 3], + bar_index + 3); + } + + // + if (isStrongSupport && showSRs) + { + // + DrawSupportResistance( + "S", + clrGreen, + sLLBuffer[bar_index + 3], + bar_index + 3); + } + } + + // + if (showTrend && bar_index < 20) + { + // + DrawSwing( + "High1", + MODE_HIGH, + clrAqua, + hSwing1, + hSwing2); + + // + DrawSwing( + "Low1", + MODE_LOW, + clrAqua, + lSwing1, + lSwing2); + + // + DrawSwing( + "High2", + MODE_HIGH, + clrMagenta, + hSwing2, + hSwing3); + + // + DrawSwing( + "Low2", + MODE_LOW, + clrMagenta, + lSwing2, + lSwing3); + } +} + +// +void DrawSwing( + string prefix, // Prefix ... + ENUM_SERIESMODE mode, // Swing Mode ... + color swingColor, // Color ... + int index1, // Index 1 ... + int index2 // Index 2 ... +) +{ + // + if (mode != MODE_HIGH && mode != MODE_LOW) + { + return; + } + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + index1); + + // + datetime time1 = GetCandleTime( + _Symbol, + _Period, + index1); + + // + XOHCL c2 = GetCandle( + _Symbol, + _Period, + index2); + + // + datetime time2 = GetCandleTime( + _Symbol, + _Period, + index2); + + // + double value1 = -1; + double value2 = -1; + + // + switch (mode) + { + // + case MODE_HIGH: + value1 = c1.high; + value2 = c2.high; + break; + + // + case MODE_LOW: + value1 = c1.low; + value2 = c2.low; + break; + } + + // + if (value1 == -1 || value2 == -1) + { + return; + } + + // + long chartId = ChartID(); + string tlName = prefix + "_" + "TrendLine"; + + // // + // if (IsDrawExists(tlName)) { + // RemoveDraw(tlName); + // } + + // + DrawTrendLine( + chartId, + tlName, + 0, + time2, + value2, + time1, + value1, + swingColor, + STYLE_DOT, + 3, + false, + false, + true); +} + +// +// Draw Support and Resistance ... +void DrawSupportResistance( + string prefix, // Prefix ... + color lColor, // Color ... + double price, // Support or Resistance price ... + int bar_index // Start Bar Index ... +) +{ + // + datetime time1 = GetCandleTime( + _Symbol, + _Period, + bar_index); + + // + datetime time2 = GetCandleTime( + _Symbol, + _Period, + bar_index - 1); + + // + long chartId = ChartID(); + string tlName = prefix + "_" + "TL" + "_" + (string)(NormalizePrice(price, _Symbol)); + + // + DrawTrendLine( + chartId, + tlName, + 0, + time1, + price, + time2, + price, + lColor, + STYLE_DOT, + 3, + false, + false, + true); +} diff --git a/MQLTestWorkspace/Libraries/x-saherelm.alert.lib.ex5 b/MQLTestWorkspace/Libraries/x-saherelm.alert.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..0c761ae5d836c69664566761c908c915b0715643 GIT binary patch literal 6372 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 Y5HRq>(wr4DMk@!1{5o^s_F9kqFXbyC(EtDd literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Libraries/x-saherelm.alert.lib.mq5 b/MQLTestWorkspace/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 0000000..429d830 --- /dev/null +++ b/MQLTestWorkspace/Libraries/x-saherelm.alert.lib.mq5 @@ -0,0 +1,187 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Alert Library +// -------------------------------------- +// Name: XAlert +// Description: provides Alerts abilities ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Inputs ... +// +input group "Alerts"; +input bool enableAlerts = true; // Enable Alerts +input bool logAlerts = true; // Log Alerts +input bool terminalAlerts = false; // Terminal Alerts +input bool mailAlerts = false; // Mail Alerts +input bool pushAlerts = false; // Push Alerts +// +// END Inputs ... +// + +// +#include "x-saherelm.log.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// +string alertPrefix = "X-Alert"; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Initial Library if required ... +bool OnInInitAlertLibrary() +{ + return false; +} + +// +// DeInitial Library if required ... +void OnDeinitAlertLibrary() +{ +} + +// +// Attach Alert Prefix to Message ... +string PrepareAlertMessage(string message) +{ + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, alertPrefix, " > ", message); + + // + return message; +} + +// +// Logging an Alert ... +void LogAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !logAlerts) + { + return; + } + + // + LogMessage(alertPrefix, message); +} + +// +// Terminal Alert ... +void TerminalAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !terminalAlerts) + { + return; + } + + // + // Prepare Message ... + message = PrepareAlertMessage(message); + + // Send Terminal Alert ... + Alert(message); +} + +// +// Mail Alert ... +void MailAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !mailAlerts) + { + return; + } + + // + // Send Mail Alert ... + SendMail(alertPrefix, message); +} + +// +// Send Push Notification ... +void PushAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !pushAlerts) + { + return; + } + + // + // Prepare Message ... + message = PrepareAlertMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); +} + +// +// Alert Sending ... +void SendAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts) + { + return; + } + + // + // Log ... + if (logAlerts) + { + LogAlert(message); + } + + // + // Terminal ... + if (terminalAlerts) + { + TerminalAlert(message); + } + + // + // Mail ... + if (mailAlerts) + { + MailAlert(message); + } + + // + // Push ... + if (pushAlerts) + { + PushAlert(message); + } +} +// +// END Provided Functions ... +// diff --git a/MQLTestWorkspace/Libraries/x-saherelm.common.lib.ex5 b/MQLTestWorkspace/Libraries/x-saherelm.common.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..b41cad31a5b92405cd78dc7d771b34447c4b0530 GIT binary patch literal 5616 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Libraries/x-saherelm.common.lib.mq5 b/MQLTestWorkspace/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..f9b09b3 --- /dev/null +++ b/MQLTestWorkspace/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,5193 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommon +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Inputs ... +// + +// +// END Inputs ... +// + +// +// Include Models Library ... +#include "x-saherelm.models.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// Detect is new Candle or not ... +bool IsNewCandle() +{ + // + bool result = false; + + // + static int barsOnChart = 0; + int currentBarsOnChart = Bars(_Symbol, _Period); + result = currentBarsOnChart > barsOnChart; + if (!result) + { + return result; + } + + // + barsOnChart = currentBarsOnChart; + result = true; + + // + return result; +} +bool IsNewCandle( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod // Trading Time Frame ... +) +{ + // + bool result = false; + + // + static string mChartTags[]; + static int mChartBars[]; + + // + string chTag = mSymbol + "," + ToString(mPeriod); + + // + int currChTagIdx = -1; + int chCountedBars = 0; + int currentBars = Bars(mSymbol, mPeriod); + + // + if (ArraySize(mChartTags) > 0) + { + // + for (int i = 0; i < ArraySize(mChartTags); i++) + { + // + string iTag = mChartTags[i]; + if (iTag != chTag) + { + continue; + } + + // + currChTagIdx = i; + break; + } + + // + if (currChTagIdx > -1) + { + chCountedBars = mChartBars[currChTagIdx]; + } + } + + // + result = currentBars > chCountedBars; + if (result) + { + // + if (currChTagIdx > -1) + { + // + mChartTags[currChTagIdx] = chTag; + mChartBars[currChTagIdx] = currentBars; + } + else + { + // + Add(chTag, mChartTags); + Add(currentBars, mChartBars); + } + } + + // + return result; +} + +// +double XNZ(double check, double val = 0) +{ + if (check == EMPTY_VALUE || check == 0) + { + return val; + } + else + { + return check; + } +} + +// +// Retrive Ask Price ... +double GetAsk() +{ + return SymbolInfoDouble(_Symbol, SYMBOL_ASK); +} +double GetAsk( + string symbol // selected symbol for calculations +) +{ + // + double result = SymbolInfoDouble(symbol, SYMBOL_ASK); + + // + return result; +} + +// +// Retrieve Bid Price ... +double GetBid() +{ + return SymbolInfoDouble(_Symbol, SYMBOL_BID); +} +double GetBid( + string symbol // selected symbol for calculations +) +{ + // + double result = SymbolInfoDouble(symbol, SYMBOL_BID); + + // + return result; +} + +// +// Calculate and Retrieve Spread Price ... +double GetSpread() +{ + // + double ask = GetAsk(); + double bid = GetBid(); + double result = MathAbs(ask - bid); + + // + return result; +} +double GetSpread( + string symbol // selected symbol for calculations +) +{ + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + double result = MathAbs(ask - bid); + + // + return result; +} + +// +// Get Points ... +double GetPoints() +{ + return _Point; +} +double GetPoints( + string symbol // selected symbol for calculations +) +{ + // + double result = SymbolInfoDouble(symbol, SYMBOL_POINT); + + // + return result; +} + +// +// Get Digits ... +int GetDigits() +{ + return _Digits; +} +int GetDigits( + string symbol // selected symbol for calculations +) +{ + // + int result = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); + + // + return result; +} + +// +// Get Signal Entry ... +double GetEntry( + ENUM_POSITION_TYPE type // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == NULL) + { + return result; + } + + // + bool isLong = type == POSITION_TYPE_BUY; + result = isLong ? GetAsk() : GetBid(); + result = NormalizePrice(result); + + // + return result; +} +double GetEntry( + string symbol, // Specified Symbol + ENUM_POSITION_TYPE type // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + bool isLong = type == POSITION_TYPE_BUY; + result = isLong ? GetAsk(symbol) : GetBid(symbol); + result = NormalizePrice(result, symbol); + + // + return result; +} + +// +// Get Signal Exit ... +double GetExit( + ENUM_POSITION_TYPE type // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == NULL) + { + return result; + } + + // + bool isLong = type == POSITION_TYPE_BUY; + result = isLong ? GetBid() : GetAsk(); + result = NormalizePrice(result); + + // + return result; +} +double GetExit( + string symbol, // Specified Symbol + ENUM_POSITION_TYPE type // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == NULL) + { + return result; + } + + // + bool isLong = type == POSITION_TYPE_BUY; + result = isLong ? GetBid(symbol) : GetAsk(symbol); + result = NormalizePrice(result, symbol); + + // + return result; +} + +// +// Determine a Position type is Long or not ... +bool IsLong(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_BUY; + + // + return result; +} +bool IsLong(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_BUY; + + // + return result; +} + +// +// Determine a Position type is Short or not ... +bool IsShort(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_SELL; + + // + return result; +} +bool IsShort(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_SELL; + + // + return result; +} + +// +// Get 1 Pip in Price Value ... +double GetPipPrice() +{ + // + double result = _Point; + if (_Digits == 3 || _Digits == 5) + { + result *= 10; + } + + // + return result; +} +double GetPipPrice( + string symbol // selected symbol for calculations +) +{ + // + double symbolPoint = GetPoints(symbol); + int symbolDigits = GetDigits(symbol); + + // + double result = symbolPoint; + if (symbolDigits == 3 || symbolDigits == 5) + { + result *= 10; + } + + // + return result; +} + +// +// Converts Pips To Price ... +double PipsToPrice( + int pips // pips amount +) +{ + // + int digits = GetDigits(); + double pipValue = GetPipPrice(); + double result = pips * pipValue; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} +double PipsToPrice( + double pips // pips amount +) +{ + // + int digits = GetDigits(); + double pipValue = GetPipPrice(); + double result = pips * pipValue; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} +double PipsToPrice( + string symbol, // selected symbol for calculation + int pips // pips amount +) +{ + // + int digits = GetDigits(symbol); + double pipValue = GetPipPrice(symbol); + double result = pips * pipValue; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} +double PipsToPrice( + string symbol, // selected symbol for calculation + double pips // pips amount +) +{ + // + int digits = GetDigits(symbol); + double pipValue = GetPipPrice(symbol); + double result = pips * pipValue; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Converts Price to Pips ... +double PriceToPips( + double price // the price amount which required to calculate +) +{ + // + int digits = GetDigits(); + double pipPrice = GetPipPrice(); + + // + double result = price / pipPrice; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} +double PriceToPips( + string symbol, // Selected Symbol + double price // the price amount which required to calculate +) +{ + // + int digits = GetDigits(symbol); + double pipPrice = GetPipPrice(symbol); + + // + double result = price / pipPrice; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Convert Price to Point ... +double PriceToPoint( + double price // the price amount which required to calculate +) +{ + return PriceToPoint(_Symbol, price); +} +double PriceToPoint( + string symbol, // Selected Symbol + double price // the price amount which required to calculate +) +{ + // + double result = 0; + + // + double point = GetPoints(symbol); + result = price / point; + + // + return result; +} + +// +// Converts Point to Price ... +double PointToPrice( + double points // Points Size +) +{ + return PointToPrice(_Symbol, points); +} +double PointToPrice( + string symbol, // Selected Symbol + double points // Points Size +) +{ + // + double result = 0; + + // + double point = GetPoints(symbol); + result = points * point; + + // + return result; +} + +// +// Get a Candle Body ... +double GetCandleBody( + XOHCL &candle // specified candle +) +{ + // + double result = MathAbs(candle.open - candle.close); + + // + return result; +} + +// +// Get a Candle Range ... +double GetCandleRange( + XOHCL &candle // specified candle +) +{ + // + double result = MathAbs(candle.high - candle.low); + + // + return result; +} + +// +// Get a Candle Shadow ... +double GetCandleShadow( + XOHCL &candle // specified candle +) +{ + // + double range = GetCandleRange(candle); + double body = GetCandleBody(candle); + + // + double result = MathAbs(range - body); + + // + return result; +} + +// +// Check a Candle is Base Candle for RTM or not ... +bool IsBaseCandle( + XOHCL &candle // specified candle +) +{ + // + double range = GetCandleRange(candle); + double body = GetCandleBody(candle); + + // + bool result = body > range; + + // + return result; +} + +// +// Retrieve Applied Price at Specific Candle ... +double GetAppliedPrice( + XOHCL &candle, // specified candle + ENUM_APPLIED_PRICE source = PRICE_CLOSE // specified Applied To +) +{ + // + double result = EMPTY_VALUE; + + // + switch (source) + { + // + // Open ... + case PRICE_OPEN: + result = candle.open; + break; + + // + // High ... + case PRICE_HIGH: + result = candle.high; + break; + + // + // Low ... + case PRICE_LOW: + result = candle.low; + break; + + // + // Median ((High + Low) / 2) ... + case PRICE_MEDIAN: + result = (candle.high + candle.low) / 2; + break; + + // + // Typical ((High + Low + Close)/3) ... + case PRICE_TYPICAL: + result = (candle.high + candle.low + candle.close) / 3; + break; + + // + // Weighted ((High + Low + Close + Close)/4) ... + case PRICE_WEIGHTED: + result = (candle.high + candle.low + (candle.close * 2)) / 4; + break; + + // + // Close ... + default: + case PRICE_CLOSE: + result = candle.close; + break; + } + + // + return result; +} +double GetAppliedPrice( + int bar_index, // specify candle index + ENUM_APPLIED_PRICE source = PRICE_CLOSE // specified Applied To +) +{ + // + double result = EMPTY_VALUE; + + // + XOHCL candle = GetCandle(bar_index); + result = GetAppliedPrice(candle, source); + + // + return result; +} +double GetAppliedPrice( + int bar_index, // specify candle index + ENUM_SERIESMODE mode // converts Series Mode to Applied Price ... +) +{ + // + double result = 0; + + // + ENUM_APPLIED_PRICE mAppliedTo = To(mode); + result = GetAppliedPrice( + bar_index, + mAppliedTo); + + // + return result; +} + +// +// Converts ... +ENUM_APPLIED_PRICE To( + ENUM_SERIESMODE mode // converts Series Mode to Applied Price ... +) +{ + // + ENUM_APPLIED_PRICE result = PRICE_CLOSE; + + // + switch (mode) + { + // + // High ... + case MODE_HIGH: + result = PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = PRICE_CLOSE; + break; + } + + // + return result; +} + +// +// Retrieve a Candel Data ... +XOHCL GetCandle(int bar_index) +{ + // + XOHCL result = {}; + + // + double open = iOpen(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + double close = iClose(_Symbol, _Period, bar_index); + double low = iLow(_Symbol, _Period, bar_index); + + // + result.low = low; + result.open = open; + result.high = high; + result.close = close; + + // + return result; +} +XOHCL GetCandle( + ENUM_TIMEFRAMES mPeriod, // specify timeframe + int bar_index // specify candle index +) +{ + // + XOHCL result = {}; + + // + double open = iOpen(_Symbol, mPeriod, bar_index); + double high = iHigh(_Symbol, mPeriod, bar_index); + double close = iClose(_Symbol, mPeriod, bar_index); + double low = iLow(_Symbol, mPeriod, bar_index); + + // + result.low = low; + result.open = open; + result.high = high; + result.close = close; + + // + return result; +} +XOHCL GetCandle( + string symbol, // specify symbol + ENUM_TIMEFRAMES mPeriod, // specify timeframe + int bar_index // specify candle index +) +{ + // + XOHCL result = {}; + + // + double open = iOpen(symbol, mPeriod, bar_index); + double high = iHigh(symbol, mPeriod, bar_index); + double close = iClose(symbol, mPeriod, bar_index); + double low = iLow(symbol, mPeriod, bar_index); + + // + result.low = low; + result.open = open; + result.high = high; + result.close = close; + + // + return result; +} + +// +// Retrieve a candle index in current timeframe inside another timeframe ... +int GetCandleBarIndex( + int bar_index, // Specify Candle index in current timeframe + ENUM_TIMEFRAMES destPeriod // Specify destination timeframe +) +{ + // + int result = -1; + + // + datetime barTime = iTime(_Symbol, _Period, bar_index); + result = iBarShift(_Symbol, destPeriod, barTime); + + // + return result; +} + +// +// Retrieve a symbol candle index in source time frame inside dest timeframe ... +int GetCandleBarIndex( + int bar_index, // Specify Candle index in current timeframe + string symbol, // Specify desired Symbol + ENUM_TIMEFRAMES sourcePeriod, // Specify bar_index timeframe + ENUM_TIMEFRAMES destPeriod // Specify destination timeframe +) +{ + // + int result = -1; + + // + datetime barTime = iTime(symbol, sourcePeriod, bar_index); + result = iBarShift(symbol, destPeriod, barTime); + + // + return result; +} + +// +// Check a Candle is Bullish or not ... +bool IsBullishCandle( + XOHCL &candle // specified candle +) +{ + // + bool result = false; + + // + result = candle.open < candle.close; + + // + return result; +} +bool IsBullishCandle( + int bar_index // candle index +) +{ + // + bool result = false; + + // + XOHCL candle = GetCandle(bar_index); + + // + result = IsBullishCandle(candle); + + // + return result; +} +bool IsBullishCandle( + string symbol, // specify symbol + ENUM_TIMEFRAMES mPeriod, // specify timeframe + int bar_index // candle index +) +{ + // + bool result = false; + + // + XOHCL candle = GetCandle( + symbol, + mPeriod, + bar_index); + + // + result = IsBullishCandle(candle); + + // + return result; +} + +// +// Check a Candle is Bullish or not ... +bool IsBearishCandle( + XOHCL &candle // specified candle +) +{ + // + bool result = false; + + // + result = candle.open > candle.close; + + // + return result; +} +bool IsBearishCandle( + int bar_index // candle index +) +{ + // + bool result = false; + + // + XOHCL candle = GetCandle(bar_index); + + // + result = IsBearishCandle(candle); + + // + return result; +} +bool IsBearishCandle( + string symbol, // specify symbol + ENUM_TIMEFRAMES mPeriod, // specify timeframe + int bar_index // candle index +) +{ + // + bool result = false; + + // + XOHCL candle = GetCandle( + symbol, + mPeriod, + bar_index); + + // + result = IsBearishCandle(candle); + + // + return result; +} + +// +// Check Candle Body Bigger Than it's Shadow ... +bool CandleHasStrongBody(XOHCL &candle) +{ + // + double bodySize = MathAbs(candle.open - candle.close); + double shadowSize = MathAbs(candle.high - candle.low) - bodySize; + + // + bool result = bodySize > (shadowSize * 1.5); + + // + return result; +} + +// +// Determines a cnadle is Swing High +// or Swing Low order block ... +ENUM_X_SWING_TYPE GetCandleSwing(int bar_index) +{ + // + ENUM_X_SWING_TYPE result = X_NO_SWING; + + // + // Reading Candle Models ... + XOHCL candles[3]; + candles[0] = GetCandle(bar_index + 1); + candles[1] = GetCandle(bar_index + 2); + candles[2] = GetCandle(bar_index + 3); + + // + // Check Swing Start Candle has Strong Body ... + bool isStrongBodyCandle = CandleHasStrongBody(candles[2]); + if (!isStrongBodyCandle) + { + return result; + } + + // + // Check Swing Low Conditions ... + bool isSwingLowOrderBlock = + candles[2].low < candles[1].low && + candles[1].low < candles[0].low && + candles[2].low < candles[0].low; + if (isSwingLowOrderBlock) + { + result = X_SWING_LOW; + } + + // + // Check Swing High Conditions ... + bool isSwingHighOrderBlock = + candles[2].high > candles[1].high && + candles[1].high > candles[0].high && + candles[2].high > candles[0].high; + if (isSwingHighOrderBlock) + { + result = X_SWING_HIGH; + } + + // + return result; +} +ENUM_X_SWING_TYPE GetCandleSwing( + ENUM_TIMEFRAMES mPeriod, // specify timeframe + int bar_index // specify candle index +) +{ + // + ENUM_X_SWING_TYPE result = X_NO_SWING; + + // + // Reading Candle Models ... + XOHCL candles[3]; + candles[0] = GetCandle(mPeriod, bar_index + 1); + candles[1] = GetCandle(mPeriod, bar_index + 2); + candles[2] = GetCandle(mPeriod, bar_index + 3); + + // + // Check Swing Start Candle has Strong Body ... + bool isStrongBodyCandle = CandleHasStrongBody(candles[2]); + if (!isStrongBodyCandle) + { + return result; + } + + // + // Check Swing Low Conditions ... + bool isSwingLowOrderBlock = + candles[2].low < candles[1].low && + candles[1].low < candles[0].low && + candles[2].low < candles[0].low; + if (isSwingLowOrderBlock) + { + result = X_SWING_LOW; + } + + // + // Check Swing High Conditions ... + bool isSwingHighOrderBlock = + candles[2].high > candles[1].high && + candles[1].high > candles[0].high && + candles[2].high > candles[0].high; + if (isSwingHighOrderBlock) + { + result = X_SWING_HIGH; + } + + // + return result; +} +ENUM_X_SWING_TYPE GetCandleSwing( + string symbol, // specify symbol + ENUM_TIMEFRAMES mPeriod, // specify timeframe + int bar_index // specify candle index +) +{ + // + ENUM_X_SWING_TYPE result = X_NO_SWING; + + // + // Reading Candle Models ... + XOHCL candles[3]; + candles[0] = GetCandle(symbol, mPeriod, bar_index + 1); + candles[1] = GetCandle(symbol, mPeriod, bar_index + 2); + candles[2] = GetCandle(symbol, mPeriod, bar_index + 3); + + // + // Check Swing Start Candle has Strong Body ... + bool isStrongBodyCandle = CandleHasStrongBody(candles[2]); + if (!isStrongBodyCandle) + { + return result; + } + + // + // Check Swing Low Conditions ... + bool isSwingLowOrderBlock = + candles[2].low < candles[1].low && + candles[1].low < candles[0].low && + candles[2].low < candles[0].low; + if (isSwingLowOrderBlock) + { + result = X_SWING_LOW; + } + + // + // Check Swing High Conditions ... + bool isSwingHighOrderBlock = + candles[2].high > candles[1].high && + candles[1].high > candles[0].high && + candles[2].high > candles[0].high; + if (isSwingHighOrderBlock) + { + result = X_SWING_HIGH; + } + + // + return result; +} + +// +// Find Swing Points ... +int FindSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_SERIESMODE mode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (StringLen(mSymbol) == 0 || (mode != MODE_HIGH && mode != MODE_LOW)) + { + return result; + } + + // + int current = bar_index; + int founded = FindNextSwing( + mSymbol, + mPeriod, + mode, + (mLength * 2) + 1, + current - mLength); + + // + while (founded != current) + { + // + current = FindNextSwing( + mSymbol, + mPeriod, + mode, + mLength, + current + 1); + + // + founded = FindNextSwing( + mSymbol, + mPeriod, + mode, + (mLength * 2) + 1, + current - mLength); + } + + // + result = current; + + // + return result; +} + +// +// Find Next Swing ... +int FindNextSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_SERIESMODE mode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (bar_index < 0) + { + mLength += bar_index; + bar_index = 0; + } + + // + result = mode == MODE_HIGH + ? iHighest( + mSymbol, + mPeriod, + mode, + mLength, + bar_index) + : iLowest( + mSymbol, + mPeriod, + mode, + mLength, + bar_index); + + // + return result; +} + +// +// Retrieve Market Highest High ... +double GetHighestHigh( + int mLength, // Which market Length use + int bar_index // bar index +) +{ + // + double result = -1; + + // + int rIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + mLength, + bar_index); + + // + result = iHigh( + _Symbol, + _Period, + rIdx); + + // + return result; +} +double GetHighestHigh( + int mLength, // Which market Length use + int bar_index, // bar index + ENUM_SERIESMODE mode // Calculation mode +) +{ + // + double result = -1; + + // + int rIdx = iHighest( + _Symbol, + _Period, + mode, + mLength, + bar_index); + + // + result = iHigh( + _Symbol, + _Period, + rIdx); + + // + return result; +} +double GetHighestHigh( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES mPeriod, // Specified Period + int mLength, // Which market Length use + int bar_index // bar index +) +{ + // + double result = -1; + + // + int rIdx = iHighest( + symbol, + mPeriod, + MODE_HIGH, + mLength, + bar_index); + + // + result = iHigh( + symbol, + mPeriod, + rIdx); + + // + return result; +} +double GetHighestHigh( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES mPeriod, // Specified Period + ENUM_SERIESMODE mode, // Calculation mode + int mLength, // Which market Length use + int bar_index // bar index +) +{ + // + double result = -1; + + // + int rIdx = iHighest( + symbol, + mPeriod, + mode, + mLength, + bar_index); + + // + result = iHigh( + symbol, + mPeriod, + rIdx); + + // + return result; +} + +// +// Retrieve Market Lowest Low ... +double GetLowestLow( + int mLength, // Which market Length use + int bar_index // bar index +) +{ + // + double result = -1; + + // + int rIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + mLength, + bar_index); + + // + result = iLow( + _Symbol, + _Period, + rIdx); + + // + return result; +} +double GetLowestLow( + int mLength, // Which market Length use + int bar_index, // bar index + ENUM_SERIESMODE mode // Calculation mode +) +{ + // + double result = -1; + + // + int rIdx = iLowest( + _Symbol, + _Period, + mode, + mLength, + bar_index); + + // + result = iLow( + _Symbol, + _Period, + rIdx); + + // + return result; +} +double GetLowestLow( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES mPeriod, // Specified Period + int mLength, // Which market Length use + int bar_index // bar index +) +{ + // + double result = -1; + + // + int rIdx = iLowest( + symbol, + mPeriod, + MODE_LOW, + mLength, + bar_index); + + // + result = iLow( + symbol, + mPeriod, + rIdx); + + // + return result; +} +double GetLowestLow( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES mPeriod, // Specified Period + ENUM_SERIESMODE mode, // Calculation mode + int mLength, // Which market Length use + int bar_index // bar index +) +{ + // + double result = -1; + + // + int rIdx = iLowest( + symbol, + mPeriod, + mode, + mLength, + bar_index); + + // + result = iLow( + symbol, + mPeriod, + rIdx); + + // + return result; +} + +// +// Find Support and Resistance for Specific Bar based on provided Buffer ... +XOHCLSupRes ExtractSupportAndResistance( + int barIndex, // Bar Index ... + const double &pivots[], // Provided Pivot Points ... + int count = 3, // Number of Requireds ... + string mSymbol = NULL, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period ... +) +{ + // + if (StringLen(mSymbol) == 0 || mSymbol == NULL) + { + mSymbol = _Symbol; + } + + // + if (mPeriod == NULL) + { + mPeriod = _Period; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + XOHCLSupRes result; + Clean(result.res); + Clean(result.sup); + + // + int pivotsCount = ArraySize(pivots); + if (pivotsCount <= 0) + { + return result; + } + + // + if (count <= 0 || + count > pivotsCount - 1) + { + return result; + } + + // + XOHCL cBar = GetCandle( + mSymbol, + mPeriod, + barIndex); + + // + double tmpR[]; + + // + double tmpS[]; + + // + // Extract Supports ... + // which prices is under low of candle ... + // + // Extract Resistance ... + // which prices is over high of candle ... + for (int i = 0; i < pivotsCount; i++) + { + // + double iFlat = pivots[i]; + + // + if (iFlat > cBar.high) + { + Add( + iFlat, + tmpR); + } + else if (iFlat < cBar.low) + { + Add( + iFlat, + tmpS); + } + } + + // + // Sorting Founded Resistance and Supports ... + + // + // Since Resistance Levels must be Increasing ... + ArraySort(tmpR); + + // + // Since Support Levels must be Decreasing ... + ArraySort(tmpS); + ArrayReverse(tmpS); + + // + // Fill Resistance ... + int tmpRCount = ArraySize(tmpR); + if (tmpRCount > 0) + { + // + if (tmpRCount < count) + { + // + ArrayCopy( + result.res, + tmpR); + } + else + { + // + ArrayCopy( + result.res, + tmpR, + 0, + 0, + count); + } + } + + // + // Fill Supports ... + int tmpSCount = ArraySize(tmpS); + if (tmpSCount > 0) + { + // + if (tmpSCount < count) + { + // + ArrayCopy( + result.sup, + tmpS); + } + else + { + // + ArrayCopy( + result.sup, + tmpS, + 0, + 0, + count); + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +double FindLesserThanValue( + double value, // Specified Value ... + const double &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + double result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + double tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + double iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +double FindBiggerThanValue( + double value, // Specified Value ... + const double &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + double result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + double tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + double iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Calculate Fib Level ... +double GetFibonacciLevel( + double upPrice, + double downPrice, + double level, + int direction) +{ + // + double ling = upPrice - downPrice; + double pLevel = (ling / 100) * (level * 100); + + // + double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; + result = NormalizeDouble(result, _Digits); + + // + return result; +} + +// +// Check first Cross Over second at bar_index ... +bool IsCrossOver( + const double &first[], // the buffer which check crossing over second buffer + const double &second[], // first buffer checks based on this buffer + const int bar_index // check crosses in specific index +) +{ + // + bool result = false; + + // + ArraySetAsSeries(first, true); + ArraySetAsSeries(second, true); + + // + // Validate Args ... + if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1) + { + return result; + } + + // + result = first[bar_index] > second[bar_index] && + !(first[bar_index + 1] > second[bar_index + 1]); + + // + return result; +} + +// +// Check first is Over second at bar_index ... +bool IsOver( + const double &first[], // the buffer which check over second buffer + const double &second[], // first buffer checks based on this buffer + const int bar_index // check crosses in specific index +) +{ + // + bool result = false; + + // + ArraySetAsSeries(first, true); + ArraySetAsSeries(second, true); + + // + // Validate Args ... + if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1) + { + return result; + } + + // + result = first[bar_index] > second[bar_index] && + first[bar_index + 1] > second[bar_index + 1]; + + // + return result; +} + +// +// Check first Cross Under second at bar_index ... +bool IsCrossUnder( + const double &first[], // the buffer which check crossing under second buffer + const double &second[], // first buffer checks based on this buffer + const int bar_index // check crosses in specific index +) +{ + // + bool result = false; + + // + ArraySetAsSeries(first, true); + ArraySetAsSeries(second, true); + + // + // Validate Args ... + if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1) + { + return result; + } + + // + result = first[bar_index] < second[bar_index] && + !(first[bar_index + 1] < second[bar_index + 1]); + + // + return result; +} + +// +// Check first is Under second at bar_index ... +bool IsUnder( + const double &first[], // the buffer which check under second buffer + const double &second[], // first buffer checks based on this buffer + const int bar_index // check crosses in specific index +) +{ + // + bool result = false; + + // + ArraySetAsSeries(first, true); + ArraySetAsSeries(second, true); + + // + // Validate Args ... + if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1) + { + return result; + } + + // + result = first[bar_index] < second[bar_index] && + first[bar_index + 1] < second[bar_index + 1]; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + int from, // In Past Index ... + int to, // In Past Index ... + double &buffer[]) +{ + // + double result = 0; + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// Check if a Value Increasing in Loopback ... +bool IsIncreasing( + int from, // Last Time Index + int to, // Fisr Tima Index + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue > fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + int from, // Last Time Index + int to, // Fisr Tima Index + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue < fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Get Max Value of Specific Loopback of a Buffer ... +double GetMaxValue( + int mLoopback, // loopback length + double &buffer[] // the Buffer which required to search +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + mLoopback < 2 || + ArraySize(buffer) < mLoopback) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < mLoopback; i++) + { + // + double iValue = buffer[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} + +// +// Get Min Value of Specific Loopback of a Buffer ... +double GetMinValue( + int mLoopback, // loopback length + double &buffer[] // the Buffer which required to search +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + mLoopback < 2 || + ArraySize(buffer) < mLoopback) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < mLoopback; i++) + { + // + double iValue = buffer[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} + +// +// Find Same Values in Array ... +void FindSameValueInBuffer( + double &result[], // Holds Result ... + double &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + double mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + double iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +bool IsInPeak( + int mLoopback, // loopback length + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + mLoopback < 2 || + ArraySize(buffer) < mLoopback + 1) + { + return result; + } + + // + int q1Length = mLoopback / 4; + int halfLength = mLoopback / 2; + int q2Length = halfLength + q1Length; + + // + double firstValue = buffer[1]; + double q1Value = buffer[q1Length]; + double q2Value = buffer[q2Length]; + double halfValue = buffer[halfLength]; + double lastValue = buffer[ArraySize(buffer) - 1]; + + // + // Peak ... + result = + // + firstValue > lastValue + // + && + // + ( + firstValue > q1Value && + firstValue > halfValue) + // + ; + + // + return result; +} + +// +bool IsInVale( + int mLoopback, // loopback length + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + mLoopback < 2 || + ArraySize(buffer) < mLoopback + 1) + { + return result; + } + + // + int q1Length = mLoopback / 4; + int halfLength = mLoopback / 2; + int q2Length = halfLength + q1Length; + + // + double firstValue = buffer[1]; + double q1Value = buffer[q1Length]; + double q2Value = buffer[q2Length]; + double halfValue = buffer[halfLength]; + double lastValue = buffer[ArraySize(buffer) - 1]; + + // + // Peak ... + result = + // + firstValue < lastValue + // + && + // + ( + firstValue < q1Value && + firstValue < halfValue) + // + ; + + // + return result; +} + +// +// Check Sharp Happens or not ... +bool IsSharpChanged( + double fromValue, // Past Value + double toValue, // Present Value + double maxValue, // Max in Range Value + double minValue // Min in Range Value +) +{ + // + bool result = false; + + // + // This Used In Increased or Decreased Sharp Detection ... + bool isIncreased = toValue > fromValue; + + // + double toFromDelta = MathAbs(toValue - fromValue); + double minMaxDelta = maxValue - minValue; + + // + result = toFromDelta >= (minMaxDelta / 3); + + // + return result; +} +bool IsSharpChanged( + int from, // Past Index in Series + int to, // Present Index in Series + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + + // + // This Used In Increased or Decreased Sharp Detection ... + bool isIncreased = toValue > fromValue; + + // + double minValue = GetMinValue( + ArraySize(buffer) - 1, + buffer); + double maxValue = GetMaxValue( + ArraySize(buffer) - 1, + buffer); + double minMaxDelta = maxValue - minValue; + + // + // Sharp Detection ... + result = IsSharpChanged( + fromValue, + toValue, + maxValue, + minValue); + + // + return result; +} +bool IsSharpChanged( + int from, // Past Bar Index + int to, // Present Bar Index + ENUM_APPLIED_PRICE appliedPrice // Which Price Choose in From or To +) +{ + // + bool result = false; + + // + double toValue = GetAppliedPrice( + to, + appliedPrice); + double fromValue = GetAppliedPrice( + from, + appliedPrice); + + // + int hIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + from, + to); + double maxValue = iHigh( + _Symbol, + _Period, + hIdx); + + // + int lIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + from, + to); + double minValue = iLow( + _Symbol, + _Period, + lIdx); + + // + result = IsSharpChanged( + fromValue, + toValue, + maxValue, + minValue); + + // + return result; +} + +// +// Check InCreased Sharp Happens or not ... +bool IsSharpIncreasedChanged( + double fromValue, // Past Value + double toValue, // Present Value + double maxValue, // Max in Range Value + double minValue // Min in Range Value +) +{ + // + bool result = false; + + // + // This Used In Increased or Decreased Sharp Detection ... + bool isIncreased = toValue > fromValue; + + // + double toFromDelta = MathAbs(toValue - fromValue); + double minMaxDelta = maxValue - minValue; + + // + result = + isIncreased && + toFromDelta >= (minMaxDelta / 3); + + // + return result; +} +bool IsSharpIncreasedChanged( + int from, // Past Index in Series + int to, // Present Index in Series + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + + // + double minValue = GetMinValue( + ArraySize(buffer) - 1, + buffer); + double maxValue = GetMaxValue( + ArraySize(buffer) - 1, + buffer); + double minMaxDelta = maxValue - minValue; + + // + // Sharp Detection ... + result = IsSharpIncreasedChanged( + fromValue, + toValue, + maxValue, + minValue); + + // + return result; +} +bool IsSharpIncreasedChanged( + int from, // Past Bar Index + int to, // Present Bar Index + ENUM_APPLIED_PRICE appliedPrice // Which Price Choose in From or To +) +{ + // + bool result = false; + + // + double toValue = GetAppliedPrice( + to, + appliedPrice); + double fromValue = GetAppliedPrice( + from, + appliedPrice); + + // + int hIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + from, + to); + double maxValue = iHigh( + _Symbol, + _Period, + hIdx); + + // + int lIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + from, + to); + double minValue = iLow( + _Symbol, + _Period, + lIdx); + + // + result = IsSharpIncreasedChanged( + fromValue, + toValue, + maxValue, + minValue); + + // + return result; +} + +// +// Check Decreased Sharp Happens or not ... +bool IsSharpDecreasedChanged( + double fromValue, // Past Value + double toValue, // Present Value + double maxValue, // Max in Range Value + double minValue // Min in Range Value +) +{ + // + bool result = false; + + // + // This Used In Increased or Decreased Sharp Detection ... + bool isIncreased = toValue > fromValue; + + // + double toFromDelta = MathAbs(toValue - fromValue); + double minMaxDelta = maxValue - minValue; + + // + result = + !isIncreased && + toFromDelta >= (minMaxDelta / 3); + + // + return result; +} +bool IsSharpDecreasedChanged( + int from, // Past Index in Series + int to, // Present Index in Series + double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + + // + double minValue = GetMinValue( + ArraySize(buffer) - 1, + buffer); + double maxValue = GetMaxValue( + ArraySize(buffer) - 1, + buffer); + double minMaxDelta = maxValue - minValue; + + // + // Sharp Detection ... + result = IsSharpDecreasedChanged( + fromValue, + toValue, + maxValue, + minValue); + + // + return result; +} +bool IsSharpDecreasedChanged( + int from, // Past Bar Index + int to, // Present Bar Index + ENUM_APPLIED_PRICE appliedPrice // Which Price Choose in From or To +) +{ + // + bool result = false; + + // + double toValue = GetAppliedPrice( + to, + appliedPrice); + double fromValue = GetAppliedPrice( + from, + appliedPrice); + + // + int hIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + from, + to); + double maxValue = iHigh( + _Symbol, + _Period, + hIdx); + + // + int lIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + from, + to); + double minValue = iLow( + _Symbol, + _Period, + lIdx); + + // + result = IsSharpDecreasedChanged( + fromValue, + toValue, + maxValue, + minValue); + + // + return result; +} + +// +void Clean(int &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clean(ulong &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clean(string &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clean(double &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +bool GetLastItem( + double &item, // Holds Result + double &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + item = buffer[bufferSize - 1]; + + // + result = true; + return result; +} +bool GetLastItem( + datetime &item, // Holds Result + datetime &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + item = buffer[bufferSize - 1]; + + // + result = true; + return result; +} + +// +void Add( + int item, // item want to add + int &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + ulong item, // item want to add + ulong &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + string item, // item want to add + string &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + double item, // item want to add + double &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XOHCL &item, // item want to add + XOHCL &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + datetime &item, // item want to add + datetime &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// Converts a Buffer to String Representation ... +string ToString( + const int &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator + +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} +string ToString( + const double &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator + +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} +string ToString( + const string &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator + +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} +string ToString( + const datetime &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} +template +string ToString(T value) +{ + return (string)value; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString, // Expression Start String must be Unique + const string endString // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Normalize a give Volume ... +double NormalizeVolume( + double volume, // desired volume to normalize + string symbol = NULL, // Specified Symbol for Normalization + int mLength = 2 // Length of Digits +) +{ + // + double result = volume; + + // + // Normalize Symbol ... + if (StringLen(symbol) == 0) + { + symbol = _Symbol; + } + + // + // Normalize Digits ... + int digits = GetDigits(symbol); + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + double maxAvailableVolume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +// +// Normallize Price ... +double NormalizePrice( + double price, // desired Price for normalization + string symbol = NULL // Specified Symbol for Normalization +) +{ + // + double result = 0; + + // + // Mormalize Symbol ... + if (StringLen(symbol) == 0) + { + symbol = _Symbol; + } + + // + int digits = GetDigits(symbol); + result = NormalizeDouble(price, digits); + + // + return result; +} + +// +// Error Descriptions Functions ... +// + +// +// Retrieve Specified Error Code Description ... +string GetErrorDescription(int err_code) +{ + // + string result = ""; + + // + switch (err_code) + { + // + //--- Constant Description + + // + case ERR_SUCCESS: + result = "The operation completed successfully"; + break; + + // + case ERR_INTERNAL_ERROR: + result = "Unexpected internal error"; + break; + + // + case ERR_WRONG_INTERNAL_PARAMETER: + result = "Wrong parameter in the inner call of the client terminal function"; + break; + + // + case ERR_INVALID_PARAMETER: + result = "Wrong parameter when calling the system function"; + break; + + // + case ERR_NOT_ENOUGH_MEMORY: + result = "Not enough memory to perform the system function"; + break; + + // + case ERR_STRUCT_WITHOBJECTS_ORCLASS: + result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"; + break; + + // + case ERR_INVALID_ARRAY: + result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array"; + break; + + // + case ERR_ARRAY_RESIZE_ERROR: + result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"; + break; + + // + case ERR_STRING_RESIZE_ERROR: + result = "Not enough memory for the relocation of string"; + break; + + // + case ERR_NOTINITIALIZED_STRING: + result = "Not initialized string"; + break; + + // + case ERR_INVALID_DATETIME: + result = "Invalid date and/or time"; + break; + + // + case ERR_ARRAY_BAD_SIZE: + result = "Requested array size exceeds 2 GB"; + break; + + // + case ERR_INVALID_POINTER: + result = "Wrong pointer"; + break; + + // + case ERR_INVALID_POINTER_TYPE: + result = "Wrong type of pointer"; + break; + + // + case ERR_FUNCTION_NOT_ALLOWED: + result = "System function is not allowed to call"; + break; + + // + //--- Charts + + // + case ERR_CHART_WRONG_ID: + result = "Wrong chart ID"; + break; + + // + case ERR_CHART_NO_REPLY: + result = "Chart does not respond"; + break; + + // + case ERR_CHART_NOT_FOUND: + result = "Chart not found"; + break; + + // + case ERR_CHART_NO_EXPERT: + result = "No Expert Advisor in the chart that could handle the event"; + break; + + // + case ERR_CHART_CANNOT_OPEN: + result = "Chart opening error"; + break; + + // + case ERR_CHART_CANNOT_CHANGE: + result = "Failed to change chart symbol and period"; + break; + + // + case ERR_CHART_CANNOT_CREATE_TIMER: + result = "Failed to create timer"; + break; + + // + case ERR_CHART_WRONG_PROPERTY: + result = "Wrong chart property ID"; + break; + + // + case ERR_CHART_SCREENSHOT_FAILED: + result = "Error creating screenshots"; + break; + + // + case ERR_CHART_NAVIGATE_FAILED: + result = "Error navigating through chart"; + break; + + // + case ERR_CHART_TEMPLATE_FAILED: + result = "Error applying template"; + break; + + // + case ERR_CHART_WINDOW_NOT_FOUND: + result = "Subwindow containing the indicator was not found"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_ADD: + result = "Error adding an indicator to chart"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_DEL: + result = "Error deleting an indicator from the chart"; + break; + + // + case ERR_CHART_INDICATOR_NOT_FOUND: + result = "Indicator not found on the specified chart"; + break; + + // + //--- Graphical Objects + case ERR_OBJECT_ERROR: + result = "Error working with a graphical object"; + break; + + // + case ERR_OBJECT_NOT_FOUND: + result = "Graphical object was not found"; + break; + + // + case ERR_OBJECT_WRONG_PROPERTY: + result = "Wrong ID of a graphical object property"; + break; + + // + case ERR_OBJECT_GETDATE_FAILED: + result = "Unable to get date corresponding to the value"; + break; + + // + case ERR_OBJECT_GETVALUE_FAILED: + result = "Unable to get value corresponding to the date"; + break; + + // + //--- MarketInfo + + // + case ERR_MARKET_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_MARKET_NOT_SELECTED: + result = "Symbol is not selected in MarketWatch"; + break; + + // + case ERR_MARKET_WRONG_PROPERTY: + result = "Wrong identifier of a symbol property"; + break; + + // + case ERR_MARKET_LASTTIME_UNKNOWN: + result = "Time of the last tick is not known (no ticks)"; + break; + + // + case ERR_MARKET_SELECT_ERROR: + result = "Error adding or deleting a symbol in MarketWatch"; + break; + + // + //--- History Access + + // + case ERR_HISTORY_NOT_FOUND: + result = "Requested history not found"; + break; + + // + case ERR_HISTORY_WRONG_PROPERTY: + result = "Wrong ID of the history property"; + break; + + // + //--- Global_Variables + + // + case ERR_GLOBALVARIABLE_NOT_FOUND: + result = "Global variable of the client terminal is not found"; + break; + + // + case ERR_GLOBALVARIABLE_EXISTS: + result = "Global variable of the client terminal with the same name already exists"; + break; + + // + case ERR_MAIL_SEND_FAILED: + result = "Email sending failed"; + break; + + // + case ERR_PLAY_SOUND_FAILED: + result = "Sound playing failed"; + break; + + // + case ERR_MQL5_WRONG_PROPERTY: + result = "Wrong identifier of the program property"; + break; + + // + case ERR_TERMINAL_WRONG_PROPERTY: + result = "Wrong identifier of the terminal property"; + break; + + // + case ERR_FTP_SEND_FAILED: + result = "File sending via ftp failed"; + break; + + // + case ERR_NOTIFICATION_SEND_FAILED: + result = "Error in sending notification"; + break; + + // + //--- Custom Indicator Buffers + + // + case ERR_BUFFERS_NO_MEMORY: + result = "Not enough memory for the distribution of indicator buffers"; + break; + + // + case ERR_BUFFERS_WRONG_INDEX: + result = "Wrong indicator buffer index"; + break; + + // + //--- Custom Indicator Properties + + // + case ERR_CUSTOM_WRONG_PROPERTY: + result = "Wrong ID of the custom indicator property"; + break; + + // + //--- Account + + // + case ERR_ACCOUNT_WRONG_PROPERTY: + result = "Wrong account property ID"; + break; + + // + case ERR_TRADE_WRONG_PROPERTY: + result = "Wrong trade property ID"; + break; + + // + case ERR_TRADE_DISABLED: + result = "Trading by Expert Advisors prohibited"; + break; + + // + case ERR_TRADE_POSITION_NOT_FOUND: + result = "Position not found"; + break; + + // + case ERR_TRADE_ORDER_NOT_FOUND: + result = "Order not found"; + break; + + // + case ERR_TRADE_DEAL_NOT_FOUND: + result = "Deal not found"; + break; + + // + case ERR_TRADE_SEND_FAILED: + result = "Trade request sending failed"; + break; + + // + //--- Indicators + + // + case ERR_INDICATOR_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_INDICATOR_CANNOT_CREATE: + result = "Indicator cannot be created"; + break; + + // + case ERR_INDICATOR_NO_MEMORY: + result = "Not enough memory to add the indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_APPLY: + result = "The indicator cannot be applied to another indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_ADD: + result = "Error applying an indicator to chart"; + break; + + // + case ERR_INDICATOR_DATA_NOT_FOUND: + result = "Requested data not found"; + break; + + // + case ERR_INDICATOR_WRONG_HANDLE: + result = "Wrong indicator handle"; + break; + + // + case ERR_INDICATOR_WRONG_PARAMETERS: + result = "Wrong number of parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_PARAMETERS_MISSING: + result = "No parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_CUSTOM_NAME: + result = "The first parameter in the array must be the name of the custom indicator"; + break; + + // + case ERR_INDICATOR_PARAMETER_TYPE: + result = "Invalid parameter type in the array when creating an indicator"; + break; + + // + case ERR_INDICATOR_WRONG_INDEX: + result = "Wrong index of the requested indicator buffer"; + break; + + // + //--- Depth of Market + + // + case ERR_BOOKS_CANNOT_ADD: + result = "Depth Of Market can not be added"; + break; + + // + case ERR_BOOKS_CANNOT_DELETE: + result = "Depth Of Market can not be removed"; + break; + + // + case ERR_BOOKS_CANNOT_GET: + result = "The data from Depth Of Market can not be obtained"; + break; + + // + case ERR_BOOKS_CANNOT_SUBSCRIBE: + result = "Error in subscribing to receive new data from Depth Of Market"; + break; + + // + //--- File Operations + + // + case ERR_TOO_MANY_FILES: + result = "More than 64 files cannot be opened at the same time"; + break; + + // + case ERR_WRONG_FILENAME: + result = "Invalid file name"; + break; + + // + case ERR_TOO_LONG_FILENAME: + result = "Too long file name"; + break; + + // + case ERR_CANNOT_OPEN_FILE: + result = "File opening error"; + break; + + // + case ERR_FILE_CACHEBUFFER_ERROR: + result = "Not enough memory for cache to read"; + break; + + // + case ERR_CANNOT_DELETE_FILE: + result = "File deleting error"; + break; + + // + case ERR_INVALID_FILEHANDLE: + result = "A file with this handle was closed, or was not opening at all"; + break; + + // + case ERR_WRONG_FILEHANDLE: + result = "Wrong file handle"; + break; + + // + case ERR_FILE_NOTTOWRITE: + result = "The file must be opened for writing"; + break; + + // + case ERR_FILE_NOTTOREAD: + result = "The file must be opened for reading"; + break; + + // + case ERR_FILE_NOTBIN: + result = "The file must be opened as a binary one"; + break; + + // + case ERR_FILE_NOTTXT: + result = "The file must be opened as a text"; + break; + + // + case ERR_FILE_NOTTXTORCSV: + result = "The file must be opened as a text or CSV"; + break; + + // + case ERR_FILE_NOTCSV: + result = "The file must be opened as CSV"; + break; + + // + case ERR_FILE_READERROR: + result = "File reading error"; + break; + + // + case ERR_FILE_BINSTRINGSIZE: + result = "String size must be specified, because the file is opened as binary"; + break; + + // + case ERR_INCOMPATIBLE_FILE: + result = "A text file must be for string arrays, for other arrays - binary"; + break; + + // + case ERR_FILE_IS_DIRECTORY: + result = "This is not a file, this is a directory"; + break; + + // + case ERR_FILE_NOT_EXIST: + result = "File does not exist"; + break; + + // + case ERR_FILE_CANNOT_REWRITE: + result = "File can not be rewritten"; + break; + + // + case ERR_WRONG_DIRECTORYNAME: + result = "Wrong directory name"; + break; + + // + case ERR_DIRECTORY_NOT_EXIST: + result = "Directory does not exist"; + break; + + // + case ERR_FILE_ISNOT_DIRECTORY: + result = "This is a file, not a directory"; + break; + + // + case ERR_CANNOT_DELETE_DIRECTORY: + result = "The directory cannot be removed"; + break; + + // + case ERR_CANNOT_CLEAN_DIRECTORY: + result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)"; + break; + + // + case ERR_FILE_WRITEERROR: + result = "Failed to write a resource to a file"; + break; + + // + //--- String Casting + + // + case ERR_NO_STRING_DATE: + result = "No date in the string"; + break; + + // + case ERR_WRONG_STRING_DATE: + result = "Wrong date in the string"; + break; + + // + case ERR_WRONG_STRING_TIME: + result = "Wrong time in the string"; + break; + + // + case ERR_STRING_TIME_ERROR: + result = "Error converting string to date"; + break; + + // + case ERR_STRING_OUT_OF_MEMORY: + result = "Not enough memory for the string"; + break; + + // + case ERR_STRING_SMALL_LEN: + result = "The string length is less than expected"; + break; + + // + case ERR_STRING_TOO_BIGNUMBER: + result = "Too large number, more than ULONG_MAX"; + break; + + // + case ERR_WRONG_FORMATSTRING: + result = "Invalid format string"; + break; + + // + case ERR_TOO_MANY_FORMATTERS: + result = "Amount of format specifiers more than the parameters"; + break; + + // + case ERR_TOO_MANY_PARAMETERS: + result = "Amount of parameters more than the format specifiers"; + break; + + // + case ERR_WRONG_STRING_PARAMETER: + result = "Damaged parameter of string type"; + break; + + // + case ERR_STRINGPOS_OUTOFRANGE: + result = "Position outside the string"; + break; + + // + case ERR_STRING_ZEROADDED: + result = "0 added to the string end, a useless operation"; + break; + + // + case ERR_STRING_UNKNOWNTYPE: + result = "Unknown data type when converting to a string"; + break; + + // + case ERR_WRONG_STRING_OBJECT: + result = "Damaged string object"; + break; + + // + //--- Operations with Arrays + + // + case ERR_INCOMPATIBLE_ARRAYS: + result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"; + break; + + // + case ERR_SMALL_ASSERIES_ARRAY: + result = "The receiving array is declared as AS_SERIES, and it is of insufficient size"; + break; + + // + case ERR_SMALL_ARRAY: + result = "Too small array, the starting position is outside the array"; + break; + + // + case ERR_ZEROSIZE_ARRAY: + result = "An array of zero length"; + break; + + // + case ERR_NUMBER_ARRAYS_ONLY: + result = "Must be a numeric array"; + break; + + // + case ERR_ONEDIM_ARRAYS_ONLY: + result = "Must be a one-dimensional array"; + break; + + // + case ERR_SERIES_ARRAY: + result = "Timeseries cannot be used"; + break; + + // + case ERR_DOUBLE_ARRAY_ONLY: + result = "Must be an array of type double"; + break; + + // + case ERR_FLOAT_ARRAY_ONLY: + result = "Must be an array of type float"; + break; + + // + case ERR_LONG_ARRAY_ONLY: + result = "Must be an array of type long"; + break; + + // + case ERR_INT_ARRAY_ONLY: + result = "Must be an array of type int"; + break; + + // + case ERR_SHORT_ARRAY_ONLY: + result = "Must be an array of type short"; + break; + + // + case ERR_CHAR_ARRAY_ONLY: + result = "Must be an array of type char"; + break; + + // + //--- Operations with OpenCL + + // + case ERR_OPENCL_NOT_SUPPORTED: + result = "OpenCL functions are not supported on this computer"; + break; + + // + case ERR_OPENCL_INTERNAL: + result = "Internal error occurred when running OpenCL"; + break; + + // + case ERR_OPENCL_INVALID_HANDLE: + result = "Invalid OpenCL handle"; + break; + + // + case ERR_OPENCL_CONTEXT_CREATE: + result = "Error creating the OpenCL context"; + break; + + // + case ERR_OPENCL_QUEUE_CREATE: + result = "Failed to create a run queue in OpenCL"; + break; + + // + case ERR_OPENCL_PROGRAM_CREATE: + result = "Error occurred when compiling an OpenCL program"; + break; + + // + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: + result = "Too long kernel name (OpenCL kernel)"; + break; + + // + case ERR_OPENCL_KERNEL_CREATE: + result = "Error creating an OpenCL kernel"; + break; + + // + case ERR_OPENCL_SET_KERNEL_PARAMETER: + result = "Error occurred when setting parameters for the OpenCL kernel"; + break; + + // + case ERR_OPENCL_EXECUTE: + result = "OpenCL program runtime error"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_SIZE: + result = "Invalid size of the OpenCL buffer"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_OFFSET: + result = "Invalid offset in the OpenCL buffer"; + break; + + // + case ERR_OPENCL_BUFFER_CREATE: + result = "Failed to create and OpenCL buffer"; + break; + + // + //--- User-Defined Errors + default: + result = "UNKNOWN Erro ..."; + break; + } + + // + return result; +} + +// +// Retrieve Specified Error Code Description ... +string GetTradeServerReturnCodeDescription(int return_code) +{ + // + string result = ""; + + // + switch (return_code) + { + // + case TRADE_RETCODE_REQUOTE: + result = "Requote"; + break; + + // + case TRADE_RETCODE_REJECT: + result = "Request rejected"; + break; + + // + case TRADE_RETCODE_CANCEL: + result = "Request canceled by trader"; + break; + + // + case TRADE_RETCODE_PLACED: + result = "Order placed"; + break; + + // + case TRADE_RETCODE_DONE: + result = "Request completed"; + break; + + // + case TRADE_RETCODE_DONE_PARTIAL: + result = "Only part of the request was completed"; + break; + + // + case TRADE_RETCODE_ERROR: + result = "Request processing error"; + break; + + // + case TRADE_RETCODE_TIMEOUT: + result = "Request canceled by timeout"; + break; + + // + case TRADE_RETCODE_INVALID: + result = "Invalid request"; + break; + + // + case TRADE_RETCODE_INVALID_VOLUME: + result = "Invalid volume in the request"; + break; + + // + case TRADE_RETCODE_INVALID_PRICE: + result = "Invalid price in the request"; + break; + + // + case TRADE_RETCODE_INVALID_STOPS: + result = "Invalid stops in the request"; + break; + + // + case TRADE_RETCODE_TRADE_DISABLED: + result = "Trade is disabled"; + break; + + // + case TRADE_RETCODE_MARKET_CLOSED: + result = "Market is closed"; + break; + + // + case TRADE_RETCODE_NO_MONEY: + result = "There is not enough money to complete the request"; + break; + + // + case TRADE_RETCODE_PRICE_CHANGED: + result = "Prices changed"; + break; + + // + case TRADE_RETCODE_PRICE_OFF: + result = "There are no quotes to process the request"; + break; + + // + case TRADE_RETCODE_INVALID_EXPIRATION: + result = "Invalid order expiration date in the request"; + break; + + // + case TRADE_RETCODE_ORDER_CHANGED: + result = "Order state changed"; + break; + + // + case TRADE_RETCODE_TOO_MANY_REQUESTS: + result = "Too frequent requests"; + break; + + // + case TRADE_RETCODE_NO_CHANGES: + result = "No changes in request"; + break; + + // + case TRADE_RETCODE_SERVER_DISABLES_AT: + result = "Autotrading disabled by server"; + break; + + // + case TRADE_RETCODE_CLIENT_DISABLES_AT: + result = "Autotrading disabled by client terminal"; + break; + + // + case TRADE_RETCODE_LOCKED: + result = "Request locked for processing"; + break; + + // + case TRADE_RETCODE_FROZEN: + result = "Order or position frozen"; + break; + + // + case TRADE_RETCODE_INVALID_FILL: + result = "Invalid order filling type"; + break; + + // + case TRADE_RETCODE_CONNECTION: + result = "No connection with the trade server"; + break; + + // + case TRADE_RETCODE_ONLY_REAL: + result = "Operation is allowed only for live accounts"; + break; + + // + case TRADE_RETCODE_LIMIT_ORDERS: + result = "The number of pending orders has reached the limit"; + break; + + // + case TRADE_RETCODE_LIMIT_VOLUME: + result = "The volume of orders and positions for the symbol has reached the limit"; + break; + + // + default: + result = "Invalid return code of the trade server"; + break; + } + + // + return result; +} + +// +// Check Expert Running in Testing Mode or not ... +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +// +// Date Time Manipulation Functions ... +// + +// +// Representation of Time Struct ... +// struct MqlDateTime +// { +// int year; // Year +// int mon; // Month +// int day; // Day +// int hour; // Hour +// int min; // Minutes +// int sec; // Seconds +// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) +// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) +// }; + +// +// Converts Time to Seconds ... +ulong TimeToSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = (ulong)time; + + // + return result; +} +ulong TimeToSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToSeconds(dTime); + + // + return result; +} + +// +// Converts Seconds To Time ... +datetime SecondsToTime( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime result = (datetime)seconds; + + // + return result; +} +MqlDateTime SecondsToStruct( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime dTime = SecondsToTime(seconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Time to MilliSeconds ... +ulong TimeToMilliSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = TimeToSeconds(time) * 1000; + + // + return result; +} +ulong TimeToMilliSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToMilliSeconds(dTime); + + // + return result; +} + +// +// Converts MillisSeconds to Time ... +datetime MilliSecondsToTiem( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + ulong seconds = milliSeconds / 1000; + + // + datetime result = SecondsToTime(seconds); + + // + return result; +} +MqlDateTime MilliSecondsToStruct( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + datetime dTime = MilliSecondsToTiem(milliSeconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Retrieve DateTime Structure ... +MqlDateTime GetCurrentTime() +{ + // + MqlDateTime result = {}; + + // + TimeCurrent(result); + + // + return result; +} + +// +// Retrieve Current Time as Seconds ... +ulong GetCurrentTimeAsSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Current Time as MilliSeconds ... +ulong GetCurrentTimeAsMilliSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Candle Time ... +datetime GetCandleTime( + string symbol = "", // Specify Symbol + ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame + int bar_index = 0 // Specify Bar Index +) +{ + // + // Validate and Normalize Args ... + + // + // Normalize Symbol ... + symbol = StringLen(symbol) == 0 + ? _Symbol + : symbol; + + // + // Normalize Period ... + period = period == NULL + ? _Period + : period; + + // + // Retrieve Bar Time ... + datetime result = iTime( + symbol, + period, + bar_index); + + // + return result; +} + +// +// Retrieve Specified Candle Time ... +ulong GetCandleTimeAsSeconds( + string symbol = "", // Specify Symbol + ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame + int bar_index = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetCandleTime( + symbol, + period, + bar_index); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Candle Time ... +ulong GetCandleTimeAsMilliSeconds( + string symbol = "", // Specify Symbol + ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame + int bar_index = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetCandleTime( + symbol, + period, + bar_index); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve a Candle Time Structure ... +MqlDateTime GetCandleTimeStruct( + string symbol = "", // Specify Symbol + ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame + int bar_index = 0 // Specify Bar Index +) +{ + // + MqlDateTime result = {}; + + // + // Retrieve Bar Time ... + datetime barTime = GetCandleTime( + symbol, + period, + bar_index); + + // + // Convert to Structure ... + TimeToStruct(barTime, result); + + // + return result; +} + +// +// Retrieve Number of Candles in a Day ... +int GetDailyCandleCount(ENUM_TIMEFRAMES mPeriod) +{ + // + int seconds = PeriodSeconds(mPeriod); + + // + int daySeconds = 24 * 60 * 60; + + // + int result = daySeconds / seconds; + + // + return result; +} + +int GetDailyCandleCount() +{ + // + int result = GetDailyCandleCount(_Period); + + // + return result; +} + +// +// +// + +// +// Holds Month ... +static int xMonth = -1; + +// +// Holds Day Of Week ... +static int xDayOfWeek = -1; +static int xForWeekDay = -1; + +// +// Holds Day ... +static int xDay = -1; + +// +// Holds Hour ... +static int xHour = -1; + +// +// Reset Timing Variables ... +void ResetTiming() +{ + // + xHour = -1; + xDay = -1; + xDayOfWeek = -1; + xMonth = -1; +} + +// +// Detecting New Houre ... +bool IsNewHour() +{ + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.hour != xHour; + if (result) + { + xHour = timeStruct.hour; + } + + // + return result; +} + +// +// Detecting New Day ... +bool IsNewDay() +{ + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.day_of_year != xDay; + if (result) + { + xDay = timeStruct.day_of_year; + } + + // + return result; +} + +// +// Detecting New Week ... +bool IsNewWeek() +{ + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Week ... + // Since Week Starts From Monday in Forex World ... + // we Calculate Start of Week by 1-Monday ... + result = + xDayOfWeek == -1 && + xForWeekDay == -1 + ? true + : timeStruct.day_of_week == 1 && + timeStruct.day_of_year > xForWeekDay; + + // + xForWeekDay = timeStruct.day_of_year; + xDayOfWeek = timeStruct.day_of_week; + + // + return result; +} + +// +// Detecting End Of Week ... +bool IsWeekEnd() +{ + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check WeekEnd ... + // Since Week Starts From Monday in Forex World ... + // we Calculate End of Week by 5-Friday ... + result = + xDayOfWeek != -1 && + timeStruct.day_of_week == 5 && + timeStruct.hour == 23 && + timeStruct.min == 59 && + timeStruct.sec == 59; + + // + return result; +} + +// +// Detecting New Month ... +bool IsNewMonth() +{ + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.mon != xMonth; + if (result) + { + xMonth = timeStruct.mon; + } + + // + return result; +} + +// +// Find Hindmost Time Frame ... +ENUM_TIMEFRAMES GetHindmostTimeFrame( + ENUM_TIMEFRAMES mPeriod // Specified Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + // Normalize Period ... + if ( + mPeriod < 0 || + mPeriod == NULL) + { + mPeriod = _Period; + } + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H12; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + case PERIOD_H4: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + case PERIOD_H12: + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Find Farest Time Frame ... +ENUM_TIMEFRAMES GetFarestTimeFrame( + ENUM_TIMEFRAMES mPeriod // Specified Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + // Normalize Period ... + if ( + mPeriod < 0 || + mPeriod == NULL) + { + mPeriod = _Period; + } + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + case PERIOD_H4: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + case PERIOD_H12: + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Find Medium Time Frame ... +ENUM_TIMEFRAMES GetMediestTimeFrame( + ENUM_TIMEFRAMES mPeriod // Specified Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + // Normalize Period ... + if ( + mPeriod < 0 || + mPeriod == NULL) + { + mPeriod = _Period; + } + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H1; + break; + + // + case PERIOD_M30: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + case PERIOD_H12: + result = PERIOD_D1; + break; + + // + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + case PERIOD_W1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Find Nearest Time Frame ... +ENUM_TIMEFRAMES GetNearestTimeFrame( + ENUM_TIMEFRAMES mPeriod // Specified Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + // Normalize Period ... + if ( + mPeriod < 0 || + mPeriod == NULL) + { + mPeriod = _Period; + } + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M5; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_M15; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_M30; + break; + + // + case PERIOD_M30: + result = PERIOD_H1; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + case PERIOD_H12: + result = PERIOD_D1; + break; + + // + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + case PERIOD_W1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Get Specific Time Frame Start Candle Time ... +datetime GetPeriodStartTime( + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + datetime mTime = NULL // Specified Bar Time ... +) +{ + // + // Normalize Arg ... + + // + if ( + mSymbol == NULL || + StringLen(mSymbol) == 0) + { + mSymbol = _Symbol; + } + + // + if ( + mPeriod < 0 || + mPeriod == NULL) + { + mPeriod = _Period; + } + + // + if ( + mTime < 0 || + mTime == NULL) + { + mTime = TimeCurrent(); + } + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false); + + // + datetime result = iTime( + mSymbol, + mPeriod, + barIndex); + + // + return result; +} + +// +struct XCandleRemains +{ + // + int days; + int hours; + int minutes; + int seconds; +}; + +// +string ToString( + XCandleRemains &item, + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true) +{ + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || item.days > 0) + { + result += dayId + idSeparator + (string)item.days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || item.hours > 0) + { + result += hourId + idSeparator + (string)item.hours + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || item.minutes > 0) + { + result += minuteId + idSeparator + (string)item.minutes + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || item.seconds > 0) + { + result += secondId + idSeparator + (string)item.seconds; + } + + // + return result; +} + +// +// Retrieve Specific Candles Ramained Time ... +void GetCandleRemainsTime( + XCandleRemains &result, // Holds Result ... + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + int mBarIndex = 0 // Specified Bar Index ... +) +{ + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetCandleTime( + mSymbol, + mPeriod, + mBarIndex); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int days = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result.days = days; + result.hours = hours; + result.minutes = minutes; + result.seconds = seconds; +} + +// +// Converts an String to TimeFrame ... +ENUM_TIMEFRAMES ToPeriod(string value) +{ + // + if (StringLen(value) == 0) + { + return _Period; + } + + // + StringTrimLeft(value); + StringTrimRight(value); + + // + ENUM_TIMEFRAMES result = _Period; + + // + if (value == "M1") + { + result = PERIOD_M1; + } + else if (value == "M2") + { + result = PERIOD_M2; + } + else if (value == "M3") + { + result = PERIOD_M3; + } + else if (value == "M4") + { + result = PERIOD_M4; + } + else if (value == "M5") + { + result = PERIOD_M5; + } + else if (value == "M6") + { + result = PERIOD_M6; + } + else if (value == "M10") + { + result = PERIOD_M10; + } + else if (value == "M12") + { + result = PERIOD_M12; + } + else if (value == "M15") + { + result = PERIOD_M15; + } + else if (value == "M20") + { + result = PERIOD_M20; + } + else if (value == "M30") + { + result = PERIOD_M30; + } + else if (value == "H1") + { + result = PERIOD_H1; + } + else if (value == "H2") + { + result = PERIOD_H2; + } + else if (value == "H3") + { + result = PERIOD_H3; + } + else if (value == "H4") + { + result = PERIOD_H4; + } + else if (value == "H6") + { + result = PERIOD_H6; + } + else if (value == "H8") + { + result = PERIOD_H8; + } + else if (value == "H12") + { + result = PERIOD_H12; + } + else if (value == "D1") + { + result = PERIOD_D1; + } + else if (value == "W1") + { + result = PERIOD_W1; + } + else if (value == "MN1") + { + result = PERIOD_MN1; + } + + // + return result; +} + +// +// Converts Period to String ... +string ToString(ENUM_TIMEFRAMES period) +{ + // + string result = ""; + + // + string mPStr = EnumToString(period); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[1]; + + // + return result; +} + +// +// END Provided Functions ... +// diff --git a/MQLTestWorkspace/Libraries/x-saherelm.draw.lib.ex5 b/MQLTestWorkspace/Libraries/x-saherelm.draw.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..4f61b18e06ac2828d6562690692a1c31711d87c8 GIT binary patch literal 7102 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Libraries/x-saherelm.draw.lib.mq5 b/MQLTestWorkspace/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..7771f54 --- /dev/null +++ b/MQLTestWorkspace/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2462 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Draw Library +// -------------------------------------- +// Name: XDraw +// Description: provides Draw abilities ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Inputs ... +// +// +// END Inputs ... +// + +// +// Include Logger Library ... +#include "x-saherelm.log.lib.mq5" +#include "x-saherelm.common.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// +string drawPrefix = "X-OBJ"; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// DeInitial Library if required ... +void OnDeinitDrawLibrary() +{ + RemoveDraws(); +} + +// +// remove drawn objects ... +void RemoveDraws( + string tag = NULL, + int chartId = -1, + int subWindow = -1) +{ + // + // Normalize Args ... + // + if (tag == NULL) + { + tag = drawPrefix; + } + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, tag) >= 0) + { + ObjectDelete(chartId, on); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +bool RemoveDraw( + string name, + int chartId = -1, + int subWindow = -1) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + string objName = ""; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, name) >= 0) + { + // + objName = on; + break; + } + } + + // + if (StringLen(objName) > 0) + { + result = ObjectDelete(chartId, objName); + } + + // + return result; +} + +// +// Deselect All Draws ... +void DeselectAllDraws() +{ + // + int objs = ObjectsTotal(ChartID(), 0); + for (int o = 0; o < objs; o++) + { + ObjectSetInteger(ChartID(), ObjectName(ChartID(), o, 0), OBJPROP_SELECTED, false); + } + + // + ChartRedraw(); +} + +// +// Check Object Exists ... +bool IsDrawExists( + string name, + int chartId = -1, + int subWindow = -1) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + result = StringFind(on, name) >= 0; + if (result) + { + break; + } + } + + // + return result; +} +// +// END Provided Functions ... +// + +// +// START Regular Draws ... +// + +// +// START Arrow Functions ... +// +// +// Draw an Arrow Object on Chart ... +bool DrawArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // arrow name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const uchar arrowCode = 252, // arrow code + const ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, // anchor point position + const color clr = clrAqua, // arrow color + const ENUM_LINE_STYLE style = STYLE_SOLID, // border line style + const int width = 3, // arrow size + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // Order Object ... +) +{ + // + // set anchor point coordinates if they are not set ... + ChangeArrowEmptyPoint(time, price); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create an arrow ... + if (!ObjectCreate(chartID, objName, OBJ_ARROW, subWindow, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to create an arrow! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set the arrow code ... + ObjectSetInteger(chartID, objName, OBJPROP_ARROWCODE, arrowCode); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set the arrow color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set the border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set the arrow's size ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the arrow by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is false by default, if you want making it possible to highlight and move the object + // change it to true ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move the anchor point of Arrow ... +bool MoveArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // reset the error value + ResetLastError(); + + // + // move the anchor point ... + if (!ObjectMove(chartID, name, 0, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete an arrow ... +bool DeleteArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow" // arrow name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete an arrow ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete an arrow! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change the arrow code ... +bool ArrowCodeChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const uchar code = 252 // arrow code +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change the arrow code ... + if (!ObjectSetInteger(chartID, name, OBJPROP_ARROWCODE, code)) + { + // + string message = + __FUNCTION__ + + ": failed to change the arrow code! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change anchor type ... +bool ArrowAnchorChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const ENUM_ARROW_ANCHOR anchor = ANCHOR_TOP // anchor type +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change anchor type ... + if (!ObjectSetInteger(chartID, name, OBJPROP_ANCHOR, anchor)) + { + // + string message = + __FUNCTION__ + + ": failed to change anchor type! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeArrowEmptyPoint( + datetime &time, + double &price) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} +// +// END Arrow Functions ... +// + +// +// START Horizontal Line Functions ... +// +// +// Create, Draw the horizontal line ... +bool DrawHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + const int subWindow = 0, // subwindow index + double price = 0, // line price + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // if the price is not set, set it at the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a horizontal line ... + if (!ObjectCreate(chartID, objName, OBJ_HLINE, subWindow, 0, price)) + { + // + string message = + __FUNCTION__ + + ": failed to create a horizontal line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move horizontal line ... +bool MoveHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + double price = 0 // line price +) +{ + // + // if the line price is not set, move it to the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move a horizontal line ... + if (!ObjectMove(chartID, name, 0, 0, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the horizontal line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete a horizontal line ... +bool DeleteHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine" // line name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete a horizontal line ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete a horizontal line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} +// +// END Horizontal Line Functions ... +// + +// +// START Vertical Line Functions ... +// +// +// Create the vertical line ... +bool DrawVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + const int subWindow = 0, // subwindow index + datetime time = 0, // line time + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // if the line time is not set, draw it via the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // reset the error value + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a vertical line ... + if (!ObjectCreate(chartID, objName, OBJ_VLINE, subWindow, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to create a vertical line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move the vertical line ... +bool MoveVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + datetime time = 0 // line time +) +{ + // + // if line time is not set, move the line to the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move the vertical line ... + if (!ObjectMove(chartID, name, 0, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to move the vertical line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete the vertical line ... +bool DeleteVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine" // line name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the vertical line ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete the vertical line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} +// +// END Vertical Line Functions ... +// + +// +// START RectangleLabel Functions ... +// +// +// Create Rectangle Label Object ... +bool DrawRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // width + const int height = 18, // height + const color bgColor = clrWhiteSmoke, // background color + const ENUM_BORDER_TYPE border = BORDER_SUNKEN, // border type + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const color clr = clrRed, // flat border color (Flat) + const ENUM_LINE_STYLE style = STYLE_SOLID, // flat border style + const int lineWidth = 1, // flat border width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // create a rectangle label + if (!ObjectCreate(chartID, objName, OBJ_RECTANGLE_LABEL, subWindow, 0, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to create a rectangle label! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set label coordinates ... + ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + // set label size ... + ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + // set background color ... + ObjectSetInteger(chartID, objName, OBJPROP_BGCOLOR, bgColor); + + // + // set border type ... + ObjectSetInteger(chartID, objName, OBJPROP_BORDER_TYPE, border); + + // + // set the chart's corner, relative to which point coordinates are defined ... + ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + // set flat border color (in Flat mode) ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set flat border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set flat border width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, lineWidth); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the label by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move Rectangle Label .. +bool MoveRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // move the rectangle label ... + if (!ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x)) + { + // + string message = + __FUNCTION__ + + ": failed to move X coordinate of the label! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + if (!ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y)) + { + // + string message = + __FUNCTION__ + + ": failed to move Y coordinate of the label! Error code = " + + (string)GetLastError(); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete the rectangle label ... +bool DeleteRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel" // label name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the label ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete a rectangle label! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change Rectangle Label Size ... +bool ChangeSizeRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int width = 50, // label width + const int height = 18 // label height +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change label size ... + if (!ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width)) + { + // + string message = + __FUNCTION__ + + ": failed to change the label's width! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + if (!ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height)) + { + // + string message = + __FUNCTION__ + + ": failed to change the label's height! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change rectangle label border type ... +bool RectLabelChangeBorderType( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const ENUM_BORDER_TYPE border = BORDER_SUNKEN // border type +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change border type ... + if (!ObjectSetInteger(chartID, name, OBJPROP_BORDER_TYPE, border)) + { + // + string message = + __FUNCTION__ + + ": failed to change the border type! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} +// +// END RectangleLabel Functions ... +// + +// +// START TrendLine Funcions ... +// +// Create a trend line by the given coordinates ... +bool DrawTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrYellow, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool rayRight = false, // line's continuation to the right + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor points' coordinates if they are not set ... + ChangeTrendLineEmptyPoints( + time1, + price1, + time2, + price2); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a trend line by the given coordinates ... + if (!ObjectCreate(chartID, objName, OBJ_TREND, subWindow, time1, price1, time2, price2)) + { + // + string message = + __FUNCTION__ + + ": failed to create a trend line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the line's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move trend line anchor point ... | +bool ChangeTrendLinePoint( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int pointindex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move trend line's anchor point ... + if (!ObjectMove(chartID, name, pointindex, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// The function deletes the trend line from the chart ... +bool DeleteTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine" // line name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete a trend line ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete a trend line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Check the values of trend line's anchor points and set default ... +// values for empty ones ... +void ChangeTrendLineEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, it is equal to the first point's one ... + if (!price2) + { + price2 = price1; + } +} +// +// END TrendLine Functions ... +// + +// +// START Text Functions ... +// +// Create and Draw a Text Object ... +bool DrawText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const string text = "Text", // the text itself + const string font = "Arial", // font + const int fontSize = 10, // font size + const color clr = clrRed, // color + const double angle = 0.0, // text slope + const ENUM_ANCHOR_POINT anchor = ANCHOR_CENTER, // anchor type + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor point coordinates if they are not set ... + ChangeTextEmptyPoint(time, price); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // create Text object + if (!ObjectCreate(chartID, objName, OBJ_TEXT, subWindow, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Text\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set the text ... + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set text font ... + ObjectSetString(chartID, objName, OBJPROP_FONT, font); + + // + // set font size ... + ObjectSetInteger(chartID, objName, OBJPROP_FONTSIZE, fontSize); + + // + // set the slope angle of the text ... + ObjectSetDouble(chartID, objName, OBJPROP_ANGLE, angle); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the object by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move the anchor point ... +bool MoveText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // + // if point position is not set, move it to the current bar having Bid price + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move the anchor point .. + if (!ObjectMove(chartID, name, 0, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change the object text ... +bool ChangeText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const string text = "Text" // text +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change object text ... + if (!ObjectSetString(chartID, name, OBJPROP_TEXT, text)) + { + // + string message = + __FUNCTION__ + + ": failed to change the text! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete Text object ... +bool DeleteText( + const long chartID = 0, // chart's ID + const string name = "Text" // object name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the object ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete \"Text\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeTextEmptyPoint( + datetime &time, + double &price) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} +// +// END Text Functions ... +// + +// +// START Fibonacchi Functions ... +// +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawFibonacci( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrRed, // object color + const ENUM_LINE_STYLE style = STYLE_SOLID, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + if (!ObjectCreate(chartID, objName, OBJ_FIBO, subWindow, time1, price1, time2, price2)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Fibonacci Retracement\"! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawCustomFibonacci( + // + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + // + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrAqua, // object color + const ENUM_LINE_STYLE style = STYLE_DOT, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + if (!ObjectCreate(chartID, name, OBJ_FIBO, subWindow, time1, price1, time2, price2)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Fibonacci Retracement\"! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // Change Levels Of Fibonacci ... + bool result = FibonacciLevelsSet( + levels, + values, + colors, + styles, + widths, + descriptions, + chartID, + objName); + + // + // successful execution ... + return result; +} + +// +// Set number of levels and their parameters ... +bool FibonacciLevelsSet( + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + // check array sizes ... + if ( + levels != ArraySize(colors) || + levels != ArraySize(styles) || + levels != ArraySize(widths) || + levels != ArraySize(widths)) + { + // + string message = + __FUNCTION__ + + ": array length does not correspond to the number of levels, error!"; + + // + LogMessage(message); + + // + return false; + } + + // + // set the number of levels ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELS, levels); + + // + // set the properties of levels in the loop ... + for (int i = 0; i < levels; i++) + { + // + // level value ... + ObjectSetDouble(chartID, name, OBJPROP_LEVELVALUE, i, values[i]); + + // + // level color ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELCOLOR, i, colors[i]); + + // + // level style ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELSTYLE, i, styles[i]); + + // + // level width ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELWIDTH, i, widths[i]); + + // + // level description ... + // ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, DoubleToString(100 * values[i], 1)); + ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, descriptions[i]); + } + + // + // successful execution ... + return true; +} + +// +// Move Fibonacci Retracement anchor point ... +bool FibonacciPointChange( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move the anchor point ... + if (!ObjectMove(chartID, name, pointIndex, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete Fibonacci Retracement ... +bool DeleteFibonachi( + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the object ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete \"Fibonacci Retracement\"! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Check the values of Fibonacci Retracement anchor points and set +// default values for empty ones ... +void ChangeFibonacciEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2) +{ + // + // if the second point's time is not set, it will be on the current bar ... + if (!time2) + { + time2 = TimeCurrent(); + } + + // + // if the second point's price is not set, it will have Bid value ... + if (!price2) + { + price2 = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // if the first point's time is not set, it is located 9 bars left from the second one ... + if (!time1) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time2, 10, temp); + + // + // set the first point 9 bars left from the second one ... + time1 = temp[0]; + } + + // + // if the first point's price is not set, move it 200 points below the second one ... + if (!price1) + { + price1 = price2 - 200 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); + } +} +// +// END Fibonacci Functions ... +// + +// +// START Event Functions ... +// + +// +// Create an Event ... +bool EventCreate( + const long chartID = 0, // chart's ID + const string name = "Event", // object name + const int subWindow = 0, // subwindow index + const string text = "Content", // event text + datetime time = 0, // anchor point time + const color clr = clrRed, // color + const int width = 1, // point width when highlighted + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + if (!time) + { + time = TimeCurrent(); + } + + // + ResetLastError(); + + // + if (!ObjectCreate(chartID, name, OBJ_EVENT, subWindow, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Event\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set event text + ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + // set color + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set anchor point width if the object is highlighted + ObjectSetInteger(chartID, name, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving event by mouse + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + // successful execution + return true; +} + +// +// Change Event object text +bool EventTextChange( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + const string text = "Content" // text +) +{ + // + // reset the error value + ResetLastError(); + + // + // change object text + if (!ObjectSetString(chartID, name, OBJPROP_TEXT, text)) + { + // + string message = + __FUNCTION__ + + ": failed to change the text! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// Move Event object +bool EventMove( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + datetime time = 0 // time +) +{ + // + // if time is not set, move event to the last bar + if (!time) + { + time = TimeCurrent(); + } + + // + // reset the error value + ResetLastError(); + + // + // move the object + if (!ObjectMove(chartID, name, 0, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to move \"Event\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// Delete Event object +bool EventDelete( + const long chartID = 0, // chart's ID + const string name = "Event" // event name +) +{ + // + // reset the error value + ResetLastError(); + + // + // delete the object + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete \"Event\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// END Event Functions ... +// + +// +// START Button Functions ... +// + +// +// Create the button ... +bool ButtonCreate( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // button width + const int height = 15, // button height + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const string text = "Button", // text + const string font = "Arial", // font + const int fontSize = 8, // font size + const color clr = clrBlack, // text color + const color bgColor = clrLightGray, // background color + const color borderColor = clrNONE, // border color + const bool state = false, // pressed/released + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // create the button + result = ObjectCreate(chartID, name, OBJ_BUTTON, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set button coordinates + ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + // set button size + ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + // set the chart's corner, relative to which point coordinates are defined + ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + // set the text + ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + // set text font + ObjectSetString(chartID, name, OBJPROP_FONT, font); + + // + // set font size + ObjectSetInteger(chartID, name, OBJPROP_FONTSIZE, fontSize); + + // + // set text color + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set background color + ObjectSetInteger(chartID, name, OBJPROP_BGCOLOR, bgColor); + + // + // set border color + ObjectSetInteger(chartID, name, OBJPROP_BORDER_COLOR, borderColor); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // set button state + ObjectSetInteger(chartID, name, OBJPROP_STATE, state); + + // + // enable true or disable false the mode of moving the button by mouse + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + return result; +} + +// +// Move the button ... +bool ButtonMove( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + bool result = false; + + // + // move the button + + // + result = ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + return result; +} + +// +// Change button size ... +bool ButtonChangeSize( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int width = 50, // button width + const int height = 18 // button height +) +{ + // + bool result = false; + + // + // change the button size + + // + result = ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + return result; +} + +// +// Change corner of the chart for binding the button ... +bool ButtonChangeCorner( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER // chart corner for anchoring +) +{ + // + bool result = false; + + // + // change anchor corner + + // + result = ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + return result; +} + +// +// Change button text ... +bool ButtonTextChange( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const string text = "Text" // text +) +{ + // + bool result = false; + + // + // change object text + result = ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Delete the button ... +bool ButtonDelete( + const long chartID = 0, // chart's ID + const string name = "Button" // button name +) +{ + // + bool result = false; + + // + // delete the button + result = ObjectDelete(chartID, name); + + // + return result; +} +// +// END Button Functions ... +// + +// +// END Regular Draws ... +// + +// +// START Chart Style Drawers ... +// +// +// Apply Styles On Chart ... +void ApplyChartStyle( + long mChartId = -1, // chart's ID + ENUM_CHART_MODE mMode = CHART_CANDLES, // chart's mMode + bool mShowBidLine = true, // show bid line + bool mShowAskLine = true, // show ask line + bool mShowGrid = false, // show grids on chart + bool mShowVolumes = false, // show volumes + bool mShowTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool mAutoScroll = true, // chart autoscroll + bool mQuickNavigation = true, // chart quick navigation state + color mForeGroundColor = clrWhite, // chart's foreground color + color mBackGroundColor = clrBlack, // chart's background color + color mUpColor = clrGreen, // Up Color + color mDownColor = clrRed, // Down Color + color mBullishColor = clrGreen, // Bullish color + color mBearishColor = clrRed, // Bearish color + color mGridColor = clrGray, // grid color + color mBidLineColor = clrGray, // bid line color + color mAskLineColor = clrRed, // ask line color + color mLineColor = clrLime, // line mMode and doji candlestick color + color mStopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color mVolumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (mChartId == -1) + { + mChartId = 0; + } + + // + ChartSetInteger(mChartId, CHART_MODE, mMode); + ChartSetInteger(mChartId, CHART_SHOW_BID_LINE, mShowBidLine); + ChartSetInteger(mChartId, CHART_SHOW_ASK_LINE, mShowAskLine); + ChartSetInteger(mChartId, CHART_SHOW_GRID, mShowGrid); + ChartSetInteger(mChartId, CHART_SHOW_VOLUMES, mShowVolumes); + ChartSetInteger(mChartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels); + ChartSetInteger(mChartId, CHART_AUTOSCROLL, mAutoScroll); + ChartSetInteger(mChartId, CHART_QUICK_NAVIGATION, mQuickNavigation); + ChartSetInteger(mChartId, CHART_COLOR_FOREGROUND, mForeGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_BACKGROUND, mBackGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_UP, mUpColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_DOWN, mDownColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BULL, mBullishColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BEAR, mBearishColor); + ChartSetInteger(mChartId, CHART_COLOR_GRID, mGridColor); + ChartSetInteger(mChartId, CHART_COLOR_BID, mBidLineColor); + ChartSetInteger(mChartId, CHART_COLOR_ASK, mAskLineColor); + ChartSetInteger(mChartId, CHART_COLOR_STOP_LEVEL, mStopColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_LINE, mLineColor); + ChartSetInteger(mChartId, CHART_COLOR_VOLUME, mVolumesColor); +} + +// +// Retrieve Chart Size in Pixel ... +struct XSize +{ + long width; + long height; + + // + int x; + int y; + int w; + int h; + + // + int wStep; + int hStep; +}; + +// +// Retrieve Chart Size ... +bool GetChartSize( + XSize &result, // Holds Result ... + long chartID = 0 // Specified Chart ID ... +) +{ + // + bool mResult = false; + + // + mResult = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0, result.width); + if (!mResult) + { + return mResult; + } + + // + mResult = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0, result.height); + + // + return mResult; +} + +// +// END Chart Style Drawers ... +// \ No newline at end of file diff --git a/MQLTestWorkspace/Libraries/x-saherelm.http.lib.ex5 b/MQLTestWorkspace/Libraries/x-saherelm.http.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..134ec795bccbde5e9afbe3a90defe8cc773eec86 GIT binary patch literal 3648 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 KfNkkry8a7U7%dF| literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Libraries/x-saherelm.log.lib.mq5 b/MQLTestWorkspace/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 0000000..3235c63 --- /dev/null +++ b/MQLTestWorkspace/Libraries/x-saherelm.log.lib.mq5 @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Logger Library +// --------------------------------------- +// Name: XLogger +// Description: provides Logging abilities ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Inputs ... +// +input group "Logging"; +input bool enableLogging = true; // Enable Logging +// +// END Inputs ... +// + +// +// Including Models ... +#include "x-saherelm.models.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// +string logTag = "X-Logger"; // LogTag +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Logging a Message ... +void LogMessage(string message) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, " > ", message); +} +void LogMessage(string tag, string message) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(tag, " > ", message); +} + +// +void LogEmptyLine() +{ + LogMessage(" "); +} + +// +// Logging an Array ... +void LogArray(int &array[]) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, ">"); + ArrayPrint(array); +} +void LogArray(double &array[]) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, ">"); + ArrayPrint(array); +} +void LogArray(string &array[]) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, ">"); + ArrayPrint(array); +} +// +// END Provided Functions ... +// diff --git a/MQLTestWorkspace/Libraries/x-saherelm.models.lib.ex5 b/MQLTestWorkspace/Libraries/x-saherelm.models.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..6fce75c98c985045b0627a87a0c8018a9fa718e8 GIT binary patch literal 4014 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 I=c$eV2UwkXI{*Lx literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Libraries/x-saherelm.models.lib.mq5 b/MQLTestWorkspace/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 0000000..d2552c1 --- /dev/null +++ b/MQLTestWorkspace/Libraries/x-saherelm.models.lib.mq5 @@ -0,0 +1,238 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Models Library +// --------------------------------------- +// Name: XModels +// Description: provides all required models ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Inputs ... +// +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// How To Calculate Static Volume ... +enum ENUM_STATIC_VOLUME_METHODS +{ + // + // Based On Deposit ... + X_STATIC_VOLUME_BASED_ON_DEPOSIT, + // + // Based On Balance ... + X_STATIC_VOLUME_BASED_ON_BALANCE, +}; + +// +// START Model Definitions ... +// +// +// OHCL Candel Model ... +enum ENUM_X_PRICE +{ + X_PRICE_HIGH, + X_PRICE_OPEN, + X_PRICE_CLOSE, + X_PRICE_LOW +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +// Available Guard Action ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_HEDGE, + X_GUARD_PARTIAL_CLOSE, + X_GUARD_ACTION_TRAIL_STOP, + X_GUARD_ACTION_FORCE_CLOSE, + X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, + X_GUARD_ACTION_CANCEL_PENDING_ORDERS, +}; + +// +// Model Guard Info ... +struct XGuard +{ + string symbol; + string provider; + ENUM_TIMEFRAMES period; + ENUM_POSITION_TYPE type; + ENUM_X_GUARD_ACTIONS action; + + // + double dblPayLoad; + string strPayload; +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + double high; + double open; + double close; + double low; +}; + +// +// Model Support and Resistance +// for Specific Bar ... +struct XOHCLSupRes +{ + // + double res[]; + + // + double sup[]; +}; + +// +// Available Order Modes ... +enum ENUM_X_ORDER_MODES +{ + X_ORDER_MODE_MARKET = 0, // Market Order + X_ORDER_MODE_STOP = 1, // Pending Stop Order + X_ORDER_MODE_LIMIT = 2, // Pending Limit Order + X_ORDER_MODE_STOP_LIMIT = 3, // Pending Stop Limit Order +}; + +// +// Model a Signal ... +struct XSignal +{ + // + string providers[]; + + // + string symbol; + + // + ENUM_TIMEFRAMES period; + + // + ENUM_POSITION_TYPE type; + + // + ENUM_X_ORDER_MODES mode; + + // + double entry; + + // + double riskAmount; + + // + double tp; + + // + double sl; + + // + double r2r; + + // + double volume; + + // + bool calculateTP; + + // + bool useSupportAndResistance; + + // + bool useRiskAmountAsVolume; +}; +// +// EXTENSION Methods ... + +// +void Add( + XSignal &item, + XSignal &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Clear an Specific Signal Item ... +void Clean(XSignal &item) +{ + // + ArrayFree(item.providers); + ArrayResize(item.providers, 0); + + // + item.symbol = ""; + item.type = NULL; + item.mode = NULL; + item.period = NULL; + + // + item.tp = 0; + item.sl = 0; + item.r2r = 0; + item.entry = 0; + item.volume = 0; + item.riskAmount = 0; +} + +// +void Clean(XSignal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +void Clean(XGuard &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + + +// +// END Provided Functions ... +// diff --git a/MQLTestWorkspace/Libraries/x-saherelm.seriallizer.lib.ex5 b/MQLTestWorkspace/Libraries/x-saherelm.seriallizer.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..71e9aa6a8e91d34f320805de002a060962d00616 GIT binary patch literal 7924 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Libraries/x-saherelm.x121.draw.lib.mq5 b/MQLTestWorkspace/Libraries/x-saherelm.x121.draw.lib.mq5 new file mode 100644 index 0000000..941d61b --- /dev/null +++ b/MQLTestWorkspace/Libraries/x-saherelm.x121.draw.lib.mq5 @@ -0,0 +1,241 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X12 Draw Library +// ------------------------------------------ +// Name: X121Draw +// Description: provides Draw Requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// START Draw Functions ... +// + +// +// Draw Signal ... +void DrawSignal(const ulong ticket, XSignal &signal) +{ + // + bool isLong = IsLong(signal.type); + + // + string prefix = (string)ticket + "_" + ToString(signal.period); + + // + // Retrieve Time ... + datetime time = iTime( + signal.symbol, + signal.period, + 0); + + // + // Retrieve 3 Time ... + datetime time3 = iTime( + signal.symbol, + signal.period, + 3); + + // + color posColor = isLong + ? clrSpringGreen + : clrTomato; + color tpColor = clrSpringGreen; + color slColor = clrTomato; + color entryColor = clrGold; + + // + ENUM_LINE_STYLE vLineStyle = STYLE_DOT; + ENUM_LINE_STYLE tpLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE slLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE entryLineStyle = STYLE_SOLID; + + // + int lineWidth = 2; + + // + long chartID = ChartID(); + + // + // Vertical Line ... + string vlName = prefix + "_" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + posColor, + vLineStyle, + lineWidth); + + // + // TP ... + double profit = (MathAbs(signal.tp - signal.entry)) * signal.volume; + string tpName = prefix + "_TP_" + (string)profit; + + // + DrawTrendLine( + chartID, + tpName, + 0, + time3, + signal.tp, + time, + signal.tp, + tpColor, + tpLineStyle, + lineWidth); + + // + // SL ... + double lost = (MathAbs(signal.sl - signal.entry)) * signal.volume; + string slName = prefix + "_SL_" + (string)lost; + + // + DrawTrendLine( + chartID, + slName, + 0, + time3, + signal.sl, + time, + signal.sl, + slColor, + slLineStyle, + lineWidth); + + // + // ENTRY ... + string entryName = prefix + "_ENTRY_" + (string)lost; + + // + DrawTrendLine( + chartID, + entryName, + 0, + time3, + signal.entry, + time, + signal.entry, + entryColor, + entryLineStyle, + lineWidth); +} + +// +// Draw Support and Resistance ... +void DrawSupportResistance( + int bar_index, + XOHCLSupRes &data, + string prefix = "", + color supportColor = clrOrange, + color resistanceColor = clrOrange) +{ + // + datetime barTime = GetCandleTime( + _Symbol, + _Period, + bar_index); + + // + datetime prevBarTime = GetCandleTime( + _Symbol, + _Period, + bar_index + 5); + + // + long chID = ChartID(); + int subWindiw = 0; + int lineWidth = 1; + + // + string mPrefix = prefix + "_" + (string)barTime + "_"; + + // + // SUPPORTS ... + + // + int supCount = ArraySize(data.sup); + if (supCount > 0) + { + // + for (int i = 0; i < supCount; i++) + { + // + double iSup = data.sup[i]; + + // + string supTlName = mPrefix + "SUP[" + (string)(i + 1) + "]_(" + (string)iSup + ")"; + + // + // Draw Support ... + DrawTrendLine( + chID, + supTlName, + subWindiw, + prevBarTime, + iSup, + barTime, + iSup, + supportColor, + STYLE_DOT, + lineWidth, + true); + } + } + + // + // RESISTANCES ... + + // + int resCount = ArraySize(data.res); + if (resCount > 0) + { + // + for (int i = 0; i < resCount; i++) + { + // + double iRes = data.res[i]; + + // + string resTlName = mPrefix + "RES[" + (string)(i + 1) + "]_(" + (string)iRes + ")"; + + // + // Draw Support ... + DrawTrendLine( + chID, + resTlName, + subWindiw, + prevBarTime, + iRes, + barTime, + iRes, + resistanceColor, + STYLE_DOT, + lineWidth, + true); + } + } +} + +// +// END Draw Functions ... +//

+v z96tNkO|1y3fiE-?)~cACR=K~Y?Wh7UrWMDn#m`8pg7MxrxKE04GhZg|++p@Vv+#qv zYALtn8NmO#x7BkmI7TKKuAbe{qXA|B}+YzKXS5TP#_Vkm|tP?DHH~KDil@XCE zae{EoVvUpfn^h-WyF3g6di7;bqf3?-4KY&Xvz5NrTNp`}8;V^6pED2xzFGi&)?|Kg zMd9=wtIZb#ZN#MPo8x5^Ix*Q=E;83ML|mzJ6Sx<+=6#j{5$uS@@1#q^(GW}f4E37n z)%ysHXfQoxmxmXh8>PQLOp#b4WoF{S9+GCPt>CbSMb3rdOqo4C54b%&_+@_1EvvF1 zOLm!r&O;{^V(-}i7F@CX4qnq$Gt1U{8#$sjJ6QpEg(dxx+M1Zck=)KlA!I`QJH=rM z&*D?-y&EEZuRzylC6I~9mRv0jIeC#W_(@^hHe^v@a;0a19V^`s^`0GwLUsLT_?^a) z>042bI`Qn(bY%2vD2cRA;1TatzcJlY99&AQBS_tSv=cOm^OucAxL|1}6vFh~S5ROT zAu2YJTBAA@D33Ycdoh#qdwFavk(;AROnTs>VH6kx?g%?<_~)kb_nB4S>@aoHTB6)U z+#1^ne=#}-#N5(bUf-GB$03)0vU5*<6J&sMu_iEb?KZ4oxuxE^F)9F4-PON--6pQt z3_j^2_cCIsy2Z_nx|HC8fWdxdP4V-?fz-HoTW0!3;m+?zy<7b+(9|)q@3p>_iT`#U zQiS-7*b{eBx{o-Y8500So2*EP{}37GBTR%^!*H1~1k7NU^siIQfY55=GvtMWJW;M+ z^=!>|w{rW>EOjjK(;EdSG+uK>lM8yNiYJiTm?Vxpl)~bn@(1sdq`7wSEJwVpx*au@ zvCOdod9WzRtTH$*$_%^nS?;3MlS9hRA=r^_iSk?m=*$+TGsNQaEamLzGKb6Vd}>33 zg`vPJil(&W^x{w0HLLfK(YFR7bc$}V6sJtz5rs3i#%!uByhg8(=$Zu3;N*w|cFhT0 z$MoclA#-&1wyrulr^3CVE7=mZg@4+1(<&$cNOD1=hzK}(?gX~3m>R7#vg%|4BNVGU zw66rGW^-gi=9y&)Y0TMUSu-2IhO&L>oxBJ2bu7Pk<#=%QxjQ>dSTd?w|KcVPvT4ib zdx8d}^tKzm)a;b;foFJcJDPos7Ucr2E2$3Og^3O*pyogdL$2A6F+JRe6)qA@2xTqh zCMS&4=JiX}dk%gGn*m`O(Y5l9W}md^A{{D=v@yt+=OKd)_L|fC8JVog%AyxgE(l~f z4M$^2xveqt>%tuzIvhY0JHfcYe>npPxa+{_f=iKIXKPl3wbC{MGqUaRorbqBZ}r!2 z$v_GD2fn|5o$R#?!E9;ZKwpzu*dnd(v$6Q{6Trd)GzLT-@PK)R?9qMB;SpP9W9-C( z)#z_3{H{vRyBym!2HKZD3cjs%1!)F&qx!WvmrhbezV@dutYs$CCrEPIjfIr?o}4uD zpLN7(m~hEHUlV$DuZ00?uJ0YimELze2cI30dTx$~}kKYWM$D(6plQB{?nL-Tc0gh-WYFGLGuKmSj*4jtwSx1g-JUzpQ~ z3ddpy)Te3xb?yrc`Z!K?s(mkxl~o4%t%mVt11}ISytO@s;LQZwNdj~8f#=IajdXW z?b3~e1L6}%D^omM`8X9EqG3sy%bAFzQTo33fY+6QY*@%zcD1g4x5zdiA=kZormpi~ z2xK+whFVn|xja@}MLB}-0*m2W4?e*9p?+FebCq;85auo;rW&{iwY6}jRoNH5r3&tR zm%^C%Qe@7CSt7E7*ZsbeC_jxQTf2n^v;4@Zt(@&o)M>BIB!qHvM6gQeGxz6a0FG1q zIV1`Hhq+G_f_`mkV!o9gm&30HR0hF*) z>caTjtQ7MaHL6YY9bI0+_KXZ{*gy&${?jbA5j$g{HW?}u3Yl2aR05gA4xmH3U*vfH zKsu{6?ziWqUM+I?X~T`f%{Z!gLhqfIDuypuwqrcSSGgzuLA|RYH7H%o z6s^Oj=iET;A4@Kgb+aq4MiRl6pXd0=x)lcHsRy|pzz4RBARut875TsoZdNXFDzR9f@)MI!wzoqgK#i zu9gjbKIhHnTJ@h!r6&XTqR9Ey#46Q?$H!bWA$+eSH)2mrXqLPol7c)eWivEeJ35+<`o{U zQJ4e<=h66P`d}!KH8?(ADzD;6dr3$G=*RaWyDj%Yx1r&MRgGsm8;oWLb>f`xD!Ghp zkJGqLXG2lxHk`od@`A!~v@CD0O%xDPF}qxZ!d=Y)o*JonLSVN@g{SRR?7Ao}2|v@J zCH%KF7-rpyz(7lPsQ*t?{y$C}=`wK_k9Y#O#PUMl_i$=#d<`JOoiLc>QHdbMRx#fT zQ{0jN;tl*f5buT|a=1{TzN%>SM>f#(WmhfhTc%M#($sniXBxkwiXU-6grdJ+@qPC)d9D!`u{uz8#Is*dreWOO4pPF9Tzf<@WlPP?R$gbAr!A;S})|{X-vzK zMH4x>ZS3m6QG`^TsAicT>1aZFe-Aw4qTq=rYlMzxmMv4OqhG%cCt+KNdP3p80{V)y;8}J>SUTI6qk!hlJ9PoL6$7uEAVFAvC9fK;2*@B+RquEu zM>#vM>|Gu1@A}l0MNB(!Q6fZ3YkW-%d$-c1K+DK);O^-e3A94hsm+R9vSlD9ERO0& z1gO3~79V_RLg8#eEew3MXA~93CNvU~nkxRcN4x>Mv|kt!9wnH2q1e^k z9qyETe=HIb1zdlod4jg8U~pWM_AyBs(O#kHEYWX4)uPht-u&kZj&s225QG!{A+O;D z3##Fd2u4V{ZaF^{wQZgIXIzAZvr!HrR|%UVG4BT4+CY}~qO6D{+9E{wI!x8bf!SmC zib55DyDw!h!v8TpP=n#>^?25LBX+W49uGu(zZ~7 z_Cj)I)o)z%S9bfR1lb=GC!`dvTLKCq_BUeGsH1mf^+SQqIBN5wp&5Hi>8epEZlEV? z$p+b=-p(5o)CeaQp^FMggWX-Pu-&u>Xj-^qA_0!Qr0&C5v`@u4w`U-o@q^z|6c8vy z>@?%BK|vErZMeSo?$1*A-Vq(rT)Shw^}SeO4X_pnvGt*5^d>ssHTO~SQ$y2Xe4wUD z%o!!7U@<4&fJyksJ_D;Cn4o_-BPP7?pyN;szHv1>1TNH`EP?CpMG4mvZGOIaH0a$f zJOBbCA;S+P2_OBGOYs7L9vdwt|rLMv10KS#4PE!S_Y9iX*S zeU_dP`%0c%rQhRzJ8kYP@~SD>kdS)_;%WqSO}4aBG|R|_?9fe%$*zE<%764A!a!}1 zGj@vpWo`TNaT(<`v6gkf5zJCJPitZ3M#&-H$%p?XLm1@m55al*!9p1xIl)DXd%Shr z=hJ6AG$)KOV097-f%BgXF10BPI>=DX#eJNX~TKCDFfsnOo;vGnOJzH_1krHbZF<-q<@v(L$=k%$B zf6tiEhFA)sSO47G*T2469oI!`nzx%wnB2d^ma%3;QLPTs6^yOnU!hRmojocw0L(0e zaG1cTPEs-8ksT-wY4X%ObvYSJHX&(`zaQC(ysR0#rQlBS=w|iJZC|pKbu_5h{_T zK%^-x(_*NbU&{fC8Giasv6TJi#}gkH!+|cx_kKt|0@Mfl*Ju`{oi=!lc(gGSDTAp_ zjCdn;6tgtR)zWx;?+5`x5zL8sBPg-Rn~MC{fPJ!14YIN&wqAOca4~ZpfdtT_luyFi zi!*<{qSnL2py9+T;IjwR_xht=ctGj$Za)S$Zvjo}-dKhQpf-?M*me|;*1t^F*VQ*> z2?MRVvw1DR?2x#SC5#|&p(%8xi4<1$y2azl)QMOcyuHWLyorl%x!;MoEue+7OhITN zez+M4yvfMQ3#5R8Z|tt*Bqp-05q1^}K=bFjJx`pej|i7%MNO#XFCF&5Kv256D=w0U zXiTaSW@PL!G3F|FR3P_e^OGvSRo1QxmTyv11f@(uwfqQ0b~x&$*&O&@9D7T$sg7w+ zfaH&*SFH93#_r*GG8GgjzT-gH-NnPEqPVu>yiD()ZLED`Wg5xsY?Bj&tQ1~T6c)DQ za{HCLTTRF*Wp6pDVj#x`1PAv6s>Kt)&h5Wq_`)SiJ^HbW+87TP!RC2J{APhqC0yjo zE(Wye+&(}c>ZPYUi&~5EE!Z8e?OPvzLX_Zs1;vxvp*Ow2$K-hSfyk0QvNEZ9KUpA7 zbHU0%pqQ9<@?dJad!jqZ>}#?SfastC$l*L=u-6kh8^~>7P zFZZ9D*$UYf5($V<@mZ65XSX0Odk56}XF1WST&qj|Y{ESBr1j^AUEP^m9Dlzd(AD0| zj4%cS?v$wAY`Rx>{RQfcP;TCS-ilv&ASUxDn4o-wxSVXgdmrV_D5pK}Hae()Nh|-k z-n*G}?8?Rk$soN^EVbVDx{t()azWz`i8D3QbO5NFHu8EiA|YuiK^aw!^B|bZZ%Bjo zsK=_XP+qde0w$F)?>sXm!Hh0Mwewca!R03Uy)<5y4&6w1Q7|^DVEoTa*xp7KnQYUg za$3kjyN&WZMm}q#;pto6&-T9;m|If*T9sAs!!2YMu4D`BLQ4%?__=L6kzF`|(sRE3 zmys5TQhHLw?2nyJ_Bs3&a8sNF1U#>1${}bWyYc}(iX~Cr(pyMaIMxiPbQLSK59Krc zNX@kEaqBS~ryv($lnZ+wF{5!(!y>c?(;m6Dol1rj!|a|k0RN=K>+9qs3O5hHghERDXypW z-$GsIFk_BZ8SA2EF&$rb{O&A7s88Mt%R>MC#l!mVAXxtS(&TIs|H`9 z`HKh`(Y~j?F5-yMkZu3+RC*KW1s#I^EOa40wftn!#`QxeGq$}h+VHn>q=8Xj1?Pul zz-zNb${J54aJSw+Sz-r0eJJmr>-k<_SDj#_H$W?EJ)j^{(?~E zd%sBs1+?wEH2Fo6#>U%?G{DOIIbz|AOGl3`gt=FnG3U%OqpkTDZ&7xUZMZe2oT99O z^6OGN*qDh{muqQEX~D|$b+~efyQFvfn`Y#pDT=ehVS!P-8bN=kJ)M%9d?YY5>IgCfv<;h!J9x#opymYjDkmM7I)M84_66$;{A!iE@?${)rIR;jQq49C2Z3o2 zF~ugEoOC~?Y^q8h(J3jx8nR+7@$-`}UVm$t_^%NIMpQx_QKp<vIXi;PNft^x05fLmA(_|!;{5@2WQB4iCp{7Wbg=~DO{82hc;-now5O3=*`HkI`Ty!A8m58EJc3T zRNG6ax`#RW^RwTXAji@Y>DIrRbUv}}dYJB8`o7yu8G-7f(QwoEgb$`LZ)5AV#1EVO zrYH1KIOD-bI8>Rts5gu5l;5n8atJ|20giKV!y45M5;EmQ-ljoqT+4jZH=>y@ZwhxT zn>N_I=5ZX?K?j3vD-sTm8PBX8I{tnkC7VT|Y&S#G8yA>%BcfXyXI+!Eo#h*-%uf9wdKUgHX+@a50Kqm&Ebwu;4Q!yJ3Q7P1%N@S(K8c zRzN8nZRE1LUL5vMhZ>Qt?Mo;{E9uOVi~9@qeWRWxEmqC`evz$gcbvrQ+J>RPhPQET zgfVv=7_9lsP(y`@2o`w2BP~%5aC&brY0q)s%3&Z-oIww%+TRH=)}IEBd^Vn?J&Toh z!YW4YpSk!CAPx4}8?l$@@ctZ^Kh80&KRIt*c)y$NCy<2thzj`iE=iZQgK>(^lMZ^H z)F){P7Fkk(0+4b@kU$fhK1-f$vd{#&4IAfC9`S}>)9xRh>^tRVtLy!-{X^#cXF$l1 zcAE0fUqtho^Em?)1B@j&%k4l|A-7J)>edu(sXm>6)%*UhNaDpjWz50n~eS&lx3jqi^KdF#Rc^FlYXCT>Jh_RAt0N$0b zCj@#_utLX8sK~74^@ABRHOrS<=XMPVYO_9Yi7-Hn3HX`sfJ|gsIS~7s102F&SmXf? zV6?@$g3pEYx40UtG_((%=XW`PM5s&dtTT_(Vo$yXyB4R2S;WAN=mXgV2!U~*Ah1Rd z^%%Re=>|-OAB}1aZlA;oiEKw-ojpdMwL8xFCM}%fZau+FC#cBY>uZ#RX1nIyr(y$m z<;i3iM|W+YmG+%ORC+A3=uIB3cLT5tDuW>r>~LJC?>=&=1lwB4Q;9)h^1Ha%>@3yD z((-d4_u-%m!9t}9NZ^HmuR7i}oX4-qDJEDItMkxvq~-_gN?K?@u&=@K0J4lA07%UX zXdn;E_?a>f#XQ~-7+%H5bfknB#%S_VSL@GAl*w?n8r3=Wy-g+YKk_YCJKzGd@4G?3 z!B?NqiBR5UFf%t5jYSOjIJlHau*%=X4N(HZgerr3V)zkG{vd#-5jOVFRb>$uoNf#* z98op8?_MH~j58R?oVs37PLC?OIN$BAM~1@(NHbx`l$9!rzE6#GW9&NbV4JK|eP|O& z=s>MRtur>wE$f`px~+R{3hN|F_r!vuwJ zG*Hql(Ar$s84|AQF?8UGyYO%q5`=WgltRe{=oqN679KrCAcEpuQynZs`g?@Ey3vN) zj8f_#2({zEHEW#2238i3ADo$%hMRecNCoGg^t?7~bL5(CM{5A&necsxzA4*f>!Qk&b-<( z*r~OT?(Lw~3+rNmx~sAC-+A#fRXu0zh8|+j&?ub4){0^ockuCEBi*B*T^F@NdLk)f z=f2+jXfR|D(RSzr)s=Z@v)C6}BzG}a*(5$|HIOYJ9c%c@(vD-T|HGW1yM%qBb&t3S z_m^;m7kfth$adHv6eOHAb}aJ%gz7Wp;9d59cE%oYo~@H8xn|wCi5bX z^k`7&LO)FJq{hzNEPd^}Sh}&OR9GSR@C=D7!dvSiSvwyZWt{U((ddrddp%Md zs-qXc_v+l6O*znRisTcBYl40)68c&H12Q+s~R~JZUbPr0pxNSc7|` zeb)cELu;75&)WFHtFT90UVI@%GR?nyb-C z)>FeTbDcA+N!MWn!S`a*kfw=rQ)u{@B1u;UNBrbTbSlA*jh~rTbpV$!Q#Q83tG6os z-opa_IzYqf#Y=(N=Pqo(^E#*XopL$!wTwgI9t7Mic-}cFJk|zA?s@OsXp>*X#_$Fk0A)-LNpuF-Cpq zZr7dIF?}iDG=3syRS3Ms521%r7OVUB*9T7QOC?A4!`!7#kYp-r$Yr|>#yKkCSD_Z% ztWRq?VvNf6AlF9CAnFm?qOE}#DKn2{Ijxsmm^2{S@XV@Cm`HVXQ9S`fYq^EG-e019 zaXRph?38}6Hw$lYAnndFJ5&>G_4s)STSi}QxVxte1-rVStuQ02(?R6={`tcb+it1H zfA>b{)NG4%e^j7My45y0D8WYY`pDUGA_nPbU-HVx3b@eIVu}QbRxxOSQU@dob7m2b zIDL;ktzu_OH>c(q%II08=`Mf)rq#)U(5Ni-7Yq^h8#rECT?@Xxkm#PRy|GrVnfHhx z_OIY3g^~V;?+Kjp824*CSav68K_PfO3mTYSNbZXPC=Gm#M$ws8?6Du1)G<9YBn^)1Gx^~2sbt@2b5MYOwK~K_o|e6&g0-Rd7-Rehb2@d@J0pW%X3A%p!uvUtp_E~?Pxew% z%`#S8O@PY4pE%phizDIeZQGtzcm79X2r&rExTINaR8B9gz{d^}9vuZ3l+_~S@6-b& zLJT!vz}{=p7ixbBkPeHw4`)6ut4E9)U@&jf3uzs%eb$)6^-{DaK-`NgPU!J8#sedH zmG|O-#|ek65!Mp>Y`9_=aU?ZehblhSY%0J6g8CkO5+Co_Kc@)JB0UPF*0m6e%o_{& z3O3y*1AZgBxft??>6xRvli`~_t!W*O9#$j0#(M~0c(r0=<dH}M{Sm{2q{fqj>39nh((QjN*TY)o?X8_^TUC`y?c-#G$B|9U3@vV9!UDL6 z34BAtV+!vkE3eGIO*m=Yy=WG?2|Y(!r)PYtvLw^lb^GfM;+mZm9JGb7Cg_wfNdL_u zN3(2wx$P4YgJz)WIZsJXo2*%c?1#ks*rLXbdvxQdVxz&>6=XE#P=MGo@Dfg(?VZ8e z^M6vb_!7GM=C%eF4&UwhWobMIlFNJGrXzLbLQGoYe<#cO6pwOwLUcD=J{-d%2FgYF z=G_xto@^2tx08)wfFlNp3NfeFQKqd6#3v0c?uH;csRcGrYZd$EK2;O`on+68!H|jy zEV5nOH|g0Hxy!YX(aD0waI|*K06e;6OK=tubeXf{rEzP{@1%orY8pFiQ;TUWTpej1 z4~d||7c_cI+({7PMU}0}J{Pcd?;F58@U6E{{eWUL?+O>NrBn?xM_w@%ZoDF=>mCw} zj#DJMg9M?x#|j?c!;6F25;D(18(0*)s3tg=v$epsZ|6Hq4@qNW&JM;+;78fGVe=(h z)ecXTg~GXSm#X$m6tz|t8C5XWs>)TaV=sM%? z!6pNl%}<(wRtL54s9B=q^qnl%Vn-T5&6_rZgk(ZO5h2S#Mh`lwEs2n9==2LUWq_}D z4jEi@pJ6R>DK*s)k1FnzZSP1-ToNy2_qFzf!mggUfa&@E7uiqFd1lf6h~P7*@~qMZ zudvQ28!yhD5x#M>eLOtZr9$Pyz>{!>jX_~LM-!mo=o`8``Bl4-x$pX3qraanmh*Oy z9L9PeW&lYbV- zR^)BD@`P_JIscfTdwup~gI$Hec8WJ5EQ1}VuX6RRf2l+1Iyh~B63lTRRlaYQt+DQ~ zWdS>v?t>O^EnBI;j{R;&QM{JW(~~x%5E-S2^~ZaU!@N&;w$uQl(zNYRjP5P1Dk0 zB8^(ttrH>iG*Ign4tWFS#%%n-p$ClXJnXKXZJPmZ-FeCZamx{~z;hvLQ>_#ifFuv> zPK8ui*R*;xtIiB2JDLWNqRheO0--cA$roCQO4A7+S05?N$h zdKF>hK};w`OX6e8v-6|2|9RkB4HPrqgK~VX3zLNp*8zuQA7;rmdp4H%jRkIA8|-GhUO73?6<>Mm8Vs*wm=SFuQ&^k zg<)YosQ_uWxdQ2FnQtm^$v8Ip?&ourZzVJK2attDX|Ze-YlYcAOWs=M0OgdmhJiI4N4WDPABFZxJv!6SbuEawsA#4}NM z#|0F2*&I(dfJ#Ydnn)=K##~6!U-$2>v^_+rcf(k z*bkjC0CKRFFB<9^KM7EkrqgaXMHyyKXah%4{ zfKWL(xf2oay_KIFqA7Enk@X0)8=Wx0vg(d`2u1NgGAa@O~IFNT8R~rwG4igpbAE=h9T+no4 zOp2U@&gm0uoxQ1yBjC2QtoM73!mTS|1rp&4n)8{N@N_$Lms62J=z&Ub-Y0W1eU%bU zTh&ayh=W<11u%q30r&PV@u<#AUfaSGbaC&XvYP9uxKXQ!v3gC8eYj}k729XhAA>_c z*n=g&zkFCK_(QJfRj;&zBGb^^8Ghy+UBfHStAP?)!GUB))FAzFDC~)i#LS@!46_`rQp}}JQq!B6d73por#8jr;)@zD!|d|Zr93Wnz60F90GNm#2jx4 zn;>r`!k+d(NijzfGtYa)kPXvMw2zaAa()4|P|-xAvRV+4Qd2c|hP;c3q9Ns@_DxNc zxZm3YqD$o4xoK}PY{E}}E!uzK7e6^zr8g;itkS7GG2i6JO#O><0L8QA+h!@lt*TN8 zTJn_8Kky~GIpN+Pgu1X6whz?1L-3=f6YMjEkh6z9vD;~41QUlo*Se>385qVf?$Yb@ zcitB?40Np`AUhKPpqR4loiVN1wL*cr*L}v#f23 zW2dt(LNR%+tQ*-^q(Bfbdu(H(g$zOtH~8As*AeqaaVgd;1WcF=9Q8HgrRA{53Vtyr zJhC7BRrAUyJCFt^czr-G=tp~6H@KaN>Gu`cN&(|GiqI~kGkW(UcAAeuO z|A$TckXE} zdr_WN#H0YtT^5n$h>FkLEYDb5>Iy2YNOK=VxuQydUm11P8r*@ecufdZ(ji0~ZT`{^ z@Ol9&!dag%n$9uNNoOp-uJmsPQ|pW7Dq&uO?^OYAg>iakrn&a#oE!asOL>aV9MwF{ z1rL8n$YTR4P9U8-TV0KzM5SS1&&nTOQKv%EbilFdPtJmxF8 zL?4H!lp`K(!9&>c+dsN-UXHjle>$OyT-x z`n52#d}B)+0)D6)a#y<({5b&<@O#d=N zEX*Qjk_)>ITF82O(tVM@mkN~Fnzy{l(%q*U4QYTARc@V+2U$O8OAkWOnIbzjP#j)q zrFuO{oo7q{Ti&9G`co$YQthVNoUB7uOzP;oTcBT2s&wmReCvBE>V;pd6QL_^ijg&Q zXHXK4^u3MKy(kq(J)XV0tu9nUTsI)uRoFY!A2NJ%5D3aax}{tj1gwA$dcNP z8M(MX`@&~@@dd3}(3h~EH7?ztCEN6h4$5K#I+0Wx=~*epg9epGZ1(&tAcAOFOjB=& zdcwMpPrUC_G;#JS?>bh)9gc$Ps^KZ9spdcD>QuzlVU6q=Z8H0bb&?986$_JRB9>nf;1o1OP^Rp z2f4@eIHcJk=d_PTk-9?WkDb@%ekchPE^n$5JG>*QCz;3!;BN>I#rte6GC5!0#^Xdh zCCbN=XSqRy@%GQGK1j4~`!||>*8(z;)K22=D-ng-ntlb5{VmZ*4%HBH0D~oCxJK|h z*nE>gT4#@^hGI>(_?+)XtvP@fI2BcC)`eD~@evT58?`0+Y_-m^4d|@WY!nhs52TcR zIW8d*=TvT|m{H#c#5{|R8*-FpcwOXa^4o@B91dMYl&t|cFqd4<9B;T3a@2-O5%^N< z`l!a=Ubt!Fo$KaI>dsGRw`3o+qJFQ0Ym{sb{_t8iyCPtQIXIu;9k6K0QXEGJ1w7ME zHpe{9&7=91bW84luIzT78pN5x`Pu7(=Ib%^?^5_Rmv`x@lJoMQ0eLY6`ZQts7CQa) zvWr)m#5$Lmvx{XyK|?^3z`TFtAJ%T0(pYyxa&EDSpms$*h>hLDfT?_)mt|Cgo?Yj=rwPP$?+j{!81VJ zq4|k?{?P{yo5}qXHXCYX3*3~Ytr?x)3hS0xKPgw|CeMKVDSeNldvVJOupV^+mBt1>`H!Sq?|^+N0b&?nyJ(we{pp zm`tW2od4VdDB9~T+@XKWy_2^rF&#Q2#3hLiVIqC~S%y2+Kk|EJl|9Jwc|DR5Q$>8lNc-;OX&c;cV%8NeJc6}Xa8KIl*~w@ZR9S8H zSrGP~+As*wdB(6yJF==-AYn~w%yKo?jY!h-HGbt{!;?lNl5X$^2-*U}1_AgNUuD;$ zj{&z%>(Wx_k$o3IiMh=oR`vO&qLk#L)*~eZ^{lH|f8xS-vIllMsQ9cB8n+kIR7L-9 zqMS9Nv=NqW9pS{9~^MrlB7EA2)e zrM>xWWTS-JB801lMvHedM?fd@ZOL&+8gsB7lpd-_xT<54zBu}GKOS}SVKY=Tr@}(k zwuYm5t2%iy3>wA{Y{Hl{x-5k8rl@Z;@eCRoF-T_u3k#-Fk0Qv6i;X!EN?_Mb8Idsw z38jN%poFPeX2bU!z`~c^t*1DxnOPh9${z9X!xDxI|5}_F&y#YR55C{fbKk zoR~t5IEZqZ%kOTmh#fac@)Cq&jj3kxj)R(9&9yhEu@xaqT-Qqg%(wMm5a6_aLR#Bn| zj}SfQ-&*zv40@)S_p4Eh3-v06gXrYni7)>sGdwQ`2{N9Bt%m-BRw?wT|3Xj1c22-M zIpmn3yoEOC&zTz^^;`fvTytwblvK6+c2aa1I#3=&o)4h-i*Y*9PM16RO|2tN5`0{J zMuX*hgnu}|4QZws;}LBz3-9o739QH zF0v0MHHAYOruHVxS_0MqzLyD)61LD^lCG1lg2lbzczy3G!BKi?IXe?af*#(e(?dEn zXw|b`lf=tdeUk^JB8Yi5rot{Lb~kz+BAbjCc<&5czpfH7_&)cIfcQ|SQGWwwYx2pC zn35zD3O{X0@3chIWvLO0VU;gx)vv%hLhp!kFWK0M7Prj?GS!!?B#Z=Fm6X0v&y;|p zj(7Dk*CZS@qXiHeY1rG6Yp%kzhk0MFx5T056~8p%?0|~4*U;>cDOYpvv!r2vHtE+(c=Y-KyF1#kV2U7y!!`2HCx(LK^7T zT|Fk`cj>>^4qITd`4g5Nd-SbbFaKopO+FP0c-$!{}AD7qS=i9ZVJ4HtIAL(IHnxvV52x!xe0;Mv)2O7d7sL%qGoM75y zQRF%dIHVz(*7Rpzv?G%vheYe^lb)ew`oa7GzZs~XQ2H)CQoMp)j-bA#W##)<&@qkEwBNhIyLr8?vmIH>U(JWu*-0@|(%RupjhIWS*XeeKuWFr$5dllG`c$(W=}+=#TbWC|hTomH(`a|{;T=-#JV z&SDb?-l$B|8J6y(IlQrz9{GimG!VnN7vUSb=~nmK$VDbbaa^6Hmp?j*6(ORBIi5vh zvZ2=c!ct0vD1w2&mS@f4G4pY*--x^nDn%|OUQM4Wh_hI~+iGrG(DG zmEviJ`WV^2Niu}heBk`65%c}BUP*8)fdd=z18>ON!IJv$hi%<8vGMp%mn%{Oat_{L zfS8_8aeeT2>{>1ya9f8wnRO$lkuIKu7r~IL7wYwl&7>^(;znj0($dbB2I5Hs&gZTF zqO+*sWA9g`cYo2kk)v6|`OaMxta%iBoqYQ_inZz*=6EvY3cI+PDQz#oYEzv*Zfirg zGk^2xjhj*_RND(AJiZijDV&R|3O$ZkBJ)Q%r79d}cNLB18B!^GRJJRwp3}%SV zBw|&_Z@x*r7^ULx_L{qSUnD-d{>|DOekiLLXWhX8ZxTLc$U_*{*%gn%MwaQkeOxVIjM;2oOOV#N})mxIe z9HX$Sup>^IB{aVpvu>BlWkv;mi2)?E?z={@1UFrU_+=&s)HnwCk7JWa3t&xCud5u{ zThPWFV4aB3c^|J(G1zljW+H#%Dy{fa)F&|eq!5*k7$h*@=r^>Uu0;gQ?#LPJ1vi<@ zCKJhSJa9GTPl?TlixhJb+YD$))Jo%6ZLF?*u8!15+w`&KI}G(%R?#9Q{#4!qrUk?w zL5qKl4etqZOr>zO>gxN#N5gwo0k!9w9kb55qX=xwJlzal-6pKufJHBw_yOFCfzv3y z1+o^g1tPs(!$DSx^1ah4Zx^+`j;S@D%W=K-N+nz$dL@p9fMI*uC3$-}7KNz1Gdi=5 zu_2q!u5-zzZ#1fh>ux+$WKG^U7Q%;Lrmk>`=emz>oc#|CN34_?uJmH-)q*#@jfJ zLq>hoe?+Po`5Evp!gx!Aguw!FzY?}lwj#heV`p@;h7W>bi4ua|L+hqy8FqmO%xpF@ z;~g#V%#UzO_=F_2MS+wtyhLq+To<}kr&w`rL)c#m>NO4pi;aKv$?n7fE{TR>6{ zOc==}2s2sf=(!9o#0C5n%kN1eCC=-4BHL=jFs#VS$PH9IF9zB#aX$0beq#w@zqKg4 zrtQfQj3sdUC<+XMFPKHQ!r~60j(jA=_H|Xx&RieU1A8-?2fN}7w@9etK$FRmfeq*f7F}u4Eaiwt1Uo&lJAhHE-24|mmTWlL=4D0J z*31qg9GpM`ZbV$C1R-Z+iMK)sdH(@vI;&UKLr;Ft!XJZkmvWw4z?I&E?0XclWH8|w zV8bW~iTG+c5~GZ{7vHILm+bCoh(jmpK*hk z*wRO~{l(~|=U_euF%7ep;>FrBdg4#QM>uF@Vlr7Ff?3*)G4-9D=ufGzJ~}kx_Uzkd z83X}G1!_tEOCS0gr89PM=#p6j3*alpy*231FBC%uI)VbBNB^@HMtcB^R=6+P8P}`( zD+8%iM?ysB)uesdtp1(;G}U`_w!rHiGe(Z!lALka3cl#pr%DO4HPlTECJ_!Jon4Wr9&fCVwQoz3RfDZ1nny z%9brNr+7L5RNW^{CzNJ^PfACqFFElsB5gk7rs!8nCd8H-)MB<`WPARF!%$u_4?X4; z#mR{331rf)|Nr#|9YHsOOmrSl$s@Ww2HVwqyt;nFD+B%EgNIT&lrRD=poQbne+^l^ zcg$U@n3X1WELv`o53AwJhVfi2VAc6;$$eO@lAjO(A`_0zVFiHH3DSKT=+#=8HZ;8b zgY@wg1LZdTt2&XOzEWihSK&J;kPi7NEtmXk6}ZHo)f%BZ6jJ}SYDnb{rM6a_*_8}m zUQk%Gq}SQ>G>mJS{?nyPTK7Xk)DgXtiIcfBext`ms~=~FBI5*{1ne-A%^-M`8NAvR z&r(Zy3QgeGC>sk929eyS9D=m2`hW^{JdW%kq$@eZpd-aW{Z6uQU(! zOOo`*IC-R4DzKb$g0mE4(ai1N{WmSY8PLX*++J{*MxR~~P<9#2&(qEdlXvZv$}1>b zPj|*=Kf(<>CXTz}hs}O_2-#dZx9Gq3h7fq|n?93vTL&ofUwytvnDyDaapCQi)dPrx z+cS!H#q?>WyLinbCIhvbKBQTNS%`0<1S`YDp+X7&QuZCH&A3h4^R{6&%gl!lEn6eP|Ln z$eVfi&o%0g@S~mkF@9y08f|lDTEl7%CHAA?>m-w^dR1x#mTbZ%nu`#CK(JIzh)_7! zBGE&XCt>m%6lyX@EfB+E!#|H0;Rfmv9qD|o*|a^hnQx<7)^Ni$fG3@L>&l3%N}1In zqqKgSei%{VDsu&FqKhOG2}zbGJPD1EdSqqfS*i(il>2!jcnBKW-dowt5{*=%S|n_* zwC>i=JuvsYn`Jq@X-HMYCH1R@J^%EFz#W>|Vs0a^PT>y>VERcanCovs-1JFDd3wgJ4($ zYtb8nX`H;2fOa# zGYc^*V{FDuy&NUkAiZXh=p%RDOmqUs3;Nxn7^qE}e&PE>gV!7X-ATngdFL)nNxNpb zRssdFiUPl}QLyJ9=w?@E9AB{%=ct_Gr`6yKV{YgoCA_}Luz&sDct+o|)?+UIfObib zKL+3Wx}$Esf~2RlZSdS_ZX9xh$+HG|-jT5CgW^B^yRo|=#}TZL@NYOAFwY%PJ5?JZ zybDTVzgeY%KMDi#=F;;TTCw2}OzKRg`*=-&15KBt(f}+j)!kqW+hUqbbbtN&r@v@3 z17}I0wGH~ctG9+zy6)9(GqHQr3p%_}xR#e~HM3CQuJg>1aXg>9?k|FD_ERRT3sR2y6#S-vHIHq`b9Ql_Q_SINNj{1Qk*1)~%di zU$`&!P{1JYti3p>s$@0LeH(KQYWo_YI!_HCHS~W+Kk!d_Het0mf7oENr8~4*Zv($_ znXqk@DJI4Gd<%LZugn5>r1u7=U(C|(_c#2ZfZ&+`X!9cB}A#QCI z9k5VPIy9IjR;?sBtEK_!Gy%X_8oLo1hrJ!6pcLGZ?A@S$2k3Vjz%IV!&AWnHoxT|r z++14T1B<&pA$yfion*L)RX=hF?qELn`O`moHCqY*H;{_|I@!9N<`!$!oNpofA-65uLr$J`?r%LYPDruJ)|m1 zd&L{b1hI~wCS_8!kDGwLC5s$@Nxt3SAs|s4J~b5U12>4&Iz6xsY&y?(-6S(L)-~co zE3qFhaAaxbAsPA<`{<&yu7C111d}}E?*E(=je$0D(KYutX98!zLXC^!)CD5MFk|D^ zP^aAxxL!88zfOnJPoCx`wwtQ^2QkEz^)Y4BN%~6U8q|Lk(!%N7aCJra<#{~DgoY)w z3FW4(l>cGkVdeo|!wPU} znL?g&;BORJK{_pMC&$jnnC6Ob`XphB9&v#??gD;-NXh{S&qu`^ zs9Kcdz$)f2p~WO~f8FEE=8b$Bycd&>8CDI2;)rbTx*M0O$@@DxN3L8Kr(m{Oed^Jc zTzJROM7S1;UK&{%ulB)QZou%g)iG$6pQ`pp} zYuX>RoCWsh6uonHQ|-rL^d;3LSRnFLJF~R$GTD$So@pK}sgux6Uj@#O-FfGr@66s? z4ypaBW(a!70$XdaKo3~hOpKnAGR_uak4ivSKHxwN#EyStb3Bo|18BHTY-Z_hiuNVQ zMXF1lFuJz%Q;%VB6ewyCUkpSfT;XXdVq=!*B?uepsU&=x%y`OAS*R!|VGiBt;;fn9 zouJMGM_|W2UYOiEWeP+S$!PjY(o<+k$6)M}TOmu~t+HZ)u10b3Wu>>h1E)LP#$)a} zciyf9>8H3V6AfP~98rm9Rhtm-*j-RZp093?A?f7-glWvqa1KrFWx$WziaXCR|6AT-JS2{zm0zG*cyj)Foa(W7?bWp0 zizi>^0D?b-_P`_&z|S}SQOo*W%`2t9;$C~X0x+q^$dLI?!-2qoopsBixc~G1pHIy) zQ=QLe)i?pGYHC4GGU>>90vJ0mREB9*v?0ahzuX3cY(b+FYa?!&1(_i|VGpEiOgeDx z6M_dN`}IJEfyLk(BgNCB51R$HARCRvvPg+0d657O1?6Mb7|Tl?|5*2J*|zzy+2jDv zsFVY}5hVM}!Aw+iN!Yv&me;6Us1ikl8y3{P4?}&;KEITovg}Q|pnYCc5(k*J4Br^vOoOSA^(#Q7ZlmROT)L$c$WKM3I=b=PHDR+tE{8b>1O42?a2JoJ_j-P2J% zJ#~3V^AALh`&JIwRKVEQVY*CWkO6tao9H?|OMZqWO$ADKT z-O+fsyn4kg1^MQMGpjie2Q9IE7k9A+UM4>>J;Fs|FZELnX-O{I14|)J0Mw)Hn|G#0 zF_$46;%|4$Yy(8DaPgggTd-zlnUxk=SuxoUvvUCQyApDq;0K?QCM02E1nu4d8EqdJ z1~WsX>?FH~p?Dxa(=D@mk6eS-uJy*|@qD^CJi0~A{d#5v(<|BF|IRVH=eIHboW|eM z-9m+;&vmoS`-jhqX%bl$X@K8x2qfJa#`s=vxwE2>v1}O9CZi8555hS+_Wybe3qwud zARuaF$bKaCx@+_KT8Ltq^XHJXv(dl4yI0h8sX!gvF=yP%&px|!Q7b~w*{RGQ$Uvzm zEUNu)|2>c3nPvQT>yg#}(h_&Z>}KI+El=F)v(p*G+oQ@lgCv7E&gL)*9cP8iN$>hp zk;T*(US%?EpIFAhmw^GlI)SEtM?uu2q*0b2TV~#y(LFj!09J?@VZpKNEqwk|LKAaW zW0ViQ4`OZ7xZ#yWtXej+gM45=+5YE$nY*!&l}WsZ-gL3Mg5h=oGKTL9*yQ`zhd)*KMvWj?-Gr+eu>%qo}##f3&tO#dAUl7oxm+#(7TIE@v|WH zHyDa-kmAh=#!Uk_X_bHPv2Z7-gtVsE#||+LI6tIQct^`#!k5&DF}aXq$O#B(l(smT z9EGE3bG}~F;4^ZjDuunKuWhHnI(9h`ZE_0&#Qpje!(Pyxg;!1^1*v?D*f&&XW9nzn zDf^<5PT|f1WTlP`HLk8aU$aBPFp_~ZBKK5r4-DDw(peQDzlmr2FRn8_kf^f2(;Ckj zASbZRU{l>kG>XU`&!G-=U+?a}h^ioggpjQpPi3Gg|9gKSSNhCW(N-OA{Mw20+2{L{ z>IS0}qXh2O2r4~SC7(?fi1u;4;cx~fQNR2uc_?4CH7iUFs*6*r169@NZF0xA!Ujsg z|24rKG4f@jQuw+-#~LN)S085?-b3AGdzDD!8Y+GanO7!2V@HT2!NsGLUuUDY6G+=b z@nB!eqxLAxW(C(oOGT3xv0Se&+kn1^9lh~|_q~$DsO-{5`&D9xsii713N5_)Nj9+T zI_y>>!tY?C?eCYLa@5ip6089+>7ajYV+ZLr1HxOGxXb$6+F?Gr`)avl>fh|Ql6uCx zVIrDH>hRdtvRX$q)ZH_F>#;Hmzen+xS6BV5m;r%L`Ene)jT|Mp+_edo^g zyZM}AX)Mj|^@C?@a7Ib>ak|M}GOuP!j7rBZ=_hPP2YEyLR6L70r5}W!Nd~%a z&ep%bF;I1B8PsK{*4d914A0L0$A5ny4RN%fiRrbIEZ+Q2_5XkT-!YxQYC+`>>2I2e z;g`D|FmOCvQ&tXr6{cPO>mQbPcRBDn84Cgwu9G!DkX3d%u}QYZ895BNS*IS@R7CyM z!~gXESpWUu?vtPb`0M|5|GAc}xBWN%ZJ7@A6OTyRqiF)r4WBnhgb9qC?<6ka1IQ?n z+$`nU5iPAVQ|QO%P+v&#z4Q&Vu|1>BUFhVr~H;#xUFVGW~ z5u_wTb$7){Q$2mFI4n2&x`1^;)ed*e{XZRNJFXHL>TBw8Ar)8;=h!mTa}e~s3ca+E znpfX>>H>-GvUk?Ug`-Ebns*zAqJNksH&&5jC-u3;7*|)$tEjKgGvWqN_szG7^(=hvln^k6Yl>B5$kZ_}D$w zVT!;sOiv(%^ny}s0hvXJvzC%bnn@CFdlZd8yNcho8&v0{AZR2LinzhxjUtTy^?wbv z7R}9{9Wela5)phBLAB@7bhjF;QR=3G-E*XPOf67dVv5lNk?D+SgGE#J!;u~Z7xD9L zO+xh69IgMjWs?W{bpJh}Ga3!~*MA;;jv-AsTTw6A%pOptHcoCymI@qJjs1Z%Q#{HS zN%EO%E|nVQZ`pViaD-giW>9CGNJ*rt$Y*686gZigGu)BRU!=@2qptAhJn+p>68nPz z#msgntnGBHu>S?f>NF{zLEHNJzleLs_sZUM-#4~dNyWD9ifvbtif!9AE2-GFZQHhO zSCTrJ*S`ANd#|(B>i+dv-RCcuFXkA}xSuaRw@CK6H8-OobpbyIr?C0Gf@Jvjy5IDP zig#_IiM`G8M2?KLjOITA@5lQd$iPc?p?^{Rf;40vTykf`wo)V?73uQI>4e0p_6S`1 zShnNkT2K&QUpGIBa&mzRx)pby7Wwo>$+yEuzr9?bcGawIgr9<7M?Qt-E$6OhU>~i#_HZvuPOSokA8ixdNW=|L9fv8bQ>n`yHp2{w4*@-3hwE!Zw5JKUX3=-k zXS|MRX@5wLD{+{@9_x!)yovBH=9IpZd?Xv_{&ukj0f~jLOUs}u`(mB_XuWkR@-d9R&FD#75xs8R$^-p};KczR0uqIz7ypYorQgWAK0!|y zntp6B-nHN#-#;9*ioL0EefM*&)k`MNCJRi!i3Q?+j>T!Mk@vJMW49?aZ>~RaX2Khj zV<^!Vetw8~5{%40QGFNT^p~;>_gd_~HqAx&6etK;+TeI5mg9wCvzoI+NM{_!V7-d3 zk`+5yL>g_m**kdW)72?j^+?87qBd)Y%_{r5BJHx=*xyj$3)e>mG#n0?=Z>Uj^X*m4Ueccw7Dzb1X^|LIgkGOX;wBDGLlvEUQ&$Vb@{2f!^A zb3S&d8Iq;FtI|#41}XY2?qe7oVie9$%8PlwS`*-lvUAF3wOVR#`%J4tFZzu%54_9! zzI#s}7)K7Q1A}kOLqHxz^qsiDx}Qs6m3Qc30x5C8S5p@lgydiR`Kf2#vEQjiOwh(o z*V`*U;qYDi(qfrTw~_j;nH_$Rp0)B<_u*P`R1R z#D-|7+_dzf3AOr)i%txk_@@R{ypku;FWa?q2@FJFPQE%o$KPkC3 z0MCCoZ86a{7@@f*>gEyP{+XS@QD4T-KOuR&ylQc*QntZdY|C07E_5E6uSG2JD`IW) zO^Z_@7k=(i6bW@+CPjXAi?$0EaR2pqhz^NNZWql>2=6R;k81#j5JixLmpOH$Fx_JE8Zs6DOgqX&MXg=;od)}E&=@A<> zjZ>3(Dy>@bt9oYWUJFR#wW)`kg!V4W@%=aJ74x9hz_s)Xjx96E6e{QEfwuJq`jOtg z$$Rg$d9(xGpccG!FOg|HX~EU^irZG~LG3w5w{dhb|L>Fz=pq@w+Iab!7U5om-T2gXr@vrjO) zjmP#10d2jC#hB+3&d_#f`BB{kObe8G2uyM*rQhJtO=HYJCdZ6-SFEglyW&AW0rV$W zy~Rv}-DW%N#@TT1e0f0&>#rUOWw@bOEN0B%Qt3z0UtYvkNQ)fJBMdiP?d-ksXu|{g z63eI|b2gnh5jSk;IJ=#NN(4vJ6os)sIz$~C^IBtzaNtyzwk@o=M;u*$~o z!!smOq@Cd*M43sHluazFz5Ob)Hr(-;%h^Ca-1m?1Qz7WwLoGG+V21zb{N?Z=?QRRT zN^@dqp+*cg>&W|!*nuB3bW<^?!v0!+%;p$%oEcXOZjjc1r3y# zNR%Z)OW(~~3d9upKG4aFI!@lVl^oOXANA+@KZOj)KW=!tBK<#6wXtF0No^vzX=~+R z(!K|I!f?qAxaS_gN=}bomFbk4VlD|37#84J`c?XwVsvgm3baI0yc8d7Pm9M-n1t5~ zt3W70(@l+lJRKk*lTezobD67g9SVNiasdASdU;EdFMOx#;7|?dv?5JJb(5eIBnNDM z6txLE4qe|6z(_w_QDEUPd51`FwdsNbkV=zvMT8P({iLF5W?kzW_mLFmgt7`q&(z%#h`NS`^-=9#& zx(?z3%B!^6=g)OUG@VKv$09c<+C+rnWPaK5DmoCQ8|iR~fXC#dHUzhVC^b7{o;dbi zSBPMmL4-i?vuKRuq>TPv^=aC){$st)36)kZ2XQ4x{+5NEsOX%qeiXl9`2PI&{=<&W7$LCQc%t@tu^voeue)`k0MmCJ zSc`x(cvol=4Ptlh$R%&66ZR4GWJ664?1&H?X5ts5((6|1l10wY*d31A)k)^?p&;G+z>->bouB^u*Lq*CFNqQO_!U&s z&8d~*jTTdf`c_(qVs>I4qZ9{~PedD6*bk>p>U z|MmEb`ERvjO6$CuT-zagrKMBV^W|{7K6MOu2uT&R%&e6EbN)IDP$@DzFwBT=BLDM9 zp~10%&NHq(&XsKZ0#jiqlO3e_?s{82f5RocSJ?!^2%B$f1r_Llh?s%hU0llDOzKeq z>M8&psEOLH?npx*db2|>S7XGFpC$^lA1cqM7yDsOZbIW&VSYX^Z$PS z80kht0P`1gRbByG9f5Q4hXXf|j|xJQk`4LSZx>rou+3i>#9K)lXCS7@k2wRW8-DIP z_X;CJQrMx(H~xl@nA1_a?y+k4N58*rILXLUcSsr*AQOv}@>G2>k>q))bad^UTSFt7 zOTww+M9Du$^4yr#ToR=CjgUcU=+}9aEjJ}rAE@r7;Ixb7R$8G_4^3IArAf0mnFOTJ zGLxbUoO4c0Czjn9+bw?WxIuqcUSKq5RLyY%V*~i_fcZ^}KDQus}+iA_sTaiB(YIp93Hb z;;-u(`9$Tr4CT+7hyapGNLIKL<_Y_f5=k@$iZ8Z{Kt*FYV4Ai|Y2HG$2 zKl0W<;)&ydv}wAg9jH)^r3m`?nw?XdfKW;ty{4aL%-NVHCBH2!7;Fby+X8!^eRCM$ zgBX(}Snx;=zzF3rwkP3l`Ci<2=uuGRdCV`B4C53)#f(%84Zq7>@q9~Fb;Y_s10 zuTp|AZpGS-z{50}epyCSw!iXWEy`ea9@^qG@c{e#rgD=!!Lo# z$(N>lKu3_jj$URb8s|J-Q>&AEnGRSj*POmGkoV9(Q&rLy2Z5dINbHBpiShvu>mOB2 z(>l%l0n~yU2LU!UhEic(J_(x_Rk;}5W+0YdYR}zLzlJ(g$lchQ*lY~LUS@`0sbQ*) z5HjgA;mkP3)_vIU?bT?eB>Vjf`{3{ze8bj3H=KPuF%v>@aLZ_B+d5>&IHJ2TB9y)) zTakTk{NZQT0DmGNo@Nl&o#mZ8!8_&$Qb-q?sC+U8PJqP)3n7~e z8OIcWK%@Ep#eWL|u^D)h=?#~g%-4psCv_1XV6j4A9?gBDjJ;3iy@MqsrqN+SQMEq5p{@3Bx{!lBAQ3Q1maU(vGmy8n zNeo&ls~#E7kZV+toYycwbeVz?ERWx2#PikvA~3G6+(>tje4OT zoRed*o0ore=fxl8*vC)QP?**uXAxI_65iAU0>mDL*w6f-b9hupJ`ltp#7#$baJd=sC8F~zIuiBN{#~SQG~vC zQcj-uNKD2AOd_RvjC?Pmd_0Fg)P23X|3g{@2QGqP-FPYoU+D}i=j8yqL4R&_PKwQ6 z72;jJ(`}T|uY91~i+|}C&w9Q<0lymrf`$?Fx01 zA?d_y@Nyabi?0$6u+1zvHd_Rcv<`pYd7D244f zqc345C5a+-?J#yNbN_pCyTBKK{%f2$pi+tzvR@`}`pzIJ+Eai;PjKYo9ls zp_BM}APLJEC^i$nEf9&YHgh{B^4Ie}@V7(e2S0GX=@hlde zV{{z_#t*D&G+anJik_ZMp5_%RsGmNhwDfnj8_Y&+49^`rC}WODH2cdRrRf91P74>{ zF1rrVeNp=bkKc~%m2#MUfG7J8Iyq*?#+Tkh_BU`ZMWcJk4}xV^$W^5F8X)^c`rmIc zLw=}+wxsYnrPFlKq&^L5n8Wv103EbyFDoLk5Luv?e<1{=QoFu98x>VQPo?NKCL#go zpMd#SW4Y18A7BAb%AW(bB&fLN|oh-of zlVeG%H%P+_W_$6~4LNf2+-e-Wag7clq9elGAZ^#4y%5b#U~WHzkKFw;f2uehUO9$F z))D%dKRxi46x-ENIXQ8;PxTK(kN=|*vZ08*rNeUZlSvlhm0-N{=rs8Wk^C1}QuRR< z#LyQ5m_(;Ol^o*hL&)vV{OjclehI`Mek9ZCeF?~7+uvNKY?D)jB~-7>?pZ=#T}sL$ zRHBwmCwNLBV~JUo0QsXdz82;ibS94|lB;Jad+CFkN{NAXdHK!nz$a&)K*jb;;TAv9 zfi&g!Ukz4zA=vJ=Jn)5_UjY|c(Wg;AIAPV63zY*67*AaTlY~LhGv4mKD+yAkW+_p@}Jerhw z^W`=|P5H_~|M4*pxF{x$C<{(M@$?7zxy85FJpS*fkhCjf_fPp?I4p(8fcXR9Kj9Sq z)%>H+jTh=H{ZC4j=j9$2tYWDm!t&{VG=GvB+0bk>u<>9rYv5hyHJ^0IxU4S}M{IM` zS-((8(c9KObm1~T0l&%SU5mNk%r}B5!aY~;RL@#}u?y)UC+b=fN^2B}Q-SlMDzlyW zEygv;7;)BTqco z=xMU>qol9QenWwfy-+lPn*Lt0G-1RZCORbQSzRAFOOydp#K2$XZPRkb)glw z59fGtbaSvwy-K|dpZRB?JWZjW9`bkA$AzOu41z296+q;`sm2B$?snkd2}q4PnbWnZ zXYR z0>FwH!jo0+F>BgX1mCa|>BuRVHTDEJ-6V5Q@dEtTzhklJGYmh7IovBnF1#WhRqwj0 zWh}%KC4dn7Qg!^z|3nBCH4mBIbrY7!9?Ic@0L{ckE+}BGR^=0zk!?d3`h~EVhJ9V4 zcnQ(#wNWqi6cPC(q9exIt04w|K^UNa0Q^rzjI(IiAVK4R@l7WIiS)hl@cc&RMx~RfsF~+eEzB`^xCZTErCtsN-L* zI|h#`DR$RlQVZyJ*S?+$M|P9$1xhcGDoO0rf%gja{=P;J(pC;``pNB(O4UY{^3bnl z`pK5~*lYg2DF4sskLE$M>FL@lB)%~I(@@HJwosG`V?Zwe|7Uvz>lEPsRLNuI-x6R{ z`p(86#SC}sDpCQFYh;9A+39dblhfg>(W$tuGyIRL)DC}6YxJ)~h?>9= zmaPE)W#eN>;cWll8YBDtkqz=k(VD^^FCr4}$up|_p1xW4L)E}GmRv5LD z!S318d?x0YE-^(|f#?iI^ub~&d*NsgLJNd>w#Fg4tBzLIZdsJUK3%cL42B~i6xSXj zPZvRICB{d_S&1!_z!4q6Mn)NRLRkpV#_DGYY!{1w{DtFX`Sb(^MOS#jA^efAw8Xxy z+S!@gV|rjPW+Jd!*p@QRjxO6(3X43{8_{I<$@#ArWXd!M7fYQbed4di=J&Ngzr~6i z;prg#zM`QMh)&az8MDVM!P?SIB@@|ZCenP!!$-r5a_dePXU%}@1a}@dK{)LRAm-Mo z!aqvTfff>`X?UgXJw&SM)~(jdU}4nIk~BAq_L(Ut?dwgFsFo9+RMLXB8v)}kj9jHf zHMSTJZa$iR_CM;q7k(DsrIJV_Q#w8Lwyf6C4t4j8-+HdhqU>=8G~ujz2uIAkOL91bmztuK%mGsO z(gOMAcO)2UG``V}IO&7IF|` z|7lRKp$;m^JFk`S2&`UOv{94`1d1ggsr4a+N6f|z-$pUrC@??iawY6oi3=)IldyLp z@=vWLi6P*&<%(0xyG+6dlHI1M^stM!IPh_G3oK=c3m;9pj!R&XIk=lgakYwUgf{Tz}9LL1MfRqt#ZyZqT*j8})fMoL&j z-Wf<+^`}V}BzLyXpCQHU$$l+5U*1k$XNy>%yl=us8 zMUZFZR;NK)ui~C!H}1JlEc59c8SHkzhbx<=OZTi93vX;w9M$7pGz@T35^=UD9YYUa z88CC$$6y4^_Ai0;=j!p>rxPbvnTml8xmGFTG^2K}$hWp3zci;VJ@u}&WFa^|GNT$ySPQQUDWr|Eyf5fiqP!kG%O`@luWYOIJ#^o-R zcZMG*xL3v&SX(TBVn~=vs43^T-(Gis@sK+E5{4c2q)gm6WKIa9Er{95T4fbi`2?M9 z;W%_TtVc^V@Y%l_*Ie>4GI@5|b7M!qB^)`;=Q3{=AF-K5l17j~1u@faZ7Q;In!Ye5y4iLk$Reet z&@)=4%ag_&;bOyLzD}tyyDP9fU%Q|2s|2b5`p-qI7(;+5@AmhFgr<31`oXx=3$)7+ zCHXTGo!eXA_q>QGyfi4C*u(F{$0odwS=?%fpp*+k*LT@KUl?-X0neW+=M|SPOvr** zf&qhsIeiHmy|(F@)9e`RI*VsD`kW)r5V{cOOx{B+bM4tSxRZ>qb5St0K{$39cIZL9 znELP9w9C0-sX>7cBL2`+#y4(W)MM_eT)jQ&nsNQ^vaMjE!mL8LPd?iD9=a&$CDya4WJOXkMFEOw>a`K=t(_Q9iHIH+JoDDf z>w75-5mz~8ao=+<)+)6#Zc*r>X+0b03-+BApns*lt15Tg@{jkgE@EMWgiHb_ww%97 zX7p#Wg94>tBIM>WR48%tPD(W+2>gVdOToM-lskj$s#^(i$64-JM9^F>$?E=vT2WY33z+{>%qkv4%dp!H?Ychuhca1O8(K->RrpW;F8@)3%6~Nc zs^3UwC$A2f9^WPRdcM_e!Qlr@# zAepW9#*rLUN~)j+9tq&Kz&HwD?U@6ooPl=ed*EZV6dj}obu~1NBGBzE$~@#e`@fl{>(3h|(qaZ9EHMjY(O1&or>+t4(zBuPhD zFkwa_1w|wCN>3l4e=~>^r-7H@K(k;MCBpdw_MMD!kxkZkS!n)>->4C|m1^8j9y+sz)Isk`^Si% z{bPNqD{JBRLO~r27>4!9r`IA#eD)Hwg6@Ydj3o*O?EIiPqZ($QN6c$;u=fvW`W6gC zIRe-2dkxHHUs#P0FZ3hMN0&!>5{Z_$(AKk2o1#gbE1e0dD}TWJONro1d}gHJv`wk= zP}$^N;PYjF$Mg9rAOJa<1qZK+=GPUW%Xz)q^JK{99>?s&R%3O)K*qR|9_CDXNgs)9 zz1sJDIz;U&?v8NZ9QXU^kkEt{q3mBPr67{tdpUwINqfkUS$2KCz`iY&b3$KHgq=S7 z$Lhy!$EtPy=wu_lX6-pH*hz?Q1h~em;~$VL-vw4?CgDPTP*HR6`pYZ%+bMl&AU%bl zLv=8_wOkoUBp;8F(Rv6u75eD9RuNYiZUm!PIRO82@?yLB~Jqc=!hlDz&1> zW`7T5!LcV+k=pygk?Vtg^Ql0Cmtaq_{7X`enRWm@p`^^KrhWLE$up`riW!y1pw-hd zSuCmOq@Cey+n9s#v)>?3_;d>a;0Wq{OI%ze_sY{u(?VZtp8$jbIJF zr_|v*v{EU2)8EGeaVz`;!y+Ot?m6~^pbr)%AMv}d1 z4VmOg*| zS@Ili7S_-HyNqbCTGi7(+kfWaoR_zUAglKzGB8R(f0BXKtMg#44gGc+oU1A8NPxo4 zcP3@vaiM+!#tEwV)v`(Fcm%WL!9|$sJ4>bbH$fSPcTJ@P!*(!^jPGy#av5Vi8q{7~ zZCnnfQSS@mAM^-yXDGSMxky$#Q`-St#LnLt=46M1ONWq%S^}fCA$QzGg*G(-_rGpq zYg_4&9}Qt!geR*SlAv22$#Q=^{}kWdC`({ZUrleS?SDJkb4LPNybYO5kqoZS*uUUP z|HVR{bXcgvBdZ-8v(n9f;cd}|n`2H+bamDAD#^=-Fq1oOk8`gKD+Q z7aTGX*?XQnis3l}r^{7*-M3K#_xU(hLBE^C60Ujzx zv9C+XYKzX#4w+4vwl7ES5p)NWgb-`qFAj_<_H7e}^c)ejk)$`5Vc>7Ev3P0UD5={y z3*P|ekN8lr9@Su#36r|H*7e;y3+1h>kLMcPaLaK^UuQ_o>Z%zx$myOk4hSZHf3 zK+Vfg6$7gnO2w)Sqjy7(+FvMfD;Vj9e+D&n@`-+#&%&_d(ZImv7@#ejoDS`LFt~vOh=ZFQQd<=(Uy3IuOTY#=&3lV@z~nd$L8m@>vF0a{o-~ z*`tp)Kwb12ZEJqv(a5cr!oauxq$`Q6Qr+ z2>ThLyC03E)1KBz%RvWIM{fJP>bvF6?5`qOlrZY2Y|TL)=}uQ+{sGbTd})dE1@9tm zo9VpZv72xpsg|7{Zyxm}lYAKP{I+uUG)jApdkU3aNQC_!hE3^qXfe=3XHW_TuLF~W z;zVsBf%s|hWMuV>OIu2|XYu z7^{$hf4&R4u6liP`tY>?h=UpM9OtZIQOFKqS6n;0{EYGqH3=-sTZ?={QEm0U&t?p-(YIq>Ng#&Dl@}cTBj!P4^N@s z_QS9815t`IMY_-hJ#JPB{EV8~Fy{WLa4t~9>O^i_5sO}s$87!bvsw8A^>-tj_N2gBrjp^v}IP5{mZ-;hA&SKWK<<@X6OfFfIyFcn{@){+AJ6= zTFcFsV$Na=2f>BIFab(WJ+>9)$;j%zu74)i9@RjNU>m{xbQw^~BfUL_-qm{g^gj}C zHI@34LZ|fx|33d^vI*v@-(*({o9}ymqs$jV$22E|)g}AO12;FwKq?fp0-~4$Osm~e zo6CMLvfj;~;niBQF7D(ZSxuCQqykQ#{2hS)39fX&Sm*1UYHA?;%mdbm-!GL}m1<0TJjjlWJiKX_W zu>ifNpuuKk(U!_{aE*yK!15+QO(&t9=1CuewO23tJ7#46ef`UXBW~qy`IjjZ<7U!A z-Cyg#97y8sSCce`11cq7X6YLxP#cNi{!0JupSynm^5<(>fgQV$OfX78e>TU#Z2nB~ zT}VoA<%|7KJ^#aKKMge8l_pGd^(^CY-0W)u)`->G-M{Wxx1VmiN~V8b|DHJW$cd~T z{;@F)W&AkIzQd<@(59ozyV*BkTS`(nn|J;{eg8HZ4W+#C9DTkFRxdR z&|FxZkGK^8|I-bQcl&cGm7&@zkh`?)F{99GK_xH+NScY^9}jy7h(zS3tQ@8)9Q*uN z8}>I31(-THi%1BJsOR0BVp|X$T;ynt1o#?{I-3k06d`oj|>Bg!81sVqeUAu z0c=b%5cTE1&OZbCx9kK;90GgnHNd3ozK344Y=6Ih_K)%(ya!)@;C2Qh|A-3sdcptZ z^~Opi*OeUIeKYM;F>m-_I7|N#mn-t;n44hGte>xDA#Fc}J|-n=a6m^x^~TEZ`8gQ0 zBrbs@2f^^?xgO=EmC#$kH*Iui`n8G2mqG|Uwqn%$uKP~(MRI$ryuew*YNkIA7*}SX zZ|_ia&FBcS_%2;{>KIKvFzUgcXonmR&JT3N;?1!kEvF;ag%jGB+G7+?;c0vin~WG& z@$eybN%3ph>=uqC(_5|#v=x;9s{ZeP)qexz|MxwNZDJZ<;u&Z=IE9xxq}uc(q}DYC zab)wcb_z*<*K5C^PxKrm1Xb4PbS_@%j%m4+J5NM!QO$hk3CA%#ZK{|oB5bQ~=svWa z7=&1&cPT@fv|;Z>;$s=lysn_DI9vm=73a6h^&`^>LN7!Q*sc;(daU?)GMOjZ!~KHG z6_7yn@L>`yzO%i79Chjq`%51xDf#=dNZJH(iY{rsJM+40qO^c9!2jFeRk7NVTzjN` zkcQVOkzZ|tPCGJVqmd!Y=3-{yH@cD*2~w?mq>7QbZ2T6}Q746KLsLOxr0H`t)Ok$^ zRImY-NSX-pgRW=Ri3Z(NhG;;b)iu2Z1g*^32f+V8giA)H>b&zy=9Q8uqu61G)6chL ztPbWs4$M}Uw#P%_ zyPPg)Yu@8pwbGFe{+}Zz` z|L&q{TZCPpx%lh($DodVM{vhoeuSJ_mH&=^vgm1OJRq3$0I8j2BGP|fLEKek!e?lp z;_XKlUD(NxMkD4anxRwmnnMkzdCt)q;+5%g6A>5`+bEFn^MCONGWj9nw-Lb7t-HNG zyc)}<1->ADvsZYeQ#trY^+(AemhhMZbEYL#J?v6Zxc-T|vke1d-R|XU{RthnO4q5_ z9U4IY56}F(rE0o_xTCSD_t<`F7;1<pa7*j<@|#0`0EKP{ zW-(^aZjG?Yb5+XObb)vu?{9pbpk%ri5EW0=tG4Fjng zdJOCZFWOi;raMd6Gmp8SIpv5*^Pj#U6HP-sWuA*%{1_ z91%GeKXMn%e5=U1B7kSfp~?i6Gu(4}?p6_tF%KcD^{NGFhR6yn(`VvG8SU#e@~Pp+ z(=#Y#9TKzzwtefR5^}9OxRRd>;tun*-8ChiP+f$7{XxH3&anE4`XKRb&`-|m6`D_I zC73sluGiqQ4VTc*j%0?nmqaAUv^2^>X%@C2;TlNJ7_jj;q{A$!qCO8Te*_>sL+{Oi zG@sM|bN>B%-+w^=Dx@6e{tQ=^b{2-QN3n-K^84kVTn)h_cez`uqk@q``ftm5<$uV4 zei`Y%yV-()#UnOkWHD4=+vYx7vA(*=LDk5Z5h8#3uQ2ebp8{OO<1IYHE72Z{4_S5G zmR$!w90>87GZHimI`;t4*Y7le<3L8l{gIeP31NhHA|L@E+zcuM8Hs~Wiyn2W=D*FC zS;3Nvr9jU3h@aCiVrA`PmQVepRf?xd1QB2hiLfdvxSMrE#aC4Ou%vP@HuH#{YcwBG zMmzUo{VT3B-if)Ro_p54#ZSwkSNT547=*EZbou;gWxS{tM%?|9|G>+>fH;C;PAT z-~TKABS8Ox`s`ot(#2|nk*1-K_EoiRn-6sZ%~0AEzzmx)w!?7H4W^tHQ50=2yqXJg zTBLgrsQVyhBYLft@W@;j#qJGf2(+=@VX}C|klnn>ILaQ?RZ9(ZDk^SkgPvV@|2FNs z7HtaDWfZ_;#q>feNd+zlYV6EaI#4mJV# z>#x3iTSZL1mH9jfy11FRs#3Pw%~d-nH$NvIf-r*aCuG`#l|N+}gCowL{886E$C&=;gTg1l z69?s77GIDlHCOr3zs>)rZPJM;?;lyL-C|B8?V~uski)<&o7lHGb22npODz(s5>04( z&LLDgqqrbT?hiJ!3f4^{y3{Nom7#|czZg$EPDN(0`LW8>0$rAu=6>fw~9S<7WaroV^L z4s0^y5+CAA+2**Bs;#%tn?&PP;YFS_OZ`>;;-I&EiZI&`eMFm(EM!l33T<+4{@68t zxC`zHtTa;{AN5&FBV)T{LT{I*&}|BxK0l&b-g%H>0ksmA2Cv3_XkK)spx>)}&T|Gi zNc`#Ktszv+Irl4-3ge<+6e7{t>>#i@K|h}Rd$g9P3=D3p(cV5{;M}GF{X0PZ7pZ*M z*D+O;L(dS|E-VMt8ePGv zxBTHf*4uo`nYB#vR0;(kf4gYrjyvCh^e}35tWO}USK6+GNA8~EfwsNjdVl8Q10T-t z1-pzQ=?vH5xZ3G{G=OG!KRvclU)jr-Hmab5K9yS3LnK|h@+F%JR^yDlCD=2=`8qrx zFs6Y&J!zrvL)3jMgAXEZ3m!Dhs>}1;vjOn^=d<K!IoDpcWOe)~X8#&dGP6iliYeXW-nHDPP0&H*bb}78I*AOdP27 zDp}`Q^#?5y4l6SIq5jyZ%pb`7Qd?Huv|-ZU@jgjroeMc&OxFU*O5K-qluw$!G5ch~ z&tjbHOsQAQ5qJk>q61^_Zkna+$|BDk{>}clNP=H2-(Rv|=C}Phxx9)v#Da+1K7NeCfI{iLk})Q}<=jg@5#m zD9?Q1a|2t$f#WL9uA%OprLO(nMMlHV6-@{Zn zZHScVP2%H+67!}QxGIOa{+;nOfnEyq33sGz|0wYuj^rnBe8p}#Xg|6xWSo7sVkW`G z9@vK3&FR@AP9f+U54=&ujwo1x)w8IhImkTOp5Y!2GFzdyQ_*shR$`mfx>O6sfomAe z-Z(zkiszFZy^?JUz<;k>^}`3U;u?|xm~ zJUJ$vxlaB&`X36ZRSqDD*m;KmPE{=DFKfJKS z{`eLu3R~IYdL>ohhks?WV2zZ?Jc-5rEwM&k;%pgZyzTDb=uG z>isT4yUOyyvLLmK9`b`hPv8Joc;0AUFv}VkrNL6AI7%Pf_qBQbMNs*yu?vM0wcOPS zDKY>Pvw�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 HoUi`{Np-S% literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.mq5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.mq5 new file mode 100644 index 0000000..44668e9 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.indicator.mq5 @@ -0,0 +1,1874 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 Indicator +// --------------------------------------------- +// Name: X121 +// Description: Market Analyser +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121" + +// +// Ichimoku Golden Numbers ... +enum ENUM_X_ICHIMOKU_GOLDEN_NUMBERS +{ + X_ICH_BASE = 9, + X_ICH_GOLDEN = 17, + X_ICH_CYCLE = 26, + X_ICH_PERIOD = 35, + X_ICH_STAR = 45, + X_ICH_MED = 52, + X_ICH_LONG = 63, + X_ICH_FULL = 72 +}; + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// PEAKSANDVALES ... + +// +input group "Peaks and Vales"; + +// +input group "Makret Cycles"; +input int shortLength = 9; // Short Length +input int mediumLength = 17; // Medium Length +input int longLength = 26; // Long Length + +// +input group "Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +// SUPPORTSANDRESISTANCE ... + +// +input group "Support and Resistance"; + +// +input group "Level 1"; +input ENUM_X_PERIOD_METHOD level1Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES level1Period = NULL; // Time Period + +// +input group "Level 2"; +input ENUM_X_PERIOD_METHOD level2Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES level2Period = NULL; // Time Period + +// +input group "Level 3"; +input ENUM_X_PERIOD_METHOD level3Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES level3Period = NULL; // Time Period + +// +input group "Level 4"; +input ENUM_X_PERIOD_METHOD level4Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES level4Period = NULL; // Time Period + +// +// MA Crosses ... +input group "Moving Averages"; + +// +input group "Fast"; +input int fastMaLength = 9; // Length +input int fastMaShift = 0; // Shift +input ENUM_MA_METHOD fastMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE fastMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Slow"; +input int slowMaLength = 18; // Length +input int slowMaShift = 0; // Shift +input ENUM_MA_METHOD slowMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE slowMaAppliedTo = PRICE_CLOSE; // Applied To + +// +// ICHIMOKU Kinko Hyo ... + +// +input group "Ichimoku Kinko Hyo"; + +// +// TENKANSEN ... +input group "Tenkan Sen"; +input int tenkanSenLength = 9; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// KIJUNSEN ... +input group "Kijun Sen"; +input int kijunSenLength = 26; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// SENKOUSPANB ... +input group "Senkou Span B"; +input int senkouSpanBLength = 52; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// CHIKOUSPAN ... +input group "Chikou Span"; +input ENUM_APPLIED_PRICE chikuoSpanAppliedTo = PRICE_CLOSE; // Price Type + +// +input group "Presentation"; + +// +input group "Peaks and Vales"; +input bool showPeaksAndVales = true; // Show Peaks and Vales + +// +input group "Support and Resistance"; +input bool showSRLevel1 = true; // Show Level 1 +input bool showSRLevel2 = true; // Show Level 2 +input bool showSRLevel3 = true; // Show Level 3 +input bool showSRLevel4 = true; // Show Level 4 + +// +input group "Moving Averages"; +input bool showFastMa = true; // Show Fast +input bool showSlowMa = true; // Show Slow + +// +input group "Ichimoku Kinko Hyo"; +input bool showTenkanSen = true; // Show Tenkan Sen +input bool showKijunSen = true; // Show Kijun Sen +input bool showChikouSpan = true; // Show Chikou Span +input bool showKumo = true; // Show Kumo + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 27 +#property indicator_plots 18 + +// +// PLOTTED Buffers ... + +// +double rUpBuffer[]; +double rUpColorBuffer[]; + +// +#property indicator_label1 "X121 R UP" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, CLR_NONE +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +double rDownBuffer[]; +double rDownColorBuffer[]; + +// +#property indicator_label2 "X121 R Down" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 clrMagenta, CLR_NONE +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// PEKSANDVALES ... + +// +// PEAKS ... + +// +double peaksBuffer[]; + +// +#property indicator_label3 "X121 PEAKS" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 3 + +// +// VALES ... + +// +double valesBuffer[]; + +// +#property indicator_label4 "X121 VALES" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrMagenta +#property indicator_width4 3 + +// +// MA ... + +// +// FAST ... +double fastMaBuffer[]; + +// +#property indicator_label5 "X121 MA F" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrYellow +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +// SLOW ... +double slowMaBuffer[]; + +// +#property indicator_label6 "X121 MA S" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrDarkOrange +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// SUPPORTANDRESISTANCE ... + +// +// LEVEL 1 ... + +// +// UP ... +double srLevel1UpBuffer[]; + +// +#property indicator_label7 "X121 L1 Up" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrLightGray +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +// DOWN ... +double srLevel1DownBuffer[]; + +// +#property indicator_label8 "X121 L1 Down" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrLightGray +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// LEVEL 2 ... + +// +// UP ... +double srLevel2UpBuffer[]; + +// +#property indicator_label9 "X121 L2 Up" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrLightGray +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 + +// +// DOWN ... +double srLevel2DownBuffer[]; + +// +#property indicator_label10 "X121 L2 Down" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrLightGray +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +// +// LEVEL 3 ... + +// +// UP ... +double srLevel3UpBuffer[]; + +// +#property indicator_label11 "X121 L3 Up" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrLightGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +// DOWN ... +double srLevel3DownBuffer[]; + +// +#property indicator_label12 "X121 L3 Down" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrLightGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// LEVEL 4 ... + +// +// UP ... +double srLevel4UpBuffer[]; + +// +#property indicator_label13 "X121 L4 Up" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrLightGray +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +// DOWN ... +double srLevel4DownBuffer[]; + +// +#property indicator_label14 "X121 L4 Down" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrLightGray +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// ICHIMOKU ... + +// +// TENKANSEN ... + +// +double tenkanSenBuffer[]; + +// +#property indicator_label15 "X121 Tenkan Sen" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrBrown +#property indicator_style15 STYLE_SOLID +#property indicator_width15 1 + +// +// KIJUNSEN ... + +// +double kijunSenBuffer[]; + +// +#property indicator_label16 "X121 Kijun Sen" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrDodgerBlue +#property indicator_style16 STYLE_SOLID +#property indicator_width16 1 + +// +// CHIKOUSPAN ... + +// +double chikouSpanBuffer[]; + +// +#property indicator_label17 "X121 Chikou Span" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrDarkGreen +#property indicator_style17 STYLE_SOLID +#property indicator_width17 1 + +// +// SENKOUSPANA ... +double senkouSpanABuffer[]; + +// +// SENKOUSPANB ... +double senkouSpanBBuffer[]; + +// +// KUMOCLOUD ... +#property indicator_label18 "X121 Kumo" +#property indicator_type18 DRAW_FILLING +#property indicator_color18 clrAqua, clrMagenta +#property indicator_style18 STYLE_SOLID +#property indicator_width18 1 + +// +// DATA Buffers ... + +// +double sHHBuffer[]; +double sLLBuffer[]; + +// +double mHHBuffer[]; +double mLLBuffer[]; + +// +double lHHBuffer[]; +double lLLBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +double lastPeak; +double lastVale; + +// +ENUM_SERIESMODE mTenkanSenTopMode = NULL; +ENUM_SERIESMODE mTenkanSenBottomMode = NULL; + +// +ENUM_SERIESMODE mKijunSenTopMode = NULL; +ENUM_SERIESMODE mKijunSenBottomMode = NULL; + +// +ENUM_SERIESMODE mSenkouSpanBTopMode = NULL; +ENUM_SERIESMODE mSenkouSpanBBottomMode = NULL; + +// +int currentPeriodSecconds = 0; + +// +int mLevel1Candles; +double mSRLastL1Up; +double mSRLastL1Down; +int mLastLevel1StartBarIndex = 0; +datetime mLevel1StartTime = NULL; +ENUM_TIMEFRAMES mLevel1Period = NULL; + +// +int mLevel2Candles; +double mSRLastL2Up; +double mSRLastL2Down; +int mLastLevel2StartBarIndex = 0; +datetime mLevel2StartTime = NULL; +ENUM_TIMEFRAMES mLevel2Period = NULL; + +// +int mLevel3Candles; +double mSRLastL3Up; +double mSRLastL3Down; +int mLastLevel3StartBarIndex = 0; +datetime mLevel3StartTime = NULL; +ENUM_TIMEFRAMES mLevel3Period = NULL; + +// +int mLevel4Candles; +double mSRLastL4Up; +double mSRLastL4Down; +int mLastLevel4StartBarIndex = 0; +datetime mLevel4StartTime = NULL; +ENUM_TIMEFRAMES mLevel4Period = NULL; + +// +int fastMaHandler = INVALID_HANDLE; +int slowMaHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // MA Initialization ... + + // + // FAST ... + fastMaHandler = iMA( + _Symbol, + _Period, + fastMaLength, + fastMaShift, + fastMaMethod, + fastMaAppliedTo); + if (fastMaHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + LogMessage(msg); + + // + return INIT_FAILED; + } + + // + // SLOW ... + slowMaHandler = iMA( + _Symbol, + _Period, + slowMaLength, + slowMaShift, + slowMaMethod, + slowMaAppliedTo); + if (slowMaHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + LogMessage(msg); + + // + return INIT_FAILED; + } + + // + if (currentPeriodSecconds == 0) + { + currentPeriodSecconds = PeriodSeconds(_Period); + } + + // + // Finde Level 1 Period ... + if (mLevel1Period == NULL) + { + // + if (level1Method == X_PERIOD_AUTO) + { + mLevel1Period = GetNearestTimeFrame(_Period); + } + else + { + mLevel1Period = level1Period; + } + + // + int level1PeriodSecconds = PeriodSeconds(mLevel1Period); + + // + mLevel1Candles = level1PeriodSecconds / currentPeriodSecconds; + } + + // + // Finde Level 2 Period ... + if (mLevel2Period == NULL) + { + // + if (level2Method == X_PERIOD_AUTO) + { + mLevel2Period = GetMediestTimeFrame(_Period); + } + else + { + mLevel2Period = level2Period; + } + + // + int level2PeriodSecconds = PeriodSeconds(mLevel2Period); + + // + mLevel2Candles = level2PeriodSecconds / currentPeriodSecconds; + } + + // + // Finde Level 3 Period ... + if (mLevel3Period == NULL) + { + // + if (level3Method == X_PERIOD_AUTO) + { + mLevel3Period = GetFarestTimeFrame(_Period); + } + else + { + mLevel3Period = level3Period; + } + + // + int level3PeriodSecconds = PeriodSeconds(mLevel3Period); + + // + mLevel3Candles = level3PeriodSecconds / currentPeriodSecconds; + } + + // + // Finde Level 4 Period ... + if (mLevel4Period == NULL) + { + // + if (level4Method == X_PERIOD_AUTO) + { + mLevel4Period = GetHindmostTimeFrame(_Period); + } + else + { + mLevel4Period = level4Period; + } + + // + int level4PeriodSecconds = PeriodSeconds(mLevel4Period); + + // + mLevel4Candles = level4PeriodSecconds / currentPeriodSecconds; + } + + // + string comment = GenerateComment(); + Comment(comment); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(fastMaHandler); + IndicatorRelease(slowMaHandler); + + // + // Clear Comments ... + Comment(""); + + // + // Remove All Drawing Objects ... + RemoveDraws(drawPrefix); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int fastMaCalculatedBars = BarsCalculated(fastMaHandler); + int slowMaCalculatedBars = BarsCalculated(slowMaHandler); + if (fastMaCalculatedBars < maxLength || + slowMaCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFastMas = CopyBuffer(fastMaHandler, 0, 0, limit, fastMaBuffer); + int copiedSlowMas = CopyBuffer(slowMaHandler, 0, 0, limit, slowMaBuffer); + if (copiedFastMas <= 0 || + copiedSlowMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Peaks and Vales ... + (shortLength > 2 && + mediumLength > shortLength && + longLength > mediumLength) + // + && + // + // Validate Supports and Resistance ... + ( + // + // Level 1 ... + (level1Method == X_PERIOD_AUTO || + (level1Method == X_PERIOD_MANUALLY && + level1Period != NULL)) + // + && + // + // Level 2 ... + (level2Method == X_PERIOD_AUTO || + (level2Method == X_PERIOD_MANUALLY && + level2Period != NULL)) + // + && + // + // Level 3 ... + (level3Method == X_PERIOD_AUTO || + (level3Method == X_PERIOD_MANUALLY && + level3Period != NULL)) + // + && + // + // Level 4 ... + (level4Method == X_PERIOD_AUTO || + (level4Method == X_PERIOD_MANUALLY && + level4Period != NULL)) + // + ) + // + && + // + // Validate Ma ... + (fastMaLength > 2 && + slowMaLength > fastMaLength) + // + && + // + // Validate Ichimoku Kinko Hyo ... + (tenkanSenLength > 2 && + kijunSenLength > tenkanSenLength && + senkouSpanBLength > kijunSenLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax(shortLength, mediumLength); + result = MathMax(result, longLength); + + // + // Ma ... + result = MathMax(result, fastMaLength); + result = MathMax(result, slowMaLength); + + // + // Ichimoku ... + result = MathMax(result, tenkanSenLength); + result = MathMax(result, kijunSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RANGE ... + + // + // UP Buffer ... + ArraySetAsSeries(rUpBuffer, true); + SetIndexBuffer(0, rUpBuffer, INDICATOR_DATA); + PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(0, PLOT_SHOW_DATA, false); + + // + // UP Color Buffer ... + ArraySetAsSeries(rUpColorBuffer, true); + SetIndexBuffer(1, rUpColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DOWN Buffer ... + ArraySetAsSeries(rDownBuffer, true); + SetIndexBuffer(2, rDownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(1, PLOT_SHOW_DATA, false); + + // + // DOWN Color Buffer ... + ArraySetAsSeries(rDownColorBuffer, true); + SetIndexBuffer(3, rDownColorBuffer, INDICATOR_COLOR_INDEX); + + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(4, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(4, PLOT_ARROW, 225); + PlotIndexSetInteger(4, PLOT_ARROW_SHIFT, 20); + PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(2, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(2, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(5, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(5, PLOT_ARROW, 225); + PlotIndexSetInteger(5, PLOT_ARROW_SHIFT, 20); + PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(3, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(3, PLOT_DRAW_TYPE, pvDrawType); + + // + // MA ... + + // + // FAST ... + ENUM_DRAW_TYPE fastMaDrawType = showFastMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fastMaBuffer, true); + SetIndexBuffer(6, fastMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(6, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(4, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(4, PLOT_DRAW_TYPE, fastMaDrawType); + + // + // SLOW ... + ENUM_DRAW_TYPE slowMaDrawType = showSlowMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(slowMaBuffer, true); + SetIndexBuffer(7, slowMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(7, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(5, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(5, PLOT_DRAW_TYPE, slowMaDrawType); + + // + // SUPPORTANDRESISTANCE ... + + // + // LEVEL 1 ... + ENUM_DRAW_TYPE srL1DrawType = showSRLevel1 ? DRAW_LINE : DRAW_NONE; + + // + // UP ... + ArraySetAsSeries(srLevel1UpBuffer, true); + SetIndexBuffer(8, srLevel1UpBuffer, INDICATOR_DATA); + PlotIndexSetInteger(8, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(6, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(6, PLOT_DRAW_TYPE, srL1DrawType); + + // + // DOWN ... + ArraySetAsSeries(srLevel1DownBuffer, true); + SetIndexBuffer(9, srLevel1DownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(9, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(7, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(7, PLOT_DRAW_TYPE, srL1DrawType); + + // + // LEVEL 2 ... + ENUM_DRAW_TYPE srL2DrawType = showSRLevel2 ? DRAW_LINE : DRAW_NONE; + + // + // UP ... + ArraySetAsSeries(srLevel2UpBuffer, true); + SetIndexBuffer(10, srLevel2UpBuffer, INDICATOR_DATA); + PlotIndexSetInteger(10, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(8, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(8, PLOT_DRAW_TYPE, srL2DrawType); + + // + // DOWN ... + ArraySetAsSeries(srLevel2DownBuffer, true); + SetIndexBuffer(11, srLevel2DownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(11, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(9, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(9, PLOT_DRAW_TYPE, srL2DrawType); + + // + // LEVEL 3 ... + ENUM_DRAW_TYPE srL3DrawType = showSRLevel3 ? DRAW_LINE : DRAW_NONE; + + // + // UP ... + ArraySetAsSeries(srLevel3UpBuffer, true); + SetIndexBuffer(12, srLevel3UpBuffer, INDICATOR_DATA); + PlotIndexSetInteger(12, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetDouble(12, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(10, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(10, PLOT_DRAW_TYPE, srL3DrawType); + + // + // DOWN ... + ArraySetAsSeries(srLevel3DownBuffer, true); + SetIndexBuffer(13, srLevel3DownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(13, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetDouble(13, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(11, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(11, PLOT_DRAW_TYPE, srL3DrawType); + + // + // LEVEL 4 ... + ENUM_DRAW_TYPE srL4DrawType = showSRLevel4 ? DRAW_LINE : DRAW_NONE; + + // + // UP ... + ArraySetAsSeries(srLevel4UpBuffer, true); + SetIndexBuffer(14, srLevel4UpBuffer, INDICATOR_DATA); + PlotIndexSetInteger(14, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetDouble(14, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(12, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(12, PLOT_DRAW_TYPE, srL4DrawType); + + // + // DOWN ... + ArraySetAsSeries(srLevel4DownBuffer, true); + SetIndexBuffer(15, srLevel4DownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(15, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetDouble(15, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(13, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(13, PLOT_DRAW_TYPE, srL4DrawType); + + // + // ICHIMOKU ... + + // + // TENKANSEN ... + + // + ENUM_DRAW_TYPE tenkanSenDrawType = showTenkanSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tenkanSenBuffer, true); + SetIndexBuffer(16, tenkanSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(16, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(14, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(14, PLOT_DRAW_TYPE, tenkanSenDrawType); + + // + // KIJUNSEN ... + + // + ENUM_DRAW_TYPE kijunSenDrawType = showKijunSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenBuffer, true); + SetIndexBuffer(17, kijunSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(17, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(15, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(15, PLOT_DRAW_TYPE, kijunSenDrawType); + + // + // CHIKOUSPAN ... + + // + ENUM_DRAW_TYPE chikouSpanDrawType = showChikouSpan ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(chikouSpanBuffer, true); + SetIndexBuffer(18, chikouSpanBuffer, INDICATOR_DATA); + PlotIndexSetInteger(18, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(16, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(16, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(16, PLOT_DRAW_TYPE, chikouSpanDrawType); + + // + // SENKOUSPANA ... + ArraySetAsSeries(senkouSpanABuffer, true); + SetIndexBuffer(19, senkouSpanABuffer, INDICATOR_DATA); + PlotIndexSetInteger(19, PLOT_DRAW_BEGIN, maxLength); + + // + // SENKOUSPANB ... + ArraySetAsSeries(senkouSpanBBuffer, true); + SetIndexBuffer(20, senkouSpanBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(20, PLOT_DRAW_BEGIN, maxLength); + + // + // KUMO ... + + // + ENUM_DRAW_TYPE kumoDrawType = showKumo ? DRAW_FILLING : DRAW_NONE; + + // + PlotIndexSetInteger(17, PLOT_SHIFT, kijunSenLength); + PlotIndexSetInteger(17, PLOT_DRAW_TYPE, kumoDrawType); + + // + int i = 21; + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(i, sHHBuffer, INDICATOR_CALCULATIONS); + + // + i++; + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(i, sLLBuffer, INDICATOR_CALCULATIONS); + + // + i++; + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(i, mHHBuffer, INDICATOR_CALCULATIONS); + + // + i++; + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(i, mLLBuffer, INDICATOR_CALCULATIONS); + + // + i++; + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(i, lHHBuffer, INDICATOR_CALCULATIONS); + + // + i++; + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(i, lLLBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate ... + + // + double rUpColorIDX = 1; + double rDownColorIDX = 1; + + // + // PEAKS and VALES ... + + // + // SHORT ... + + // + // HH Buffer ... + int sHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + shortLength, + bar_index); + double sHHValue = GetAppliedPrice( + sHHIndex, + hhMode); + + // + sHHBuffer[bar_index] = sHHValue; + + // + // LL Buffer ... + int sLLIndex = iLowest( + _Symbol, + _Period, + llMode, + shortLength, + bar_index); + double sLLValue = GetAppliedPrice( + sLLIndex, + llMode); + + // + sLLBuffer[bar_index] = sLLValue; + + // + // MEDIUM ... + + // + // HH Buffer ... + int mHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + mediumLength, + bar_index); + double mHHValue = GetAppliedPrice( + mHHIndex, + hhMode); + + // + mHHBuffer[bar_index] = mHHValue; + + // + // LL Buffer ... + int mLLIndex = iLowest( + _Symbol, + _Period, + llMode, + mediumLength, + bar_index); + double mLLValue = GetAppliedPrice( + mLLIndex, + llMode); + + // + mLLBuffer[bar_index] = mLLValue; + + // + // LONG ... + + // + // HH Buffer ... + int lHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + longLength, + bar_index); + double lHHValue = GetAppliedPrice( + lHHIndex, + hhMode); + + // + lHHBuffer[bar_index] = lHHValue; + + // + // LL Buffer ... + int lLLIndex = iLowest( + _Symbol, + _Period, + llMode, + longLength, + bar_index); + double lLLValue = GetAppliedPrice( + lLLIndex, + llMode); + + // + lLLBuffer[bar_index] = lLLValue; + + // + // RANGE ... + + // + // UP ... + double rUpValue = (sHHValue + mHHValue + lHHValue) / 3; + rUpBuffer[bar_index] = rUpValue; + + // + // DOWN ... + double rDownValue = (sLLValue + mLLValue + lLLValue) / 3; + rDownBuffer[bar_index] = rDownValue; + + // + // Detecting Peaks and Vales ... + + // + // PEAKS ... + bool isPeak = rUpValue == lHHValue && + lHHValue == mHHValue && + mHHValue == sHHValue; + + // + if (isPeak && lastPeak != rUpValue) + { + // + if (showPeaksAndVales) + { + rUpColorIDX = 0; + } + + // + lastPeak = rUpValue; + peaksBuffer[bar_index] = lastPeak; + } + else + { + peaksBuffer[bar_index] = 0; + } + + // + // VALES ... + bool isVale = rDownValue == lLLValue && + lLLValue == mLLValue && + mLLValue == sLLValue; + + if (isVale && lastVale != rDownValue) + { + // + if (showPeaksAndVales) + { + rDownColorIDX = 0; + } + + // + lastVale = rDownValue; + valesBuffer[bar_index] = lastVale; + } + else + { + valesBuffer[bar_index] = 0; + } + + // + // Set Default Colors ... + + // + rUpColorBuffer[bar_index] = rUpColorIDX; + rDownColorBuffer[bar_index] = rDownColorIDX; + + // + // SUPPORTANDRESISTANCE ... + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + + // + // LEVEL 1 ... + + // + // Calculate Start Bar Index ... + if (mLastLevel1StartBarIndex == 0) + { + // + datetime level1StartTime = GetPeriodStartTime( + _Symbol, + mLevel1Period, + barTime); + + // + // Check Level 1 Start Time is New or Not ... + if (mLevel1StartTime != level1StartTime) + { + mLevel1StartTime = level1StartTime; + } + + // + // Access Level 1 Start Bar Index on Current Chart ... + mLastLevel1StartBarIndex = iBarShift( + _Symbol, + _Period, + mLevel1StartTime); + + // + // Calculate level1 Highest Open ... + mSRLastL1Up = GetHighestHigh( + _Symbol, + _Period, + MODE_HIGH, + mLevel1Candles, + mLastLevel1StartBarIndex); + + // + srLevel1UpBuffer[bar_index] = mSRLastL1Up; + + // + // Calculate level1 Lowest Close ... + mSRLastL1Down = GetLowestLow( + _Symbol, + _Period, + MODE_LOW, + mLevel1Candles, + mLastLevel1StartBarIndex); + + // + srLevel1DownBuffer[bar_index] = mSRLastL1Down; + } + else + { + // + int lDiff = mLastLevel1StartBarIndex - bar_index; + if (lDiff == mLevel1Candles) + { + mLastLevel1StartBarIndex = 0; + } + + // + srLevel1UpBuffer[bar_index] = mSRLastL1Up; + srLevel1DownBuffer[bar_index] = mSRLastL1Down; + } + + // + // LEVEL 2 ... + + // + // Calculate Start Bar Index ... + if (mLastLevel2StartBarIndex == 0) + { + // + datetime level2StartTime = GetPeriodStartTime( + _Symbol, + mLevel2Period, + barTime); + + // + // Check Level 2 Start Time is New or Not ... + if (mLevel2StartTime != level2StartTime) + { + mLevel2StartTime = level2StartTime; + } + + // + // Access Level 2 Start Bar Index on Current Chart ... + mLastLevel2StartBarIndex = iBarShift( + _Symbol, + _Period, + mLevel2StartTime); + + // + // Calculate level2 Highest Open ... + mSRLastL2Up = GetHighestHigh( + _Symbol, + _Period, + MODE_HIGH, + mLevel2Candles, + mLastLevel2StartBarIndex); + + // + srLevel2UpBuffer[bar_index] = mSRLastL2Up; + + // + // Calculate level2 Lowest Close ... + mSRLastL2Down = GetLowestLow( + _Symbol, + _Period, + MODE_LOW, + mLevel2Candles, + mLastLevel2StartBarIndex); + + // + srLevel2DownBuffer[bar_index] = mSRLastL2Down; + } + else + { + // + int lDiff = mLastLevel2StartBarIndex - bar_index; + if (lDiff == mLevel2Candles) + { + mLastLevel2StartBarIndex = 0; + } + + // + srLevel2UpBuffer[bar_index] = mSRLastL2Up; + srLevel2DownBuffer[bar_index] = mSRLastL2Down; + } + + // + // LEVEL 3 ... + + // + // Calculate Start Bar Index ... + if (mLastLevel3StartBarIndex == 0) + { + // + datetime level3StartTime = GetPeriodStartTime( + _Symbol, + mLevel3Period, + barTime); + + // + // Check Level 3 Start Time is New or Not ... + if (mLevel3StartTime != level3StartTime) + { + mLevel3StartTime = level3StartTime; + } + + // + // Access Level 3 Start Bar Index on Current Chart ... + mLastLevel3StartBarIndex = iBarShift( + _Symbol, + _Period, + mLevel3StartTime); + + // + // Calculate level3 Highest Open ... + mSRLastL3Up = GetHighestHigh( + _Symbol, + _Period, + MODE_HIGH, + mLevel3Candles, + mLastLevel3StartBarIndex); + + // + srLevel3UpBuffer[bar_index] = mSRLastL3Up; + + // + // Calculate level3 Lowest Close ... + mSRLastL3Down = GetLowestLow( + _Symbol, + _Period, + MODE_LOW, + mLevel3Candles, + mLastLevel3StartBarIndex); + + // + srLevel3DownBuffer[bar_index] = mSRLastL3Down; + } + else + { + // + int lDiff = mLastLevel3StartBarIndex - bar_index; + if (lDiff == mLevel3Candles) + { + mLastLevel3StartBarIndex = 0; + } + + // + srLevel3UpBuffer[bar_index] = mSRLastL3Up; + srLevel3DownBuffer[bar_index] = mSRLastL3Down; + } + + // + // LEVEL 4 ... + + // + // Calculate Start Bar Index ... + if (mLastLevel4StartBarIndex == 0) + { + // + datetime level4StartTime = GetPeriodStartTime( + _Symbol, + mLevel4Period, + barTime); + + // + // Check Level 4 Start Time is New or Not ... + if (mLevel4StartTime != level4StartTime) + { + mLevel4StartTime = level4StartTime; + } + + // + // Access Level 4 Start Bar Index on Current Chart ... + mLastLevel4StartBarIndex = iBarShift( + _Symbol, + _Period, + mLevel4StartTime); + + // + // Calculate level4 Highest Open ... + mSRLastL4Up = GetHighestHigh( + _Symbol, + _Period, + MODE_OPEN, + mLevel4Candles, + mLastLevel4StartBarIndex); + + // + srLevel4UpBuffer[bar_index] = mSRLastL4Up; + + // + // Calculate level4 Lowest Close ... + mSRLastL4Down = GetLowestLow( + _Symbol, + _Period, + MODE_LOW, + mLevel4Candles, + mLastLevel4StartBarIndex); + + // + srLevel4DownBuffer[bar_index] = mSRLastL4Down; + } + else + { + // + int lDiff = mLastLevel4StartBarIndex - bar_index; + if (lDiff == mLevel4Candles) + { + mLastLevel4StartBarIndex = 0; + } + + // + srLevel4UpBuffer[bar_index] = mSRLastL4Up; + srLevel4DownBuffer[bar_index] = mSRLastL4Down; + } + + // + // ICHIMOKU ... + + // + double topValue; + double bottomValue; + + // + // TENKANSEN ... + + // + // Extract Tenkan Sen Top/Bottom Calculation Mode based on User Input ... + if (mTenkanSenTopMode == NULL || mTenkanSenBottomMode == NULL) + { + // + switch (tenkanSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mTenkanSenTopMode = MODE_HIGH; + mTenkanSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mTenkanSenTopMode = MODE_OPEN; + mTenkanSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mTenkanSenTopMode, + tenkanSenLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mTenkanSenBottomMode, + tenkanSenLength, + bar_index); + + // + double tenkanSenValue = (topValue + bottomValue) / 2; + tenkanSenBuffer[bar_index] = tenkanSenValue; + + // + // KIJUNSEN ... + + // + // Extract Kijun Sen Top/Bottom Calculation Mode based on User Input ... + if (mKijunSenTopMode == NULL || mKijunSenBottomMode == NULL) + { + // + switch (kijunSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mKijunSenTopMode = MODE_HIGH; + mKijunSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mKijunSenTopMode = MODE_OPEN; + mKijunSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mKijunSenTopMode, + kijunSenLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mKijunSenBottomMode, + kijunSenLength, + bar_index); + + // + double kijunSenValue = (topValue + bottomValue) / 2; + kijunSenBuffer[bar_index] = kijunSenValue; + + // + // CHIKOUSPAN ... + double chikouSpanValue = GetAppliedPrice( + bar_index, + chikuoSpanAppliedTo); + chikouSpanBuffer[bar_index] = chikouSpanValue; + + // + // KUMO ... + + // + // SENKOUSPANA ... + double senkouSpanAValue = (tenkanSenValue + kijunSenValue) / 2; + senkouSpanABuffer[bar_index] = senkouSpanAValue; + + // + // SENKOUSPANB ... + + // + // Extract Senkou Span B Top/Bottom Calculation Mode based on User Input ... + if (mSenkouSpanBTopMode == NULL || mSenkouSpanBBottomMode == NULL) + { + // + switch (senkouSpanBMode) + { + // + case X_XICH_HH_LL_MODE: + // + mSenkouSpanBTopMode = MODE_HIGH; + mSenkouSpanBBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mSenkouSpanBTopMode = MODE_OPEN; + mSenkouSpanBBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mSenkouSpanBTopMode, + senkouSpanBLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mSenkouSpanBBottomMode, + senkouSpanBLength, + bar_index); + + // + double senkouSpanBValue = (topValue + bottomValue) / 2; + senkouSpanBBuffer[bar_index] = senkouSpanBValue; +} + +// +// Generate Comment String ... +string GenerateComment() +{ + // + string result = ""; + + // + result += "L1 P: " + EnumToString(mLevel1Period) + "\n"; + // result += "L1 C: " + (string)mLevel1Candles + "\n"; + // result += "\n"; + + // + result += "L2 P: " + EnumToString(mLevel2Period) + "\n"; + // result += "L2 C: " + (string)mLevel2Candles + "\n"; + // result += "\n"; + + // + result += "L3 P: " + EnumToString(mLevel3Period) + "\n"; + // result += "L3 C: " + (string)mLevel3Candles + "\n"; + // result += "\n"; + + // + result += "L4 P: " + EnumToString(mLevel4Period) + "\n"; + // result += "L4 C: " + (string)mLevel4Candles + "\n"; + // result += "\n"; + + // + return result; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xpv.mq5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xpv.mq5 new file mode 100644 index 0000000..11b2dac --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xpv.mq5 @@ -0,0 +1,640 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_PV Peaks and Vales Indicator +// ----------------------------------------------------------- +// Name: X121_PV +// Description: Market Peaks and Vales +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_PV Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_PV" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret Cycles"; +input int shortLength = 9; // Short Length +input int mediumLength = 17; // Medium Length +input int longLength = 26; // Long Length + +// +input group "Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; +input bool showPeaksAndVales = true; // Show Peaks and Vales + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 12 +#property indicator_plots 4 + +// +// PEKSANDVALES ... + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "X121_PV PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 3 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "X121_PV VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 3 + +// +#define rUpBufferIndex 2 +#define rUpPlotBufferIndex 2 +double rUpBuffer[]; + +// +#define rUpColorBufferIndex 3 +double rUpColorBuffer[]; + +// +#property indicator_label3 "X121_PV R UP" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 clrAqua, CLR_NONE +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define rDownBufferIndex 4 +#define rDownPlotBufferIndex 3 +double rDownBuffer[]; + +// +#define rDownColorBufferIndex 5 +double rDownColorBuffer[]; + +// +#property indicator_label4 "X121_PV R Down" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 clrMagenta, CLR_NONE +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// DATA Buffers ... + +// +#define sHHBufferIndex 6 +double sHHBuffer[]; + +#define sLLBufferIndex 7 +double sLLBuffer[]; + +// +#define mHHBufferIndex 8 +double mHHBuffer[]; + +// +#define mLLBufferIndex 9 +double mLLBuffer[]; + +// +#define lHHBufferIndex 10 +double lHHBuffer[]; + +// +#define lLLBufferIndex 11 +double lLLBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +double lastPeak; +double lastVale; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Peaks and Vales ... + (shortLength > 2 && + mediumLength > shortLength && + longLength > mediumLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax(shortLength, mediumLength); + result = MathMax(result, longLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RANGE ... + + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, 225); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW_SHIFT, -20); + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, 225); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW_SHIFT, 20); + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // UP Buffer ... + ArraySetAsSeries(rUpBuffer, true); + SetIndexBuffer(rUpBufferIndex, rUpBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rUpBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(rUpBufferIndex, PLOT_SHOW_DATA, false); + + // + // UP Color Buffer ... + ArraySetAsSeries(rUpColorBuffer, true); + SetIndexBuffer(rUpColorBufferIndex, rUpColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DOWN Buffer ... + ArraySetAsSeries(rDownBuffer, true); + SetIndexBuffer(rDownBufferIndex, rDownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rDownBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(rDownPlotBufferIndex, PLOT_SHOW_DATA, false); + + // + // DOWN Color Buffer ... + ArraySetAsSeries(rDownColorBuffer, true); + SetIndexBuffer(rDownColorBufferIndex, rDownColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DATA Buffers ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate ... + + // + double rUpColorIDX = 1; + double rDownColorIDX = 1; + + // + // PEAKS and VALES ... + + // + // SHORT ... + + // + // HH Buffer ... + int sHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + shortLength, + bar_index); + double sHHValue = GetAppliedPrice( + sHHIndex, + hhMode); + + // + sHHBuffer[bar_index] = sHHValue; + + // + // LL Buffer ... + int sLLIndex = iLowest( + _Symbol, + _Period, + llMode, + shortLength, + bar_index); + double sLLValue = GetAppliedPrice( + sLLIndex, + llMode); + + // + sLLBuffer[bar_index] = sLLValue; + + // + // MEDIUM ... + + // + // HH Buffer ... + int mHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + mediumLength, + bar_index); + double mHHValue = GetAppliedPrice( + mHHIndex, + hhMode); + + // + mHHBuffer[bar_index] = mHHValue; + + // + // LL Buffer ... + int mLLIndex = iLowest( + _Symbol, + _Period, + llMode, + mediumLength, + bar_index); + double mLLValue = GetAppliedPrice( + mLLIndex, + llMode); + + // + mLLBuffer[bar_index] = mLLValue; + + // + // LONG ... + + // + // HH Buffer ... + int lHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + longLength, + bar_index); + double lHHValue = GetAppliedPrice( + lHHIndex, + hhMode); + + // + lHHBuffer[bar_index] = lHHValue; + + // + // LL Buffer ... + int lLLIndex = iLowest( + _Symbol, + _Period, + llMode, + longLength, + bar_index); + double lLLValue = GetAppliedPrice( + lLLIndex, + llMode); + + // + lLLBuffer[bar_index] = lLLValue; + + // + // RANGE ... + + // + // UP ... + double rUpValue = (sHHValue + mHHValue + lHHValue) / 3; + rUpBuffer[bar_index] = rUpValue; + + // + // DOWN ... + double rDownValue = (sLLValue + mLLValue + lLLValue) / 3; + rDownBuffer[bar_index] = rDownValue; + + // + // Detecting Peaks and Vales ... + + // + // PEAKS ... + bool isPeak = rUpValue == lHHValue && + lHHValue == mHHValue && + mHHValue == sHHValue; + + // + if (isPeak && lastPeak != rUpValue) + { + // + if (showPeaksAndVales) + { + rUpColorIDX = 0; + } + + // + lastPeak = rUpValue; + peaksBuffer[bar_index] = lastPeak; + } + else + { + peaksBuffer[bar_index] = 0; + } + + // + // VALES ... + bool isVale = rDownValue == lLLValue && + lLLValue == mLLValue && + mLLValue == sLLValue; + + if (isVale && lastVale != rDownValue) + { + // + if (showPeaksAndVales) + { + rDownColorIDX = 0; + } + + // + lastVale = rDownValue; + valesBuffer[bar_index] = lastVale; + } + else + { + valesBuffer[bar_index] = 0; + } + + // + // Set Default Colors ... + + // + rUpColorBuffer[bar_index] = rUpColorIDX; + rDownColorBuffer[bar_index] = rDownColorIDX; + +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xtrnd.single.cycle.mq5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xtrnd.single.cycle.mq5 new file mode 100644 index 0000000..769c8af --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x-saherelm.x121.xtrnd.single.cycle.mq5 @@ -0,0 +1,459 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_XTRND Trends Indicator +// ----------------------------------------------------------- +// Name: X121_XTRND +// Description: Market Trend Detector ... +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XTRND Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_XTRND" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int cycleLength = 2; // Cycle Length to Check +input int numberOfVerifications = 2; // Number of Verifications + +// +input group "Calculation"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Detect Up +input ENUM_SERIESMODE llMode = MODE_LOW; // Detect Low + +// +input group "Presentation"; +input bool showConsolidations = false; // Show Consolidations +input bool showTrend = true; // Show Trend + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// Higher High ... +#define hhBufferIndex 0 +#define hhPlotBufferIndex 0 +double hhBuffer[]; + +#define hhColorBufferIndex 1 +double hhColorBuffer[]; + +// +#property indicator_label1 "X121_XTRND U" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// Lower Low ... +#define llBufferIndex 2 +#define llPlotBufferIndex 1 +double llBuffer[]; + +#define llColorBufferIndex 3 +double llColorBuffer[]; + +// +#property indicator_label2 "X121_XTRND D" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (cycleLength > 0 && + numberOfVerifications > 0) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax( + cycleLength, + numberOfVerifications); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showTrend ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(hhBuffer, true); + SetIndexBuffer(hhBufferIndex, hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_DRAW_TYPE, drawType); + + // + // COLOR Buffer ... + ArraySetAsSeries(hhColorBuffer, true); + SetIndexBuffer(hhColorBufferIndex, hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(llBuffer, true); + SetIndexBuffer(llBufferIndex, llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(llPlotBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(llPlotBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(llColorBuffer, true); + SetIndexBuffer(llColorBufferIndex, llColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // HIGHER Highs ... + double hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + cycleLength, + bar_index); + + // + hhBuffer[bar_index] = hh; + + // + // LOWER Lows ... + double ll = GetLowestLow( + _Symbol, + _Period, + llMode, + cycleLength, + bar_index); + + // + llBuffer[bar_index] = ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double hhColorIDX = showConsolidations ? 1 : 0; + double llColorIDX = showConsolidations ? 1 : 0; + + // + // Calculate Cycle Changes ... + + // + int cycleCLength = cycleLength * numberOfVerifications; + bool isCycleCLengthPassed = MathAbs(ArraySize(hhBuffer) - bar_index) > cycleCLength + 1; + + // + if (isCycleCLengthPassed) + { + // + bool isLowestLowUp = true; // ll > llBuffer[bar_index + 1]; + bool isLowestLowDown = true; // ll < llBuffer[bar_index + 1]; + bool isHighsestHighUp = true; // hh > hhBuffer[bar_index + 1]; + bool isHighsestHighDown = true; // hh < hhBuffer[bar_index + 1]; + for (int i = bar_index; i < bar_index + cycleCLength; i++) + { + // + double iHH = hhBuffer[i]; + double iLL = llBuffer[i]; + + // + if (hh < iHH) + { + isHighsestHighUp = false; + } + else if (hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (ll < iLL) + { + isLowestLowUp = false; + } + else if (ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + hhColorIDX = 2; + llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + hhColorIDX = 3; + llColorIDX = 3; + } + } + + // + hhColorBuffer[bar_index] = hhColorIDX; + llColorBuffer[bar_index] = llColorIDX; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.xea.mq5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.xea.mq5 new file mode 100644 index 0000000..8041b38 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x-saherelm.xea.mq5 @@ -0,0 +1,1359 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ---------------------------------------- +// Name: X121EA +// Description: this is an expert controller +// advisors which provides a mechanism for use them ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121EA" +#property strict + +// +// START Definitions ... +// + +// +// Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Alert Library ... +#include "../Libraries/x-saherelm.alert.lib.mq5" + +// +// Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Account Class ... +#include "../Classes/x-saherelm.xaccount.class.mq5" + +// +// Trade Class ... +#include "../Classes/x-saherelm.xtrade.class.mq5" + +// +// Signal Provider Class Library ... +#include "../Providers/x.saherelm.x121.provider.mq5" + +// +// Draw Library ... +#include "../Libraries/x-saherelm.x121.draw.lib.mq5" + +// +#define ShortName "X121EA" + +// +// Convert Position to Signal ... +XSignal ToSignalInfo( + XPosition &position) +{ + // + XSignal result; + + // + result.tp = position.tp; + result.sl = position.sl; + result.type = position.type; + result.entry = position.entry; + result.symbol = position.symbol; + result.period = position.period; + result.volume = position.volume; + + // + return result; +} + +// +// END Definitions ... +// + +// +// START Inputs ... +// + +// +// EA ... +input group "Common"; +input bool xEAEnable = true; // Enable EA +input int xEASlippage = 10; // Slippgae +input ulong xEAMagicNumber = 1604056; // Magic Number + +// +// Signals ... +input group "Signals"; +input bool xEAEnableLongs = true; // Enable Long Trades +input bool xEAEnableShorts = true; // Enable Short Trades + +// +// Risk Management ... +input group "Risk Management"; +input int xEAMaxOpenPositions = 15; // Max Allowed Open Positions +input double xEAMaxAllowedDrawDownFactor = 0.15; // Max Allowed Drawdown Factor +// input double xEAMinProfitPerOpenPositionForHedging = 0.9; // Close All Positions Fctor + +// +// Alerts ... +input group "Alerts"; +input bool xEAEnableAlerts = true; // Enable Events Alert +input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day +input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month + +// +// END Inputs ... +// + +// +// START Including Providers ... +// + +// +// Logger Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +bool isXEANewHour; +bool isXEANewDay; +bool isXEANewWeek; +bool isXEANewMonth; + +// +// Determines EA is Running On Test Mode or not ... +bool xEAIsTestMode = false; + +// +// Check prevent Double Signalling on Same Candle ... +bool xEAWaitUntilNextCandle = false; + +// +XSCTrade *xEATrade; +XSCAccount *xEAAccount; +XSCX121Provider *xEAProvider; +// X121SignalProvider xEAProviders[]; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = ShortName; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize X121EA Providers ... + if (!InitializeProviders()) + { + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + delete xEATrade; + delete xEAAccount; + delete xEAProvider; + + // + // De Initialize XEA Providers ... +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXEANewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXEANewMonth && + xEAEnableAlerts && + xEAEnableMonthlyAlerts; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXEANewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXEANewWeek && + xEAEnableAlerts && + xEAEnableWeeklyAlerts; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXEANewDay = IsNewDay(); + bool canDailyAlert = + isXEANewDay && + xEAEnableAlerts && + xEAEnableDailyAlerts; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXEANewHour = IsNewHour(); + bool canHourlyAlert = + isXEANewHour && + xEAEnableAlerts && + xEAEnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + // + // Handle Guarding Strategies ... + HandleGuard(); + + // + // Prevent Going Forward if user Disable it ... + if (xEAEnable) + { + // + // TODO: Remove this due test ... + // if (IsRunningOnTestMode()) + // { + // xEATrade. + // } + + // + // Call All Providers OnTick Method ... + CallProvidersOnTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + // + // Handle Trading State ... + xEATrade.HandleOnTrade(); +} + +// +// Chart Events Handling ... +void OnChartEvent( + const int id, // event ID + const long &lparam, // long type event parameter + const double &dparam, // double type event parameter + const string &sparam // string type event parameter +) +{ +} + +// +// Handle Signal Event ... +void OnSignalConditionsRecieved(X121MarketConditions &info) +{ + // + if (!info.hasSignal) + { + return; + } + + // + // Diable Trading if a Direction is Disabled ... + if ((info.signal.type == POSITION_TYPE_BUY && !xEAEnableLongs) || + (info.signal.type != POSITION_TYPE_SELL && !xEAEnableShorts)) + { + return; + } + + // + // Count Open Positions ... + int openPositionsCount = xEATrade.PositionsCount(); + if (xEAMaxOpenPositions > 0 && + openPositionsCount >= xEAMaxOpenPositions) + { + // + string msg = "Max Allowed Positions Reached, Ignore Trading ..."; + LogMessage(msg); + + // + return; + } + + // + // Retrieve Tradable Balance ... + double availableBalance = xEAAccount.GetEquity(); + + // + // Verify Available Balance ... + double balance = xEAAccount.GetBalance(); + + // + double forCalculationBalance = MathMax(balance, availableBalance); + double forTradeBalance = MathMin(balance, availableBalance); + double mustHaveBalanceForTrading = forCalculationBalance * xEAMaxAllowedDrawDownFactor; + if (availableBalance < mustHaveBalanceForTrading) + { + // + string msg = "Max Allowed Equity for Trading Reached, Ignore Trading ..."; + LogMessage(msg); + + // + return; + } + + // + // Here i Must Calculate TP and SL based on R2R and riskable Factor ... + bool isLong = IsLong(info.signal.type); + + // + // Check Order Mode ... + if (info.signal.mode == NULL) + { + // + // Set Market Execution as Default ... + info.signal.mode = X_ORDER_MODE_MARKET; + } + + // + bool isMarketMode = info.signal.mode == X_ORDER_MODE_MARKET; + + // + // Calculate Entry Price ... + if (info.signal.entry <= 0) + { + // + info.signal.entry = GetEntry( + info.signal.symbol, + info.signal.type); + } + + // + // Calculate TP and SL ... + double mPoint = GetPoints(info.signal.symbol); + + // + // Normalize SL Price ... + if (info.signal.sl > 0) + { + info.signal.sl = NormalizePrice(info.signal.sl, info.signal.symbol); + } + + // + // Retrieve Symbol Point Value ... + double pointValue = xEAAccount.GetPointValue(info.signal.symbol); + + // + // Calculate Risk ... + double riskPrice = MathAbs(info.signal.entry - info.signal.sl); + riskPrice = NormalizePrice(riskPrice, info.signal.symbol); + + // + double riskPoints = PriceToPoint(riskPrice); + riskPoints = NormalizeDouble(riskPoints, 0); + + // + // Calculating Reward based On Ratio ... + double rewardPoints = riskPoints * info.signal.r2r; + double rewardPrice = PointToPrice(rewardPoints); + rewardPrice = NormalizePrice(rewardPrice, info.signal.symbol); + + // + // Calculate TP Price ... + double tpValue = isLong + ? info.signal.entry + rewardPrice + : info.signal.entry - rewardPrice; + + // + // Calculate SL Price ... + double slValue = isLong + ? info.signal.entry - riskPrice + : info.signal.entry + riskPrice; + + // + // Balance Amount which we risks on each Provider's Trade ... + double amount = availableBalance * info.signal.riskAmount; + + // + // Calculating Trade Volume based on risk Points and Amount ... + double volume = + info.signal.useRiskAmountAsVolume + ? info.signal.riskAmount + : xEAAccount.CalculateVolume( + info.signal.symbol, + amount, + riskPoints); + volume = NormalizeVolume(volume, info.signal.symbol); + + // + // Set Caculated TP, SL and Volume ... + if (info.signal.calculateTP) + { + // + if (info.signal.useSupportAndResistance) + { + // + double mTmp[]; + double mTmpPrice; + LogMessage("MomentumStep: " + (string)info.momentumStep); + + // + // Find Good Entry Points ... + if (!isMarketMode) + { + // + if (isLong) + { + // + ArrayCopy( + mTmp, + info.supportResistances.res); + } + else + { + // + ArrayCopy( + mTmp, + info.supportResistances.sup); + } + + // + mTmpPrice = + isLong + ? info.signal.entry + info.momentumStep + : info.signal.entry - info.momentumStep; + double entry = + FindLesserThanValue( + mTmpPrice, + mTmp, + !isLong); + Clean(mTmp); + + // + info.signal.entry = entry; + } + + // + // Find Good SL Point ... + + // + if (isLong) + { + // + ArrayCopy( + mTmp, + info.supportResistances.sup); + } + else + { + // + ArrayCopy( + mTmp, + info.supportResistances.res); + } + + // + mTmpPrice = + isLong + ? info.signal.entry - info.momentumStep + : info.signal.entry + info.momentumStep; + double sl = + FindBiggerThanValue( + mTmpPrice, + mTmp, + !isLong); + Clean(mTmp); + + // + info.signal.sl = sl; + + // + // Find Good TP Point ... + + // + if (isLong) + { + // + ArrayCopy( + mTmp, + info.supportResistances.res); + } + else + { + // + ArrayCopy( + mTmp, + info.supportResistances.sup); + } + + // + // Risk Price ... + mTmpPrice = MathAbs(info.signal.entry - info.signal.sl); + + // + // Reward Price ... + mTmpPrice *= info.signal.r2r; + + // + // Start Search TP ... + mTmpPrice = isLong + ? info.signal.entry + mTmpPrice + : info.signal.entry - mTmpPrice; + double tp = + FindLesserThanValue( + mTmpPrice, + mTmp, + !isLong); + Clean(mTmp); + + // + info.signal.tp = tp; + } + else + { + // + info.signal.tp = tpValue; + info.signal.sl = slValue; + } + } + + // + info.signal.volume = volume; + + // + string comment = GenerateProvidersString(info.signal); + + // + // TODO: Remove this ... + ulong mTicket = MathRand() * 100000; + DrawSignal( + mTicket, + info.signal); + + // + DrawSupportResistance( + 0, + info.supportResistances, + info.signal.providers[0]); + + // + return; + + // + // Here We Execute the Signal by Trader Class Instance ... + bool isPositionExecuted = xEATrade.ExecuteSignal( + info.signal, + comment); + + // + if (isPositionExecuted) + { + // + // Retrieve Position Ticket ... + ulong ticket = 0; + bool isMarketMode = info.signal.mode == X_ORDER_MODE_MARKET; + if (isMarketMode) + { + ticket = xEATrade.GetLastOpenPositionTicket(); + } + else + { + ticket = xEATrade.GetLastPlacedOrderTicket(); + } + + if (ticket == 0) + { + return; + } + + // + // Draw Signal ... + DrawSignal(ticket, info.signal); + + // + // Alert Position ... + string msg = + (isMarketMode + ? "Position" + : "Order") + + ": " + (string)ticket + " was " + (isMarketMode ? "Opened" : "Placed") + " ..."; + LogMessage(msg); + } +} + +// +// Handle StopLoss Event ... +void OnStopLossTriggered(const XDeal &deal) +{ + // + string msg = "SL: " + (string)deal.positionId; + LogMessage(msg); +} + +// +// Handle TakeProfit Event ... +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + string msg = "TP: " + (string)deal.positionId; + LogMessage(msg); +} + +// +// Handle Deals Changed Event ... +void OnDealsChangedHandler(int count) +{ + // + // string msg = "Deals Changed: " + (string)count; + // LogMessage(msg); +} + +// +// Handle Order Changed Event ... +void OnOrdersChangedHandler(int count) +{ + // + // string msg = "Orders Changed: " + (string)count; + // LogMessage(msg); +} + +// +// Handle Position Changed Event ... +void OnPositionsChangedHandler(int count) +{ + // // + // int positionsCount = xEATrade.PositionsCount(); + // if (count <= 0 || positionsCount <= 0) + // { + // return; + // } + + // // + // XPosition positions[]; + // xEATrade.GetPositions(positions); + // for (int i = 0; i < positionsCount; i++) + // { + // // + // XPosition iPosition = positions[i]; + + // // + // bool isIPositionHasSupport = + // xEATrade.HasSupport(iPosition.ticket); + // if (isIPositionHasSupport) + // { + // continue; + // } + + // // + // double sl = iPosition.sl; + + // // + // XSignal signal; + // bool isGenerated = xEATrade.GenerateSLSupportSignal( + // signal, + // iPosition.ticket); + // if (!isGenerated) + // { + // continue; + // } + + // // + // string comment = GenerateSupportSignalComment(iPosition.ticket); + + // // + // bool isExecuted = xEATrade.ExecuteSignal( + // signal, + // comment); + // if (!isExecuted) + // { + // continue; + // } + + // // + // // Now we have to Disable Position SL ... + // bool isModified = xEATrade.Modify( + // iPosition.ticket, + // 0, + // iPosition.tp, + // iPosition.comment); + // if (!isModified) + // { + // return; + // } + + // // + // string msg = "Execute SL Support Signal for Position (" + (string)iPosition.ticket + ") successfully ..."; + // LogMessage(msg); + // } + + // + // LogMessage("OnPositionsChangedHandler ..."); +} + +// +// Handle Trade State Changed ... +void OnTradeStateChangedHandler( + const XOnTradeHandlerState &state) +{ + // // + // string msg = "Trade State Changed ..."; + // LogMessage(msg); +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + // Validate Args ... + result = + // + xEASlippage > 0 && + xEAMagicNumber > 0 + // + // TODO: add new validations here ... + // + ; + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// Extract Signal Provider Struct from User Input ... +bool InitializeProviders() +{ + // + bool result = false; + + // + // Account Manager ... + xEAAccount = new XSCAccount(); + + // + // Trader ... + xEATrade = new XSCTrade( + xEASlippage, + xEAMagicNumber); + + // + // Attach Event Handlers ... + xEATrade.AddOnStopLossEventHandler(OnStopLossTriggered); + xEATrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + xEATrade.AddOnDealsChangedEventHandler(OnDealsChangedHandler); + xEATrade.AddOnOrdersChangedEventHandler(OnOrdersChangedHandler); + xEATrade.AddOnPositionsChangedEventHandler(OnPositionsChangedHandler); + xEATrade.AddOnTradeStateChangedEventHandler(OnTradeStateChangedHandler); + + // + // Prepare Config ... + // + // Prepare Default and Clean Config ... + // in this Config non of Indicators doesn't Draw anything on chart ... + // TODO: We Have to Get These from Inputs of Users ... + X121ProviderInputs configs; + + // + // XCT ... + // Candle Timing ... + configs.xctConfig.clr = clrBlueViolet; + configs.xctConfig.corner = CORNER_RIGHT_UPPER; + configs.xctConfig.showCandleTime = true; + + // + // XCC ... + // Candle Styling ... + configs.xccConfig.upColor = clrLime; + configs.xccConfig.downColor = clrRed; + configs.xccConfig.lineColor = clrLime; + configs.xccConfig.bearishColor = clrRed; + configs.xccConfig.bullishColor = clrLime; + configs.xccConfig.volumesColor = clrGreen; + configs.xccConfig.showCandles = true; + + // + // XHK ... + // HikenAshi Candle Representing ... + configs.xhkConfig.drawCandleLines = false; + + // + // XTM ... + // Trend Magic ... + configs.xtmConfig.length = 35; + configs.xtmConfig.shift = 0; + configs.xtmConfig.method = MODE_SMA; + configs.xtmConfig.appliedTo = PRICE_LOW; + configs.xtmConfig.showLine = false; + + // + // XPV ... + // Peaks And Vales ... + configs.xpvConfig.shortLength = 9; + configs.xpvConfig.mediumLength = 17; + configs.xpvConfig.longLength = 26; + configs.xpvConfig.hindLength = 35; + configs.xpvConfig.fiboLevel1 = 0.382; + configs.xpvConfig.fiboLevel2 = 0.5; + configs.xpvConfig.fiboLevel3 = 0.618; + configs.xpvConfig.hhMode = MODE_HIGH; + configs.xpvConfig.llMode = MODE_LOW; + configs.xpvConfig.showPeaksAndVales = false; + configs.xpvConfig.showLevels = false; + configs.xpvConfig.showFibo1Levels = false; + configs.xpvConfig.showFibo2Levels = false; + configs.xpvConfig.showFibo3Levels = false; + + // + // XAMA ... + // Adaptive Moving Average ... + configs.xamaConfig.length = 52; + configs.xamaConfig.fastEMA = 2; + configs.xamaConfig.slowEMA = 30; + configs.xamaConfig.maShift = 0; + configs.xamaConfig.appliedTo = PRICE_LOW; + configs.xamaConfig.showLine = false; + + // + // XMRB ... + // Moving Average Ribbon ... + configs.xmrbConfig.fast1Length = 3; + configs.xmrbConfig.slow1Length = 5; + configs.xmrbConfig.fast2Length = 8; + configs.xmrbConfig.slow2Length = 13; + configs.xmrbConfig.fast3Length = 21; + configs.xmrbConfig.slow3Length = 34; + configs.xmrbConfig.fast4Length = 55; + configs.xmrbConfig.slow4Length = 89; + configs.xmrbConfig.fast5Length = 144; + configs.xmrbConfig.slow5Length = 233; + configs.xmrbConfig.ribbonMode = MODE_EMA; + configs.xmrbConfig.ribbonAppliedTo = PRICE_CLOSE; + configs.xmrbConfig.showFastMa = false; + configs.xmrbConfig.showSlowMa = false; + configs.xmrbConfig.showRibbon = false; + + // + // XCHE ... + // Chandelier Exit Points ... + configs.xcheConfig.length = 35; + configs.xcheConfig.loopback = 26; + configs.xcheConfig.multiplier1 = 3; + configs.xcheConfig.multiplier2 = 3.5; + configs.xcheConfig.upAppliedTo = PRICE_HIGH; + configs.xcheConfig.downAppliedTo = PRICE_LOW; + configs.xcheConfig.showLongExit1Line = false; + configs.xcheConfig.showShortExit1Line = false; + configs.xcheConfig.showLongExit2Line = false; + configs.xcheConfig.showShortExit2Line = false; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + configs.xichConfig.tenkanSenLength = 9; + configs.xichConfig.tenkanSenMode = X_XICH_HH_LL_MODE; + configs.xichConfig.kijunSenLength = 26; + configs.xichConfig.kijunSenMode = X_XICH_HH_LL_MODE; + configs.xichConfig.senkouSpanBLength = 52; + configs.xichConfig.senkouSpanBMode = X_XICH_HH_LL_MODE; + configs.xichConfig.chikuoSpanAppliedTo = PRICE_CLOSE; + configs.xichConfig.showTenkanSen = false; + configs.xichConfig.showKijunSen = false; + configs.xichConfig.showKijunSenPlus = false; + configs.xichConfig.showKijunSenNegative = false; + configs.xichConfig.showChikouSpan = false; + configs.xichConfig.showSenkouSpanA = false; + configs.xichConfig.showSenkouSpanB = false; + configs.xichConfig.showKumo = false; + configs.xichConfig.shiftKumo = true; + + // + // XTRND ... + // Trend Detector ... + configs.xtrndConfig.cycleLength = 2; + configs.xtrndConfig.numberOfVerifications = 2; + configs.xtrndConfig.hhMode = MODE_HIGH; + configs.xtrndConfig.llMode = MODE_LOW; + configs.xtrndConfig.l1Method = X_PERIOD_AUTO; + configs.xtrndConfig.l1Period = NULL; + configs.xtrndConfig.l2Method = X_PERIOD_AUTO; + configs.xtrndConfig.l2Period = NULL; + configs.xtrndConfig.l3Method = X_PERIOD_AUTO; + configs.xtrndConfig.l3Period = NULL; + configs.xtrndConfig.showConsolidations = false; + configs.xtrndConfig.showTrend = false; + configs.xtrndConfig.showL1Trend = false; + configs.xtrndConfig.showL2Trend = false; + configs.xtrndConfig.showL3Trend = false; + + // + // XSSLC ... + // SSL Channel ... + configs.xsslcConfig.length = 36; + configs.xsslcConfig.method = MODE_SMA; + configs.xsslcConfig.upAppliedTo = PRICE_HIGH; + configs.xsslcConfig.downAppliedTo = PRICE_LOW; + configs.xsslcConfig.showUp = false; + configs.xsslcConfig.showDown = false; + + // + // XHULL ... + // Hull Trend Detection Channel ... + configs.xhullConfig.length = 72; + configs.xhullConfig.divisor = 2; + configs.xhullConfig.upAppliedTo = PRICE_HIGH; + configs.xhullConfig.downAppliedTo = PRICE_LOW; + configs.xhullConfig.showUpZone = false; + configs.xhullConfig.showDownZone = false; + + // + // Default Configs For Different States ... + bool showPV = true; + bool showHK = true; + bool showCHE = true; + bool showTRND = true; + bool simpleIchi = true; + + // + + // + if (showHK) + { + // + // Hiken Ashi ... + configs.xccConfig.showCandles = false; + configs.xhkConfig.drawCandles = true; + } + if (showPV) + { + // + // Peaks and Vales ... + configs.xpvConfig.showFibo1Levels = true; + configs.xpvConfig.showFibo2Levels = true; + configs.xpvConfig.showFibo3Levels = true; + configs.xpvConfig.showPeaksAndVales = true; + } + if (simpleIchi) + { + // + // Simple Ichimoku Kinko Hyo ... + configs.xichConfig.showKijunSen = true; + configs.xichConfig.showTenkanSen = true; + configs.xichConfig.showSenkouSpanA = true; + configs.xichConfig.showSenkouSpanB = true; + } + if (showCHE) + { + // + // Chandelier Exit ... + configs.xcheConfig.showLongExit1Line = true; + configs.xcheConfig.showLongExit2Line = true; + configs.xcheConfig.showShortExit1Line = true; + configs.xcheConfig.showShortExit2Line = true; + } + if (showTRND) + { + // + // Show Trend ... + configs.xtrndConfig.showL1Trend = true; + configs.xtrndConfig.showL2Trend = true; + configs.xtrndConfig.showL3Trend = true; + } + + // + xEAProvider = new XSCX121Provider( + _Symbol, + _Period); + + // + // Attach Event Handlers ... + xEAProvider.AddOnSignalConditionEventHandler(OnSignalConditionsRecieved); + + // + // Initialize Provider ... + result = xEAProvider.SetConfig(configs); + if (!result) + { + return result; + } + + // + return result; +} + +// +void CallProvidersOnTick() +{ + // + // int providersCount = ArraySize(xEAProviders); + // if (providersCount <= 0) + // { + // return; + // } + + // // + // // Loop Through Providers ... + // for (int i = 0; i < providersCount; i++) + // { + // // + // X121SignalProvider providerDescriptor = xEAProviders[i]; + + // // + // providerDescriptor.provider.OnTick(); + // } + + // + xEAProvider.OnTick(); +} + +// +void GetPositions( + XPosition &result[], // Hold Result ... + string symbol = NULL, // Trading Symbol ... + ENUM_POSITION_TYPE type = NULL, // Trading Type ... + ENUM_TIMEFRAMES period = NULL, // Trading Period ... + ENUM_X121_SIGNAL_PROVIDERS provider = NULL // Trade Provider ... +) +{ + // + Clean(result); + + // + int positionsCount = xEATrade.PositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition positions[]; + xEATrade.GetPositions( + positions, + symbol, + period); + positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return; + } + + // + if (provider == NULL && type == NULL) + { + // + ArrayResize( + result, + ArraySize(positions)); + + // + for (int i = 0; i < positionsCount; i++) + { + // + Add( + positions[i], + result); + } + + // + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + ENUM_X121_SIGNAL_PROVIDERS iProvider = ExtractProvider(iPosition); + if (provider != NULL && iProvider != provider) + { + continue; + } + + // + if (type == NULL || iPosition.type == type) + { + // + Add( + iPosition, + result); + } + } +} + +// +// START Guard Functions ... +// + +// +// Do Guard Actions ... +void HandleGuard() +{ + // + // Retrieve Provider Guard Actions ... + X121Guard guards[]; + xEAProvider.ProvideGuard(guards); + int guardsCount = ArraySize(guards); + if (guardsCount <= 0) + { + return; + } + + // + for (int i = 0; i < guardsCount; i++) + { + // + X121Guard iGuard = guards[i]; + + // + switch (iGuard.action) + { + // + // Hedge In Profit Specified Positions ... + case X_GUARD_ACTION_HEDGE: + HandleGuardHedgeAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Trail Stop Loss in Specified Positions ... + case X_GUARD_ACTION_TRAIL_STOP: + HandleGuardTrailingStopAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period, + iGuard.dblPayLoad); + break; + + // + // Force Close Specified Positions ... + case X_GUARD_ACTION_FORCE_CLOSE: + HandleGuardForceCloseAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Generate and Place Support Signals ... + case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL: + HandleGuardAddSupportPositionAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Delete All Placed Pending Orders ... + case X_GUARD_ACTION_CANCEL_PENDING_ORDERS: + HandleGuardCancelPendingOrdersAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + } + } +} + +// +// Close All Specified Provider's Positions in Profit Summary ... +void HandleGuardHedgeAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame +) +{ + // + // TODO: Implement this ... +} + +// +// Force Close Specified Set Of Position ... +void HandleGuardForceCloseAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame +) +{ + // + ENUM_X121_SIGNAL_PROVIDERS mProvider = ExtractProvider(provider); + + // + XPosition positions[]; + GetPositions( + positions, + symbol, + type, + period, + mProvider); + if (ArraySize(positions) <= 0) + { + return; + } + + // + string comment = provider + " Force Close Due Market Sense Change ..."; + xEATrade.ClosePositions( + positions, + comment); + + // + LogMessage(comment); +} + +// +// Trailing Specified Set Of Positions Stop Losses ... +void HandleGuardTrailingStopAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double sl // Desired SL Value ... +) +{ + // + // TODO: Implement this ... +} + +// +// Add Support Signal for Specified Positions ... +void HandleGuardAddSupportPositionAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame +) +{ + // + // TODO: Implement this ... +} + +// +// Cancel all Placed Orders ... +void HandleGuardCancelPendingOrdersAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame +) +{ + // + // TODO: Implement this ... +} + +// +// END Guard Functions ... +// + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.xhull.class.mq5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.xhull.class.mq5 new file mode 100644 index 0000000..185449a --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x-saherelm.xhull.class.mq5 @@ -0,0 +1,216 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Hull Class Library +// ---------------------------------------------- +// Name: XSCHull +// Description: provides all Hull requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +struct XHullData +{ + // + double value; + double value3; + + // + double wsum1; + double wsum2; + double wsum3; + + // + double lsum1; + double lsum2; + double lsum3; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class For Hull Calculations ... +class XSCHull +{ + // +public: + // + // Constructor ... + XSCHull() : mFullPeriod(1), mHalfPeriod(1), mSqrtPeriod(1), mArraySize(-1) + { + // + // These are a way above to assign Private variables at Construct time ... + } + + // + // Deconstructor ... + ~XSCHull() + { + ArrayFree(mData); + } + + // + // Initial Hull ... + bool Init(int period, double divisor) + { + // + bool result = false; + + // + mFullPeriod = (int)(period > 1 ? period : 1); + mHalfPeriod = (int)(mFullPeriod > 1 ? mFullPeriod / (divisor > 1 ? divisor : 1) : 1); + mSqrtPeriod = (int)MathSqrt(mFullPeriod); + + // + mArraySize = -1; + mWeight1 = mWeight2 = mWeight3 = 1; + + // + result = true; + + // + return result; + } + + // + // CalCulate Specific Value ... + double Calculate( + double value, + int i, + int bars) + { + // + double result = 0; + + // + if (mArraySize < bars) + { + // + mArraySize = ArrayResize(mData, bars + 500); + if (mArraySize < bars) + return result; + } + + // + mData[i].value = value; + if (i > mFullPeriod) + { + // + mData[i].wsum1 = mData[i - 1].wsum1 + value * mHalfPeriod - mData[i - 1].lsum1; + mData[i].lsum1 = mData[i - 1].lsum1 + value - mData[i - mHalfPeriod].value; + mData[i].wsum2 = mData[i - 1].wsum2 + value * mFullPeriod - mData[i - 1].lsum2; + mData[i].lsum2 = mData[i - 1].lsum2 + value - mData[i - mFullPeriod].value; + } + else + { + // + mData[i].wsum1 = mData[i].wsum2 = + mData[i].lsum1 = mData[i].lsum2 = mWeight1 = mWeight2 = 0; + for (int k = 0, w1 = mHalfPeriod, w2 = mFullPeriod; w2 > 0 && i >= k; k++, w1--, w2--) + { + // + if (w1 > 0) + { + // + mData[i].wsum1 += mData[i - k].value * w1; + mData[i].lsum1 += mData[i - k].value; + mWeight1 += w1; + } + + // + mData[i].wsum2 += mData[i - k].value * w2; + mData[i].lsum2 += mData[i - k].value; + mWeight2 += w2; + } + } + + // + mData[i].value3 = 2.0 * mData[i].wsum1 / mWeight1 - mData[i].wsum2 / mWeight2; + + // + if (i > mSqrtPeriod) + { + // + mData[i].wsum3 = mData[i - 1].wsum3 + mData[i].value3 * mSqrtPeriod - mData[i - 1].lsum3; + mData[i].lsum3 = mData[i - 1].lsum3 + mData[i].value3 - mData[i - mSqrtPeriod].value3; + } + else + { + // + mData[i].wsum3 = + mData[i].lsum3 = mWeight3 = 0; + + // + for (int k = 0, w3 = mSqrtPeriod; w3 > 0 && i >= k; k++, w3--) + { + // + mData[i].wsum3 += mData[i - k].value3 * w3; + mData[i].lsum3 += mData[i - k].value3; + mWeight3 += w3; + } + } + + // + result = mData[i].wsum3 / mWeight3; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + int mFullPeriod; + int mHalfPeriod; + int mSqrtPeriod; + int mArraySize; + double mWeight1; + double mWeight2; + double mWeight3; + + // + XHullData mData[]; +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x-saherelm.xtrade.before.ontrade.handlers.class.mq5 b/MQLTestWorkspace/BKPS/BKP/x-saherelm.xtrade.before.ontrade.handlers.class.mq5 new file mode 100644 index 0000000..f0d5b4a --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x-saherelm.xtrade.before.ontrade.handlers.class.mq5 @@ -0,0 +1,2838 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Class Library +// ---------------------------------------------- +// Name: XSCTrade +// Description: provides all Trade requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Model an Open Position ... +struct XPosition +{ + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Position Comment ... + string comment; +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long pocitionID; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string smybol; + + // + // Order Comment ... + string comment; +}; + +// +// Model a Deal ... +struct XDeal +{ + // + // the ID of the Expert Advisor, that executed the deal ... + ulong magic; + + // + // the ID of position, in which the deal was involved ... + ulong positionId; + + // + // Ticket ... + ulong ticket; + + // + // the name of the deal symbol ... + string symbol; + + // + // order by which the deal is executed ... + ulong order; + + // + // the time of deal execution ... + datetime time; + + // + // Deal price ... + double price; + + // + // the financial result of the deal (in deposit currency) ... + double profit; + + // + // the amount of swap when position is closed ... + double swap; + + // + // the amount of commission of the deal ... + double commission; + + // + // the volume of deal ... + double volume; + + // + // the deal comment ... + string comment; + + // + // the deal type ... + // ------------------------------------------------------------------ + // DEAL_TYPE_BUY => Buy ... + // DEAL_TYPE_SELL => Sell ... + // DEAL_TYPE_BUY_CANCELED => Canceled buy deal ... + // There can be a situation when a previously executed buy deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ... + // + // DEAL_TYPE_SELL_CANCELED => Canceled sell deal ... + // There can be a situation when a previously executed sell deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation + // + // DEAL_TYPE_BALANCE => Balance ... + // DEAL_TYPE_CREDIT => Credit ... + // DEAL_TYPE_CHARGE => Additional charge ... + // DEAL_TYPE_CORRECTION => Correction ... + // DEAL_TAX => Tax charges ... + // DEAL_TYPE_BONUS => Bonus ... + // DEAL_TYPE_INTEREST => Interest rate ... + // DEAL_DIVIDEND => Dividend operations... + // DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ... + // DEAL_TYPE_COMMISSION => Additional commission ... + // DEAL_TYPE_COMMISSION_DAILY => Daily commission ... + // DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ... + // DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ... + // DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission + ENUM_DEAL_TYPE type; + + // + // the deal direction ... + // ---------------------------------- + // DEAL_ENTRY_IN => Entry in ... + // DEAL_ENTRY_OUT => Entry out ... + // DEAL_ENTRY_INOUT => Reverse ... + // DEAL_ENTRY_OUT_BY => Close a position by an opposite one ... + ENUM_DEAL_ENTRY entry; + + // + // deal reson ... + // --------------------- + // DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ... + // DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ... + // DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ... + // DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ... + // DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ... + // DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ... + // DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ... + // DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ... + // DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ... + // DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ... + ENUM_DEAL_REASON reason; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// XCTrade Base Class ... +class XSCTradeBase : public CTrade +{ +public: + // + // Modify Specific Position, by Specific Comment ... + bool PositionModify( + const string symbol, // Symbol + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!SelectPosition(symbol)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + bool PositionModify( + const ulong ticket, // Position Ticket + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.position = ticket; + m_request.symbol = PositionGetString(POSITION_SYMBOL); + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + + // + // Close Specific Position, by Specific Comment ... + bool PositionClose( + const string symbol, // Symbol + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + bool partial_close = false; + int retry_count = 10; + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + do + { + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specify Comment ... + m_request.comment = comment; + + // + // check volume + double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + if (m_request.volume > max_volume) + { + // + m_request.volume = max_volume; + partial_close = true; + } + else + { + partial_close = false; + } + + // + // hedging? just send order + if (IsHedging()) + { + return (OrderSend(m_request, m_result)); + } + + // + // order send + if (!OrderSend(m_request, m_result)) + { + // + if (--retry_count != 0) + { + continue; + } + + // + if (retcode == TRADE_RETCODE_DONE_PARTIAL) + { + m_result.retcode = retcode; + } + + // + return (false); + } + + // + //--- WARNING. If position volume exceeds the maximum volume allowed for deal, + //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, + //--- but partially. It is decreased by the maximum volume allowed for deal. + if (m_async_mode) + { + break; + } + + // + retcode = TRADE_RETCODE_DONE_PARTIAL; + if (partial_close) + { + Sleep(1000); + } + } while (partial_close); + + // + // succeed + return (true); + } + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } + + // + // Partial Close Specific Position, by Specific Comment ... + bool PositionClosePartial( + const string symbol, // Symbol + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // hedging? just send order + return (OrderSend(m_request, m_result)); + } + bool PositionClosePartial( + const ulong ticket, // Position Ticket + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } +}; + +// +// END Overrides ... +// + +// +// a Class for Manage Trades ... +class XSCTrade +{ + // + // Public ... +public: + // + // Constructor ... + void XSCTrade( + int slippage, // Specify Slippage + ulong magicNumber // Specify Magic Number + ) + { + // + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mPeriodPrefix = "PR"; + + // + mTrader = new XSCTradeBase(); + + // + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + // Prepare Trade Event Materials ... + mStartDate = 0; + mLastOrdersCount = OrdersTotal(); + mLastDealsCount = HistoryDealsTotal(); + mLastPositionsCount = PositionsTotal(); + + // + GetDeals(mLastDeals); + GetOrders(mLastOrders); + GetPositions(mLastPositions); + } + + // + // Deconstructor ... + void ~XSCTrade() + { + } + + // + // START Event Processing ... + // + + // + // This Must be Called Every time OnTrade Event Happening ... + void HandleOnTrade() + { + // + int ordersCount = OrdersTotal(); + int dealsCount = HistoryDealsTotal(); + int positionsCount = PositionsTotal(); + + // + // LogMessage("Salam"); + + // + GetDeals(mDeals); + GetOrders(mOrders); + GetPositions(mPositions); + + // + datetime currentTime = TimeCurrent(); + HistorySelect(mStartDate, currentTime); + + // + // Processing Positions ... + if (positionsCount > mLastPositionsCount) + { + // + // Position Appeared ... + LogMessage("Position Appeared ..."); + + // + // Update Deals ... + dealsCount = HistoryDealsTotal(); + GetDeals(mDeals); + } + else if (positionsCount < mLastPositionsCount) + { + // + // Position Disappeared ... + LogMessage("Position Disappeared ..."); + + // + // Update Deals ... + dealsCount = HistoryDealsTotal(); + GetDeals(mDeals); + } + + // + // Processing Order Changes ... + if (ordersCount > mLastOrdersCount) + { + // + // Orders Appeared ... + LogMessage("Orders Appeared ..."); + } + else if (ordersCount < mLastOrdersCount) + { + // + // Orders Disappeared ... + LogMessage("Orders Disappeared ..."); + } + + // + // Processing Deal Changes ... + if (dealsCount > mLastDealsCount) + { + // + // Deals Appeared ... + LogMessage("Deals Appeared ..."); + } + else if (dealsCount > mLastDealsCount) + { + // + // Deals Disappeard ... + LogMessage("Deals Disappeard ..."); + } + + // + // Update Date after processing ... + + // + mLastOrdersCount = OrdersTotal(); + mLastDealsCount = HistoryDealsTotal(); + mLastPositionsCount = PositionsTotal(); + + // + GetDeals(mLastDeals); + GetOrders(mLastOrders); + GetPositions(mLastPositions); + } + + // + // END Event Processing ... + // + + // + // START Provided Functions ... + // + + // + // Count Currently Open Positions ... + int PositionsCount( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + int result = 0; + + // + int allPositions = 0; + int longPositions = 0; + int shortPositions = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + allPositions++; + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + longPositions++; + } + else + { + shortPositions++; + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + allPositions++; + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + longPositions++; + } + else + { + shortPositions++; + } + + // + continue; + } + } + } + + // + // Specify Result ... + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + result = allPositions; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == POSITION_TYPE_BUY) + { + result = longPositions; + } + else + { + result = shortPositions++; + } + } + else if (StringLen(symbol) > 0) + { + // + result = allPositions; + } + else if (type != NULL) + { + // + if (type == POSITION_TYPE_BUY) + { + result = longPositions; + } + else + { + result = shortPositions; + } + } + + // + return result; + } + + // + // Retrieve Max In Profit Position Ticket ... + ulong GetMaxInProfitPosition( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + ulong result = -1; + + // + double profit = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + double positionAbsProfit = MathAbs(positionProfit); + if (positionProfit <= 0) + { + continue; + } + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Retrieve Max In DrawDown Position Ticket ... + ulong GetMaxInDrawDownPosition( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + ulong result = -1; + + // + double profit = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + double positionAbsProfit = MathAbs(positionProfit); + if (positionProfit >= 0) + { + continue; + } + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Retrieve Specific Position's Profit ... + double GetPositionProfit( + const ulong ticket // Specified Position Ticket + ) + { + // + double result = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + result = mPositionInfo.Profit(); + break; + } + + // + return result; + } + + // + // Retrieve Specific Position's OpenDate ... + datetime GetPositionOpenDate( + const ulong ticket // Specified Position Ticket + ) + { + // + datetime result = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + result = mPositionInfo.Time(); + break; + } + + // + return result; + } + + // + // Retrieve Specific Position's Comment ... + string GetPositionComment( + const ulong ticket // Specified Position Ticket + ) + { + // + string result = ""; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + result = mPositionInfo.Comment(); + break; + } + + // + return result; + } + + // + // Retrieve All Open Positions Profit ... + double GetPositionsProfit( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + double result = 0; + + // + double profit = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (profit < positionProfit) + { + // + result += positionProfit; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionProfit) + { + // + result += positionProfit; + } + } + else + { + // + if (profit < positionProfit) + { + // + result += positionProfit; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (profit < positionProfit) + { + // + result += positionProfit; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionProfit) + { + // + result += positionProfit; + } + } + else + { + // + if (profit < positionProfit) + { + // + result += positionProfit; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Find Oldes Position ... + ulong GetOldestPosition( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + ulong result = 0; + + // + int age = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + double positionAbsProfit = MathAbs(positionProfit); + if (positionProfit >= 0) + { + continue; + } + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + string positionComment = mPositionInfo.Comment(); + ENUM_TIMEFRAMES positionPeriod = ExtractPositionPeriod(positionComment); + + // + // Calculate Position's Age ... + datetime positionOpenTime = mPositionInfo.Time(); + + // + // Retrieve Trade Open Bar Index based on Current Period ... + int positionOpenBarIndex = iBarShift( + positionSymbol, + positionPeriod, + positionOpenTime); + + // + // Calculate Trade Life ... + int positionAge = MathAbs(0 - positionOpenBarIndex); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + else + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + else + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = "" // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + if (tp <= 0 && sl <= 0) + { + result = false; + return result; + } + + // + // Use Position Comment when there isn't new One ... + if (StringLen(comment) == 0) + { + comment = GetPositionComment(ticket); + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment); + + // + return result; + } + + // + // Close Position By Ticket ... + bool Close( + ulong ticket, // Position Ticket + string comment = "" // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + // Try to Select Position ... + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + // Close Position By Specific Comment ... + result = mTrader.PositionClose( + ticket, + mSlippage, + comment); + + // + return result; + } + + // + // Close All Positions ... + void CloseAllPositions( + string comment = "" // Close Position By Specific Comment + ) + { + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + Close( + positionTicket, + comment); + } + } + + // + // Close Partial By Ticket ... + bool ClosePartial( + ulong ticket, // Position Ticket + double volume, // Volume Size for Partial Closing + string comment = "" // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume, + mSlippage, + comment); + + // + return result; + } + + // + // Find Position Open Bar Index ... + int GetPositionOpenBarIndex( + const ulong ticket // position ticket + ) + { + // + int result = -1; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + string symbol = mPositionInfo.Symbol(); + datetime openAt = mPositionInfo.Time(); + string comment = mPositionInfo.Comment(); + ENUM_TIMEFRAMES period = ExtractPositionPeriod(comment); + + // + result = iBarShift( + symbol, + period, + openAt); + } + + // + return result; + } + + // + // Retrieve Positions as an Array ... + void GetPositions( + XPosition &result[] // Hold Result ... + ) + { + // + Clear(result); + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong magic = mPositionInfo.Magic(); + ulong ticket = mPositionInfo.Ticket(); + string symbol = mPositionInfo.Symbol(); + datetime openAt = mPositionInfo.Time(); + double swap = mPositionInfo.Swap(); + double sl = mPositionInfo.StopLoss(); + double tp = mPositionInfo.TakeProfit(); + double profit = mPositionInfo.Profit(); + double volume = mPositionInfo.Volume(); + string comment = mPositionInfo.Comment(); + double entry = mPositionInfo.PriceOpen(); + double price = mPositionInfo.PriceCurrent(); + double commission = mPositionInfo.Commission(); + ENUM_POSITION_TYPE type = mPositionInfo.PositionType(); + ENUM_TIMEFRAMES period = ExtractPositionPeriod(comment); + + // + XPosition iPosition = {}; + + // + iPosition.tp = tp; + iPosition.sl = sl; + iPosition.swap = swap; + iPosition.type = type; + iPosition.magic = magic; + iPosition.entry = entry; + iPosition.price = price; + iPosition.ticket = ticket; + iPosition.symbol = symbol; + iPosition.period = period; + iPosition.volume = volume; + iPosition.openAt = openAt; + iPosition.profit = profit; + iPosition.comment = comment; + iPosition.commission = commission; + + // + Add( + iPosition, + result); + } + } + + // + void GetPositions( + XPosition &result[], // Hold Result ... + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period // Trading Period ... + ) + { + // + Clear(result); + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition allPositions[]; + GetPositions(allPositions); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + if (symbol != iPosition.symbol) + { + continue; + } + + // + ENUM_TIMEFRAMES positionPeriod = ExtractPositionPeriod(iPosition.comment); + if (period != positionPeriod) + { + continue; + } + + // + Add( + iPosition, + result); + } + } + + // + // Retrieve in Profit Positions ... + void GetInProfitPositions( + XPosition &result[] // Hold Result ... + ) + { + // + Clear(result); + + // + XPosition allPositions[]; + GetPositions(allPositions); + int positionsCount = ArraySize(allPositions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + if (iPosition.profit > 0) + { + Add( + iPosition, + result); + } + } + } + + // + // Retrieve in Drawdown Positions ... + void GetInDrawdownPositions( + XPosition &result[] // Hold Result ... + ) + { + // + Clear(result); + + // + XPosition allPositions[]; + GetPositions(allPositions); + int positionsCount = ArraySize(allPositions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + if (iPosition.profit < 0) + { + Add( + iPosition, + result); + } + } + } + + // + // Close a Collection Of Positions ... + void ClosePositions( + XPosition &positions[], // Positions to Close ... + string comment = "" // Specified Comment ... + ) + { + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + Close( + iPosition.ticket, + comment); + } + } + + // + // Retrieve All Orders ... + void GetOrders(XOrder &result[]) + { + // + Clear(result); + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return; + } + + // + // Since Orders may be so more than positions ... + // start Orders Collectiong Loops reverse ... + for (int i = ordersCount - 1; i >= 0; i--) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mOrderInfo.Magic() != mMagicNumber) + { + continue; + } + + // + // Reading Order Info ... + long magic = mOrderInfo.Magic(); + double sl = mOrderInfo.StopLoss(); + ulong ticket = mOrderInfo.Ticket(); + double tp = mOrderInfo.TakeProfit(); + string smybol = mOrderInfo.Symbol(); + string comment = mOrderInfo.Comment(); + long pocitionID = mOrderInfo.PositionId(); + double openPrice = mOrderInfo.PriceOpen(); + datetime setupAt = mOrderInfo.TimeSetup(); + datetime executedAt = mOrderInfo.TimeDone(); + ENUM_ORDER_STATE state = mOrderInfo.State(); + ENUM_ORDER_TYPE type = mOrderInfo.OrderType(); + double currentPrice = mOrderInfo.PriceCurrent(); + datetime expiredAt = mOrderInfo.TimeExpiration(); + double initialVolume = mOrderInfo.VolumeInitial(); + double currentVolume = mOrderInfo.VolumeCurrent(); + double stopLimitPrice = mOrderInfo.PriceStopLimit(); + ENUM_ORDER_TYPE_TIME lifetime = mOrderInfo.TypeTime(); + ENUM_ORDER_TYPE_FILLING filling = mOrderInfo.TypeFilling(); + + // + // Now Create an instance of XOrder struct and fill it by + // retrieved data, and add it to results ... + XOrder iOrder = {}; + + // + iOrder.sl = sl; + iOrder.tp = tp; + iOrder.type = type; + iOrder.state = state; + iOrder.magic = magic; + iOrder.ticket = ticket; + iOrder.smybol = smybol; + iOrder.setupAt = setupAt; + iOrder.comment = comment; + iOrder.filling = filling; + iOrder.lifetime = lifetime; + iOrder.expiredAt = expiredAt; + iOrder.openPrice = openPrice; + iOrder.pocitionID = pocitionID; + iOrder.executedAt = executedAt; + iOrder.currentPrice = currentPrice; + iOrder.initialVolume = initialVolume; + iOrder.currentVolume = currentVolume; + iOrder.stopLimitPrice = stopLimitPrice; + + // + Add( + iOrder, + result); + } + } + + // + // Retrieve All Deals ... + void GetDeals(XDeal &result[]) + { + // + Clear(result); + + // + int dealsCount = HistoryDealsTotal(); + if (dealsCount <= 0) + { + return; + } + + // + for (int i = dealsCount - 1; i >= 0; i--) + { + // + if (!mDealInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mDealInfo.Magic() != mMagicNumber) + { + continue; + } + + // + // Reading Order Info ... + double swap = mDealInfo.Swap(); + ulong magic = mDealInfo.Magic(); + ulong order = mDealInfo.Order(); + ulong ticket = mDealInfo.Ticket(); + datetime time = mDealInfo.Time(); + double price = mDealInfo.Price(); + string symbol = mDealInfo.Symbol(); + double profit = mDealInfo.Profit(); + double volume = mDealInfo.Volume(); + string comment = mDealInfo.Comment(); + ulong positionId = mDealInfo.PositionId(); + ENUM_DEAL_ENTRY entry = mDealInfo.Entry(); + double commission = mDealInfo.Commission(); + ENUM_DEAL_TYPE type = mDealInfo.DealType(); + ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + XDeal iDeal = {}; + + // + iDeal.swap = swap; + iDeal.time = time; + iDeal.type = type; + iDeal.magic = magic; + iDeal.entry = entry; + iDeal.order = order; + iDeal.price = price; + iDeal.ticket = ticket; + iDeal.symbol = symbol; + iDeal.profit = profit; + iDeal.volume = volume; + iDeal.reason = reason; + iDeal.comment = comment; + iDeal.positionId = positionId; + iDeal.commission = commission; + + // + Add( + iDeal, + result); + } + } + + // + // Generate String Representation Of Position's Time Frame ... + string GeneratePositionPeriodComment(ENUM_TIMEFRAMES period) + { + // + string result = mPeriodPrefix + "(" + ToString(period) + ")"; + + // + return result; + } + + // + // Extract Position Time Frame From it's Comment ... + ENUM_TIMEFRAMES ExtractPositionPeriod(string comment) + { + // + ENUM_TIMEFRAMES result = _Period; + + // + if (StringLen(comment) <= 0) + { + return result; + } + + // + string periodStr = ExtractString( + comment, + mPeriodPrefix + "(", + ")"); + if (StringLen(periodStr) <= 0) + { + return result; + } + + // + result = ToPeriod(periodStr); + + // + return result; + } + + // + // Retrieve Last Open Position Ticket ... + ulong GetLastOpenPositionTicket() + { + // + ulong result = 0; + + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + result = PositionGetTicket(PositionsTotal() - 1); + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // using deviation, it must be in Point ... + int mSlippage; + + // + // using magic number ... + ulong mMagicNumber; + + // + // using CTrade instance ... + XSCTradeBase mTrader; + + // + // Deals Info ... + CDealInfo mDealInfo; + + // + // Order Info ... + COrderInfo mOrderInfo; + + // + // using PositionInfo instance ... + CPositionInfo mPositionInfo; + + // + // ADDITIONAL Data ... + + // + string mPeriodPrefix; + + // + // Trade Processing ... + datetime mStartDate; + int mLastDealsCount; + int mLastOrdersCount; + int mLastPositionsCount; + // + XDeal mDeals[]; + XOrder mOrders[]; + XPosition mPositions[]; + // + XDeal mLastDeals[]; + XOrder mLastOrders[]; + XPosition mLastPositions[]; +}; + +// +// START Usefull Functions ... +// + +// +// Add Specific XPosition to Specified Array ... +void Add( + XDeal &item, + XDeal &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XOrder &item, + XOrder &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XPosition &item, + XPosition &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Clear All Items Inside Array ... +void Clear(XDeal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clear(XOrder &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clear(XPosition &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/Test/x-saherelm.xea.test.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/Test/x-saherelm.xea.test.mq5 new file mode 100644 index 0000000..f01ba68 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/Test/x-saherelm.xea.test.mq5 @@ -0,0 +1,1353 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ---------------------------------------- +// Name: XEA TEST +// Description: this is an expert controller +// advisors which provides a mechanism for use them ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XEA EA" +#property strict + +// +// START Definitions ... +// + +// +string mSupportToken = "SP"; +string mProviderToken = "PRV"; +string mRiskFreeToken = "RF"; + +// +enum ENUM_X_SIGNAL_PROVIDERS +{ + NONE = 0, + XTRND = 1, + XICHI = 2, + XTest = 10, +}; + +// +// END Definitions ... +// + +// +// START Inputs ... +// + +// +// EA ... +input group "Common"; +input bool xEAEnable = true; // Enable EA +input int xEASlippage = 10; // Slippgae +input ulong xEAMagicNumber = 1604056; // Magic Number + +// +// Signals ... +input group "Signals"; +input bool xEAEnableLongs = true; // Enable Long Trades +input bool xEAEnableShorts = true; // Enable Short Trades + +// +// Alerts ... +input group "Alerts"; +input bool xEAEnableAlerts = true; // Enable Events Alert +input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day +input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month + +// +// END Inputs ... +// + +// +// START Including Providers ... +// + +// +// Classes ... +#include "../../Classes/x-saherelm.xtrade.class.mq5" +#include "../../Classes/x-saherelm.xaccount.class.mq5" +#include "../../Classes/x-saherelm.xdatacollector.class.mq5" + +// +// Test Provider Library ... +#include "../../Providers/Test/x121.test.provider.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +bool isXEANewHour; +bool isXEANewDay; +bool isXEANewWeek; +bool isXEANewMonth; + +// +// Determines EA is Running On Test Mode or not ... +bool xEAIsTestMode = false; + +// +// Check prevent Double Signalling on Same Candle ... +bool xEAWaitUntilNextCandle = false; + +// +XSCTrade *xEATrade; +XSCAccount *xEAAccount; +XSCDataCollector *xEACollector; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = "XEA"; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Init Provider ... + if (!XTestPRVDOnInit()) + { + return INIT_FAILED; + } + + // + xEAIsTestMode = IsRunningOnTestMode(); + + // + xEACollector = new XSCDataCollector("XTestEA"); + xEACollector.CleanStore(); + + // + // Initialize Trade Class ... + xEATrade = new XSCTrade( + xEASlippage, + xEAMagicNumber); + + // + // Attach Event Handlers ... + xEATrade.AddOnStopLossEventHandler(OnStopLossTriggered); + xEATrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + xEATrade.AddOnDealsChangedEventHandler(OnDealsChangedHandler); + xEATrade.AddOnOrdersChangedEventHandler(OnOrdersChangedHandler); + + // + // Initialize Account Class ... + xEAAccount = new XSCAccount(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + delete xEATrade; + delete xEAAccount; + delete xEACollector; + + // + // De Initialize XEA Providers ... + XTestPRVDOnDeInit(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXEANewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXEANewMonth && + xEAEnableAlerts && + xEAEnableMonthlyAlerts; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXEANewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXEANewWeek && + xEAEnableAlerts && + xEAEnableWeeklyAlerts; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXEANewDay = IsNewDay(); + bool canDailyAlert = + isXEANewDay && + xEAEnableAlerts && + xEAEnableDailyAlerts; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXEANewHour = IsNewHour(); + bool canHourlyAlert = + isXEANewHour && + xEAEnableAlerts && + xEAEnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + // + // Prevent Going Forward if user Disable it ... + if (xEAEnable) + { + // + // Call All Providers OnTick Method ... + XTestPRVDOnTick(); + + // + // Do all Guard Mechanism ... + HandleGuard(); + + // + // Check Can Ignore Tick or not .. + bool canIgnoreTick = xEAIsTestMode + ? !IsNewCandle() + : !IsNewCandle() && xEAWaitUntilNextCandle; + if (canIgnoreTick) + { + return; + } + + // + xEAWaitUntilNextCandle = false; + + // + XSignal signal; + bool hasSignal = XTestPRVDProcessSignals(signal); + if (hasSignal) + { + // + xEAWaitUntilNextCandle = true; + OnSignalRecieved(signal); + } + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + // + // Process Trades ... + xEATrade.HandleOnTrade(); +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + // TODO: Fix this ... + bool result = true; + + // + // Validate Args ... + result = + // + xEASlippage > 0 && + xEAMagicNumber > 0 + // + ; + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// Handle Signal Recieved Event ... +void OnSignalRecieved( + XSignal &signal // Recieved Signal ... +) +{ + // + // Ignore Disabled Signals ... + if ((signal.type == POSITION_TYPE_BUY && !xEAEnableLongs) || + (signal.type == POSITION_TYPE_SELL && !xEAEnableShorts)) + { + return; + } + + // + if (StringLen(signal.symbol) == 0 || signal.period == NULL) + { + return; + } + + // + xEACollector.CollectSignal(signal); + + // + // Count Open Positions ... + int openPositionsCount = xEATrade.PositionsCount(); + + // + string mTagId = GenerateTag(signal); + + // + // Check Last Signal ... + datetime barTime = iTime( + signal.symbol, + signal.period, + 0); + + // + // Retrieve Tradable Balance ... + double availableBalance = xEAAccount.GetEquity(); + + // + // Verify Available Balance ... + double balance = xEAAccount.GetBalance(); + + // + // Here i Must Calculate TP and SL based on R2R and riskable Factor ... + bool isLong = IsLong(signal.type); + + // + // Check Order Mode ... + if (signal.mode == NULL) + { + // + // Set Market Execution as Default ... + signal.mode = X_ORDER_MODE_MARKET; + } + + // + // Calculate Entry Price ... + if (signal.entry <= 0) + { + // + signal.entry = GetEntry( + signal.symbol, + signal.type); + } + + // + // R2R ... + if (signal.r2r <= 0) + { + // + // Set Default Risk to Reward Ratio to 1 ... + signal.r2r = 1; + } + + // + // Calculate TP and SL ... + double mPoint = GetPoints(signal.symbol); + + // + // Normalize SL Price ... + if (signal.sl > 0) + { + signal.sl = NormalizePrice(signal.sl, signal.symbol); + } + + // + // Retrieve Symbol Point Value ... + double pointValue = xEAAccount.GetPointValue(signal.symbol); + + // + // Calculate Risk ... + double riskPrice = MathAbs(signal.entry - signal.sl); + riskPrice = NormalizePrice(riskPrice, signal.symbol); + + // + double riskPoints = PriceToPoint(riskPrice); + riskPoints = NormalizeDouble(riskPoints, 0); + + // + // Calculating Reward based On Ratio ... + double rewardPoints = riskPoints * signal.r2r; + double rewardPrice = PointToPrice(rewardPoints); + rewardPrice = NormalizePrice(rewardPrice, signal.symbol); + + // + // Calculate TP Price ... + double tpValue = isLong + ? signal.entry + rewardPrice + : signal.entry - rewardPrice; + + // + // Calculate SL Price ... + double slValue = isLong + ? signal.entry - riskPrice + : signal.entry + riskPrice; + + // + // Balance Amount which we risks on each Provider's Trade ... + double amount = availableBalance * signal.riskAmount; + + // + // Calculating Trade Volume based on risk Points and Amount ... + double volume = 0.02; + // xEAAccount.CalculateVolume( + // signal.symbol, + // amount, + // riskPoints); + volume = NormalizeVolume(volume, signal.symbol); + + // + // Set Caculated TP, SL and Volume ... + signal.tp = tpValue; + signal.sl = slValue; + signal.volume = volume; + + // + string comment = ""; + int signalProvidersCount = ArraySize(signal.providers); + if (signalProvidersCount > 0) + { + // + string prvs = ""; + for (int i = 0; i < signalProvidersCount; i++) + { + // + string p = signal.providers[i]; + + // + if (StringLen(prvs) > 0) + { + prvs += ","; + } + + // + prvs += p; + } + + // + comment = "PRV(" + prvs + ")"; + } + + // + // Here before Open Signal Position ... + // and after complete TP SL and Volume Calculations ... + // Recieve a List Of Supported Positions, based on retrieve Support and Resistance ares + // for Signal ... + XSignal supportSignals[]; + xEATrade.GenerateSupportSignals( + supportSignals, + signal); + int supportSignalsCount = ArraySize(supportSignals); + + // + bool isPositionOpen = xEATrade.ExecuteSignal( + signal, + comment); + + // + if (isPositionOpen) + { + // + // Retrieve Position Ticket ... + ulong ticket = xEATrade.GetLastOpenPositionTicket(); + if (ticket == 0) + { + return; + } + + // + if (supportSignalsCount >= 0) + { + // + // Here we Must Place Orders ... + string comment = mSupportToken + "(" + (string)ticket + ")"; + + // + // CleanSupport Positions SLs ... + // for (int i = 0; i < supportSignalsCount; i++) { + // // + // XSignal iSignal = supportSignals[i]; + + // // + // // iSignal.sl = 0; + // } + + // + // TODO: Add Expiration Date, Volume Calculation ... + // int executedSignals = xEATrade.ExecuteSignals( + // supportSignals, + // comment); + } + + // + // Draw Signal ... + ReDrawSignal(ticket, signal); + + // + // Alert Position ... + LogMessage("Position: " + (string)ticket + " was Open ..."); + } else { + DrawSupportResistance(1, signal.supportAndResistance); + } +} + +// +// Handle StopLoss Event ... +void OnStopLossTriggered(const XDeal &deal) +{ + // + string msg = "SL: " + (string)deal.positionId; + LogMessage(msg); + + // + xEACollector.CollectLog(msg); + + // + xEACollector.CollectDeal(deal); +} + +// +// Handle TakeProfit Event ... +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + string msg = "TP: " + (string)deal.positionId; + LogMessage(msg); + + // + xEACollector.CollectLog(msg); + + // + xEACollector.CollectDeal(deal); +} + +// +void OnDealsChangedHandler(int count) +{ + // + string msg = "Deals Changed: " + (string)count; + LogMessage(msg); + xEACollector.CollectLog(msg); +} + +// +void OnOrdersChangedHandler(int count) +{ + // + string msg = "Orders Changed: " + (string)count; + LogMessage(msg); + xEACollector.CollectLog(msg); +} + +// +void HandleGuard() +{ + // + // Handle Force Close Positions ... + // HandleForceClosing(); + + // + // Trailing Stops and Make Positions Risk Free ... + // HandleRiskFree(); + + // + // When all Positions Profit Going Positive ... + // HandlePyramidHedge(); + + // + // When a Position running in profit long time ... + // HandleCloseOldInProfitTrades(); +} + +// +// Force Close Provider's Signals on Special Conditions ... +void HandleForceClosing() +{ + // + // Force Close all XTRND Short Positions ... + bool canCloseAllXTRNDShortPositions = + // + XTRNDForceCloseAllShorts() + // + ; + if (canCloseAllXTRNDShortPositions) + { + // + XPosition positions[]; + GetSpecificProviderPositions( + positions, + _Symbol, + _Period, + XTRND, + POSITION_TYPE_SELL); + int positionsCount = ArraySize(positions); + if (positionsCount > 0) + { + // + string comment = "Force Close XTRND Shorts ..."; + + // + xEATrade.ClosePositions( + positions, + comment); + + // + DrawForceCloseEvent(); + } + } + + // + // Force Close all XTRND Long Positions ... + bool canCloseAllXTRNDLongPositions = + // + XTRNDForceCloseAllLongs() + // + ; + if (canCloseAllXTRNDLongPositions) + { + // + XPosition positions[]; + GetSpecificProviderPositions( + positions, + _Symbol, + _Period, + XTRND, + POSITION_TYPE_BUY); + int positionsCount = ArraySize(positions); + if (positionsCount > 0) + { + // + string comment = "Force Close XTRND Shorts ..."; + + // + xEATrade.ClosePositions( + positions, + comment); + + // + DrawForceCloseEvent(); + } + } +} + +// +// Make Positions Risk Free and Trailing Stops ... +void HandleRiskFree() +{ + // + double distanceFactorForRiskFree = 0.3; + + // + XPosition inProfitPositions[]; + xEATrade.GetInProfitPositions(inProfitPositions); + int inProfitPositionsCount = ArraySize(inProfitPositions); + if (inProfitPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < inProfitPositionsCount; i++) + { + // + XPosition iPosition = inProfitPositions[i]; + + // + // Only Make Positions Risk Free based On their SL or TP ... + if (iPosition.tp <= 0 && iPosition.sl <= 0) + { + continue; + } + + // + bool isLong = IsLong(iPosition.type); + + // + bool isRFBefore = StringFind( + iPosition.comment, + "RF") > 0; + + // + double lastRFPrice = iPosition.entry; + string lastRFPriceStr = ""; + if (isRFBefore) { + // + lastRFPriceStr = ExtractString( + iPosition.comment, + mRiskFreeToken + "(", + ")" + ); + if (StringLen(lastRFPriceStr) > 0) { + lastRFPrice = (double) lastRFPriceStr; + } + } + + // + double tpDistancePrice = MathAbs(lastRFPrice - iPosition.tp); + double rfPrice = (tpDistancePrice * distanceFactorForRiskFree); + + // + bool canRiskFree = MathAbs(lastRFPrice - iPosition.price) > rfPrice; + if (!canRiskFree) + { + continue; + } + + // + double tp = + isLong + ? iPosition.tp + rfPrice + : iPosition.tp - rfPrice; + double sl = + isLong + ? iPosition.tp - rfPrice + : iPosition.sl - rfPrice; + + // + string comment = iPosition.comment; + if (isRFBefore) { + // + StringReplace( + comment, + lastRFPriceStr, + "" + ); + } + + // + comment += mRiskFreeToken + "(" + (string)iPosition.price + ")"; + + // + bool isModified = xEATrade.Modify( + iPosition.ticket, + sl, + tp, + comment); + if (isModified) + { + // + string msg = "Make Position (" + (string)iPosition.ticket + ") Risk Free ..."; + LogMessage(msg); + } + } +} + +// +// Pyramid Hedging ... +void HandlePyramidHedge() +{ + // + int positionsCount = xEATrade.PositionsCount(); + if (positionsCount <= 1) + { + return; + } + + // + double minProfitForHedging = positionsCount * 1; + double positionsProfit = xEATrade.GetPositionsProfit(); + + // + if (positionsProfit < minProfitForHedging) + { + return; + } + + // + string comment = "Pyramid Hedging ..."; + + // + xEATrade.CloseAllPositions(comment); +} + +// +// Close In Profit Old Trades ... +void HandleCloseOldInProfitTrades() +{ + // + int oldAge = 50; + double minProfit = 1; + bool onlySupports = false; + + // + XPosition inProfitPositions[]; + xEATrade.GetInProfitPositions(inProfitPositions); + int inProfitPositionsCount = ArraySize(inProfitPositions); + if (inProfitPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < inProfitPositionsCount; i++) + { + // + XPosition iPosition = inProfitPositions[i]; + if (iPosition.profit < minProfit || + (iPosition.tp > 0 && + MathAbs(iPosition.entry - iPosition.price) < MathAbs(iPosition.entry - iPosition.tp) / 2)) + { + continue; + } + + // + // Check Position Age ... + int iPositionBarIndex = xEATrade.GetPositionOpenBarIndex(iPosition.ticket); + int iPositionAge = MathAbs(iPositionBarIndex - 0); + if (iPositionAge < oldAge) + { + continue; + } + + // + string comment = "Close On Old In Profit Trade ..."; + + // + bool isPositionClosed = false; + + // + if (onlySupports) + { + // + // Check Position is Support or not ... + bool isSupport = IsSupportPosition(iPosition); + if (isSupport) + { + // + // Close Position ... + isPositionClosed = xEATrade.Close( + iPosition.ticket, + comment); + } + } + else + { + // + // Close Position ... + isPositionClosed = xEATrade.Close( + iPosition.ticket, + comment); + } + + // + // Alert Events ... + string msg = "Position (" + (string)iPosition.ticket + ") Closed due InProfit Old Event ..."; + LogMessage(msg); + } +} + +// +// Tools and Usefull Functions ... +// + +// +// Convert Position to Signal ... +XSignal ToSignalInfo( + XPosition &position) +{ + // + XSignal result; + + // + result.tp = position.tp; + result.sl = position.sl; + result.type = position.type; + result.entry = position.entry; + result.symbol = position.symbol; + result.period = position.period; + result.volume = position.volume; + + // + return result; +} + +// +string ToString(ENUM_X_SIGNAL_PROVIDERS provider) +{ + // + return EnumToString(provider); +} + +// +ENUM_X_SIGNAL_PROVIDERS ToProvider(string provider) +{ + // + ENUM_X_SIGNAL_PROVIDERS result; + + // + if (ToString(XTest) == provider) + { + result = XTest; + } + else if (ToString(XTRND) == provider) + { + result = XTRND; + } else if (ToString(XICHI) == provider) { + result = XICHI; + } else + { + result = NONE; + } + + // + return result; +} + +// +// Extract Position Provider ... +ENUM_X_SIGNAL_PROVIDERS ExtractProviderFromComment(string comment) +{ + // + ENUM_X_SIGNAL_PROVIDERS result = NONE; + + // + if (StringLen(comment) <= 0) + { + return result; + } + + // + string providerStr = ExtractString( + comment, + mProviderToken + "(", + ")"); + if (StringLen(providerStr) <= 0) + { + return result; + } + + // + result = ToProvider(providerStr); + + // + return result; +} + +// +// Retrieve Specific Type of Providers Positions ... +void GetSpecificProviderPositions( + XPosition &result[], // Holds Result + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + ENUM_X_SIGNAL_PROVIDERS provider, // Position Provider + ENUM_POSITION_TYPE type = NULL // Position Type +) +{ + // + Clean(result); + + // + if (StringLen(symbol) == 0 || provider == NONE) + { + return; + } + + // + int positionsCount = xEATrade.PositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition symbolPeriodPositions[]; + xEATrade.GetPositions( + symbolPeriodPositions, + symbol, + period); + int symbolPeriodPositionsCount = ArraySize(symbolPeriodPositions); + if (symbolPeriodPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < symbolPeriodPositionsCount; i++) + { + // + XPosition iPosition = symbolPeriodPositions[i]; + + // + ENUM_X_SIGNAL_PROVIDERS iProvider = ExtractProviderFromComment(iPosition.comment); + if (iProvider == NONE || iProvider != provider) + { + continue; + } + + // + if (type == NULL) + { + // + Add( + iPosition, + result); + } + else if (type == iPosition.type) + { + // + Add( + iPosition, + result); + } + } +} + +// +// Determines a Position is Support Position or not ... +bool IsSupportPosition(XPosition &position) +{ + // + bool result = false; + + // + if (StringLen(position.comment) <= 0) + { + return result; + } + + // + int supTokenPos = StringFind( + position.comment, + mSupportToken + "("); + result = supTokenPos >= 0; + + // + return result; +} + +// +// END Functions ... +// + +// +// Draw Signal ... +void ReDrawSignal(const ulong ticket, XSignal &signal) +{ + // + // return; + + // + DrawSupportResistance(1, signal.supportAndResistance); + + // + bool isLong = IsLong(signal.type); + + // + string prefix = (string)ticket + "_" + ToString(signal.period); + + // + // Retrieve Time ... + datetime time = iTime( + signal.symbol, + signal.period, + 0); + + // + // Retrieve 3 Time ... + datetime time3 = iTime( + signal.symbol, + signal.period, + 3); + + // + color posColor = isLong + ? clrSpringGreen + : clrTomato; + color tpColor = clrSpringGreen; + color slColor = clrTomato; + color entryColor = clrGold; + + // + ENUM_LINE_STYLE vLineStyle = STYLE_DOT; + ENUM_LINE_STYLE tpLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE slLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE entryLineStyle = STYLE_SOLID; + + // + int lineWidth = 2; + + // + long chartID = ChartID(); + + // + // Vertical Line ... + string vlName = prefix + "_" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + posColor, + vLineStyle, + lineWidth); + + // + // TP ... + double profit = (MathAbs(signal.tp - signal.entry)) * signal.volume; + string tpName = prefix + "_TP_" + (string)profit; + + // + DrawTrendLine( + chartID, + tpName, + 0, + time3, + signal.tp, + time, + signal.tp, + tpColor, + tpLineStyle, + lineWidth); + + // + // SL ... + double lost = (MathAbs(signal.sl - signal.entry)) * signal.volume; + string slName = prefix + "_SL_" + (string)lost; + + // + DrawTrendLine( + chartID, + slName, + 0, + time3, + signal.sl, + time, + signal.sl, + slColor, + slLineStyle, + lineWidth); + + // + // ENTRY ... + string entryName = prefix + "_ENTRY_" + (string)lost; + + // + DrawTrendLine( + chartID, + entryName, + 0, + time3, + signal.entry, + time, + signal.entry, + entryColor, + entryLineStyle, + lineWidth); +} + +// +// Alert Force Close Event on Chart ... +void DrawForceCloseEvent() +{ + // + datetime barTime = GetCandleTime( + _Symbol, + _Period, + 1); + + // + long chartID = ChartID(); + string vlName = "XTRND Force Close: " + (string)barTime; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + barTime, + clrDarkViolet, + STYLE_SOLID, + 2); +} + +// +void DrawSupportResistance( + int bar_index, + XOHCLSupRes &data, + string prefix = "", + color supportColor = clrLime, + color resistanceColor = clrRed) +{ + // + // return; + + // + datetime barTime = GetCandleTime( + _Symbol, + _Period, + bar_index); + + // + datetime prevBarTime = GetCandleTime( + _Symbol, + _Period, + bar_index + 5); + + // + long chID = ChartID(); + int subWindiw = 0; + int lineWidth = 2; + + // + string mPrefix = prefix + "_" + (string)barTime + "_"; + + // + // SUPPORTS ... + + // + int supCount = ArraySize(data.sup); + if (supCount > 0) + { + // + for (int i = 0; i < supCount; i++) + { + // + double iSup = data.sup[i]; + + // + string supTlName = mPrefix + "SUP[" + (string)(i + 1) + "]_(" + (string)iSup + ")"; + + // + // Draw Support ... + DrawTrendLine( + chID, + supTlName, + subWindiw, + prevBarTime, + iSup, + barTime, + iSup, + supportColor, + STYLE_DOT, + lineWidth, + true); + } + } + + // + // RESISTANCES ... + + // + int resCount = ArraySize(data.res); + if (resCount > 0) + { + // + for (int i = 0; i < resCount; i++) + { + // + double iRes = data.res[i]; + + // + string resTlName = mPrefix + "RES[" + (string)(i + 1) + "]_(" + (string)iRes + ")"; + + // + // Draw Support ... + DrawTrendLine( + chID, + resTlName, + subWindiw, + prevBarTime, + iRes, + barTime, + iRes, + resistanceColor, + STYLE_DOT, + 2, + true); + } + } +} diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/x-saherelm.xea.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/x-saherelm.xea.mq5 new file mode 100644 index 0000000..c13c604 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/x-saherelm.xea.mq5 @@ -0,0 +1,1553 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ---------------------------------------- +// Name: XEA +// Description: this is an expert controller +// advisors which provides a mechanism for use them ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XEA EA" +#property strict + +// +// START Definitions ... +// + +// +string mProviderPrefix = "PRV"; +string mSupportPrefix = "SP"; + +// +enum ENUM_X_SIGNAL_PROVIDERS +{ + NONE = 0, + XICHI = 1, +}; + +// +// END Definitions ... +// + +// +// START Inputs ... +// + +// +// EA ... +input group "Common"; +input bool xEAEnable = true; // Enable EA +input int xEASlippage = 10; // Slippgae +input ulong xEAMagicNumber = 1604056; // Magic Number + +// +// Determine Symbols and TimeFrames ... +input group "Symbols and Time Frames"; +// +// (EURUSDb|M5|0.0005) +// (EURUSDb|M5|0.0005)_(USDCHFb|M5|0.0005)_(USDJPYb|M5|0.0005)_(GBPUSDb|M5|0.0005) +// (EURUSDb|M5,M15,M30|0.0005)_(USDCHFb|M5,M15|0.0005)_(USDJPYb|M5,M15|0.0005)_(GBPUSDb|M5,M15,M30|0.0005)_(AUDUSDb|M5,M15|0.0005)_(USDCADb|M5,M15|0.0005)_(NZDUSDb|M5,M15|0.0005)_(XAUUSDb|M5|0.0005) +input string xEAProvidersDescription = "(EURUSDb|M5|0.0005)"; // Specify Symbols and Time Frames + +// +// Signals ... +input group "Signals"; +input bool xEAEnableLongs = true; // Enable Long Trades +input bool xEAEnableShorts = true; // Enable Short Trades + +// +// Risk Management ... +input group "Risk Management"; +input int xEAMaxOpenPositions = 15; // Max Allowed Open Positions +input bool xEABalancePositions = true; // Balance Positions +input double xEAMaxAllowedDrawDownFactor = 0.15; // Max Allowed Drawdown Factor +input int xEATrailStopsInPoint = 0; // Trail Stops Moving Rate in Points +input int xEAMinProfitForHedging = 5; // Hedge Positions on Minimum Profit +input double xEAMaxDrawdownForClosePosition = 0; // Max Drawdown For Close Positions +input double xEAMaxDrawdownForSupportPosition = 0; // Max Drawdown For Open Support Positions + +// +// Alerts ... +input group "Alerts"; +input bool xEAEnableAlerts = true; // Enable Events Alert +input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day +input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month + +// +// END Inputs ... +// + +// +// START Including Providers ... +// + +// +// Logger Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Alert Library ... +#include "../Libraries/x-saherelm.alert.lib.mq5" + +// +// Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Account Class ... +#include "../Classes/x-saherelm.xaccount.class.mq5" + +// +// Trade Class ... +#include "../Classes/x-saherelm.xtrade.class.mq5" + +// +// Signal Provider Class Library ... +#include "../Providers/x.saherelm.x121.provider.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +bool isXEANewHour; +bool isXEANewDay; +bool isXEANewWeek; +bool isXEANewMonth; + +// +// Determines EA is Running On Test Mode or not ... +bool xEAIsTestMode = false; + +// +// Check prevent Double Signalling on Same Candle ... +bool xEAWaitUntilNextCandle = false; + +// +XSCTrade *xEATrade; +XSCAccount *xEAAccount; +XLastSignal xEALastSignals[]; +X121SignalProvider xEAProviders[]; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = "XEA"; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize XEA Providers ... + if (!InitializeProviders()) + { + return INIT_FAILED; + } + + // + // Initialize Trade Class ... + xEATrade = new XSCTrade( + xEASlippage, + xEAMagicNumber); + + // + // Initialize Account Class ... + xEAAccount = new XSCAccount(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + delete xEATrade; + delete xEAAccount; + + // + // De Initialize XEA Providers ... +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXEANewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXEANewMonth && + xEAEnableAlerts && + xEAEnableMonthlyAlerts; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXEANewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXEANewWeek && + xEAEnableAlerts && + xEAEnableWeeklyAlerts; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXEANewDay = IsNewDay(); + bool canDailyAlert = + isXEANewDay && + xEAEnableAlerts && + xEAEnableDailyAlerts; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXEANewHour = IsNewHour(); + bool canHourlyAlert = + isXEANewHour && + xEAEnableAlerts && + xEAEnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + // + Guard(); + + // + // Prevent Going Forward if user Disable it ... + if (xEAEnable) + { + // + // Call All Providers OnTick Method ... + CallProvidersOnTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + // + // TODO: Complete this ... +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + // TODO: Fix this ... + bool result = true; + + // + // Validate Args ... + result = + // + xEASlippage > 0 && + xEAMagicNumber > 0 && + xEAMaxOpenPositions > 0 && + xEAMaxAllowedDrawDownFactor > 0 && + xEAMaxAllowedDrawDownFactor <= 0.4 && + StringLen(xEAProvidersDescription) > 0 + // + ; + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// Extract Signal Provider Struct from User Input ... +bool InitializeProviders() +{ + // + bool result = false; + + // + string workingString = xEAProvidersDescription; + StringTrimLeft(workingString); + StringTrimRight(workingString); + if (StringLen(workingString) == 0) + { + return result; + } + + // + string descriptors[]; + int numOfDescriptors = StringSplit( + workingString, + StringGetCharacter("_", 0), + descriptors); + if (numOfDescriptors <= 0) + { + return result; + } + + // + // Loop Through Descriptors ... + for (int iDX = 0; iDX < numOfDescriptors; iDX++) + { + // + string descriptor = descriptors[iDX]; + + // + // Clear Start and End Pranteses ... + StringReplace( + descriptor, + "(", + ""); + StringReplace( + descriptor, + ")", + ""); + + // + string descriptorData[]; + int numOfData = StringSplit( + descriptor, + StringGetCharacter("|", 0), + descriptorData); + if (numOfData < 3) + { + continue; + } + + // + string symbols[]; + int numOfSymbols = StringSplit( + descriptorData[0], + StringGetCharacter(",", 0), + symbols); + if (numOfSymbols <= 0) + { + continue; + } + + // + string timeFrames[]; + int numOfTimeFrames = StringSplit( + descriptorData[1], + StringGetCharacter(",", 0), + timeFrames); + if (numOfTimeFrames <= 0) + { + continue; + } + + // + string riskAmounts[]; + int numOfRiskAmounts = StringSplit( + descriptorData[2], + StringGetCharacter(",", 0), + riskAmounts); + if (numOfRiskAmounts <= 0) + { + continue; + } + + // + for (int cpIdx = 0; cpIdx < numOfSymbols; cpIdx++) + { + // + string symbol = symbols[cpIdx]; + + // + for (int tfIdx = 0; tfIdx < numOfTimeFrames; tfIdx++) + { + // + string timeFrame = timeFrames[tfIdx]; + ENUM_TIMEFRAMES period = ToPeriod(timeFrame); + + // + double riskAmount = (double)(numOfRiskAmounts == numOfTimeFrames + ? riskAmounts[tfIdx] + : riskAmounts[0]); + + // + string magicNumberString = "169" + (string)iDX + (string)cpIdx + (string)tfIdx + (string)PeriodSeconds(period) + "4056"; + ulong magicNumber = (ulong)magicNumberString; + + // + X121SignalProvider providerDescriptor; + + // + providerDescriptor.symbol = symbol; + providerDescriptor.period = period; + providerDescriptor.riskAmount = riskAmount; + providerDescriptor.magicNumber = magicNumber; + + // + // Initial Provider Class Instance ... + XSCX121Provider *x121Provider = new XSCX121Provider( + symbol, + period); + + // + // Attach On Signal Event Listener ... + x121Provider.AddOnSignalEventHandler(OnSignalRecieved); + + // + providerDescriptor.provider = x121Provider; + + // + Add( + providerDescriptor, + xEAProviders); + } + } + } + + // + result = true; + + // + return result; +} + +// +void CallProvidersOnTick() +{ + // + int providersCount = ArraySize(xEAProviders); + if (providersCount <= 0) + { + return; + } + + // + // Loop Through Providers ... + for (int i = 0; i < providersCount; i++) + { + // + X121SignalProvider providerDescriptor = xEAProviders[i]; + + // + providerDescriptor.provider.OnTick(); + } +} + +// +void OnSignalRecieved( + XSignalInfo &info) +{ + // + // Ignore Disabled Signals ... + if ((info.type == POSITION_TYPE_BUY && !xEAEnableLongs) || + (info.type == POSITION_TYPE_SELL && !xEAEnableShorts)) + { + return; + } + + // + // Find Provider based On Signal Info ... + int providersCount = ArraySize(xEAProviders); + if (providersCount <= 0) + { + return; + } + + // + if (StringLen(info.symbol) == 0 || info.period == NULL) + { + return; + } + + // + bool isFoundDescriptor = false; + X121SignalProvider providerDescriptor; + + // + for (int i = 0; i < providersCount; i++) + { + // + X121SignalProvider provDesc = xEAProviders[i]; + + // + if (provDesc.symbol == info.symbol && + provDesc.period == info.period) + { + // + isFoundDescriptor = true; + providerDescriptor = provDesc; + + // + break; + } + } + + // + // Prevent Moving Forward if there is no Descriptor Found ... + if (!isFoundDescriptor) + { + return; + } + + // + // Count Open Positions ... + int openPositionsCount = xEATrade.OpenPositionsCount(); + + // + if (xEABalancePositions) + { + // + // Count Same Signals for Balancing ... + int smaeTypeOpenPositionsCount = xEATrade.OpenPositionsCount("", info.type); + + // + if (openPositionsCount > (int)xEAMaxOpenPositions / 3) + { + // + if (smaeTypeOpenPositionsCount > (int)openPositionsCount / 2) + { + return; + } + } + } + + // + string mTagId = GenerateTag(info); + + // + // Check Last Signal ... + datetime barTime = iTime( + info.symbol, + info.period, + 0); + + // + XLastSignal lastSignal = {}; + int foundedLastSignalId = -1; + bool isFoundLastSignal = false; + int lastSignalsCount = ArraySize(xEALastSignals); + + // + for (int i = 0; i < lastSignalsCount; i++) + { + // + XLastSignal mLS = xEALastSignals[i]; + if (mLS.provider == mTagId) + { + // + lastSignal = mLS; + foundedLastSignalId = i; + isFoundLastSignal = true; + + // + break; + } + } + + // + if (isFoundLastSignal) + { + // + bool isSameDate = xEALastSignals[foundedLastSignalId].at == barTime; + if (isSameDate) + { + return; + } + else + { + xEALastSignals[foundedLastSignalId].at = barTime; + } + } + else + { + // + lastSignal.at = barTime; + lastSignal.provider = mTagId; + + // + ArrayResize( + xEALastSignals, + ArraySize(xEALastSignals) + 1); + + // + xEALastSignals[ArraySize(xEALastSignals) - 1] = lastSignal; + } + + // + // Retrieve Tradable Balance ... + double availableBalance = xEAAccount.GetEquity(); + + // + // Here we Have to Check Some Conditions for Open + // Positions, before Do Calculations, for improve Performance ... + + // + // Verify Open Positions ... + if (openPositionsCount >= xEAMaxOpenPositions) + { + // + LogMessage("Max Allowed Positions Reached ..."); + return; + } + + // + // Verify Available Balance ... + double balance = xEAAccount.GetBalance(); + double minBalanceForTrades = balance * xEAMaxAllowedDrawDownFactor; + if (availableBalance <= minBalanceForTrades) + { + // + LogMessage("Max Drawdown Reached ..."); + return; + } + + // + // Here i Must Calculate TP and SL based on R2R and riskable Factor ... + bool isLong = IsLong(info.type); + + // + // Correct Period ... + if (info.period == NULL) + { + info.period = providerDescriptor.period; + } + + // + // Check Order Mode ... + if (info.mode == NULL) + { + // + // Set Market Execution as Default ... + info.mode = X_ORDER_MODE_MARKET; + } + + // + // Calculate Entry Price ... + if (info.entry <= 0) + { + // + info.entry = GetEntry( + info.symbol, + info.type); + } + + // + // R2R ... + if (info.r2r <= 0) + { + // + // Set Default Risk to Reward Ratio to 1 ... + info.r2r = 1; + } + + // + // Set Risk Amount Factor ... + if (info.riskAmount <= 0) + { + // + info.riskAmount = providerDescriptor.riskAmount; + } + + // + // Calculate TP and SL ... + double mPoint = GetPoints(info.symbol); + + // + // Normalize SL Price ... + if (info.sl > 0) + { + info.sl = NormalizePrice(info.sl, info.symbol); + } + + // + // Retrieve Symbol Point Value ... + double pointValue = xEAAccount.GetPointValue(info.symbol); + + // + // Calculate Risk ... + double riskPrice = MathAbs(info.entry - info.sl); + riskPrice = NormalizePrice(riskPrice, info.symbol); + + // + double riskPoints = PriceToPoint(riskPrice); + riskPoints = NormalizeDouble(riskPoints, 0); + + // + // Calculating Reward based On Ratio ... + double rewardPoints = riskPoints * info.r2r; + double rewardPrice = PointToPrice(rewardPoints); + rewardPrice = NormalizePrice(rewardPrice, info.symbol); + + // + // TODO: Remove This ... + // rewardPrice = PipsToPrice( + // info.symbol, + // 15 + // ); + + // + // Calculate TP Price ... + double tpValue = isLong + ? info.entry + rewardPrice + : info.entry - rewardPrice; + + // + // Calculate SL Price ... + double slValue = isLong + ? info.entry - riskPrice + : info.entry + riskPrice; + + // + // Balance Amount which we risks on each Provider's Trade ... + double amount = availableBalance * info.riskAmount; + + // + // Calculating Trade Volume based on risk Points and Amount ... + double volume = xEAAccount.CalculateVolume( + info.symbol, + amount, + riskPoints); + volume = NormalizeVolume(volume, info.symbol); + + // + // Set Caculated TP, SL and Volume ... + info.tp = tpValue; + info.sl = slValue; + info.volume = 0.01; // volume; + + // + string comment = ""; + int signalProvidersCount = ArraySize(info.providers); + if (signalProvidersCount > 0) + { + // + string prvs = ""; + for (int i = 0; i < signalProvidersCount; i++) + { + // + string p = info.providers[i]; + + // + if (StringLen(prvs) > 0) + { + prvs += ","; + } + + // + prvs += p; + } + + // + comment = "PRV(" + prvs + ")"; + } + + // + bool isPositionOpen = false; + + // + // Open Signal Position ... + if (isLong) + { + // + isPositionOpen = xEATrade.Buy( + info.symbol, + info.period, + info.volume, + info.entry, + info.sl, + info.tp, + comment); + } + else + { + // + isPositionOpen = xEATrade.Sell( + info.symbol, + info.period, + info.volume, + info.entry, + info.sl, + info.tp, + comment); + } + + // + if (isPositionOpen) + { + // + // Retrieve Position Ticket ... + ulong ticket = xEATrade.GetLastOpenPositionTicket(); + if (ticket == 0) + { + return; + } + + // + // Draw Signal ... + ReDrawSignal(ticket, info); + + // + // Alert Position ... + LogMessage("Position: " + (string)ticket + " was Open ..."); + } +} + +// +// Do Guard Actions ... +void Guard() +{ + // + // Close Max In Drawdown Position ... + HandleMaxDrawdown(); + + // + // Trailing Stops ... + HandleTrailing(); + + // + // Close All Open Positions in Pyramid ... + HandleHedging(); + + // + // Handle Support Signal Opening ... + HandleSupport(); +} + +// +// it is a way to Protect Open Signal ... +void HandleTrailing() +{ + // + if (xEATrailStopsInPoint <= 0) + { + return; + } + + // + XPosition inProfitPositions[]; + xEATrade.GetInProfitPositions(inProfitPositions); + int inProfitPositionsCount = ArraySize(inProfitPositions); + if (inProfitPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < inProfitPositionsCount; i++) + { + // + XPosition iPosition = inProfitPositions[i]; + + // + bool isLong = IsLong(iPosition.type); + + // + // Retrieve Exit Price ... + double exitPrice = GetExit( + iPosition.symbol, + iPosition.type); + + // + double entryPrice = GetEntry( + iPosition.symbol, + iPosition.type); + + // + // Calculate Price Distance ... + double distancePrice = iPosition.sl == 0 + ? MathAbs(iPosition.entry - exitPrice) + : MathAbs(iPosition.sl - exitPrice); + double distancePoint = PriceToPoint( + iPosition.symbol, + distancePrice); + + // + if (distancePoint >= xEATrailStopsInPoint) + { + // + double trailStepPrice = PointToPrice( + iPosition.symbol, + xEATrailStopsInPoint); + + // + double tp = + isLong + ? iPosition.tp + trailStepPrice + : iPosition.tp - trailStepPrice; + double sl = + iPosition.sl == 0 + ? isLong + ? entryPrice - trailStepPrice + : entryPrice + trailStepPrice + : isLong + ? iPosition.sl + trailStepPrice + : iPosition.sl - trailStepPrice; + + // + bool isModified = xEATrade.Modify( + iPosition.ticket, + sl, + tp); + if (isModified) + { + // + // Convert Position to Signal ... + + // + XSignalInfo signal = ToSignalInfo(iPosition); + // ReDrawSignal(iPosition.ticket, signal); + + // + // Alert Trailing ... + LogMessage("Position: " + (string)iPosition.ticket + ", was Trailed ..."); + } + } + } +} + +// +// Hedging Close Positions ... +void HandleHedging() +{ + // + if (xEAMinProfitForHedging <= 0) + { + return; + } + + // + int positionsCount = xEATrade.OpenPositionsCount(); + if (positionsCount <= 1) + { + return; + } + + // + double profit = xEATrade.GetPositionsProfit(); + + // + if (profit < xEAMinProfitForHedging) + { + return; + } + + // + string comment = "Hedging Pyramid ..."; + + // + xEATrade.CloseAllPositions(comment); +} + +// +// Support Positions ... +void HandleSupport() +{ + // + if (xEAMaxDrawdownForSupportPosition <= 0) + { + return; + } + + // + int positionsCount = xEATrade.OpenPositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition inDrawdownPositions[]; + xEATrade.GetInDrawdownPositions(inDrawdownPositions); + int inDrawdownPositionsCount = ArraySize(inDrawdownPositions); + if (inDrawdownPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < inDrawdownPositionsCount; i++) + { + // + XPosition iPosition = inDrawdownPositions[i]; + + // + if (MathAbs(iPosition.profit) >= xEAMaxDrawdownForSupportPosition) + { + // + // Here we have to Open Support Indirectional Position ... + OpenSupportPosition(iPosition); + } + } +} + +// +// Close Max In Drawdown Position ... +void HandleMaxDrawdown() +{ + // + if (xEAMaxDrawdownForClosePosition <= 0) + { + return; + } + + // + int positionsCount = xEATrade.OpenPositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition inDrawdownPositions[]; + xEATrade.GetInDrawdownPositions(inDrawdownPositions); + int inDrawdownPositionsCount = ArraySize(inDrawdownPositions); + if (inDrawdownPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < inDrawdownPositionsCount; i++) + { + // + XPosition iPosition = inDrawdownPositions[i]; + + // + if (MathAbs(iPosition.profit) >= xEAMaxDrawdownForClosePosition) + { + // + // Here we have to Force Close Position ... + string comment = "Close On Guard ..."; + bool isClosed = xEATrade.Close( + iPosition.ticket, + comment); + if (isClosed) + { + LogMessage("Position: " + (string)iPosition.ticket + " was Closed On Guard ..."); + } + } + } +} + +// +// Draw Signal ... +void ReDrawSignal(const ulong ticket, XSignalInfo &signal) +{ + // + return; + + // + bool isLong = IsLong(signal.type); + + // + string prefix = (string)ticket + "_" + ToString(signal.period); + + // + RemoveDraws(prefix); + + // + // Retrieve Time ... + datetime time = iTime( + signal.symbol, + signal.period, + 0); + + // + // Retrieve 3 Time ... + datetime time3 = iTime( + signal.symbol, + signal.period, + 3); + + // + color posColor = isLong + ? clrAqua + : clrMagenta; + color tpColor = clrAqua; + color slColor = clrMagenta; + color entryColor = clrGold; + + // + ENUM_LINE_STYLE vLineStyle = STYLE_DOT; + ENUM_LINE_STYLE tpLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE slLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE entryLineStyle = STYLE_SOLID; + + // + long chartID = ChartID(); + + // + // Vertical Line ... + string vlName = prefix + "_" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + posColor, + vLineStyle); + + // + // TP ... + double profit = (MathAbs(signal.tp - signal.entry)) * signal.volume; + string tpName = prefix + "_TP_" + (string)profit; + + // + DrawTrendLine( + chartID, + tpName, + 0, + time3, + signal.tp, + time, + signal.tp, + tpColor, + tpLineStyle); + + // + // SL ... + double lost = (MathAbs(signal.sl - signal.entry)) * signal.volume; + string slName = prefix + "_SL_" + (string)lost; + + // + DrawTrendLine( + chartID, + slName, + 0, + time3, + signal.sl, + time, + signal.sl, + slColor, + slLineStyle); + + // + // ENTRY ... + string entryName = prefix + "_ENTRY_" + (string)lost; + + // + DrawTrendLine( + chartID, + entryName, + 0, + time3, + signal.entry, + time, + signal.entry, + entryColor, + entryLineStyle); +} + +// +// Convert Position to Signal ... +XSignalInfo ToSignalInfo( + XPosition &position) +{ + // + XSignalInfo result; + + // + result.tp = position.tp; + result.sl = position.sl; + result.type = position.type; + result.entry = position.entry; + result.symbol = position.symbol; + result.period = position.period; + result.volume = position.volume; + + // + return result; +} + +// +string ToString(ENUM_X_SIGNAL_PROVIDERS provider) +{ + // + return EnumToString(provider); +} + +// +ENUM_X_SIGNAL_PROVIDERS ToProvider(string provider) +{ + // + ENUM_X_SIGNAL_PROVIDERS result; + + // + if (ToString(XICHI) == provider) + { + result = XICHI; + } + else + { + result = NONE; + } + + // + return result; +} + +// +// Extract Position Provider ... +ENUM_X_SIGNAL_PROVIDERS ExtractProviderFromComment(string comment) +{ + // + ENUM_X_SIGNAL_PROVIDERS result = NONE; + + // + if (StringLen(comment) <= 0) + { + return result; + } + + // + string providerStr = ExtractString( + comment, + mProviderPrefix + "(", + ")"); + if (StringLen(providerStr) <= 0) + { + return result; + } + + // + result = ToProvider(providerStr); + + // + return result; +} + +// +// Retrieve Specific Type of Providers Positions ... +void GetSpecificProviderPositions( + XPosition &result[], // Holds Result + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + ENUM_X_SIGNAL_PROVIDERS provider // Position Provider +) +{ + // + Clear(result); + + // + if (StringLen(symbol) == 0 || provider == NONE) + { + return; + } + + // + int positionsCount = xEATrade.OpenPositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition symbolPeriodPositions[]; + xEATrade.GetPositions( + symbolPeriodPositions, + symbol, + period); + int symbolPeriodPositionsCount = ArraySize(symbolPeriodPositions); + if (symbolPeriodPositionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < symbolPeriodPositionsCount; i++) + { + // + XPosition iPosition = symbolPeriodPositions[i]; + + // + ENUM_X_SIGNAL_PROVIDERS iProvider = ExtractProviderFromComment(iPosition.comment); + if (iProvider == NONE || iProvider != provider) + { + continue; + } + + // + Add( + iPosition, + result); + } +} + +// +// Find Reversal Position Type ... +ENUM_POSITION_TYPE GetSupportPositionType(ENUM_POSITION_TYPE type) +{ + // + ENUM_POSITION_TYPE result = POSITION_TYPE_BUY; + + // + if (type == POSITION_TYPE_BUY) + { + result = POSITION_TYPE_SELL; + } + else + { + result = POSITION_TYPE_BUY; + } + + // + return result; +} + +// +// Check a Position Has Supportable or not ... +bool IsSupportablePosition(XPosition &position) +{ + // + bool result = false; + + // + if (StringLen(position.comment) <= 0) + { + return result; + } + + // + int supStrPos = StringFind( + position.comment, + mSupportPrefix + "("); + + // + result = supStrPos < 0; + + // + return result; +} + +// +// Check a Position has Support Position or not ... +bool HasSupportPosition(XPosition &position) +{ + // + bool result = false; + + // + int positionsCount = xEATrade.OpenPositionsCount(); + + // + if (positionsCount <= 0 || + position.ticket == 0 || + StringLen(position.comment) <= 0) + { + return result; + } + + // + string supCommentStr = mSupportPrefix + "(" + (string)position.ticket + ")"; + + // + XPosition positions[]; + xEATrade.GetPositions(positions); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + int supCommentPos = StringFind( + iPosition.comment, + supCommentStr); + + // + result = supCommentPos >= 0; + if (result) + { + break; + } + } + + // + return result; +} + +// +// Open a Support Position based on Exists ... +void OpenSupportPosition(XPosition &position) +{ + // + bool isSupportable = IsSupportablePosition(position); + if (!isSupportable) + { + return; + } + + // + bool hasSupport = HasSupportPosition(position); + if (hasSupport) + { + return; + } + + // + ENUM_POSITION_TYPE type = GetSupportPositionType(position.type); + double entry = GetEntry( + position.symbol, + type); + + // + bool isLong = IsLong(type); + + // + double tpPrice = PipsToPrice( + position.symbol, + 10); + double slPrice = PipsToPrice( + position.symbol, + 5); + + // + double tp = 0; + // isLong + // ? entry + tpPrice + // : entry - tpPrice; + + // + double sl = 0; + // isLong + // ? entry - slPrice + // : entry + slPrice; + + // + string comment = mSupportPrefix + "(" + (string)position.ticket + ")"; + + // + bool isPositionOpen = false; + // + // Open Signal Position ... + if (isLong) + { + // + isPositionOpen = xEATrade.Buy( + position.symbol, + position.period, + position.volume, + entry, + sl, + tp, + comment); + } + else + { + // + isPositionOpen = xEATrade.Sell( + position.symbol, + position.period, + position.volume, + entry, + sl, + tp, + comment); + } + + // + if (isPositionOpen) + { + // + LogMessage("Open Support Psition for: " + position.comment); + } +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xatrsl.test.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xatrsl.test.helper.mq5 new file mode 100644 index 0000000..d5c8985 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xatrsl.test.helper.mq5 @@ -0,0 +1,235 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XATRSLHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XATRSL_BUFFERS +{ + // + X_ATRSL_UP_LINE = 0, + X_ATRSL_DOWN_LINE = 1, + X_ATRSL_SAR_LINE = 2, + X_ATRSL_RMA_LINE = 3, + X_ATRSL_WMA_LINE = 4, + X_ATRSL_MA1_LINE = 5, + X_ATRSL_SMA_LINE = 6, + X_ATRSL_EMA_LINE = 7, + X_ATRSL_ATR_LINE = 8, +}; + +// +// END Constants/Enums ... +// + +// +// START Definitions ... +// + +// +double atrslUpBuffer[]; +double atrslDownBuffer[]; +double atrslSarBuffer[]; + +// +int atrslHandler = INVALID_HANDLE; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XATRSLHLPOnInit() +{ + // + bool result = false; + + // + ArraySetAsSeries(atrslUpBuffer, true); + ArraySetAsSeries(atrslSarBuffer, true); + ArraySetAsSeries(atrslDownBuffer, true); + + // + // Initial Handler ... + atrslHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xatrsl", + // + // Inputs ... + // + // MARKET ... + "", + 14, + 0.02, + 0.2, + PRICE_HIGH, + PRICE_LOW, + // + // PRESENTATION ... + "", + false, + false, + true + // + ); + result = atrslHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XATRSLHLPOnDeInit() +{ + // + // Release Indicators ... + IndicatorRelease(atrslHandler); +} + +// +void XATRSLHLPReadBuffers() +{ + // + // UP ... + CopyBuffer( + atrslHandler, + X_ATRSL_UP_LINE, + 0, + 10, + atrslUpBuffer); + + // + // DOWN ... + CopyBuffer( + atrslHandler, + X_ATRSL_DOWN_LINE, + 0, + 10, + atrslDownBuffer); + + // + // SAR ... + CopyBuffer( + atrslHandler, + X_ATRSL_SAR_LINE, + 0, + 10, + atrslSarBuffer); +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// Calculate Change Rate For Specific Bar ... +double XATRSLHLPGetChangeRate( + int bar_index // Bar Index ... +) +{ + // + double result = 0; + + // + if (!XATRSLHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = MathAbs(atrslUpBuffer[bar_index] - atrslDownBuffer[bar_index]); + + // + return result; +} + +// +// Calculate Change Rate For Specific Lenght ... +double XATRSLHLPGetRangeChangeRate( + int bar_index, // Bar Index ... + int length = 5 // Loopback Length ... +) +{ + // + double result = 0; + + // + int size = bar_index + length; + if (!XATRSLHLPIsValidArraySize(size)) + { + return result; + } + + // + double summary = 0; + for (int i = bar_index; i < size; i++) + { + summary += MathAbs(atrslUpBuffer[i] - atrslDownBuffer[i]); + } + + // + result = summary / size; + + // + return result; +} + +// +// Check Array Size ... +bool XATRSLHLPIsValidArraySize(int bar_index) +{ + // + bool result = false; + + // + int rCount = ArraySize(atrslUpBuffer); + result = rCount > bar_index + 1; + + // + return result; +} + +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xichi.test.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xichi.test.helper.mq5 new file mode 100644 index 0000000..e00f0cc --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xichi.test.helper.mq5 @@ -0,0 +1,938 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XICHIHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// Ichimoku Indicator Exported Buffers ... +enum ENUM_X_ICHIMOKU_BUFFERS +{ + // + X_TENKANSEN_LINE = 0, + X_KIJUNSEN_LINE = 1, + X_CHIKOUSPAN_LINE = 4, + X_SENKOUSPAN_A_LINE = 5, + X_SENKOUSPAN_B_LINE = 6, +}; + +// +// Model Ichimoku Data ... +struct XIchiInfo +{ + // + int bar; + + // + double tenkanSen; + double kijunSen; + + // + double chikouSpan; + + // + double senkouSpanA; + double senkouSpanB; + + // + double senkouSpanAFuture; + double senkouSpanBFuture; +}; + +// +double ichiPivots[]; + +// +// END Constants/Enums ... +// + +// +// START Definitions ... +// + +// +double ichiTenkanSenBuffer[]; +double ichiKijunSenBuffer[]; +double ichiChikouSpanBuffer[]; +double ichiSenkouSpanABuffer[]; +double ichiSenkouSpanBBuffer[]; + +// +int ichiHandler = INVALID_HANDLE; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XICHIHLPOnInit() +{ + // + bool result = false; + + // + ArraySetAsSeries(ichiTenkanSenBuffer, true); + ArraySetAsSeries(ichiKijunSenBuffer, true); + ArraySetAsSeries(ichiChikouSpanBuffer, true); + ArraySetAsSeries(ichiSenkouSpanABuffer, true); + ArraySetAsSeries(ichiSenkouSpanBBuffer, true); + + // + ArraySetAsSeries(ichiPivots, true); + + // + // Initial Handler ... + ichiHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xich", + // + // Inputs ... + // + // TENKANSEN ... + "", + 9, + X_XICH_HH_LL_MODE, + // + // KIJUNSEN ... + "", + 26, + X_XICH_HH_LL_MODE, + // + // SENKOUSPANB ... + "", + 52, + X_XICH_HH_LL_MODE, + // + // CHIKOUSPAN ... + "", + PRICE_CLOSE, + // + // PRESENTATION ... + "", + true, + true, + false, + false, + false, + false, + false, + true, + true // Shift Kumo ... + // + ); + result = ichiHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XICHIHLPOnDeInit() +{ + // + // Release Indicators ... + IndicatorRelease(ichiHandler); +} + +// +void XICHIHLPReadBuffers() +{ + // + // TENKANSEN ... + CopyBuffer( + ichiHandler, + X_TENKANSEN_LINE, + 0, + 26, + ichiTenkanSenBuffer); + + // + // KIJUNSEN ... + CopyBuffer( + ichiHandler, + X_KIJUNSEN_LINE, + 0, + 26, + ichiKijunSenBuffer); + + // + // CHIKOUSPAN ... + CopyBuffer( + ichiHandler, + X_CHIKOUSPAN_LINE, + 27, + 52, + ichiChikouSpanBuffer); + + // + // SENKOUSPANA ... + CopyBuffer( + ichiHandler, + X_SENKOUSPAN_A_LINE, + -26, + 52, + ichiSenkouSpanABuffer); + + // + // SENKOUSPANB ... + CopyBuffer( + ichiHandler, + X_SENKOUSPAN_B_LINE, + -26, + 52, + ichiSenkouSpanBBuffer); + + // + XICHIHLPFindPivotPoints(); +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// Retrieve Ichimoku Data at Specific Bar Index ... +XIchiInfo XICHIHLPGetInfo( + int bar_index // Bar Index ... +) +{ + // + XIchiInfo result = {}; + + // + result.bar = bar_index; + result.tenkanSen = ichiTenkanSenBuffer[bar_index]; + result.kijunSen = ichiKijunSenBuffer[bar_index]; + result.chikouSpan = ichiChikouSpanBuffer[bar_index + 26]; + result.senkouSpanA = ichiSenkouSpanABuffer[bar_index + 26]; + result.senkouSpanB = ichiSenkouSpanBBuffer[bar_index + 26]; + result.senkouSpanAFuture = ichiSenkouSpanABuffer[bar_index]; + result.senkouSpanBFuture = ichiSenkouSpanBBuffer[bar_index]; + + // + return result; +} + +// +// Check Tenkan Sen Over Kijun Sen ... +bool XICHIHLPIsTenkanSenOverKijunSen( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + + // + result = + // + point.tenkanSen > point.kijunSen + // + ; + + // + return result; +} + +// +// Is Tenkan Sen Under Kijun Sen ... +bool XICHIHLPIsTenkanSenUnderKijunSen( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + + // + result = + // + point.tenkanSen < point.kijunSen + // + ; + + // + return result; +} + +// +// Tenkan Sen Croosed Over Kijun Sen ... +bool XICHIHLPIsTenkanSenCrossedOverKijunSen( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + result = + // + point.tenkanSen > point.kijunSen && + pointPrev.tenkanSen <= pointPrev.kijunSen + // + ; + + // + return result; +} + +// +// Tenkan Sen Croosed Under Kijun Sen ... +bool XICHIHLPIsTenkanSenCrossedUnderKijunSen( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + result = + // + point.tenkanSen < point.kijunSen && + pointPrev.tenkanSen >= pointPrev.kijunSen + // + ; + + // + return result; +} + +// +// Check Kumo is Bullish ... +bool XICHIHLPIsKumoBullish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double ssa = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double ssb = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + result = + // + ssa > ssb + // + ; + + // + return result; +} + +// +// Check Kumo is Bearish ... +bool XICHIHLPIsKumoBearish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double ssa = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double ssb = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + result = + // + ssa < ssb + // + ; + + // + return result; +} + +// +// Check Kumo is Change to Bullish ... +bool XICHIHLPIsKumoSwitchedToBullish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double ssa = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double ssb = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + double ssaPrev = onFuture + ? pointPrev.senkouSpanAFuture + : pointPrev.senkouSpanA; + + // + double ssbPrev = onFuture + ? pointPrev.senkouSpanBFuture + : pointPrev.senkouSpanB; + + // + result = + // + ssa > ssb && + ssaPrev <= ssbPrev + // + ; + + // + return result; +} + +// +// Check Kumo is Change to Bearish ... +bool XICHIHLPIsKumoSwitchedToBearish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double ssa = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double ssb = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + double ssaPrev = onFuture + ? pointPrev.senkouSpanAFuture + : pointPrev.senkouSpanA; + + // + double ssbPrev = onFuture + ? pointPrev.senkouSpanBFuture + : pointPrev.senkouSpanB; + + // + result = + // + ssa < ssb && + ssaPrev >= ssbPrev + // + ; + + // + return result; +} + +// +// TENKANSEN and SENKOUSPAN ... + +// +bool XICHIHLPIsTenkanSenCrossedOverSenkouSpanA( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanAFuture + : pointPrev.senkouSpanA; + + // + result = + // + point.tenkanSen > dest && + pointPrev.tenkanSen <= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsTenkanSenCrossedUnderSenkouSpanA( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanAFuture + : pointPrev.senkouSpanA; + + // + result = + // + point.tenkanSen < dest && + pointPrev.tenkanSen >= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsTenkanSenCrossedOverSenkouSpanB( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanBFuture + : pointPrev.senkouSpanB; + + // + result = + // + point.tenkanSen > dest && + pointPrev.tenkanSen <= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsTenkanSenCrossedUnderSenkouSpanB( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanBFuture + : pointPrev.senkouSpanB; + + // + result = + // + point.tenkanSen < dest && + pointPrev.tenkanSen >= destPrev + // + ; + + // + return result; +} + +// +// KIJUNSEN and SENKOUSPAN ... + +// +bool XICHIHLPIsKijunSenCrossedOverSenkouSpanA( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanAFuture + : pointPrev.senkouSpanA; + + // + result = + // + point.kijunSen > dest && + pointPrev.kijunSen <= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsKijunSenCrossedUnderSenkouSpanA( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanAFuture + : point.senkouSpanA; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanAFuture + : pointPrev.senkouSpanA; + + // + result = + // + point.kijunSen < dest && + pointPrev.kijunSen >= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsKijunSenCrossedOverSenkouSpanB( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanBFuture + : pointPrev.senkouSpanB; + + // + result = + // + point.kijunSen > dest && + pointPrev.kijunSen <= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsKijunSenCrossedUnderSenkouSpanB( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... +) +{ + // + bool result = false; + + // + XIchiInfo point = XICHIHLPGetInfo(bar_index); + XIchiInfo pointPrev = XICHIHLPGetInfo(bar_index + 1); + + // + double dest = onFuture + ? point.senkouSpanBFuture + : point.senkouSpanB; + + // + double destPrev = onFuture + ? pointPrev.senkouSpanBFuture + : pointPrev.senkouSpanB; + + // + result = + // + point.kijunSen < dest && + pointPrev.kijunSen >= destPrev + // + ; + + // + return result; +} + +// +bool XICHIHLPIsValidArraySize(int bar_index) +{ + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(ichiTenkanSenBuffer); + result = rCount > bar_index + 1; + + // + return result; +} + +// +// SUPPORT and RESISTANCE ... + +// +// Find Pivot Areas in Ichimooku ... +void XICHIHLPFindPivotPoints() +{ + // + double smoothingPoint = 3; + int verifications = 3; + + // + // FLATS ... + double tmpFlats[]; + int tmpFlatsCount = 0; + + // + // TenkanSen Flats ... + FindSameValueInBuffer( + tmpFlats, + ichiTenkanSenBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + ichiPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // KijunSen Flats ... + FindSameValueInBuffer( + tmpFlats, + ichiKijunSenBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + ichiPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // SenkouSpanA Flats ... + FindSameValueInBuffer( + tmpFlats, + ichiSenkouSpanABuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + ichiPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // SenkouSpanB Flats ... + FindSameValueInBuffer( + tmpFlats, + ichiSenkouSpanBBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + ichiPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } +} + +// +// Extract Support and Resistances ... +XOHCLSupRes XICHIHLPFindCandleSupprtAndResistance( + int bar_index, // Bar Index ... + int count = 3 // Number of Requireds ... +) +{ + // + XOHCLSupRes result = ExtractSupportAndResistance( + bar_index, + ichiPivots, + count, + _Symbol, + _Period); + + // + return result; +} + +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmc.test.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmc.test.helper.mq5 new file mode 100644 index 0000000..52a3d82 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmc.test.helper.mq5 @@ -0,0 +1,309 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XMCHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// XMC Exported Buffers ... +enum ENUM_X_XMC_BUFFERS +{ + // + X_MC_FAST_LINE = 0, + X_MC_SLOW_LINE = 1, + X_MC_VERIFIER_LINE = 2, +}; + +// +// END Constants/Enums ... +// + +// +// START Definitions ... +// + +// +double mcFastBuffer[]; +double mcSlowBuffer[]; +double mcVerifierBuffer[]; + +// +int mcHandler = INVALID_HANDLE; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XMCHLPOnInit() +{ + // + bool result = false; + + // + ArraySetAsSeries(mcFastBuffer, true); + ArraySetAsSeries(mcSlowBuffer, true); + ArraySetAsSeries(mcVerifierBuffer, true); + + // + // Initial Handler ... + mcHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xmc", + // + // Inputs ... + // + // FAST ... + "", + 9, + 0, + MODE_EMA, + PRICE_CLOSE, + // + // SLOW ... + "", + 18, + 0, + MODE_EMA, + PRICE_CLOSE, + // + // VERIFIER ... + "", + 50, + 0, + MODE_EMA, + PRICE_CLOSE, + // + "", + false, + false, + false + // + ); + result = mcHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XMCHLPOnDeInit() +{ + // + // Release Indicators ... + IndicatorRelease(mcHandler); +} + +// +void XMCHLPReadBuffers() +{ + // + // FAST ... + CopyBuffer( + mcHandler, + X_MC_FAST_LINE, + 0, + 52, + mcFastBuffer); + + // + // SLOW ... + CopyBuffer( + mcHandler, + X_MC_SLOW_LINE, + 0, + 52, + mcSlowBuffer); + + // + // VERIFIER ... + CopyBuffer( + mcHandler, + X_MC_VERIFIER_LINE, + 0, + 52, + mcVerifierBuffer); +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// Check Fast Over Slow ... +bool XMCHLPIsFastOverSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMCHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsOver( + mcFastBuffer, + mcSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +// Check Fast Crossed Over Slow ... +bool XMCHLPIsFastCrossedOverSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMCHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsCrossOver( + mcFastBuffer, + mcSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +// Check Fast Under Slow ... +bool XMCHLPIsFastUnderSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMCHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +// Check Fast Crossed Under Slow ... +bool XMCHLPIsFastCrossedUnderSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMCHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsCrossUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +bool XMCHLPIsValidArraySize(int bar_index) +{ + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(mcFastBuffer); + result = rCount > bar_index + 1; + + // + return result; +} + +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmrb.test.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmrb.test.helper.mq5 new file mode 100644 index 0000000..c952088 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xmrb.test.helper.mq5 @@ -0,0 +1,314 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XMRBHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// XMRB Exported Buffers ... +enum ENUM_X_XMRB_BUFFERS +{ + // + X_MRB_FAST_LINE = 0, + X_MRB_SLOW_LINE = 1, + + // + X_MRB_FAST_1_LINE = 2, + X_MRB_FAST_2_LINE = 3, + X_MRB_FAST_3_LINE = 4, + X_MRB_FAST_4_LINE = 5, + X_MRB_FAST_5_LINE = 6, + + // + X_MRB_SLOW_1_LINE = 7, + X_MRB_SLOW_2_LINE = 8, + X_MRB_SLOW_3_LINE = 9, + X_MRB_SLOW_4_LINE = 10, + X_MRB_SLOW_5_LINE = 11, +}; + +// +// END Constants/Enums ... +// + +// +// START Definitions ... +// + +// +double mrbFastBuffer[]; +double mrbSlowBuffer[]; + +// +int mrbHandler = INVALID_HANDLE; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XMRBHLPOnInit() +{ + // + bool result = false; + + // + ArraySetAsSeries(mrbFastBuffer, true); + ArraySetAsSeries(mrbSlowBuffer, true); + + // + // Initial Handler ... + mrbHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xmrb", + // + // Inputs ... + // + "", + 3, + 5, + // + "", + 8, + 13, + // + "", + 21, + 34, + // + "", + 55, + 89, + // + "", + 144, + 233, + // + "", + MODE_EMA, + PRICE_CLOSE, + // + "", + false, + false, + false + // + ); + result = mrbHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XMRBHLPOnDeInit() +{ + // + // Release Indicators ... + IndicatorRelease(mrbHandler); +} + +// +void XMRBHLPReadBuffers() +{ + // + // FAST ... + CopyBuffer( + mrbHandler, + X_MRB_FAST_LINE, + 0, + 52, + mrbFastBuffer); + + // + // SLOW ... + CopyBuffer( + mrbHandler, + X_MRB_SLOW_LINE, + 0, + 52, + mrbSlowBuffer); +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// Check Fast Over Slow ... +bool XMRBHLPIsFastOverSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMRBHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsOver( + mrbFastBuffer, + mrbSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +// Check Fast Crossed Over Slow ... +bool XMRBHLPIsFastCrossedOverSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMRBHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsCrossOver( + mrbFastBuffer, + mrbSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +// Check Fast Under Slow ... +bool XMRBHLPIsFastUnderSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMRBHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsUnder( + mrbFastBuffer, + mrbSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +// Check Fast Crossed Under Slow ... +bool XMRBHLPIsFastCrossedUnderSlow( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XMRBHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + IsCrossUnder( + mrbFastBuffer, + mrbSlowBuffer, + bar_index) + // + ; + + // + return result; +} + +// +bool XMRBHLPIsValidArraySize(int bar_index) +{ + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(mrbFastBuffer); + result = rCount > bar_index + 1; + + // + return result; +} + +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xpv.test.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xpv.test.helper.mq5 new file mode 100644 index 0000000..0af7755 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xpv.test.helper.mq5 @@ -0,0 +1,803 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XPVHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XPV_BUFFERS +{ + // + // PEAKSANDVALES ... + X_PV_P_LINE = 0, + X_PV_V_LINE = 1, + // + // SUPPORTRESISTANCE ... + X_PV_R_LINE = 2, + X_PV_S_LINE = 4, + // + // SHORT ... + X_PV_SHH_LINE = 6, + X_PV_SLL_LINE = 7, + // + // MEDIUM ... + X_PV_MHH_LINE = 8, + X_PV_MLL_LINE = 9, + // + // LONG ... + X_PV_LHH_LINE = 10, + X_PV_LLL_LINE = 11, + // + // HIND ... + X_PV_HHH_LINE = 12, + X_PV_HLL_LINE = 13, +}; + +// +// END Constants/Enums ... +// + +// +// START Definitions ... +// + +// +double pvPivots[]; + +// +double pvPBuffer[]; +double pvVBuffer[]; +double pvRBuffer[]; +double pvSBuffer[]; +double pvSHHBuffer[]; +double pvSLLBuffer[]; +double pvMHHBuffer[]; +double pvMLLBuffer[]; +double pvLHHBuffer[]; +double pvLLLBuffer[]; +double pvHHHBuffer[]; +double pvHLLBuffer[]; + +// +int mpvHandler = INVALID_HANDLE; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XPVHLPOnInit() +{ + // + bool result = false; + + // + ArraySetAsSeries(pvPivots, true); + + // + ArraySetAsSeries(pvPBuffer, true); + ArraySetAsSeries(pvVBuffer, true); + ArraySetAsSeries(pvRBuffer, true); + ArraySetAsSeries(pvSBuffer, true); + ArraySetAsSeries(pvSHHBuffer, true); + ArraySetAsSeries(pvSLLBuffer, true); + ArraySetAsSeries(pvMHHBuffer, true); + ArraySetAsSeries(pvMLLBuffer, true); + ArraySetAsSeries(pvLHHBuffer, true); + ArraySetAsSeries(pvLLLBuffer, true); + ArraySetAsSeries(pvHHHBuffer, true); + ArraySetAsSeries(pvHLLBuffer, true); + + // + // Initial Handler ... + mpvHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xpv", + // + // Inputs ... + // + // MARKET ... + "", + 9, + 17, + 26, + 35, + // + // TREND ... + "", + 10, + // + // DETECTION ... + "", + MODE_HIGH, + MODE_LOW, + // + "", + true, + false, + false, + false + // + ); + result = mpvHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XPVHLPOnDeInit() +{ + // + // Release Indicators ... + IndicatorRelease(mpvHandler); +} + +// +void XPVHLPReadBuffers(int bar_index = 0) +{ + // + // PEAKS ... + CopyBuffer( + mpvHandler, + X_PV_P_LINE, + bar_index, + bar_index + 100, + pvPBuffer); + + // + // VALES ... + CopyBuffer( + mpvHandler, + X_PV_V_LINE, + bar_index, + bar_index + 100, + pvVBuffer); + + // + // R ... + CopyBuffer( + mpvHandler, + X_PV_R_LINE, + bar_index, + bar_index + 100, + pvRBuffer); + + // + // S ... + CopyBuffer( + mpvHandler, + X_PV_S_LINE, + bar_index, + bar_index + 100, + pvSBuffer); + + // + // SHORT ... + + // + // HIGH ... + CopyBuffer( + mpvHandler, + X_PV_SHH_LINE, + bar_index, + bar_index + 100, + pvSHHBuffer); + + // + // LOW ... + CopyBuffer( + mpvHandler, + X_PV_SLL_LINE, + bar_index, + bar_index + 100, + pvSLLBuffer); + + // + // MEIUM ... + + // + // HIGH ... + CopyBuffer( + mpvHandler, + X_PV_MHH_LINE, + bar_index, + bar_index + 100, + pvMHHBuffer); + + // + // LOW ... + CopyBuffer( + mpvHandler, + X_PV_MLL_LINE, + bar_index, + bar_index + 100, + pvMLLBuffer); + + // + // LONG ... + + // + // HIGH ... + CopyBuffer( + mpvHandler, + X_PV_LHH_LINE, + bar_index, + bar_index + 100, + pvLHHBuffer); + + // + // LOW ... + CopyBuffer( + mpvHandler, + X_PV_LLL_LINE, + bar_index, + bar_index + 100, + pvLLLBuffer); + + // + // HIND ... + + // + // HIGH ... + CopyBuffer( + mpvHandler, + X_PV_HHH_LINE, + bar_index, + bar_index + 100, + pvHHHBuffer); + + // + // LOW ... + CopyBuffer( + mpvHandler, + X_PV_HLL_LINE, + bar_index, + bar_index + 100, + pvHLLBuffer); + + // + XPVHLPFindPivotPoints(); +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// Check isPeak ... +bool XPVHLPIsPeak(int bar_index) +{ + // + bool result = false; + + // + if (!XPVHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = pvRBuffer[bar_index] == pvHHHBuffer[bar_index] && + pvHHHBuffer[bar_index] == pvLHHBuffer[bar_index] && + pvLHHBuffer[bar_index] == pvMHHBuffer[bar_index] && + pvMHHBuffer[bar_index] == pvSHHBuffer[bar_index]; + + // + return result; +} + +// +// Check isVale ... +bool XPVHLPIsVale(int bar_index) +{ + // + bool result = false; + + // + if (!XPVHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = pvSBuffer[bar_index] == pvHLLBuffer[bar_index] && + pvHLLBuffer[bar_index] == pvLLLBuffer[bar_index] && + pvLLLBuffer[bar_index] == pvMLLBuffer[bar_index] && + pvMLLBuffer[bar_index] == pvSLLBuffer[bar_index]; + + // + return result; +} + +// +// Is Strong Support ... +bool XPVHLPIsStrongSupport(int bar_index) +{ + // + bool result = false; + + // + if (!XPVHLPIsValidArraySize(bar_index + 3)) + { + return result; + } + + // + result = + // + pvHLLBuffer[bar_index + 1] == pvHLLBuffer[bar_index + 2] && + pvHLLBuffer[bar_index + 2] == pvHLLBuffer[bar_index + 3] && + // + pvLLLBuffer[bar_index + 1] == pvLLLBuffer[bar_index + 2] && + pvLLLBuffer[bar_index + 2] == pvLLLBuffer[bar_index + 3] && + // + pvMLLBuffer[bar_index + 1] == pvMLLBuffer[bar_index + 2] && + pvMLLBuffer[bar_index + 2] == pvMLLBuffer[bar_index + 3] && + // + pvSLLBuffer[bar_index + 1] == pvSLLBuffer[bar_index + 2] && + pvSLLBuffer[bar_index + 2] == pvSLLBuffer[bar_index + 3] + // + ; + + // + return result; +} + +// +// Is Strong Resistance ... +bool XPVHLPIsStrongResistance(int bar_index) +{ + // + bool result = false; + + // + if (!XPVHLPIsValidArraySize(bar_index + 2)) + { + return result; + } + + // + result = + // + pvHHHBuffer[bar_index + 1] == pvHHHBuffer[bar_index + 2] && + pvHHHBuffer[bar_index + 2] == pvHHHBuffer[bar_index + 3] && + // + pvLHHBuffer[bar_index + 1] == pvLHHBuffer[bar_index + 2] && + pvLHHBuffer[bar_index + 2] == pvLHHBuffer[bar_index + 3] && + // + pvMHHBuffer[bar_index + 1] == pvMHHBuffer[bar_index + 2] && + pvMHHBuffer[bar_index + 2] == pvMHHBuffer[bar_index + 3] && + // + pvSHHBuffer[bar_index + 1] == pvSHHBuffer[bar_index + 2] && + pvSHHBuffer[bar_index + 2] == pvSHHBuffer[bar_index + 3] + // + ; + // + return result; +} + +// +// Retrieve Highs ... +double XPVHLPGetMaxHH(int bar_index) +{ + // + double result = 0; + + // + if (!XPVHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = MathMax(pvSHHBuffer[bar_index], pvMHHBuffer[bar_index]); + result = MathMax(result, pvLHHBuffer[bar_index]); + result = MathMax(result, pvHHHBuffer[bar_index]); + + // + return result; +} + +double XPVHLPGetMinHH(int bar_index) +{ + // + double result = 0; + + // + if (!XPVHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = MathMin(pvSHHBuffer[bar_index], pvMHHBuffer[bar_index]); + result = MathMin(result, pvLHHBuffer[bar_index]); + result = MathMin(result, pvHHHBuffer[bar_index]); + + // + return result; +} + +// +// Retrieve Lows ... +double XPVHLPGetMaxLL(int bar_index) +{ + // + double result = 0; + + // + if (!XPVHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = MathMax(pvSLLBuffer[bar_index], pvMLLBuffer[bar_index]); + result = MathMax(result, pvLLLBuffer[bar_index]); + result = MathMax(result, pvHLLBuffer[bar_index]); + + // + return result; +} + +double XPVHLPGetMinLL(int bar_index) +{ + // + double result = 0; + + // + if (!XPVHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = MathMin(pvSLLBuffer[bar_index], pvMLLBuffer[bar_index]); + result = MathMin(result, pvLLLBuffer[bar_index]); + result = MathMin(result, pvHLLBuffer[bar_index]); + + // + return result; +} + +// +bool XPVHLPIsValidArraySize(int bar_index) +{ + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(pvRBuffer); + result = rCount > bar_index + 1; + + // + return result; +} + +// +// SUPPORT and RESISTANCE ... + +// +// Find Pivot Areas in PV ... +void XPVHLPFindPivotPoints() +{ + // + double smoothingPoint = 3; + int verifications = 26; + + // + // FLATS ... + double tmpFlats[]; + int tmpFlatsCount = 0; + + // + // PEAKS and VALES ... + + // + // R ... + FindSameValueInBuffer( + tmpFlats, + pvRBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // S ... + FindSameValueInBuffer( + tmpFlats, + pvSBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // CYCLES ... + + // + // SHORT ... + // LEVEL 1 ... + + // + // HH ... + FindSameValueInBuffer( + tmpFlats, + pvSHHBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // LL ... + FindSameValueInBuffer( + tmpFlats, + pvSLLBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // MEDIUM ... + // LEVEL 2 ... + + // + // HH ... + FindSameValueInBuffer( + tmpFlats, + pvMHHBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // LL ... + FindSameValueInBuffer( + tmpFlats, + pvMLLBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // LONG ... + // LEVEL 3 ... + + // + // HH ... + FindSameValueInBuffer( + tmpFlats, + pvLHHBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // LL ... + FindSameValueInBuffer( + tmpFlats, + pvLLLBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // HINDMOST ... + // LEVEL 4 ... + + // + // HH ... + FindSameValueInBuffer( + tmpFlats, + pvHHHBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // LL ... + FindSameValueInBuffer( + tmpFlats, + pvHLLBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // PEAKS and VALES ... + + // + // PEAKS ... + FindSameValueInBuffer( + tmpFlats, + pvPBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } + + // + // VALES ... + FindSameValueInBuffer( + tmpFlats, + pvVBuffer); + tmpFlatsCount = ArraySize(tmpFlats); + if (tmpFlatsCount > 0) + { + // + AddsIfNotExists( + tmpFlats, + pvPivots, + smoothingPoint); + + // + Clean(tmpFlats); + } +} + +// +// Extract Support and Resistances ... +XOHCLSupRes XPVHLPFindCandleSupprtAndResistance( + int bar_index, // Bar Index ... + int count = 3 // Number of Requireds ... +) +{ + // + XOHCLSupRes result = ExtractSupportAndResistance( + bar_index, + pvPivots, + count, + _Symbol, + _Period); + + // + return result; +} + +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xtrnd.test.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xtrnd.test.helper.mq5 new file mode 100644 index 0000000..0b2e4cf --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/Test/x121.xtrnd.test.helper.mq5 @@ -0,0 +1,1383 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTRNDHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XTRND_BUFFERS +{ + // + X_TRND_UP_LINE = 0, + X_TRND_UP_STATE_LINE = 1, + // + X_TRND_DOWN_LINE = 2, + X_TRND_DOWN_STATE_LINE = 3, + // + // Nearest ... + // CYCLE 1 ... + X_TRND_L1_UP_LINE = 4, + X_TRND_L1_UP_STATE_LINE = 5, + // + X_TRND_L1_DOWN_LINE = 6, + X_TRND_L1_DOWN_STATE_LINE = 7, + // + // Mediest ... + // CYCLE 2 ... + X_TRND_L2_UP_LINE = 8, + X_TRND_L2_UP_STATE_LINE = 9, + // + X_TRND_L2_DOWN_LINE = 10, + X_TRND_L2_DOWN_STATE_LINE = 11, + // + // Farest ... + // CYCLE 3 ... + X_TRND_L3_UP_LINE = 12, + X_TRND_L3_UP_STATE_LINE = 13, + // + X_TRND_L3_DOWN_LINE = 14, + X_TRND_L3_DOWN_STATE_LINE = 15, +}; + +// +// Trend State at unique Bar ... +enum ENUM_X_XTRND_STATE +{ + X_TRND_STATE_RANGE = 0, + X_TRND_STATE_CONSOLIDATION = 1, + X_TRND_STATE_UP = 2, + X_TRND_STATE_DOWN = 3, +}; + +// +// END Constants/Enums ... +// + +// +double trndUpBuffer[]; +double trndUpStateBuffer[]; +double trndDownBuffer[]; +double trndDownStateBuffer[]; +// +// Nearest ... +// CYCLE 1 ... +double trndl1UpBuffer[]; +double trndl1UpStateBuffer[]; +double trndl1DownBuffer[]; +double trndl1DownStateBuffer[]; +// +// Mediest ... +// CYCLE 2 ... +double trndl2UpBuffer[]; +double trndl2UpStateBuffer[]; +double trndl2DownBuffer[]; +double trndl2DownStateBuffer[]; +// +// Farest ... +// CYCLE 3 ... +double trndl3UpBuffer[]; +double trndl3UpStateBuffer[]; +double trndl3DownBuffer[]; +double trndl3DownStateBuffer[]; + +// +int mtrndHandler = INVALID_HANDLE; + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XTRNDHLPOnInit() +{ + // + bool result = false; + + // + ArraySetAsSeries(trndUpBuffer, true); + ArraySetAsSeries(trndUpStateBuffer, true); + ArraySetAsSeries(trndDownBuffer, true); + ArraySetAsSeries(trndDownStateBuffer, true); + // + // Nearest ... + // CYCLE 1 ... + ArraySetAsSeries(trndl1UpBuffer, true); + ArraySetAsSeries(trndl1UpStateBuffer, true); + ArraySetAsSeries(trndl1DownBuffer, true); + ArraySetAsSeries(trndl1DownStateBuffer, true); + // + // Mediest ... + // CYCLE 2 ... + ArraySetAsSeries(trndl2UpBuffer, true); + ArraySetAsSeries(trndl2UpStateBuffer, true); + ArraySetAsSeries(trndl2DownBuffer, true); + ArraySetAsSeries(trndl2DownStateBuffer, true); + // + // Farest ... + // CYCLE 3 ... + ArraySetAsSeries(trndl3UpBuffer, true); + ArraySetAsSeries(trndl3UpStateBuffer, true); + ArraySetAsSeries(trndl3DownBuffer, true); + ArraySetAsSeries(trndl3DownStateBuffer, true); + + // + // Initial Handler ... + mtrndHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xtrnd", + // + // Inputs ... + // + // MARKET ... + "", + 2, + 2, + // + // CALCULATIONS ... + "", + MODE_HIGH, + MODE_LOW, + // + // CYCLES ... + "", + // + // LEVEL 1 ... + "", + X_PERIOD_AUTO, + _Period, + // + // LEVEL 2 ... + "", + X_PERIOD_AUTO, + _Period, + // + // LEVEL 3 ... + "", + X_PERIOD_AUTO, + _Period, + // + // PRESENTATION ... + "", + true, + true, + true, + true, + true + // + ); + result = mtrndHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XTRNDHLPOnDeInit() +{ + // + // Release Indicators ... + IndicatorRelease(mtrndHandler); +} + +// +void XTRNDHLPReadBuffers() +{ + // + // UP ... + CopyBuffer( + mtrndHandler, + X_TRND_UP_LINE, + 0, + 52, + trndUpBuffer); + + // + // UP STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_UP_STATE_LINE, + 0, + 52, + trndUpStateBuffer); + + // + // DOWN ... + CopyBuffer( + mtrndHandler, + X_TRND_DOWN_LINE, + 0, + 52, + trndDownBuffer); + + // + // DOWN STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_DOWN_STATE_LINE, + 0, + 52, + trndDownStateBuffer); + + // + // CYCLES ... + + // + // Nearest ... + // CYCLE 1 ... + + // + // UP ... + CopyBuffer( + mtrndHandler, + X_TRND_L1_UP_LINE, + 0, + 52, + trndl1UpBuffer); + + // + // UP STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_L1_UP_STATE_LINE, + 0, + 52, + trndl1UpStateBuffer); + + // + // DOWN ... + CopyBuffer( + mtrndHandler, + X_TRND_L1_DOWN_LINE, + 0, + 52, + trndl1DownBuffer); + + // + // DOWN STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_L1_DOWN_STATE_LINE, + 0, + 52, + trndl1DownStateBuffer); + + // + // Mediest ... + // CYCLE 2 ... + + // + // UP ... + CopyBuffer( + mtrndHandler, + X_TRND_L2_UP_LINE, + 0, + 52, + trndl2UpBuffer); + + // + // UP STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_L2_UP_STATE_LINE, + 0, + 52, + trndl2UpStateBuffer); + + // + // DOWN ... + CopyBuffer( + mtrndHandler, + X_TRND_L2_DOWN_LINE, + 0, + 52, + trndl2DownBuffer); + + // + // DOWN STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_L2_DOWN_STATE_LINE, + 0, + 52, + trndl2DownStateBuffer); + + // + // Farest ... + // CYCLE 3 ... + + // + // UP ... + CopyBuffer( + mtrndHandler, + X_TRND_L3_UP_LINE, + 0, + 52, + trndl3UpBuffer); + + // + // UP STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_L3_UP_STATE_LINE, + 0, + 52, + trndl3UpStateBuffer); + + // + // DOWN ... + CopyBuffer( + mtrndHandler, + X_TRND_L3_DOWN_LINE, + 0, + 52, + trndl3DownBuffer); + + // + // DOWN STATE ... + CopyBuffer( + mtrndHandler, + X_TRND_L3_DOWN_STATE_LINE, + 0, + 52, + trndl3DownStateBuffer); +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// START Strongly Trend Detects ... +// + +// +// Detect Strongly Bullish Trend ... +bool XTRNDHLPIsTrendStronglyBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendBullish(bar_index) && + ( + // + (XTRNDHLPIsL1TrendBullish(bar_index) && + XTRNDHLPIsL2TrendBullish(bar_index)) + // + || + // + (XTRNDHLPIsL1TrendBullish(bar_index) && + XTRNDHLPIsL3TrendBullish(bar_index)) + // + || + // + (XTRNDHLPIsL2TrendBullish(bar_index) && + XTRNDHLPIsL3TrendBullish(bar_index)) + // + ) + // + ; + + // + return result; +} + +// +// Detect Strongly Trends Switched to Bullish ... +bool XTRNDHLPIsTrendStronglySwitchedBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendStronglyBullish(bar_index) && + !XTRNDHLPIsTrendStronglyBullish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Strongly Bearish Trend ... +bool XTRNDHLPIsTrendStronglyBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendBearish(bar_index) && + ( + // + (XTRNDHLPIsL1TrendBearish(bar_index) && + XTRNDHLPIsL2TrendBearish(bar_index)) + // + || + // + (XTRNDHLPIsL1TrendBearish(bar_index) && + XTRNDHLPIsL3TrendBearish(bar_index)) + // + || + // + (XTRNDHLPIsL2TrendBearish(bar_index) && + XTRNDHLPIsL3TrendBearish(bar_index)) + // + ) + // + ; + + // + return result; +} + +// +// Detect Strongly Trends Switched to Bearish ... +bool XTRNDHLPIsTrendStronglySwitchedBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendStronglyBearish(bar_index) && + !XTRNDHLPIsTrendStronglyBearish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Strongly Consolidation/Range Trend ... +bool XTRNDHLPIsTrendStronglyConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendConsolidation(bar_index) && + ( + // + (XTRNDHLPIsL1TrendConsolidation(bar_index) && + XTRNDHLPIsL2TrendConsolidation(bar_index)) + // + || + // + (XTRNDHLPIsL1TrendConsolidation(bar_index) && + XTRNDHLPIsL3TrendConsolidation(bar_index)) + // + || + // + (XTRNDHLPIsL2TrendConsolidation(bar_index) && + XTRNDHLPIsL3TrendConsolidation(bar_index)) + // + ) + // + ; + + // + return result; +} + +// +// Detect Strongly Trends Switched to Consolidation/Range ... +bool XTRNDHLPIsTrendStronglySwitchedConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendStronglyConsolidation(bar_index) && + !XTRNDHLPIsTrendStronglyConsolidation(bar_index + 1) + // + ; + + // + return result; +} + +// +// END Strongly Trend Detects ... +// + +// +// Detect Trend Up ... +bool XTRNDHLPIsTrendBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndUpStateBuffer[bar_index] == X_TRND_STATE_UP && + trndDownStateBuffer[bar_index] == X_TRND_STATE_UP + // + ; + + // + return result; +} + +// +// Detect Trend Switched Up ... +bool XTRNDHLPIsTrendSwitchedBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendBullish(bar_index) && + !XTRNDHLPIsTrendBullish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Down ... +bool XTRNDHLPIsTrendBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndUpStateBuffer[bar_index] == X_TRND_STATE_DOWN && + trndDownStateBuffer[bar_index] == X_TRND_STATE_DOWN + // + ; + + // + return result; +} + +// +// Detect Trend Switched Down ... +bool XTRNDHLPIsTrendSwitchedBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendBearish(bar_index) && + !XTRNDHLPIsTrendBearish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Consolidation ... +bool XTRNDHLPIsTrendConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + (trndUpStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndUpStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + && + // + (trndDownStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndDownStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + ; + + // + return result; +} + +// +// Detect Trend Switched Consolidation ... +bool XTRNDHLPIsTrendSwitchedConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsTrendConsolidation(bar_index) && + !XTRNDHLPIsTrendConsolidation(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Previous Trend Switched To Bullish ... +int XTRNDHLPFindNextTrendSwitchedBullish( + int bar_index // Bar Index ... +) { + // + int result = -1; + + // + int size = ArraySize(trndDownStateBuffer); + if (size <= 0) { + return result; + } + + // + for (int i = bar_index + 1; i < size + bar_index; i++) { + // + bool isTrendSwitched = + XTRNDHLPIsTrendSwitchedBullish(i); + + // + if (isTrendSwitched && i != bar_index) { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Detect Previous Trend Switched To Bearish ... +int XTRNDHLPFindNextTrendSwitchedBearish( + int bar_index // Bar Index ... +) { + // + int result = -1; + + // + int size = ArraySize(trndDownStateBuffer); + if (size <= 0) { + return result; + } + + // + for (int i = bar_index + 1; i < size + bar_index; i++) { + // + bool isTrendSwitched = + XTRNDHLPIsTrendSwitchedBearish(i); + + // + if (isTrendSwitched && i != bar_index) { + // + result = i; + break; + } + } + + // + return result; +} + +// +// CYCLE 1 ... + +// +// Detect Trend Up ... +bool XTRNDHLPIsL1TrendBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndl1UpStateBuffer[bar_index] == X_TRND_STATE_UP && + trndl1DownStateBuffer[bar_index] == X_TRND_STATE_UP + // + ; + + // + return result; +} + +// +// Detect Trend Switched Up ... +bool XTRNDHLPIsL1TrendSwitchedBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL1TrendBullish(bar_index) && + !XTRNDHLPIsL1TrendBullish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Down ... +bool XTRNDHLPIsL1TrendBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndl1UpStateBuffer[bar_index] == X_TRND_STATE_DOWN && + trndl1DownStateBuffer[bar_index] == X_TRND_STATE_DOWN + // + ; + + // + return result; +} + +// +// Detect Trend Switched Down ... +bool XTRNDHLPIsL1TrendSwitchedBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL1TrendBearish(bar_index) && + !XTRNDHLPIsL1TrendBearish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Consolidation ... +bool XTRNDHLPIsL1TrendConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + (trndl1UpStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndl1UpStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + && + // + (trndl1DownStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndl1DownStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + ; + + // + return result; +} + +// +// Detect Trend Switched Consolidation ... +bool XTRNDHLPIsL1TrendSwitchedConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL1TrendConsolidation(bar_index) && + !XTRNDHLPIsL1TrendConsolidation(bar_index + 1) + // + ; + + // + return result; +} + +// +// CYCLE 2 ... + +// +// Detect Trend Up ... +bool XTRNDHLPIsL2TrendBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndl2UpStateBuffer[bar_index] == X_TRND_STATE_UP && + trndl2DownStateBuffer[bar_index] == X_TRND_STATE_UP + // + ; + + // + return result; +} + +// +// Detect Trend Switched Up ... +bool XTRNDHLPIsL2TrendSwitchedBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL2TrendBullish(bar_index) && + !XTRNDHLPIsL2TrendBullish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Down ... +bool XTRNDHLPIsL2TrendBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndl2UpStateBuffer[bar_index] == X_TRND_STATE_DOWN && + trndl2DownStateBuffer[bar_index] == X_TRND_STATE_DOWN + // + ; + + // + return result; +} + +// +// Detect Trend Switched Down ... +bool XTRNDHLPIsL2TrendSwitchedBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL2TrendBearish(bar_index) && + !XTRNDHLPIsL2TrendBearish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Consolidation ... +bool XTRNDHLPIsL2TrendConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + (trndl2UpStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndl2UpStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + && + // + (trndl2DownStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndl2DownStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + ; + + // + return result; +} + +// +// Detect Trend Switched Consolidation ... +bool XTRNDHLPIsL2TrendSwitchedConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL2TrendConsolidation(bar_index) && + !XTRNDHLPIsL2TrendConsolidation(bar_index + 1) + // + ; + + // + return result; +} + +// +// CYCLE 3 ... + +// +// Detect Trend Up ... +bool XTRNDHLPIsL3TrendBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndl3UpStateBuffer[bar_index] == X_TRND_STATE_UP && + trndl3DownStateBuffer[bar_index] == X_TRND_STATE_UP + // + ; + + // + return result; +} + +// +// Detect Trend Switched Up ... +bool XTRNDHLPIsL3TrendSwitchedBullish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL3TrendBullish(bar_index) && + !XTRNDHLPIsL3TrendBullish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Down ... +bool XTRNDHLPIsL3TrendBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + trndl3UpStateBuffer[bar_index] == X_TRND_STATE_DOWN && + trndl3DownStateBuffer[bar_index] == X_TRND_STATE_DOWN + // + ; + + // + return result; +} + +// +// Detect Trend Switched Down ... +bool XTRNDHLPIsL3TrendSwitchedBearish( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL3TrendBearish(bar_index) && + !XTRNDHLPIsL3TrendBearish(bar_index + 1) + // + ; + + // + return result; +} + +// +// Detect Trend Consolidation ... +bool XTRNDHLPIsL3TrendConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + (trndl3UpStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndl3UpStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + && + // + (trndl3DownStateBuffer[bar_index] == X_TRND_STATE_RANGE || + trndl3DownStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + ; + + // + return result; +} + +// +// Detect Trend Switched Consolidation ... +bool XTRNDHLPIsL3TrendSwitchedConsolidation( + int bar_index // Bar Index ... +) +{ + // + bool result = false; + + // + if (!XTRNDHLPIsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + XTRNDHLPIsL3TrendConsolidation(bar_index) && + !XTRNDHLPIsL3TrendConsolidation(bar_index + 1) + // + ; + + // + return result; +} + +// +bool XTRNDHLPIsValidArraySize(int bar_index) +{ + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(trndUpBuffer); + result = rCount > bar_index + 1; + + // + return result; +} +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xatrsl.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xatrsl.helper.mq5 new file mode 100644 index 0000000..4286103 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xatrsl.helper.mq5 @@ -0,0 +1,324 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XATRSL Indicator Provider +// Description: ATR Stop Loss ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XATRSL_BUFFERS +{ + // + X_ATRSL_UP_LINE = 0, + X_ATRSL_DOWN_LINE = 1, + X_ATRSL_SAR_LINE = 2, + X_ATRSL_RMA_LINE = 3, + X_ATRSL_WMA_LINE = 4, + X_ATRSL_MA1_LINE = 5, + X_ATRSL_SMA_LINE = 6, + X_ATRSL_EMA_LINE = 7, + X_ATRSL_ATR_LINE = 8, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXATRSLHelper +{ + // +public: + // + // Properties ... + double upBuffer[]; + double downBuffer[]; + double sarBuffer[]; + double rmaBuffer[]; + double wmaBuffer[]; + double ma1Buffer[]; + double smaBuffer[]; + double emaBuffer[]; + double atrBuffer[]; + + // + // Constructor ... + void XSCXATRSLHelper() { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXATRSLHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // MARKET ... + int length = 14, // Length + double step = 0.02, // Increment Step + double maximum = 0.2, // Maximum + ENUM_APPLIED_PRICE highAppliedTo = PRICE_HIGH, // High Line Applied To + ENUM_APPLIED_PRICE lowAppliedTo = PRICE_LOW // Low Line Applied To + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // MARKET ... + mLength = length; + mStep = step; + mMaximum = maximum; + mHighAppliedTo = highAppliedTo; + mLowAppliedTo = lowAppliedTo; + + // + mTag = "XATRSL " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xatrsl", + // + // Inputs ... + // + // MARKET ... + "", + mLength, + mStep, + mMaximum, + mHighAppliedTo, + mLowAppliedTo, + // + // PRESENTATION ... + "", + false, + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(upBuffer, true); + ArraySetAsSeries(downBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(rmaBuffer, true); + ArraySetAsSeries(wmaBuffer, true); + ArraySetAsSeries(ma1Buffer, true); + ArraySetAsSeries(smaBuffer, true); + ArraySetAsSeries(emaBuffer, true); + ArraySetAsSeries(atrBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXATRSLHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // UP ... + CopyBuffer( + mHandler, + X_ATRSL_UP_LINE, + 0, + mNumberOfItemsReadPerTick, + upBuffer); + + // + // DOWN ... + CopyBuffer( + mHandler, + X_ATRSL_DOWN_LINE, + 0, + mNumberOfItemsReadPerTick, + downBuffer); + + // + // SAR ... + CopyBuffer( + mHandler, + X_ATRSL_SAR_LINE, + 0, + mNumberOfItemsReadPerTick, + sarBuffer); + + // + // RMA ... + CopyBuffer( + mHandler, + X_ATRSL_RMA_LINE, + 0, + mNumberOfItemsReadPerTick, + rmaBuffer); + + // + // WMA ... + CopyBuffer( + mHandler, + X_ATRSL_WMA_LINE, + 0, + mNumberOfItemsReadPerTick, + wmaBuffer); + + // + // MA1 ... + CopyBuffer( + mHandler, + X_ATRSL_MA1_LINE, + 0, + mNumberOfItemsReadPerTick, + ma1Buffer); + + // + // MA 1 ... + CopyBuffer( + mHandler, + X_ATRSL_SMA_LINE, + 0, + mNumberOfItemsReadPerTick, + smaBuffer); + + // + // EMA ... + CopyBuffer( + mHandler, + X_ATRSL_EMA_LINE, + 0, + mNumberOfItemsReadPerTick, + emaBuffer); + + // + // ATR ... + CopyBuffer( + mHandler, + X_ATRSL_ATR_LINE, + 0, + mNumberOfItemsReadPerTick, + atrBuffer); + } + + // + // START Tools Functions ... + // + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // MARKET ... + + // + // Length ... + int mLength; + + // + // Increment Step ... + double mStep; + + // + // Maximum ... + double mMaximum; + + // + // High Line Applied To ... + ENUM_APPLIED_PRICE mHighAppliedTo; + + // + // Low Line Applied To ... + ENUM_APPLIED_PRICE mLowAppliedTo; + + // + string mTag; + + // + int mHandler; +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xhk.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xhk.helper.mq5 new file mode 100644 index 0000000..acd7b21 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xhk.helper.mq5 @@ -0,0 +1,215 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XHikenAshi Indicator Provider +// Description: Provides Features ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XHikenAshi Exported Buffers ... +enum ENUM_X_HIKENASHI_BUFFERS +{ + // + X_HK_OPEN_LINE = 0, + X_HK_HIGH_LINE = 1, + X_HK_LOW_LINE = 2, + X_HK_CLOSE_LINE = 3, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXHKHelper +{ + // +public: + // + // Properties ... + double openBuffer[]; + double highBuffer[]; + double lowBuffer[]; + double closeBuffer[]; + + // + // Constructor ... + void XSCXHKHelper() { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXHKHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52 + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + mTag = "XHK " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xhk", + // + // Inputs ... + "", + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(openBuffer, true); + ArraySetAsSeries(highBuffer, true); + ArraySetAsSeries(lowBuffer, true); + ArraySetAsSeries(closeBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXHKHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // OPEN ... + CopyBuffer( + mHandler, + X_HK_OPEN_LINE, + 0, + mNumberOfItemsReadPerTick, + openBuffer); + + // + // HIGH ... + CopyBuffer( + mHandler, + X_HK_HIGH_LINE, + 0, + mNumberOfItemsReadPerTick, + highBuffer); + + // + // LOW ... + CopyBuffer( + mHandler, + X_HK_LOW_LINE, + 0, + mNumberOfItemsReadPerTick, + lowBuffer); + + // + // CLOSE ... + CopyBuffer( + mHandler, + X_HK_CLOSE_LINE, + 0, + mNumberOfItemsReadPerTick, + closeBuffer); + } + + // + // START Tools Functions ... + // + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + string mTag; + + // + int mHandler; +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xich.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xich.helper.mq5 new file mode 100644 index 0000000..d67b1d0 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xich.helper.mq5 @@ -0,0 +1,690 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XIchimoku Indicator Provider +// Description: Provides Features ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// Ichimoku Indicator Exported Buffers ... +enum ENUM_X_ICHIMOKU_BUFFERS +{ + // + X_TENKANSEN_LINE = 0, + X_KIJUNSEN_LINE = 1, + X_CHIKOUSPAN_LINE = 4, + X_SENKOUSPAN_A_LINE = 5, + X_SENKOUSPAN_B_LINE = 6, +}; + +// +// Model Ichimoku Data ... +struct XIchiInfo +{ + // + int bar; + + // + double tenkanSen; + double kijunSen; + + // + double senkouSpanA; + double senkouSpanB; + + // + double senkouSpanAFuture; + double senkouSpanBFuture; +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXICHHelper +{ + // + // Public ... +public: + // + // Properties ... + double tenkanSenBuffer[]; + double kijunSenBuffer[]; + double chikouSpanBuffer[]; + double senkouSpanABuffer[]; + double senkouSpanBBuffer[]; + + // + // Constructor ... + void XSCXICHHelper() + { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXICHHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // TenkanSen ... + int tenkanSenLength = 9, + ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode = X_XICH_HH_LL_MODE, + // + // KijunSen ... + int kijunSenLength = 26, + ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode = X_XICH_HH_LL_MODE, + // + // Senkou Span B ... + int senkouSpanBLength = 52, + ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode = X_XICH_HH_LL_MODE, + // + // Chikou Span ... + ENUM_APPLIED_PRICE chikuoSpanAppliedTo = PRICE_CLOSE + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // TenkanSen ... + mKijunSenMode = kijunSenMode; + mKijunSenLength = kijunSenLength; + + // + // KijunSen ... + mTenkanSenMode = tenkanSenMode; + mTenkanSenLength = tenkanSenLength; + + // + // Senkou Span B ... + mSenkouSpanBMode = senkouSpanBMode; + mSenkouSpanBLength = senkouSpanBLength; + + // + mSenkouSpanBTopMode = NULL; + mSenkouSpanBBottomMode = NULL; + + // + // Chikou Span ... + mChikuoSpanAppliedTo = chikuoSpanAppliedTo; + + // + mTag = "XICH " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xich", + // + // Inputs ... + // + // TENKANSEN ... + "", + mTenkanSenLength, + mTenkanSenMode, + // + // KIJUNSEN ... + "", + kijunSenLength, + kijunSenMode, + // + // SENKOUSPANB ... + "", + senkouSpanBLength, + senkouSpanBMode, + // + // CHIKOUSPAN ... + "", + mChikuoSpanAppliedTo, + // + // PRESENTATION ... + "", + false, + false, + false, + false, + false, + false, + false, + false, + true // Shift Kumo ... + // + ); + if (mHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(tenkanSenBuffer, true); + ArraySetAsSeries(kijunSenBuffer, true); + ArraySetAsSeries(chikouSpanBuffer, true); + ArraySetAsSeries(senkouSpanABuffer, true); + ArraySetAsSeries(senkouSpanBBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXICHHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // TENKANSEN ... + CopyBuffer( + mHandler, + X_TENKANSEN_LINE, + 0, + mNumberOfItemsReadPerTick, + tenkanSenBuffer); + + // + // KIJUNSEN ... + CopyBuffer( + mHandler, + X_KIJUNSEN_LINE, + 0, + mNumberOfItemsReadPerTick, + kijunSenBuffer); + + // + // CHIKOUSPAN ... + CopyBuffer( + mHandler, + X_CHIKOUSPAN_LINE, + mKijunSenLength - 1, + mNumberOfItemsReadPerTick, + chikouSpanBuffer); + + // + // SENKOUSPANA ... + CopyBuffer( + mHandler, + X_SENKOUSPAN_A_LINE, + -mKijunSenLength + 1, + mNumberOfItemsReadPerTick, + senkouSpanABuffer); + + // + // SENKOUSPANB ... + CopyBuffer( + mHandler, + X_SENKOUSPAN_B_LINE, + -mKijunSenLength + 1, + mNumberOfItemsReadPerTick, + senkouSpanBBuffer); + } + + // + // START Tools Functions ... + // + + // + // Retrieve Ichimoku Data at Specific Bar Index ... + XIchiInfo GetInfo( + int bar_index // Bar Index ... + ) + { + // + XIchiInfo result = {}; + + // + result.bar = bar_index; + result.tenkanSen = tenkanSenBuffer[bar_index]; + result.kijunSen = kijunSenBuffer[bar_index]; + result.senkouSpanA = senkouSpanABuffer[bar_index + mKijunSenLength]; + result.senkouSpanB = senkouSpanBBuffer[bar_index + mKijunSenLength]; + result.senkouSpanAFuture = senkouSpanABuffer[bar_index]; + result.senkouSpanBFuture = senkouSpanBBuffer[bar_index]; + + // + return result; + } + + // + // Check Tenkan Sen Over Kijun Sen ... + bool IsTenkanSenOverKijunSen( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + tenkanSenBuffer[bar_index] > kijunSenBuffer[bar_index] + // + ; + + // + return result; + } + + // + // Is Tenkan Sen Under Kijun Sen ... + bool IsTenkanSenUnderKijunSen( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + tenkanSenBuffer[bar_index] < kijunSenBuffer[bar_index] + // + ; + + // + return result; + } + + // + // Tenkan Sen Croosed Over Kijun Sen ... + bool IsTenkanSenCrossedOverKijunSen( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 2)) + { + return result; + } + + // + result = IsCrossOver( + tenkanSenBuffer, + kijunSenBuffer, + bar_index); + + // + return result; + } + + // + // Tenkan Sen Croosed Under Kijun Sen ... + bool IsTenkanSenCrossedUnderKijunSen( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 2)) + { + return result; + } + + // + result = IsCrossUnder( + tenkanSenBuffer, + kijunSenBuffer, + bar_index); + + // + return result; + } + + // + // Check Kumo is Bullish ... + bool IsKumoBullish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... + ) + { + // + bool result = false; + + // + int start = 0; + + // + if (!onFuture) + { + start = (mKijunSenLength - bar_index); + } + else + { + start = (mKijunSenLength - bar_index) * 2; + } + + // + if (!IsValidArraySize(start)) + { + return result; + } + + // + result = + // + senkouSpanABuffer[start + 1] > senkouSpanBBuffer[start + 1] && + senkouSpanABuffer[start] > senkouSpanBBuffer[start] + // + ; + + // + return result; + } + + // + // Check Kumo is Bearish ... + bool IsKumoBearish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... + ) + { + // + bool result = false; + + // + int start = 0; + + // + if (!onFuture) + { + start = (mKijunSenLength - bar_index); + } + else + { + start = (mKijunSenLength - bar_index) * 2; + } + + // + if (!IsValidArraySize(start)) + { + return result; + } + + // + result = + // + senkouSpanABuffer[start + 1] < senkouSpanBBuffer[start + 1] && + senkouSpanABuffer[start] < senkouSpanBBuffer[start] + // + ; + + // + return result; + } + + // + // Check Kumo is Change to Bullish ... + bool IsKumoSwitchedToBullish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... + ) + { + // + bool result = false; + + // + int start = 0; + + // + if (!onFuture) + { + start = (mKijunSenLength - bar_index); + } + else + { + start = (mKijunSenLength - bar_index) * 2; + } + + // + if (!IsValidArraySize(start)) + { + return result; + } + + // + result = + // + senkouSpanABuffer[start + 1] > senkouSpanBBuffer[start + 1] && + senkouSpanABuffer[start] <= senkouSpanBBuffer[start] + // + ; + + // + return result; + } + + // + // Check Kumo is Change to Bearish ... + bool IsKumoSwitchedToBearish( + int bar_index, // Bar Index ... + bool onFuture = false // Future Check ... + ) + { + // + bool result = false; + + // + int start = 0; + + // + if (!onFuture) + { + start = (mKijunSenLength - bar_index); + } + else + { + start = (mKijunSenLength - bar_index) * 2; + } + + // + if (!IsValidArraySize(start)) + { + return result; + } + + // + result = + // + senkouSpanABuffer[start + 1] < senkouSpanBBuffer[start + 1] && + senkouSpanABuffer[start] >= senkouSpanBBuffer[start] + // + ; + + // + return result; + } + + // + // Check Ichimokou Common Conditions for Long Trades ... + // TenkanSen > Kumo + // KijunSen > Kumo + // ChikouSpan > Kumo + // Kumo has Good Body + bool CheckCommonLongConditions() { + // + bool result = false; + + // + // TODO: Complete this ... + + // + return result; + } + + // + // Check Ichimoku Common Conditions for Short Trades ... + // TenkanSen < Kumo + // KijunSen < Kumo + // ChikouSpan < Kumo + // Kumo has Good Body + bool CheckCommonShortConditions() { + // + bool result = false; + + // + // TODO: Complete this ... + + // + return result; + } + + // + // END Tools Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // TenkanSen ... + int mTenkanSenLength; + ENUM_X_ICHIMOKU_CALCULATION_MODE mTenkanSenMode; + + // + // KijunSen ... + int mKijunSenLength; + ENUM_X_ICHIMOKU_CALCULATION_MODE mKijunSenMode; + + // + // Senkou Span B ... + int mSenkouSpanBLength; + ENUM_X_ICHIMOKU_CALCULATION_MODE mSenkouSpanBMode; + + // + ENUM_SERIESMODE mSenkouSpanBTopMode; + ENUM_SERIESMODE mSenkouSpanBBottomMode; + + // + // Chikou Span ... + ENUM_APPLIED_PRICE mChikuoSpanAppliedTo; + + // + string mTag; + + // + int mHandler; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(tenkanSenBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmc.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmc.helper.mq5 new file mode 100644 index 0000000..42dfaba --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmc.helper.mq5 @@ -0,0 +1,418 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XMC Indicator Provider +// Description: Provides Features ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XMC Exported Buffers ... +enum ENUM_X_XMC_BUFFERS +{ + // + X_MC_FAST_LINE = 0, + X_MC_SLOW_LINE = 1, + X_MC_VERIFIER_LINE = 2, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXMCHelper +{ + // +public: + // + // Properties ... + double fastBuffer[]; + double slowBuffer[]; + double verifierBuffer[]; + + // + // Constructor ... + void XSCXMCHelper() { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXMCHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // FAST ... + int fastMaLength = 9, + int fastMaShift = 0, + ENUM_MA_METHOD fastMaMethod = MODE_EMA, + ENUM_APPLIED_PRICE fastMaAppliedTo = PRICE_CLOSE, + // + // SLOW ... + int slowMaLength = 18, + int slowMaShift = 0, + ENUM_MA_METHOD slowMaMethod = MODE_EMA, + ENUM_APPLIED_PRICE slowMaAppliedTo = PRICE_CLOSE, + // + // VERIFIER ... + int verifierMaLength = 50, + int verifierMaShift = 0, + ENUM_MA_METHOD verifierMaMethod = MODE_EMA, + ENUM_APPLIED_PRICE verifierMaAppliedTo = PRICE_CLOSE + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // FAST ... + mFastMaLength = fastMaLength; + mFastMaShift = fastMaShift; + mFastMaMethod = fastMaMethod; + mFastMaAppliedTo = fastMaAppliedTo; + + // + // SLOW ... + mSlowMaLength = slowMaLength; + mSlowMaShift = slowMaShift; + mSlowMaMethod = slowMaMethod; + mSlowMaAppliedTo = slowMaAppliedTo; + + // + // VERIFIER ... + mVerifierMaLength = verifierMaLength; + mVerifierMaShift = verifierMaShift; + mVerifierMaMethod = verifierMaMethod; + mVerifierMaAppliedTo = verifierMaAppliedTo; + + // + mTag = "XMC " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xmc", + // + // Inputs ... + // + // FAST ... + "", + mFastMaLength, + mFastMaShift, + mFastMaMethod, + mFastMaAppliedTo, + // + // SLOW ... + "", + mSlowMaLength, + mSlowMaShift, + mSlowMaMethod, + mSlowMaAppliedTo, + // + // VERIFIER ... + "", + mVerifierMaLength, + mVerifierMaShift, + mVerifierMaMethod, + mVerifierMaAppliedTo, + // + "", + false, + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(verifierBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXMCHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // FAST ... + CopyBuffer( + mHandler, + X_MC_FAST_LINE, + 0, + mNumberOfItemsReadPerTick, + fastBuffer); + + // + // SLOW ... + CopyBuffer( + mHandler, + X_MC_SLOW_LINE, + 0, + mNumberOfItemsReadPerTick, + slowBuffer); + + // + // VERIFIER ... + CopyBuffer( + mHandler, + X_MC_VERIFIER_LINE, + 0, + mNumberOfItemsReadPerTick, + verifierBuffer); + } + + // + // START Tools Functions ... + // + + // + // Check Fast Over Slow ... + bool IsFastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsFastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsFastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsFastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // FAST ... + int mFastMaLength; + int mFastMaShift; + ENUM_MA_METHOD mFastMaMethod; + ENUM_APPLIED_PRICE mFastMaAppliedTo; + + // + // SLOW ... + int mSlowMaLength; + int mSlowMaShift; + ENUM_MA_METHOD mSlowMaMethod; + ENUM_APPLIED_PRICE mSlowMaAppliedTo; + + // + // VERIFIER ... + int mVerifierMaLength; + int mVerifierMaShift; + ENUM_MA_METHOD mVerifierMaMethod; + ENUM_APPLIED_PRICE mVerifierMaAppliedTo; + + // + string mTag; + + // + int mHandler; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(fastBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmrb.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmrb.helper.mq5 new file mode 100644 index 0000000..2d85cdd --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xmrb.helper.mq5 @@ -0,0 +1,1102 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XMRB Indicator Provider +// Description: MA Ribbons ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XMRB Exported Buffers ... +enum ENUM_X_XMRB_BUFFERS +{ + // + X_MRB_FAST_LINE = 0, + X_MRB_SLOW_LINE = 1, + + // + X_MRB_FAST_1_LINE = 2, + X_MRB_FAST_2_LINE = 3, + X_MRB_FAST_3_LINE = 4, + X_MRB_FAST_4_LINE = 5, + X_MRB_FAST_5_LINE = 6, + + // + X_MRB_SLOW_1_LINE = 7, + X_MRB_SLOW_2_LINE = 8, + X_MRB_SLOW_3_LINE = 9, + X_MRB_SLOW_4_LINE = 10, + X_MRB_SLOW_5_LINE = 11, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXMRBHelper +{ + // +public: + // + // Properties ... + double fastBuffer[]; + double slowBuffer[]; + + // + double fast1Buffer[]; + double fast2Buffer[]; + double fast3Buffer[]; + double fast4Buffer[]; + double fast5Buffer[]; + + // + double slow1Buffer[]; + double slow2Buffer[]; + double slow3Buffer[]; + double slow4Buffer[]; + double slow5Buffer[]; + + // + // Constructor ... + void XSCXMRBHelper() { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXMRBHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // RIBBONS ... + // + int fast1Length = 3, + int slow1Length = 5, + // + int fast2Length = 8, + int slow2Length = 13, + // + int fast3Length = 21, + int slow3Length = 34, + // + int fast4Length = 55, + int slow4Length = 89, + // + int fast5Length = 144, + int slow5Length = 233, + // + // CALCULATION ... + ENUM_MA_METHOD ribbonMode = MODE_EMA, + ENUM_APPLIED_PRICE ribbonAppliedTo = PRICE_CLOSE + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // RIBBONS ... + // + mFast1Length = fast1Length; + mSlow1Length = slow1Length; + // + mFast2Length = fast2Length; + mSlow2Length = slow2Length; + // + mFast3Length = fast3Length; + mSlow3Length = slow3Length; + // + mFast4Length = fast4Length; + mSlow4Length = slow4Length; + // + mFast5Length = fast5Length; + mSlow5Length = slow5Length; + // + // CALCULATION ... + mRibbonMode = ribbonMode; + mRibbonAppliedTo = ribbonAppliedTo; + + // + mTag = "XMRB " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xmrb", + // + // Inputs ... + // + "", + mFast1Length, + mSlow1Length, + // + "", + mFast2Length, + mSlow2Length, + // + "", + mFast3Length, + mSlow3Length, + // + "", + mFast4Length, + mSlow4Length, + // + "", + mFast5Length, + mSlow5Length, + // + "", + mRibbonMode, + mRibbonAppliedTo, + // + "", + false, + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(slowBuffer, true); + + // + ArraySetAsSeries(fast1Buffer, true); + ArraySetAsSeries(fast2Buffer, true); + ArraySetAsSeries(fast3Buffer, true); + ArraySetAsSeries(fast4Buffer, true); + ArraySetAsSeries(fast5Buffer, true); + + // + ArraySetAsSeries(slow1Buffer, true); + ArraySetAsSeries(slow2Buffer, true); + ArraySetAsSeries(slow3Buffer, true); + ArraySetAsSeries(slow4Buffer, true); + ArraySetAsSeries(slow5Buffer, true); + } + + // + // DeConstructor ... + void ~XSCXMRBHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // FAST ... + CopyBuffer( + mHandler, + X_MRB_FAST_LINE, + 0, + mNumberOfItemsReadPerTick, + fastBuffer); + + CopyBuffer( + mHandler, + X_MRB_FAST_1_LINE, + 0, + mNumberOfItemsReadPerTick, + fast1Buffer); + + CopyBuffer( + mHandler, + X_MRB_FAST_2_LINE, + 0, + mNumberOfItemsReadPerTick, + fast2Buffer); + + CopyBuffer( + mHandler, + X_MRB_FAST_3_LINE, + 0, + mNumberOfItemsReadPerTick, + fast3Buffer); + + CopyBuffer( + mHandler, + X_MRB_FAST_4_LINE, + 0, + mNumberOfItemsReadPerTick, + fast4Buffer); + + CopyBuffer( + mHandler, + X_MRB_FAST_5_LINE, + 0, + mNumberOfItemsReadPerTick, + fast5Buffer); + + // + // SLOW ... + CopyBuffer( + mHandler, + X_MRB_SLOW_LINE, + 0, + mNumberOfItemsReadPerTick, + slowBuffer); + + CopyBuffer( + mHandler, + X_MRB_SLOW_1_LINE, + 0, + mNumberOfItemsReadPerTick, + slow1Buffer); + + CopyBuffer( + mHandler, + X_MRB_SLOW_2_LINE, + 0, + mNumberOfItemsReadPerTick, + slow2Buffer); + + CopyBuffer( + mHandler, + X_MRB_SLOW_3_LINE, + 0, + mNumberOfItemsReadPerTick, + slow3Buffer); + + CopyBuffer( + mHandler, + X_MRB_SLOW_4_LINE, + 0, + mNumberOfItemsReadPerTick, + slow4Buffer); + + CopyBuffer( + mHandler, + X_MRB_SLOW_5_LINE, + 0, + mNumberOfItemsReadPerTick, + slow5Buffer); + } + + // + // START Tools Functions ... + // + + // + // Check Fast Over Slow ... + bool IsFastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsFastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsFastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsFastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fastBuffer, + slowBuffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // RIBBON 1 ... + + // + // Check Fast Over Slow ... + bool IsR1FastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fast1Buffer, + slow1Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsR1FastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fast1Buffer, + slow1Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsR1FastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fast1Buffer, + slow1Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsR1FastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fast1Buffer, + slow1Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // RIBBON 2 ... + + // + // Check Fast Over Slow ... + bool IsR2FastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fast2Buffer, + slow2Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsR2FastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fast2Buffer, + slow2Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsR2FastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fast2Buffer, + slow2Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsR2FastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fast2Buffer, + slow2Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // RIBBON 3 ... + + // + // Check Fast Over Slow ... + bool IsR3FastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fast3Buffer, + slow3Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsR3FastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fast3Buffer, + slow3Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsR3FastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fast3Buffer, + slow3Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsR3FastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fast3Buffer, + slow3Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // RIBBON 4 ... + + // + // Check Fast Over Slow ... + bool IsR4FastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fast4Buffer, + slow4Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsR4FastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fast4Buffer, + slow4Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsR4FastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fast4Buffer, + slow4Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsR4FastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fast4Buffer, + slow4Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // RIBBON 5 ... + + // + // Check Fast Over Slow ... + bool IsR5FastOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsOver( + fast5Buffer, + slow5Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Over Slow ... + bool IsR5FastCrossedOverSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossOver( + fast5Buffer, + slow5Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Under Slow ... + bool IsR5FastUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsUnder( + fast5Buffer, + slow5Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // Check Fast Crossed Under Slow ... + bool IsR5FastCrossedUnderSlow( + int bar_index // Bar Index ... + ) { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) { + return result; + } + + // + result = + // + IsCrossUnder( + fast5Buffer, + slow5Buffer, + bar_index + ) + // + ; + + // + return result; + } + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // RIBBONS ... + // + int mFast1Length; + int mSlow1Length; + // + int mFast2Length; + int mSlow2Length; + // + int mFast3Length; + int mSlow3Length; + // + int mFast4Length; + int mSlow4Length; + // + int mFast5Length; + int mSlow5Length; + + // + // CALCULATION ... + ENUM_MA_METHOD mRibbonMode; + ENUM_APPLIED_PRICE mRibbonAppliedTo; + + // + string mTag; + + // + int mHandler; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(fastBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xppsr.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xppsr.helper.mq5 new file mode 100644 index 0000000..2b80595 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xppsr.helper.mq5 @@ -0,0 +1,575 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPPSR Indicator Provider +// Description: Provides Features ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// XPPSR Exported Buffers ... +enum ENUM_X_XPPSR_BUFFERS +{ + // + // LEVEL 1 ... + X_PPSR_L1_R_LINE = 0, + X_PPSR_L1_R1_LINE = 1, + X_PPSR_L1_R2_LINE = 2, + X_PPSR_L1_S_LINE = 3, + X_PPSR_L1_S1_LINE = 4, + X_PPSR_L1_S2_LINE = 5, + // + // LEVEL 2 ... + X_PPSR_L2_R_LINE = 6, + X_PPSR_L2_R1_LINE = 7, + X_PPSR_L2_R2_LINE = 8, + X_PPSR_L2_S_LINE = 9, + X_PPSR_L2_S1_LINE = 10, + X_PPSR_L2_S2_LINE = 11, + // + // LEVEL 3 ... + X_PPSR_L3_R_LINE = 12, + X_PPSR_L3_R1_LINE = 13, + X_PPSR_L3_R2_LINE = 14, + X_PPSR_L3_S_LINE = 15, + X_PPSR_L3_S1_LINE = 16, + X_PPSR_L3_S2_LINE = 17, + // + // LEVEL 4 ... + X_PPSR_L4_R_LINE = 18, + X_PPSR_L4_R1_LINE = 19, + X_PPSR_L4_R2_LINE = 20, + X_PPSR_L4_S_LINE = 21, + X_PPSR_L4_S1_LINE = 22, + X_PPSR_L4_S2_LINE = 23, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXPPSRHelper +{ + // +public: + // + // Properties ... + + // + // LEVEL 1 ... + double l1RBuffer[]; + double l1R1Buffer[]; + double l1R2Buffer[]; + double l1SBuffer[]; + double l1S1Buffer[]; + double l1S2Buffer[]; + + // + // LEVEL 2 ... + double l2RBuffer[]; + double l2R1Buffer[]; + double l2R2Buffer[]; + double l2SBuffer[]; + double l2S1Buffer[]; + double l2S2Buffer[]; + + // + // LEVEL 3 ... + double l3RBuffer[]; + double l3R1Buffer[]; + double l3R2Buffer[]; + double l3SBuffer[]; + double l3S1Buffer[]; + double l3S2Buffer[]; + + // + // LEVEL 4 ... + double l4RBuffer[]; + double l4R1Buffer[]; + double l4R2Buffer[]; + double l4SBuffer[]; + double l4S1Buffer[]; + double l4S2Buffer[]; + + // + // Constructor ... + void XSCXPPSRHelper() + { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXPPSRHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // LEVEL 1 ... + ENUM_X_PERIOD_METHOD l1Method = X_PERIOD_AUTO, + ENUM_TIMEFRAMES l1Period = NULL, + ENUM_SERIESMODE l1HHMode = MODE_HIGH, + ENUM_SERIESMODE l1LLMode = MODE_LOW, + // + // LEVEL 2 ... + ENUM_X_PERIOD_METHOD l2Method = X_PERIOD_AUTO, + ENUM_TIMEFRAMES l2Period = NULL, + ENUM_SERIESMODE l2HHMode = MODE_HIGH, + ENUM_SERIESMODE l2LLMode = MODE_LOW, + // + // LEVEL 3 ... + ENUM_X_PERIOD_METHOD l3Method = X_PERIOD_AUTO, + ENUM_TIMEFRAMES l3Period = NULL, + ENUM_SERIESMODE l3HHMode = MODE_HIGH, + ENUM_SERIESMODE l3LLMode = MODE_LOW, + // + // LEVEL 4 ... + ENUM_X_PERIOD_METHOD l4Method = X_PERIOD_AUTO, + ENUM_TIMEFRAMES l4Period = NULL, + ENUM_SERIESMODE l4HHMode = MODE_HIGH, + ENUM_SERIESMODE l4LLMode = MODE_LOW + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // LEVEL 1 ... + mL1Method = l1Method; + mL1Period = l1Period; + mL1HHMode = l1HHMode; + mL1LLMode = l1LLMode; + + // + // LEVEL 2 ... + mL2Method = l2Method; + mL2Period = l2Period; + mL2HHMode = l2HHMode; + mL2LLMode = l2LLMode; + + // + // LEVEL 3 ... + mL3Method = l3Method; + mL3Period = l3Period; + mL3HHMode = l3HHMode; + mL3LLMode = l3LLMode; + + // + // LEVEL 4 ... + mL4Method = l4Method; + mL4Period = l4Period; + mL4HHMode = l4HHMode; + mL4LLMode = l4LLMode; + + // + mTag = "XPPSR " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xppsr", + // + // Inputs ... + // + // LEVEL 1 ... + "", + mL1Method, + mL1Period, + mL1HHMode, + mL1LLMode, + // + // LEVEL 2 ... + "", + mL2Method, + mL2Period, + mL2HHMode, + mL2LLMode, + // + // LEVEL 3 ... + "", + mL3Method, + mL3Period, + mL3HHMode, + mL3LLMode, + // + // LEVEL 4 ... + "", + mL4Method, + mL4Period, + mL4HHMode, + mL4LLMode, + // + "", + "", + false, + false, + false, + false, + "", + false, + false, + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + // LEVEL 1 ... + ArraySetAsSeries(l1RBuffer, true); + ArraySetAsSeries(l1R1Buffer, true); + ArraySetAsSeries(l1R2Buffer, true); + ArraySetAsSeries(l1SBuffer, true); + ArraySetAsSeries(l1S1Buffer, true); + ArraySetAsSeries(l1S2Buffer, true); + + // + // LEVEL 2 ... + ArraySetAsSeries(l2RBuffer, true); + ArraySetAsSeries(l2R1Buffer, true); + ArraySetAsSeries(l2R2Buffer, true); + ArraySetAsSeries(l2SBuffer, true); + ArraySetAsSeries(l2S1Buffer, true); + ArraySetAsSeries(l2S2Buffer, true); + + // + // LEVEL 3 ... + ArraySetAsSeries(l3RBuffer, true); + ArraySetAsSeries(l3R1Buffer, true); + ArraySetAsSeries(l3R2Buffer, true); + ArraySetAsSeries(l3SBuffer, true); + ArraySetAsSeries(l3S1Buffer, true); + ArraySetAsSeries(l3S2Buffer, true); + + // + // LEVEL 4 ... + ArraySetAsSeries(l4RBuffer, true); + ArraySetAsSeries(l4R1Buffer, true); + ArraySetAsSeries(l4R2Buffer, true); + ArraySetAsSeries(l4SBuffer, true); + ArraySetAsSeries(l4S1Buffer, true); + ArraySetAsSeries(l4S2Buffer, true); + } + + // + // DeConstructor ... + void ~XSCXPPSRHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // LEVEL 1 ... + CopyBuffer( + mHandler, + X_PPSR_L1_R_LINE, + 0, + mNumberOfItemsReadPerTick, + l1RBuffer); + CopyBuffer( + mHandler, + X_PPSR_L1_R1_LINE, + 0, + mNumberOfItemsReadPerTick, + l1R1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L1_R2_LINE, + 0, + mNumberOfItemsReadPerTick, + l1R2Buffer); + CopyBuffer( + mHandler, + X_PPSR_L1_S_LINE, + 0, + mNumberOfItemsReadPerTick, + l1SBuffer); + CopyBuffer( + mHandler, + X_PPSR_L1_S1_LINE, + 0, + mNumberOfItemsReadPerTick, + l1S1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L1_S2_LINE, + 0, + mNumberOfItemsReadPerTick, + l1S2Buffer); + + // + // LEVEL 2 ... + CopyBuffer( + mHandler, + X_PPSR_L2_R_LINE, + 0, + mNumberOfItemsReadPerTick, + l2RBuffer); + CopyBuffer( + mHandler, + X_PPSR_L2_R1_LINE, + 0, + mNumberOfItemsReadPerTick, + l2R1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L2_R2_LINE, + 0, + mNumberOfItemsReadPerTick, + l2R2Buffer); + CopyBuffer( + mHandler, + X_PPSR_L2_S_LINE, + 0, + mNumberOfItemsReadPerTick, + l2SBuffer); + CopyBuffer( + mHandler, + X_PPSR_L2_S1_LINE, + 0, + mNumberOfItemsReadPerTick, + l2S1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L2_S2_LINE, + 0, + mNumberOfItemsReadPerTick, + l2S2Buffer); + + // + // LEVEL 3 ... + CopyBuffer( + mHandler, + X_PPSR_L3_R_LINE, + 0, + mNumberOfItemsReadPerTick, + l3RBuffer); + CopyBuffer( + mHandler, + X_PPSR_L3_R1_LINE, + 0, + mNumberOfItemsReadPerTick, + l3R1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L3_R2_LINE, + 0, + mNumberOfItemsReadPerTick, + l3R2Buffer); + CopyBuffer( + mHandler, + X_PPSR_L3_S_LINE, + 0, + mNumberOfItemsReadPerTick, + l3SBuffer); + CopyBuffer( + mHandler, + X_PPSR_L3_S1_LINE, + 0, + mNumberOfItemsReadPerTick, + l3S1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L3_S2_LINE, + 0, + mNumberOfItemsReadPerTick, + l3S2Buffer); + + // + // LEVEL 4 ... + CopyBuffer( + mHandler, + X_PPSR_L4_R_LINE, + 0, + mNumberOfItemsReadPerTick, + l4RBuffer); + CopyBuffer( + mHandler, + X_PPSR_L4_R1_LINE, + 0, + mNumberOfItemsReadPerTick, + l4R1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L4_R2_LINE, + 0, + mNumberOfItemsReadPerTick, + l4R2Buffer); + CopyBuffer( + mHandler, + X_PPSR_L4_S_LINE, + 0, + mNumberOfItemsReadPerTick, + l4SBuffer); + CopyBuffer( + mHandler, + X_PPSR_L4_S1_LINE, + 0, + mNumberOfItemsReadPerTick, + l4S1Buffer); + CopyBuffer( + mHandler, + X_PPSR_L4_S2_LINE, + 0, + mNumberOfItemsReadPerTick, + l4S2Buffer); + } + + // + // START Tools Functions ... + // + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // LEVEL 1 ... + ENUM_X_PERIOD_METHOD mL1Method; + ENUM_TIMEFRAMES mL1Period; + ENUM_SERIESMODE mL1HHMode; + ENUM_SERIESMODE mL1LLMode; + + // + // LEVEL 2 ... + ENUM_X_PERIOD_METHOD mL2Method; + ENUM_TIMEFRAMES mL2Period; + ENUM_SERIESMODE mL2HHMode; + ENUM_SERIESMODE mL2LLMode; + + // + // LEVEL 3 ... + ENUM_X_PERIOD_METHOD mL3Method; + ENUM_TIMEFRAMES mL3Period; + ENUM_SERIESMODE mL3HHMode; + ENUM_SERIESMODE mL3LLMode; + + // + // LEVEL 4 ... + ENUM_X_PERIOD_METHOD mL4Method; + ENUM_TIMEFRAMES mL4Period; + ENUM_SERIESMODE mL4HHMode; + ENUM_SERIESMODE mL4LLMode; + + // + string mTag; + + // + int mHandler; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(l1RBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xpv.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xpv.helper.mq5 new file mode 100644 index 0000000..d71d3da --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xpv.helper.mq5 @@ -0,0 +1,707 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPV Indicator Provider +// Description: Peaks and Vales ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XPV_BUFFERS +{ + // + // PEAKSANDVALES ... + X_PV_P_LINE = 0, + X_PV_V_LINE = 1, + // + // SUPPORTRESISTANCE ... + X_PV_R_LINE = 2, + X_PV_S_LINE = 4, + // + // SHORT ... + X_PV_SHH_LINE = 6, + X_PV_SLL_LINE = 7, + // + // MEDIUM ... + X_PV_MHH_LINE = 8, + X_PV_MLL_LINE = 9, + // + // LONG ... + X_PV_LHH_LINE = 10, + X_PV_LLL_LINE = 11, + // + // HIND ... + X_PV_HHH_LINE = 12, + X_PV_HLL_LINE = 13, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXPVHelper +{ + // +public: + // + // Properties ... + double pBuffer[]; + double vBuffer[]; + double rBuffer[]; + double sBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + + // + // Constructor ... + void XSCXPVHelper() + { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXPVHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // MARKET ... + int shortLength = 9, + int mediumLength = 17, + int longLength = 26, + int hindLength = 35, + // + // TREND ... + int numOfShoulder = 10, + // + // DETECTION ... + ENUM_SERIESMODE hhMode = MODE_HIGH, + ENUM_SERIESMODE llMode = MODE_LOW + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // MARKET ... + mShortLength = shortLength; + mMediumLength = mediumLength; + mLongLength = longLength; + mHindLength = hindLength; + + // + // TREND ... + mNumOfShoulder = numOfShoulder; + + // + // DETECTION ... + mHhMode = hhMode; + mLlMode = llMode; + + // + mTag = "XPV " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xpv", + // + // Inputs ... + // + // MARKET ... + "", + mShortLength, + mMediumLength, + mLongLength, + mHindLength, + // + // TREND ... + "", + mNumOfShoulder, + // + // DETECTION ... + "", + mHhMode, + mLlMode, + // + "", + false, + false, + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + // PEAKSANDVALES ... + ArraySetAsSeries(pBuffer, true); + ArraySetAsSeries(vBuffer, true); + // + // RESISTANCESUPPORT ... + ArraySetAsSeries(rBuffer, true); + ArraySetAsSeries(sBuffer, true); + // + // SHORT ... + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + // + // MEDIUM ... + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + // + // LONG ... + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + // + // HIND ... + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXPVHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // PEAKS ... + CopyBuffer( + mHandler, + X_PV_P_LINE, + 0, + mNumberOfItemsReadPerTick, + pBuffer); + + // + // VALES ... + CopyBuffer( + mHandler, + X_PV_V_LINE, + 0, + mNumberOfItemsReadPerTick, + vBuffer); + + // + // R ... + CopyBuffer( + mHandler, + X_PV_R_LINE, + 0, + mNumberOfItemsReadPerTick, + rBuffer); + + // + // S ... + CopyBuffer( + mHandler, + X_PV_S_LINE, + 0, + mNumberOfItemsReadPerTick, + sBuffer); + + // + // SHORT ... + + // + // HIGH ... + CopyBuffer( + mHandler, + X_PV_SHH_LINE, + 0, + mNumberOfItemsReadPerTick, + sHHBuffer); + + // + // LOW ... + CopyBuffer( + mHandler, + X_PV_SLL_LINE, + 0, + mNumberOfItemsReadPerTick, + sLLBuffer); + + // + // MEIUM ... + + // + // HIGH ... + CopyBuffer( + mHandler, + X_PV_MHH_LINE, + 0, + mNumberOfItemsReadPerTick, + mHHBuffer); + + // + // LOW ... + CopyBuffer( + mHandler, + X_PV_MLL_LINE, + 0, + mNumberOfItemsReadPerTick, + mLLBuffer); + + // + // LONG ... + + // + // HIGH ... + CopyBuffer( + mHandler, + X_PV_LHH_LINE, + 0, + mNumberOfItemsReadPerTick, + lHHBuffer); + + // + // LOW ... + CopyBuffer( + mHandler, + X_PV_LLL_LINE, + 0, + mNumberOfItemsReadPerTick, + lLLBuffer); + + // + // HIND ... + + // + // HIGH ... + CopyBuffer( + mHandler, + X_PV_HHH_LINE, + 0, + mNumberOfItemsReadPerTick, + hHHBuffer); + + // + // LOW ... + CopyBuffer( + mHandler, + X_PV_HLL_LINE, + 0, + mNumberOfItemsReadPerTick, + hLLBuffer); + } + + // + // START Tools Functions ... + // + + // + // Check isPeak ... + bool IsPeak(int bar_index) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = rBuffer[bar_index] == hHHBuffer[bar_index] && + hHHBuffer[bar_index] == lHHBuffer[bar_index] && + lHHBuffer[bar_index] == mHHBuffer[bar_index] && + mHHBuffer[bar_index] == sHHBuffer[bar_index]; + + // + return result; + } + + // + // Check isVale ... + bool IsVale(int bar_index) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = sBuffer[bar_index] == hLLBuffer[bar_index] && + hLLBuffer[bar_index] == lLLBuffer[bar_index] && + lLLBuffer[bar_index] == mLLBuffer[bar_index] && + mLLBuffer[bar_index] == sLLBuffer[bar_index]; + + // + return result; + } + + // + // Is Strong Support ... + bool IsStrongSupport(int bar_index) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 3)) + { + return result; + } + + // + result = + // + hLLBuffer[bar_index + 1] == hLLBuffer[bar_index + 2] && + hLLBuffer[bar_index + 2] == hLLBuffer[bar_index + 3] && + // + lLLBuffer[bar_index + 1] == lLLBuffer[bar_index + 2] && + lLLBuffer[bar_index + 2] == lLLBuffer[bar_index + 3] && + // + mLLBuffer[bar_index + 1] == mLLBuffer[bar_index + 2] && + mLLBuffer[bar_index + 2] == mLLBuffer[bar_index + 3] && + // + sLLBuffer[bar_index + 1] == sLLBuffer[bar_index + 2] && + sLLBuffer[bar_index + 2] == sLLBuffer[bar_index + 3] + // + ; + + // + return result; + } + + // + // Is Strong Resistance ... + bool IsStrongResistance(int bar_index) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 2)) + { + return result; + } + + // + result = + // + hHHBuffer[bar_index + 1] == hHHBuffer[bar_index + 2] && + hHHBuffer[bar_index + 2] == hHHBuffer[bar_index + 3] && + // + lHHBuffer[bar_index + 1] == lHHBuffer[bar_index + 2] && + lHHBuffer[bar_index + 2] == lHHBuffer[bar_index + 3] && + // + mHHBuffer[bar_index + 1] == mHHBuffer[bar_index + 2] && + mHHBuffer[bar_index + 2] == mHHBuffer[bar_index + 3] && + // + sHHBuffer[bar_index + 1] == sHHBuffer[bar_index + 2] && + sHHBuffer[bar_index + 2] == sHHBuffer[bar_index + 3] + // + ; + // + return result; + } + + // + // Find Last Strong Support ... + double GetLastStrongSupport( + int bar_index, // Bar Index ... + int length // LoopBack ... + ) + { + // + double result = 0; + + // + bool isBarIndexSupport = IsStrongSupport(bar_index); + if (isBarIndexSupport) + { + length += bar_index; + } + + // + if (!IsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (IsStrongSupport(i)) + { + // + result = sLLBuffer[i]; + break; + } + } + + // + return result; + } + + // + // Find Last Strong Resistance ... + double GetLastStrongResistance( + int bar_index, // Bar Index ... + int length // LoopBack ... + ) + { + // + double result = 0; + + // + bool isBarIndexResistance = IsStrongResistance(bar_index); + if (isBarIndexResistance) + { + length += bar_index; + } + + // + if (!IsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (IsStrongResistance(i)) + { + // + result = sHHBuffer[i]; + break; + } + } + + // + return result; + } + + // + // Find Strong Support Break Stop ... + bool IsSupportBreakedStop( + int bar_index, // Bar Index ... + int length // LoopBack ... + ) + { + // + bool result = false; + + // + bool isBaIndexSupport = IsStrongSupport(bar_index); + if (isBaIndexSupport) + { + return result; + } + + // + if (!IsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + bool isAllStrongSupport = true; + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (!IsStrongSupport(i) && isAllStrongSupport) + { + // + isAllStrongSupport = false; + break; + } + } + + // + result = !isBaIndexSupport && isAllStrongSupport; + + // + return result; + } + + // + // Find Strong Resistance Break Stop ... + bool IsResistanceBreakedStop( + int bar_index, // Bar Index ... + int length // LoopBack ... + ) + { + // + bool result = false; + + // + bool isBaIndexResistance = IsStrongResistance(bar_index); + if (isBaIndexResistance) + { + return result; + } + + // + if (!IsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + bool isAllStrongResistance = true; + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (!IsStrongResistance(i) && isAllStrongResistance) + { + // + isAllStrongResistance = false; + break; + } + } + + // + result = !isBaIndexResistance && isAllStrongResistance; + + // + return result; + } + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // MARKET ... + int mShortLength; + int mMediumLength; + int mLongLength; + int mHindLength; + + // + // TREND ... + int mNumOfShoulder; + + // + // DETECTION ... + ENUM_SERIESMODE mHhMode; + ENUM_SERIESMODE mLlMode; + + // + string mTag; + + // + int mHandler; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(rBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xsslc.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xsslc.helper.mq5 new file mode 100644 index 0000000..583dddd --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xsslc.helper.mq5 @@ -0,0 +1,332 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XSSLC Indicator Provider +// Description: SSL Channel ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XSSLC_BUFFERS +{ + // + X_SSLC_UP_LINE = 0, + X_SSLC_DOWN_LINE = 1, + X_SSLC_UP_MA_LINE = 2, + X_SSLC_DOWN_MA_LINE = 3, + X_SSLC_KPI_LINE = 4, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXSSLCHelper +{ + // +public: + // + // Properties ... + double upBuffer[]; + double downBuffer[]; + double kpiBuffer[]; + + // + // Constructor ... + void XSCXSSLCHelper() + { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXSSLCHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // MARKET ... + int length = 10, // Length + // + // CALCULATION ... + ENUM_MA_METHOD method = MODE_SMA, // Method + ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH, // Up Applied To + ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW // Down Applied To + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // MARKET ... + mLength = length; + + // + // CALCULATION ... + mMethod = method; + mUpAppliedTo = upAppliedTo; + mDownAppliedTo = downAppliedTo; + + // + mTag = "XSSLC " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xsslc", + // + // Inputs ... + // + // MARKET ... + "", + mLength, + // + // CALCULATION ... + "", + mMethod, + mUpAppliedTo, + mDownAppliedTo, + // + // PRESENTATION ... + "", + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(upBuffer, true); + ArraySetAsSeries(downBuffer, true); + ArraySetAsSeries(kpiBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXSSLCHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // UP ... + CopyBuffer( + mHandler, + X_SSLC_UP_LINE, + 0, + mNumberOfItemsReadPerTick, + upBuffer); + + // + // DOWN ... + CopyBuffer( + mHandler, + X_SSLC_DOWN_LINE, + 0, + mNumberOfItemsReadPerTick, + downBuffer); + + // + // KPI ... + CopyBuffer( + mHandler, + X_SSLC_KPI_LINE, + 0, + mNumberOfItemsReadPerTick, + kpiBuffer); + } + + // + // START Tools Functions ... + // + + // + // Check Up Buffer Crossed Over Down ... + bool IsUpCrossedOverDown( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + upBuffer[bar_index] > downBuffer[bar_index] && + upBuffer[bar_index + 1] <= downBuffer[bar_index + 1] + // + ; + + // + return result; + } + + // + // Check Up Buffer Crossed Under Down ... + bool IsUpCrossedUnderDown( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + upBuffer[bar_index] < downBuffer[bar_index] && + upBuffer[bar_index + 1] >= downBuffer[bar_index + 1] + // + ; + + // + return result; + } + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + // MARKET ... + + // + // Length ... + int mLength; + + // + // CALCULATION ... + + // + // Method ... + ENUM_MA_METHOD mMethod; + + // + // Up Applied To + ENUM_APPLIED_PRICE mUpAppliedTo; + + // + // Down Applied To + ENUM_APPLIED_PRICE mDownAppliedTo; + + // + string mTag; + + // + int mHandler; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(upBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xtrnd.helper.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xtrnd.helper.mq5 new file mode 100644 index 0000000..c4ecfd2 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Helpers/x-saherelm.x121.xtrnd.helper.mq5 @@ -0,0 +1,469 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XTRND Indicator Provider +// Description: Trend Finder ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// XPeaksAndVales Exported Buffers ... +enum ENUM_X_XTRND_BUFFERS +{ + // + X_TRND_UP_LINE = 0, + X_TRND_UP_STATE_LINE = 1, + // + X_TRND_DOWN_LINE = 2, + X_TRND_DOWN_STATE_LINE = 3, +}; + +// +// Trend State at unique Bar ... +enum ENUM_X_XTRND_STATE +{ + X_TRND_STATE_RANGE = 0, + X_TRND_STATE_CONSOLIDATION = 1, + X_TRND_STATE_UP = 2, + X_TRND_STATE_DOWN = 3, +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +class XSCXTRNDHelper +{ + // +public: + // + // Properties ... + double upBuffer[]; + double upStateBuffer[]; + double downBuffer[]; + double downStateBuffer[]; + + // + // Constructor ... + void XSCXTRNDHelper() + { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCXTRNDHelper( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period, + // + // Buffer Reading ... + int numberOfItemsReadPerTick = 52, + // + // MARKET ... + int cycleLength = 2, // Cycle Length to Check + int numberOfVerifications = 2, // Number of Verifications + // + // CALCULATION ... + ENUM_SERIESMODE hhMode = MODE_HIGH, // Detect Up + ENUM_SERIESMODE llMode = MODE_LOW // Detect Low + // + ) + { + // + // Setting Requirements ... + + // + // Symbol ... + mSymbol = symbol; + + // + // Period ... + mPeriod = period; + + // + // Number of Reading Buffer Items per Tick ... + mNumberOfItemsReadPerTick = numberOfItemsReadPerTick; + + // + // MARKET ... + mCycleLength = cycleLength; + mNumberOfVerifications = numberOfVerifications; + + // + // CALCULATIONS ... + mHHMode = hhMode; + mLLMode = llMode; + + // + mTag = "XTRND " + mSymbol + ", " + ToString(mPeriod); + + // + // Initial Handler ... + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xtrnd", + // + // Inputs ... + // + // MARKET ... + "", + mCycleLength, + mNumberOfVerifications, + // + // CALCULATIONS ... + "", + mHHMode, + mLLMode, + // + // PRESENTATION ... + "", + false, + false + // + ); + if (mHandler == INVALID_HANDLE) + { + LogMessage("failed to Initialize Indicator: " + (string)GetLastError()); + } + + // + ArraySetAsSeries(upBuffer, true); + ArraySetAsSeries(upStateBuffer, true); + ArraySetAsSeries(downBuffer, true); + ArraySetAsSeries(downStateBuffer, true); + } + + // + // DeConstructor ... + void ~XSCXTRNDHelper() + { + // + // Release Indicators ... + IndicatorRelease(mHandler); + } + + // + // Reading Buffers ... + void ReadBuffers() + { + // + // UP ... + CopyBuffer( + mHandler, + X_TRND_UP_LINE, + 0, + mNumberOfItemsReadPerTick, + upBuffer); + + // + // UP STATE ... + CopyBuffer( + mHandler, + X_TRND_UP_STATE_LINE, + 0, + mNumberOfItemsReadPerTick, + upStateBuffer); + + // + // DOWN ... + CopyBuffer( + mHandler, + X_TRND_DOWN_LINE, + 0, + mNumberOfItemsReadPerTick, + downBuffer); + + // + // DOWN STATE ... + CopyBuffer( + mHandler, + X_TRND_DOWN_STATE_LINE, + 0, + mNumberOfItemsReadPerTick, + downStateBuffer); + } + + // + // START Tools Functions ... + // + + // + // Detect Trend Up ... + bool IsTrendBullish( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + upStateBuffer[bar_index] == X_TRND_STATE_UP && + downStateBuffer[bar_index] == X_TRND_STATE_UP + // + ; + + // + return result; + } + + // + // Detect Trend Switched Up ... + bool IsTrendSwitchedBullish( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + IsTrendBullish(bar_index) && + !IsTrendBullish(bar_index + 1) + // + ; + + // + return result; + } + + // + // Detect Trend Down ... + bool IsTrendBearish( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + upStateBuffer[bar_index] == X_TRND_STATE_DOWN && + downStateBuffer[bar_index] == X_TRND_STATE_DOWN + // + ; + + // + return result; + } + + // + // Detect Trend Switched Down ... + bool IsTrendSwitchedBearish( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + IsTrendBearish(bar_index) && + !IsTrendBearish(bar_index + 1) + // + ; + + // + return result; + } + + // + // Detect Trend Consolidation ... + bool IsTrendConsolidation( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index)) + { + return result; + } + + // + result = + // + (upStateBuffer[bar_index] == X_TRND_STATE_RANGE || + upStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + && + // + (downStateBuffer[bar_index] == X_TRND_STATE_RANGE || + downStateBuffer[bar_index] == X_TRND_STATE_CONSOLIDATION) + // + ; + + // + return result; + } + + // + // Detect Trend Switched Consolidation ... + bool IsTrendSwitchedConsolidation( + int bar_index // Bar Index ... + ) + { + // + bool result = false; + + // + if (!IsValidArraySize(bar_index + 1)) + { + return result; + } + + // + result = + // + IsTrendConsolidation(bar_index) && + !IsTrendConsolidation(bar_index + 1) + // + ; + + // + return result; + } + + // + // END Tools Functions ... + // + + // +protected: + // +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Buffer Reading ... + int mNumberOfItemsReadPerTick; + + // + string mTag; + + // + int mHandler; + + // + // INPUTS ... + + // + // MARKET ... + + // + // Cycle Length to Check ... + int mCycleLength; + + // + // Number of Verifications ... + int mNumberOfVerifications; + + // + // CALCULATIONS ... + + // + // Detect Up ... + ENUM_SERIESMODE mHHMode; + + // + // Detect Low ... + ENUM_SERIESMODE mLLMode; + + // + bool IsValidArraySize(int bar_index) + { + // + bool result = false; + + // + if (bar_index < 0) + { + return result; + } + + // + int rCount = ArraySize(upBuffer); + result = rCount > bar_index + 1; + + // + return result; + } +}; \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xama.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xama.mq5 new file mode 100644 index 0000000..ce62a15 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xama.mq5 @@ -0,0 +1,367 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAMA Indicator +// --------------------------------------------- +// Name: XAMA +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XAMA Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XAMA" + +// +// XAMA Indicator States ... +enum ENUM_X_XAMA_STATES +{ + X_XAMA_BULLISH = 1, + X_XAMA_BEARISH = -1, + X_XAMA_NEUTURAL = 0, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int length = 52; // Period +input int fastEMA = 2; // Fast EMA Period +input int slowEMA = 30; // Slow EMA Period +input int maShift = 0; // Shift +input ENUM_APPLIED_PRICE appliedTo = PRICE_LOW; // Applied To + +// +input group "Presentation"; +input bool showLine = true; // Show Line + +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 1 + +// +// maBuffer ... +#define maBufferIndex 0 +#define maColorBufferIndex 1 +#define stateBufferIndex 2 + +double maBuffer[]; +double maColorBuffer[]; +double stateBuffer[]; + +#property indicator_label1 "XAMA" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int maHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // Initializing MA Handler ... + maHandler = iAMA( + _Symbol, + _Period, + length, + fastEMA, + slowEMA, + maShift, + appliedTo); + if (maHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Ma Handler ..."; + LogMessage(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(maHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(fastEMA, slowEMA); + maxLength = MathMax(maxLength, length); + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showLine ? DRAW_COLOR_LINE : DRAW_NONE; + + // + string maBufferLabel = "XAMA " + "(" + (string)length + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showLine); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + + // + // State Buffer ... + ArraySetAsSeries(stateBuffer, true); + SetIndexBuffer(stateBufferIndex, stateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "(", length, ")"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Define State Value ... + // lineColorIndex == 0 => Bullish => 1; + // lineColorIndex == 1 => Neutural => 0; + // lineColorIndex == 2 => Bearish => -1; + double stateValue = + lineColorIndex == 0 ? X_XAMA_BULLISH : lineColorIndex == 2 ? X_XAMA_BEARISH + : X_XAMA_NEUTURAL; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; + + // + // Set State Buffer Value ... + stateBuffer[bar_index] = stateValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xatrsl.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xatrsl.mq5 new file mode 100644 index 0000000..e58e7da --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xatrsl.mq5 @@ -0,0 +1,765 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_ATRSL ATR Indicator +// --------------------------------------------------- +// Name: X121_ATRSL +// Description: ATR StopLoss Finer +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_ATRSL Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_ATRSL" + +// +// Available Smoothing Methods ... +enum X_XATRSL_SMOOTHING_METHOD +{ + X_ATRSL_SMOOTHING_RMA = 0, // RMA + X_ATRSL_SMOOTHING_SMA = 1, // SMA + X_ATRSL_SMOOTHING_EMA = 2, // EMA + X_ATRSL_SMOOTHING_WMA = 3, // WMA +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 14; // Length +input double step = 0.02; // Increment Step +input double maximum = 0.2; // Maximum +input ENUM_APPLIED_PRICE highAppliedTo = PRICE_HIGH; // High Line Applied To +input ENUM_APPLIED_PRICE lowAppliedTo = PRICE_LOW; // Low Line Applied To + +// +input group "Presentation"; +input bool showHigh = true; // Show High +input bool showLow = true; // Show Low +input bool showSar = true; // Show PSar + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 3 + +// +// PLOTTED Buffers ... + +// +// HIGH ... +#define highBufferIndex 0 +double highBuffer[]; + +// +#property indicator_label1 "X121_ATRSL H" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLightGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// LOW ... +#define lowBufferIndex 1 +double lowBuffer[]; + +// +#property indicator_label2 "X121_ATRSL L" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrLightGray +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// SAR ... +#define sarBufferIndex 2 +double sarBuffer[]; + +// +#property indicator_label3 "X121_ATRSL SAR" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +// DATA Buffers ... + +// +// RMA ... +#define rmaBufferIndex 3 +double rmaBuffer[]; + +// +// WMA ... +#define wmaBufferIndex 4 +double wmaBuffer[]; + +// +// WMA CALCULATIONS ... + +// +// MA 1 ... +#define ma1BufferIndex 5 +double ma1Buffer[]; + +// +// MA P ... +#define maPBufferIndex 6 +double maPBuffer[]; + +// +// EMA P ... +#define emaPBufferIndex 7 +double emaPBuffer[]; + +// +// ATR ... +#define atrBufferIndex 8 +double atrBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +double smoothFactor; + +// +// WMA ... +int ma1Handler = INVALID_HANDLE; +int maPHandler = INVALID_HANDLE; +ENUM_APPLIED_PRICE wmaAppliedTo = PRICE_CLOSE; + +// +// EMA ... +int emaPHandler = INVALID_HANDLE; + +// +// ATR ... +int atrHandler = INVALID_HANDLE; + +// +// SAR ... +int sarHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Calculate RMA and WMA Smooth Factoir ... + smoothFactor = 1.0 / length; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Initialize Handlers ... + if (!InitialHandlers()) + { + return INIT_FAILED; + } + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(sarHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(ma1Handler); + IndicatorRelease(maPHandler); + IndicatorRelease(emaPHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int sarCalculatedBars = BarsCalculated(sarHandler); + int atrCalculatedBars = BarsCalculated(atrHandler); + int ma1CalculatedBars = BarsCalculated(ma1Handler); + int maPCalculatedBars = BarsCalculated(maPHandler); + int emaPCalculatedBars = BarsCalculated(emaPHandler); + if (sarCalculatedBars < maxLength || + atrCalculatedBars < maxLength || + ma1CalculatedBars < maxLength || + maPCalculatedBars < maxLength || + emaPCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedSars = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, limit, atrBuffer); + int copiedMa1s = CopyBuffer(ma1Handler, 0, 0, limit, ma1Buffer); + int copiedMaPs = CopyBuffer(maPHandler, 0, 0, limit, maPBuffer); + int copiedEMaPs = CopyBuffer(emaPHandler, 0, 0, limit, emaPBuffer); + if (copiedSars <= 0 || + copiedAtrs <= 0 || + copiedMa1s <= 0 || + copiedMaPs <= 0 || + copiedEMaPs <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Determines First Calculation ... + bool isFirstBar = ((limit == rates_total) && + i == rates_total - 1); + + // + CalculateBuffers( + i, + isFirstBar, + limit, + rates_total, + prev_calculated, + open, + high, + low, + close + // + ); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Inputs ... + (length > 2 && + step > 0 && + maximum > step) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Max ... + result = MathMax(result, length); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // HIGH ... + ENUM_DRAW_TYPE highDrawType = showHigh ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + PlotIndexSetDouble(highBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(highBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(highBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(highBufferIndex, PLOT_DRAW_TYPE, highDrawType); + + // + // LOW ... + ENUM_DRAW_TYPE lowDrawType = showLow ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); + PlotIndexSetDouble(lowBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(lowBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(lowBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lowBufferIndex, PLOT_DRAW_TYPE, lowDrawType); + + // + // SAR ... + ENUM_DRAW_TYPE sarDrawType = showSar ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + PlotIndexSetDouble(sarBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(sarBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(sarBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(sarBufferIndex, PLOT_DRAW_TYPE, sarDrawType); + + // + // DATA Buffers ... + + // + // RMA ... + ArraySetAsSeries(rmaBuffer, true); + SetIndexBuffer(rmaBufferIndex, rmaBuffer, INDICATOR_CALCULATIONS); + + // + // MA 1 ... + ArraySetAsSeries(ma1Buffer, true); + SetIndexBuffer(ma1BufferIndex, ma1Buffer, INDICATOR_CALCULATIONS); + + // + // MA P ... + ArraySetAsSeries(maPBuffer, true); + SetIndexBuffer(maPBufferIndex, maPBuffer, INDICATOR_CALCULATIONS); + + // + // WMA ... + ArraySetAsSeries(wmaBuffer, true); + SetIndexBuffer(wmaBufferIndex, wmaBuffer, INDICATOR_DATA); + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); +} + +// +// Initialize WMA Required Handlers ... +bool InitialHandlers() +{ + // + bool result = false; + + // + // MA 1 ... + ma1Handler = iMA( + _Symbol, + _Period, + 1, // Lenght of MA 1 ... + 0, + MODE_SMA, + wmaAppliedTo); + + // + // MA P ... + maPHandler = iMA( + _Symbol, + _Period, + length, + 0, + MODE_SMA, + wmaAppliedTo); + + // + // EMA P ... + emaPHandler = iMA( + _Symbol, + _Period, + length, + 0, + MODE_EMA, + wmaAppliedTo); + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + length); + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + step, + maximum); + + // + result = + // + sarHandler != INVALID_HANDLE && + atrHandler != INVALID_HANDLE && + ma1Handler != INVALID_HANDLE && + maPHandler != INVALID_HANDLE && + emaPHandler != INVALID_HANDLE + // + ; + + // + // Log Error Message if Initialization Failed ... + if (!result) + { + LogMessage("Error in Initializing Indicator ..."); + } + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + bool isFirstBar, // Determines First Bar + const int limit, // Limit Of Calculations + const int ratesTotal, // Total Rates + const int prevCalculated, // Prev Calculated Bars + const double &open[], // Open Price Series + const double &high[], // High Price Series + const double &low[], // Low Price Series + const double &close[] // Close Price Series +) +{ + // + // RMA Calculation ... + + // + double closeValue = close[bar_index]; + double prevRMAValue = isFirstBar + ? closeValue + : rmaBuffer[bar_index + 1]; + + // + double rmaValue = (closeValue * smoothFactor) + prevRMAValue * (1.0 - smoothFactor); + + // + rmaBuffer[bar_index] = rmaValue; + + // + // WMA Calculations ... + + // + double maPValue = maPBuffer[bar_index]; + double ma1Value = ma1Buffer[bar_index]; + + // + double wmaValue; + if (isFirstBar) + { + wmaValue = maPValue; + } + else + { + wmaValue = (ma1Value - wmaBuffer[bar_index + 1]) * smoothFactor + wmaBuffer[bar_index + 1]; + } + + // + wmaBuffer[bar_index] = wmaValue; + + // + // CALCULATE Buffers ... + + // + double atrValue = atrBuffer[bar_index]; + double highSourcePrice = GetSourcePrice( + bar_index, + highAppliedTo, + open, + high, + low, + close); + double lowSourcePrice = GetSourcePrice( + bar_index, + lowAppliedTo, + open, + high, + low, + close); + + // + // Retrieve SMoothing Value ... + // double smoothingValue = GetSmoothedValue(bar_index); + + // + double smoothedATR = atrValue; + + // + // HIGH ... + double highValue = highSourcePrice + smoothedATR; + highBuffer[bar_index] = highValue; + + // + // LOW ... + double lowValue = lowSourcePrice - smoothedATR; + lowBuffer[bar_index] = lowValue; +} + +// +// Retrieve Smoothed Value based on User Choice ... +double GetSmoothedValue( + int bar_index // Bar Index +) +{ + // + double result = EMPTY_VALUE; + + // + // switch (smoothingMethod) + // { + // // + // // RMA ... + // case X_ATRSL_SMOOTHING_RMA: + // result = rmaBuffer[bar_index]; + // break; + + // // + // // WMA ... + // case X_ATRSL_SMOOTHING_WMA: + // result = wmaBuffer[bar_index]; + // break; + + // // + // // EMA ... + // case X_ATRSL_SMOOTHING_EMA: + // result = emaPBuffer[bar_index]; + // break; + + // // + // // SMA ... + // case X_ATRSL_SMOOTHING_SMA: + // result = maPBuffer[bar_index]; + // break; + + // // + // default: + // result = maPBuffer[bar_index]; + // break; + // } + + // + return result; +} + +// +// Retrive Which Price Selected By User as Source ... +double GetSourcePrice( + int bar_index, // BarIndex + ENUM_APPLIED_PRICE appliedPrice, // Selected Price Source + const double &open[], // Open Price Series + const double &high[], // High Price Series + const double &low[], // Low Price Series + const double &close[] // Close Price Series +) +{ + // + double result = EMPTY_VALUE; + + // + switch (appliedPrice) + { + // + // OPEN ... + case PRICE_OPEN: + result = open[bar_index]; + break; + + // + // HIGH ... + case PRICE_HIGH: + result = high[bar_index]; + break; + + // + // LOW ... + case PRICE_LOW: + result = low[bar_index]; + break; + + // + // CLOSE ... + default: + case PRICE_CLOSE: + result = close[bar_index]; + break; + } + + // + return result; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xcclear.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xcclear.mq5 new file mode 100644 index 0000000..6f318e0 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xcclear.mq5 @@ -0,0 +1,481 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_CC Candle Styles +// --------------------------------------------------- +// Name: X121_CC +// Description: Candle Styles ... +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_CC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_CC" + +// +// Holds an SnapShot of Charts Configuration ... +struct XChartStyle +{ + // + // chart's ID ... + long chartId; + // + // chart's mode ... + ENUM_CHART_MODE mode; + // + // show bid line ... + bool showBidLine; + // + // show ask line ... + bool showAskLine; + // + // show grids on chart ... + bool showGrid; + // + // show volumes ... + bool showVolumes; + // + // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ... + bool showTradeLevels; + // + // chart autoscroll ... + bool autoScroll; + // + // chart quick navigation state ... + bool quickNavigation; + // + // chart's foreground color ... + color foreGroundColor; + // + // chart's background color ... + color backGroundColor; + // + // Up Color ... + color upColor; + // + // Down Color ... + color downColor; + // + // Bullish color ... + color bullishColor; + // + // Bearish color ... + color bearishColor; + // + // grid color ... + color gridColor; + // + // bid line color ... + color bidLineColor; + // + // ask line color ... + color askLineColor; + // + // line mode and doji candlestick color ... + color lineColor; + // + // Color of stop order levels (Stop Loss and Take Profit) ... + color stopColor; + // + // volumes color ... + color volumesColor; +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Chart Style"; +input color mUpColor = clrLime; // Up Color +input color mDownColor = clrRed; // Down Color +input color mLineColor = clrLime; // Line mode and Doji candlestick Color +input color mBearishColor = clrRed; // Bullish Color +input color mBullishColor = clrLime; // Bearish Color +input color mVolumesColor = clrGreen; // Volumes Color + +// +input group "Presentation"; +input bool showCandles = false; // Show Candles + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XChartStyle chartStyle; +XChartStyle clearStyle; +bool hasChartConfig = false; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Apply Chart Style ... + ApplyCustomChartStyle(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + RemoveDraws(drawPrefix); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// Apply Custom Chart Style ... +void ApplyCustomChartStyle() +{ + // + // Read Prev Applied Chart Style ans Store it ... + if (!hasChartConfig) + { + // + // Read Current Chart Config and Store it ... + ReadChartStyle(); + + // + // After Reading Current Chart Style ... + // we have to Save Configs and Change Styles ... + clearStyle = chartStyle; + + // + clearStyle.upColor = CLR_NONE; + clearStyle.downColor = CLR_NONE; + clearStyle.lineColor = CLR_NONE; + clearStyle.volumesColor = CLR_NONE; + clearStyle.bullishColor = CLR_NONE; + clearStyle.bearishColor = CLR_NONE; + } + + // + // Decide to Show or not Candles based on User Input ... + if (showCandles) + { + SetChartStyle(chartStyle); + } + else + { + SetChartStyle(clearStyle); + } +} + +// +// Read Previous Chart Style ... +void ReadChartStyle() +{ + // + if (hasChartConfig) + { + return; + } + + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + chartStyle.chartId = chartId; + + // + // Retrieve Chart Mode ... + chartStyle.mode = (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); + + // + chartStyle.showBidLine = (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); + chartStyle.showAskLine = (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); + chartStyle.showGrid = (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); + chartStyle.showVolumes = (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); + chartStyle.showTradeLevels = (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); + chartStyle.autoScroll = (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); + chartStyle.quickNavigation = (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); + + // + chartStyle.foreGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); + chartStyle.backGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); + chartStyle.upColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); + chartStyle.downColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); + chartStyle.bullishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); + chartStyle.bearishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); + chartStyle.gridColor = (color)ChartGetInteger(chartId, CHART_COLOR_GRID); + chartStyle.bidLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_BID); + chartStyle.askLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_ASK); + chartStyle.stopColor = (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); + chartStyle.lineColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); + chartStyle.volumesColor = (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); + + // + chartStyle.upColor = mUpColor; + chartStyle.downColor = mDownColor; + chartStyle.lineColor = mLineColor; + chartStyle.bearishColor = mBearishColor; + chartStyle.bullishColor = mBullishColor; + chartStyle.volumesColor = mVolumesColor; +} + +// +// Set Chart Style ... +void SetChartStyle( + XChartStyle &mChartStyle // Chart Style to Apply +) +{ + // + ApplyChartStyle( + mChartStyle.chartId, + mChartStyle.mode, + mChartStyle.showBidLine, + mChartStyle.showAskLine, + mChartStyle.showGrid, + mChartStyle.showVolumes, + mChartStyle.showTradeLevels, + mChartStyle.autoScroll, + mChartStyle.quickNavigation, + mChartStyle.foreGroundColor, + mChartStyle.backGroundColor, + mChartStyle.upColor, + mChartStyle.downColor, + mChartStyle.bullishColor, + mChartStyle.bearishColor, + mChartStyle.gridColor, + mChartStyle.bidLineColor, + mChartStyle.askLineColor, + mChartStyle.lineColor, + mChartStyle.stopColor, + mChartStyle.volumesColor); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xche.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xche.mq5 new file mode 100644 index 0000000..92ea4f1 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xche.mq5 @@ -0,0 +1,629 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHE Indicator +// --------------------------------------------- +// Name: XCHE +// Description: Hull Trend Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XHull Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "XCHE" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 35; // Length +input int loopback = 26; // Loopback +input double multiplier1 = 3.0; // 1st Multiplier +input double multiplier2 = 3.5; // 2nd Multiplier + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Zone Applied to +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Zone Applied to + +// +input group "Presentation"; +input bool showLongExit1Line = true; // Show 1st Long Exit +input bool showShortExit1Line = true; // Show 1st Short Exit +input bool showLongExit2Line = true; // Show 2st Long Exit +input bool showShortExit2Line = true; // Show 2st Short Exit + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Long Exit 1 ... +#define longExit1BufferIndex 0 +double longExit1Buffer[]; + +// +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_DOT + +// +// Short Exit 1 ... +#define shortExit1BufferIndex 1 +double shortExit1Buffer[]; + +// +#property indicator_type2 DRAW_LINE +#property indicator_style2 STYLE_DOT +#property indicator_color2 clrRed + +// +// Long Exit 2 ... +#define longExit2BufferIndex 2 +double longExit2Buffer[]; + +// +#property indicator_type3 DRAW_LINE +#property indicator_style2 STYLE_DOT +#property indicator_color3 clrAqua + +// +// Short Exit 2 ... +#define shortExit2BufferIndex 3 +double shortExit2Buffer[]; + +// +#property indicator_type4 DRAW_LINE +#property indicator_style2 STYLE_DOT +#property indicator_color4 clrMagenta + +// +// START Arrows ... + +// +// Long Exit 1 Start ... +#define longExit1StartBufferIndex 4 +double longExit1StartBuffer[]; + +// +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrLime + +// +// Short Exit 1 Start ... +#define shortExit1StartBufferIndex 5 +double shortExit1StartBuffer[]; + +// +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrRed + +// +// Long Exit 2 Start ... +#define longExit2StartBufferIndex 6 +double longExit2StartBuffer[]; + +// +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrAqua + +// +// Short Exit 2 Start ... +#define shortExit2StartBufferIndex 7 +double shortExit2StartBuffer[]; + +// +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrMagenta + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// Working Array ... +double work[][6]; +#define hi1Idx 0 +#define lo1Idx 1 +#define hi2Idx 2 +#define lo2Idx 3 +#define trend1Idx 4 +#define trend2Idx 5 + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + if (Bars(_Symbol, _Period) < rates_total) + { + return (prev_calculated); + } + + // + if (ArrayRange(work, 0) != rates_total) + { + ArrayResize(work, rates_total); + } + + // + // this counts Available Bars ... + int limit; + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + low, + close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + length >= 9 && + loopback >= 0; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(length, loopback); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + uint arrowCode = 159; + + // + // LEVEL 1 ... + + // + // Long Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE longExit1DrawType = showLongExit1Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE longExit1StartDrawType = showLongExit1Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(longExit1BufferIndex, longExit1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit1BufferIndex, PLOT_SHOW_DATA, showLongExit1Line); + PlotIndexSetInteger(longExit1BufferIndex, PLOT_DRAW_TYPE, longExit1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(longExit1StartBufferIndex, longExit1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_DRAW_TYPE, longExit1StartDrawType); + + // + // Short Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE shortExit1DrawType = showShortExit1Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE shortExit1StartDrawType = showShortExit1Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(shortExit1BufferIndex, shortExit1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit1BufferIndex, PLOT_SHOW_DATA, showShortExit1Line); + PlotIndexSetInteger(shortExit1BufferIndex, PLOT_DRAW_TYPE, shortExit1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(shortExit1StartBufferIndex, shortExit1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_DRAW_TYPE, shortExit1StartDrawType); + + // + // LEVEL 2 ... + + // + // Long Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE longExit2DrawType = showLongExit2Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE longExit2StartDrawType = showLongExit2Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(longExit2BufferIndex, longExit2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit2BufferIndex, PLOT_SHOW_DATA, showLongExit2Line); + PlotIndexSetInteger(longExit2BufferIndex, PLOT_DRAW_TYPE, longExit2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(longExit2StartBufferIndex, longExit2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_DRAW_TYPE, longExit2StartDrawType); + + // + // Short Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE shortExit2DrawType = showShortExit2Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE shortExit2StartDrawType = showShortExit2Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(shortExit2BufferIndex, shortExit2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit2BufferIndex, PLOT_SHOW_DATA, showShortExit2Line); + PlotIndexSetInteger(shortExit2BufferIndex, PLOT_DRAW_TYPE, shortExit2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(shortExit2StartBufferIndex, shortExit2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_DRAW_TYPE, shortExit2StartDrawType); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int prevCalculated, // Previous Calculated + int ratesTotal, // Total Rates + const double &open[], // Rates Open ... + const double &high[], // Rates High ... + const double &low[], // Rates Low ... + const double &close[] // Rates Close ... +) +{ + // + // Cleanup Buffers ... + longExit1Buffer[bar_index] = longExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index] = shortExit1StartBuffer[bar_index] = EMPTY_VALUE; + longExit2Buffer[bar_index] = longExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index] = shortExit2StartBuffer[bar_index] = EMPTY_VALUE; + + // + int start = MathMax(bar_index - loopback, 0); + + // + // Calculate ATR Value ... + double atrValue = 0; + for (int k = 1; k <= length && (bar_index - k - 1) >= 0; k++) + { + // + atrValue += MathMax(high[bar_index - k], close[MathMax(bar_index - k - 1, 0)]) - + MathMin(low[bar_index - k], close[MathMax(bar_index - k - 1, 0)]); + } + atrValue /= (double)length; + + // + // Retrieve Highest High and Lowest Lows ... + double loopbackMax = high[ArrayMaximum(high, start, loopback)]; + double loopbackMin = low[ArrayMinimum(low, start, loopback)]; + + // + // Fill Multi Dimesional Working Array ... + work[bar_index][hi1Idx] = loopbackMax - multiplier1 * atrValue; + work[bar_index][lo1Idx] = loopbackMin + multiplier1 * atrValue; + work[bar_index][hi2Idx] = loopbackMax - multiplier2 * atrValue; + work[bar_index][lo2Idx] = loopbackMin + multiplier2 * atrValue; + work[bar_index][trend1Idx] = (bar_index > 0) ? work[bar_index - 1][trend1Idx] : 0; + work[bar_index][trend2Idx] = (bar_index > 0) ? work[bar_index - 1][trend2Idx] : 0; + + // + if (bar_index > 0) + { + // + // Calculate Trends ... + if (close[bar_index] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][trend1Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][trend1Idx] = -1; + } + + // + if (close[bar_index] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][trend2Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][trend2Idx] = -1; + } + + // + // Calculate Exit Values ... + + // + // Exit 1 ... + + // + // Long ... + if (multiplier1 > 0 && work[bar_index][trend1Idx] == 1) + { + // + if (work[bar_index][hi1Idx] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][hi1Idx] = work[bar_index - 1][hi1Idx]; + } + + // + longExit1Buffer[bar_index] = work[bar_index][hi1Idx]; + + // + if (longExit1Buffer[bar_index - 1] == EMPTY_VALUE) + { + longExit1StartBuffer[bar_index] = longExit1Buffer[bar_index]; + } + } + + // + // Short ... + if (multiplier1 > 0 && work[bar_index][trend1Idx] == -1) + { + // + if (work[bar_index][lo1Idx] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][lo1Idx] = work[bar_index - 1][lo1Idx]; + } + + // + shortExit1Buffer[bar_index] = work[bar_index][lo1Idx]; + + // + if (shortExit1Buffer[bar_index - 1] == EMPTY_VALUE) + { + shortExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index]; + } + } + + // + // Exit 2 ... + + // + // Long ... + if (multiplier2 > 0 && work[bar_index][trend2Idx] == 1) + { + if (work[bar_index][hi2Idx] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][hi2Idx] = work[bar_index - 1][hi2Idx]; + } + + // + longExit2Buffer[bar_index] = work[bar_index][hi2Idx]; + + // + if (longExit2Buffer[bar_index - 1] == EMPTY_VALUE) + { + longExit2StartBuffer[bar_index] = longExit2Buffer[bar_index]; + } + } + + // + // Short ... + if (multiplier2 > 0 && work[bar_index][trend2Idx] == -1) + { + // + if (work[bar_index][lo2Idx] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][lo2Idx] = work[bar_index - 1][lo2Idx]; + } + + // + shortExit2Buffer[bar_index] = work[bar_index][lo2Idx]; + + // + if (shortExit2Buffer[bar_index - 1] == EMPTY_VALUE) + { + shortExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index]; + } + } + } +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.ex5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..379fc9455b8620f886d21117cda02ae56fce85c6 GIT binary patch literal 12826 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..84e7e8f --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,214 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCTimer Indicator +// --------------------------------------------- +// Name: XCTimer +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCTimer Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCTimer" +// +// END Constants ... +// + +// +// START Inputs ... +// +input color clr = clrYellow; +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + CreateIndicatorObject(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Delete Object ... + ObjectDelete(0, ShortName); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + ArraySetAsSeries(time, true); + + // + int m = int(time[0] + PeriodSeconds() - TimeCurrent()); + int s = m % 60; + m = (m - s) / 60; + + // + long mSpread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); + + string _sp = "", _m = "", _s = ""; + if (mSpread < 10) + _sp = ".."; + else if (mSpread < 100) + _sp = "."; + if (m < 10) + _m = "0"; + if (s < 10) + _s = "0"; + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + " Next Bar in " + _m + IntegerToString(m) + ":" + _s + IntegerToString(s); + + // + ObjectSetInteger(0, ShortName, OBJPROP_COLOR, clr); + ObjectSetString(0, ShortName, OBJPROP_TEXT, objText); + ObjectSetInteger(0, ShortName, OBJPROP_FONTSIZE, 10); + ObjectSetString(0, ShortName, OBJPROP_FONT, "Courier"); + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +void CreateIndicatorObject() +{ + // + ObjectCreate(0, ShortName, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, ShortName, OBJPROP_CORNER, corner); + ObjectSetInteger(0, ShortName, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, ShortName, OBJPROP_YDISTANCE, 2); + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + ObjectSetInteger(0, ShortName, OBJPROP_ANCHOR, Anchor); +} +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhk.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhk.mq5 new file mode 100644 index 0000000..34ad3ff --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhk.mq5 @@ -0,0 +1,500 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_HK HikenAshi Candles +// --------------------------------------------------- +// Name: X121_HK +// Description: Hiken Ashi ... +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_HK Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_HK" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Presentation"; +input bool drawCandles = true; // Draw Hiken Ashi Candle +input bool drawCandleLines = false; // Show HikenAshi Lines + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 13 +#property indicator_plots 5 + +// +// PLOTTED Buffers ... + +// +// Open ... +#define openBufferIndex 0 +double openBuffer[]; + +// +// High ... +#define highBufferIndex 1 +double highBuffer[]; + +// +// Low ... +#define lowBufferIndex 2 +double lowBuffer[]; + +// +// Close ... +#define closeBufferIndex 3 +double closeBuffer[]; + +// +// Candle Color ... +#define candleColorBufferIndex 4 +double candleColorBuffer[]; + +// +#define candlesBufferIndex 0 + +// +#property indicator_label1 "X121_HK Open;X121_HK High;X121_HK Low;X121_HK Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 clrAqua, clrMagenta, CLR_NONE + +// +#define openHKBufferIndex 5 +#define openHKColorBufferIndex 6 +double openHKBuffer[]; +double openHKColorBuffer[]; + +// +#define openHKBufferPlotIndex 1 +#property indicator_label2 "X121_HK O" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 clrAqua, clrMagenta, clrLightGray +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +#define highHKBufferIndex 7 +#define highHKColorBufferIndex 8 +double highHKBuffer[]; +double highHKColorBuffer[]; + +// +#define highHKBufferPlotIndex 2 +#property indicator_label3 "X121_HK H" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 clrAqua, clrMagenta, clrLightGray +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define lowHKBufferIndex 9 +#define lowHKColorBufferIndex 10 +double lowHKBuffer[]; +double lowHKColorBuffer[]; + +// +#define lowHKBufferPlotIndex 3 +#property indicator_label4 "X121_HK L" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 clrAqua, clrMagenta, clrLightGray +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define closeHKBufferIndex 11 +#define closeHKColorBufferIndex 12 +double closeHKBuffer[]; +double closeHKColorBuffer[]; + +// +#define closeHKBufferPlotIndex 4 +#property indicator_label5 "X121_HK C" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 clrAqua, clrMagenta, clrLightGray +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i, prev_calculated, rates_total, open, high, close, low); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Candles Color ... + ArraySetAsSeries(candleColorBuffer, true); + SetIndexBuffer(candleColorBufferIndex, candleColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(candlesBufferIndex, PLOT_EMPTY_VALUE, 0.0); + + // + PlotIndexSetInteger(candlesBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(candleColorBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + PlotIndexSetInteger(openBufferIndex, PLOT_SHOW_DATA, false); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + PlotIndexSetInteger(highBufferIndex, PLOT_SHOW_DATA, false); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + PlotIndexSetInteger(closeBufferIndex, PLOT_SHOW_DATA, false); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open HK ... + ENUM_DRAW_TYPE openDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(openHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(openHKBufferPlotIndex, PLOT_DRAW_TYPE, openDrawType); + + // + ArraySetAsSeries(openHKColorBuffer, true); + SetIndexBuffer(openHKColorBufferIndex, openHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // High HK ... + ENUM_DRAW_TYPE highDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(highHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(highHKBufferPlotIndex, PLOT_DRAW_TYPE, highDrawType); + + // + ArraySetAsSeries(highHKColorBuffer, true); + SetIndexBuffer(highHKColorBufferIndex, highHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Low HK ... + ENUM_DRAW_TYPE lowDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(lowHKBufferPlotIndex, PLOT_DRAW_TYPE, lowDrawType); + + // + ArraySetAsSeries(lowHKColorBuffer, true); + SetIndexBuffer(lowHKColorBufferIndex, lowHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Close HK ... + ENUM_DRAW_TYPE closeDrawType = drawCandleLines ? DRAW_COLOR_LINE : DRAW_NONE; + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + PlotIndexSetInteger(closeHKBufferPlotIndex, PLOT_SHOW_DATA, drawCandleLines); + PlotIndexSetInteger(closeHKBufferPlotIndex, PLOT_DRAW_TYPE, closeDrawType); + + // + ArraySetAsSeries(closeHKColorBuffer, true); + SetIndexBuffer(closeHKColorBufferIndex, closeHKColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[]) +{ + // + double mPrevHKOpenValue; + double mPrevHKCloseValue; + + // + if (ArraySize(open) <= bar_index + 1) + { + // + mPrevHKOpenValue = 0; + mPrevHKCloseValue = 0; + } + else + { + // + mPrevHKOpenValue = openBuffer[bar_index + 1]; + mPrevHKCloseValue = closeBuffer[bar_index + 1]; + } + + // + double mHKOpenValue = (mPrevHKOpenValue + mPrevHKCloseValue) / 2; + double mHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double mHKHighValue = MathMax(high[bar_index], MathMax(mHKOpenValue, mHKCloseValue)); + double mHKLowValue = MathMin(low[bar_index], MathMin(mHKOpenValue, mHKCloseValue)); + + // + openBuffer[bar_index] = mHKOpenValue; + highBuffer[bar_index] = mHKHighValue; + lowBuffer[bar_index] = mHKLowValue; + closeBuffer[bar_index] = mHKCloseValue; + + // + double candleColorValue = + mHKOpenValue < mHKCloseValue ? 0 : 1; + + // + candleColorBuffer[bar_index] = drawCandles ? candleColorValue : 2; + + // + openHKBuffer[bar_index] = mHKOpenValue; + openHKColorBuffer[bar_index] = candleColorValue; + + // + highHKBuffer[bar_index] = mHKHighValue; + highHKColorBuffer[bar_index] = candleColorValue; + + // + lowHKBuffer[bar_index] = mHKLowValue; + lowHKColorBuffer[bar_index] = candleColorValue; + + // + closeHKBuffer[bar_index] = mHKCloseValue; + closeHKColorBuffer[bar_index] = candleColorValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhull.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhull.mq5 new file mode 100644 index 0000000..d0396ca --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xhull.mq5 @@ -0,0 +1,587 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XHULL Indicator +// --------------------------------------------- +// Name: XHULL +// Description: Hull Trend Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XHull Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "XHULL" + +// +// END Constants ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START XSCHULL Class Definition ... +// + +// +// a Class For Hull Calculations ... +class XSCHull +{ + // +public: + // + // Constructor ... + XSCHull() : mFullPeriod(1), mHalfPeriod(1), mSqrtPeriod(1), mArraySize(-1) + { + // + // These are a way above to assign Private variables at Construct time ... + } + + // + // Deconstructor ... + ~XSCHull() + { + ArrayFree(mData); + } + + // + // Initial Hull ... + bool Init( + int mPeriod, + double mDivisor) + { + // + bool result = false; + + // + mFullPeriod = (int)(mPeriod > 1 ? mPeriod : 1); + mHalfPeriod = (int)(mFullPeriod > 1 ? mFullPeriod / (mDivisor > 1 ? mDivisor : 1) : 1); + mSqrtPeriod = (int)MathSqrt(mFullPeriod); + + // + mArraySize = -1; + mWeight1 = mWeight2 = mWeight3 = 1; + + // + result = true; + + // + return result; + } + + // + // CalCulate Specific Value ... + double Calculate( + double value, + int i, + int bars) + { + // + double result = 0; + + // + if (mArraySize < bars) + { + // + mArraySize = ArrayResize(mData, bars + 500); + if (mArraySize < bars) + return result; + } + + // + mData[i].value = value; + if (i > mFullPeriod) + { + // + mData[i].wsum1 = mData[i - 1].wsum1 + value * mHalfPeriod - mData[i - 1].lsum1; + mData[i].lsum1 = mData[i - 1].lsum1 + value - mData[i - mHalfPeriod].value; + mData[i].wsum2 = mData[i - 1].wsum2 + value * mFullPeriod - mData[i - 1].lsum2; + mData[i].lsum2 = mData[i - 1].lsum2 + value - mData[i - mFullPeriod].value; + } + else + { + // + mData[i].wsum1 = mData[i].wsum2 = + mData[i].lsum1 = mData[i].lsum2 = mWeight1 = mWeight2 = 0; + for (int k = 0, w1 = mHalfPeriod, w2 = mFullPeriod; w2 > 0 && i >= k; k++, w1--, w2--) + { + // + if (w1 > 0) + { + // + mData[i].wsum1 += mData[i - k].value * w1; + mData[i].lsum1 += mData[i - k].value; + mWeight1 += w1; + } + + // + mData[i].wsum2 += mData[i - k].value * w2; + mData[i].lsum2 += mData[i - k].value; + mWeight2 += w2; + } + } + + // + mData[i].value3 = 2.0 * mData[i].wsum1 / mWeight1 - mData[i].wsum2 / mWeight2; + + // + if (i > mSqrtPeriod) + { + // + mData[i].wsum3 = mData[i - 1].wsum3 + mData[i].value3 * mSqrtPeriod - mData[i - 1].lsum3; + mData[i].lsum3 = mData[i - 1].lsum3 + mData[i].value3 - mData[i - mSqrtPeriod].value3; + } + else + { + // + mData[i].wsum3 = + mData[i].lsum3 = mWeight3 = 0; + + // + for (int k = 0, w3 = mSqrtPeriod; w3 > 0 && i >= k; k++, w3--) + { + // + mData[i].wsum3 += mData[i - k].value3 * w3; + mData[i].lsum3 += mData[i - k].value3; + mWeight3 += w3; + } + } + + // + result = mData[i].wsum3 / mWeight3; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + int mFullPeriod; + int mHalfPeriod; + int mSqrtPeriod; + int mArraySize; + double mWeight1; + double mWeight2; + double mWeight3; + + // + XHullData mData[]; +}; + +// +// END XSCHULL Class Definition ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 72; // Length +input double divisor = 2.0; // Divisor (Speed) + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Zone Applied to +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Zone Applied to + +// +input group "Presentation"; +input bool showUpZone = true; // Show Up Zone +input bool showDownZone = true; // Show Down Zone + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// UP Zone ... + +// +#define upZoneBufferIndex 0 +#define upZoneColorBufferIndex 1 + +// +double upZoneBuffer[]; +double upZoneColorBuffer[]; + +// +#property indicator_label1 "XHULL Up" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLightGray, clrAqua, clrMagenta +#property indicator_width1 1 + +// +// DOWN Zone ... + +// +#define downZoneBufferIndex 2 +#define downZoneColorBufferIndex 3 + +// +double downZoneBuffer[]; +double downZoneColorBuffer[]; + +// +#property indicator_label2 "XHULL Down" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 clrLightGray, clrAqua, clrMagenta +#property indicator_width2 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XSCHull *mUpZHull; +XSCHull *mDownZHull; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Make an Instance of Hull Class ... + + // + mUpZHull = new XSCHull(); + mUpZHull.Init( + length, + divisor); + + // + mDownZHull = new XSCHull(); + mDownZHull.Init( + length, + divisor); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + delete mUpZHull; + delete mDownZHull; +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // this counts Available Bars ... + int limit; + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + double upPrice = getPrice( + upAppliedTo, + open, high, low, close, i); + + // + double downPrice = getPrice( + downAppliedTo, + open, high, low, close, i); + + // + CalculateBuffers( + i, + rates_total, + upPrice, + downPrice); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + length >= 9 && + divisor >= 0.5; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = length; + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // UP Zone ... + + // + // Draw Type ... + ENUM_DRAW_TYPE upZoneDrawType = showUpZone ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(upZoneBufferIndex, upZoneBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upZoneBufferIndex, PLOT_SHOW_DATA, showUpZone); + PlotIndexSetInteger(upZoneBufferIndex, PLOT_DRAW_TYPE, upZoneDrawType); + + // + // Color Buffer ... + SetIndexBuffer(upZoneColorBufferIndex, upZoneColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DOWN Zone ... + + // + // Draw Type ... + ENUM_DRAW_TYPE downZoneDrawType = showDownZone ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(downZoneBufferIndex, downZoneBuffer, INDICATOR_DATA); + PlotIndexSetInteger(downZoneBufferIndex - 1, PLOT_SHOW_DATA, showDownZone); + PlotIndexSetInteger(downZoneBufferIndex - 1, PLOT_DRAW_TYPE, downZoneDrawType); + + // + // Color Buffer ... + SetIndexBuffer(downZoneColorBufferIndex, downZoneColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int ratesTotal, // Total Rates + double upPrice, // Up Price ... + double downPrice // Down Price ... +) +{ + // + double upValue = mUpZHull.Calculate( + upPrice, + bar_index, + ratesTotal); + upZoneBuffer[bar_index] = upValue; + double upColorIDX = (bar_index > 0) + ? (upZoneBuffer[bar_index] > upZoneBuffer[bar_index - 1]) + ? 1 + : (upZoneBuffer[bar_index] < upZoneBuffer[bar_index - 1]) + ? 2 + : upZoneColorBuffer[bar_index - 1] + : 0; + upZoneColorBuffer[bar_index] = upColorIDX; + + // + double downValue = mDownZHull.Calculate( + downPrice, + bar_index, + ratesTotal); + downZoneBuffer[bar_index] = downValue; + double downColorIDX = (bar_index > 0) + ? (downZoneBuffer[bar_index] > downZoneBuffer[bar_index - 1]) + ? 1 + : (downZoneBuffer[bar_index] < downZoneBuffer[bar_index - 1]) + ? 2 + : downZoneColorBuffer[bar_index - 1] + : 0; + downZoneColorBuffer[bar_index] = downColorIDX; +} + +// +// END Functions ... +// + +template +double getPrice(ENUM_APPLIED_PRICE tprice, T &open[], T &high[], T &low[], T &close[], int i) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xich.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xich.mq5 new file mode 100644 index 0000000..96eb522 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xich.mq5 @@ -0,0 +1,895 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_ICH Ichimoku +// ------------------------------------------------- +// Name: X121_ICH +// Description: +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_ICH Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_ICH" + +// +// Ichimoku Golden Numbers ... +enum ENUM_X_ICHIMOKU_GOLDEN_NUMBERS +{ + X_ICH_BASE = 9, + X_ICH_GOLDEN = 17, + X_ICH_CYCLE = 26, + X_ICH_PERIOD = 35, + X_ICH_STAR = 45, + X_ICH_MED = 52, + X_ICH_LONG = 63, + X_ICH_FULL = 72 +}; + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// ICHIMOKU Kinko Hyo ... + +// +// TENKANSEN ... +input group "Tenkan Sen"; +input int tenkanSenLength = 9; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// KIJUNSEN ... +input group "Kijun Sen"; +input int kijunSenLength = 26; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// SENKOUSPANB ... +input group "Senkou Span B"; +input int senkouSpanBLength = 52; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// CHIKOUSPAN ... +input group "Chikou Span"; +input ENUM_APPLIED_PRICE chikuoSpanAppliedTo = PRICE_CLOSE; // Price Type + +// +input group "Presentation"; +input bool showTenkanSen = true; // Show Tenkan Sen +input bool showKijunSen = true; // Show Kijun Sen +input bool showKijunSenPlus = false; // Show Kijun Sen + +input bool showKijunSenNegative = false; // Show Kijun Sen - +input bool showChikouSpan = true; // Show Chikou Span +input bool showSenkouSpanA = true; // Show Senkou Span A +input bool showSenkouSpanB = true; // Show Senkou Span B +input bool showKumo = true; // Show Kumo +input bool shiftKumo = true; // Shift Kumo to Future + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 8 + +// +// PLOTTED Buffers ... + +// +// ICHIMOKU ... + +// +// TENKANSEN ... + +// +#define tenkanSenBufferIndex 0 +double tenkanSenBuffer[]; + +// +#property indicator_label1 "X121_ICH Tenkan Sen" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// KIJUNSEN ... + +// +#define kijunSenBufferIndex 1 +double kijunSenBuffer[]; + +// +#property indicator_label2 "X121_ICH Kijun Sen" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrDodgerBlue +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define kijunSenPlusBufferIndex 2 +double kijunSenPlusBuffer[]; + +// +#property indicator_label3 "X121_ICH Kijun Sen +" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrMediumTurquoise +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define kijunSenNegativeBufferIndex 3 +double kijunSenNegativeBuffer[]; + +// +#property indicator_label4 "X121_ICH Kijun Sen -" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrDarkSeaGreen +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// CHIKOUSPAN ... + +// +#define chikouSpanBufferIndex 4 +double chikouSpanBuffer[]; + +// +#property indicator_label5 "X121_ICH Chikou Span" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrDarkGreen +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +#define senkouABufferIndex 5 +double senkouABuffer[]; + +// +#property indicator_label6 "X121_ICH Senkou Span A" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrLightGray +#property indicator_style6 STYLE_DASHDOTDOT +#property indicator_width6 1 + +// +#define senkouBBufferIndex 6 +double senkouBBuffer[]; + +// +#property indicator_label7 "X121_ICH Senkou Span B" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrLightGray +#property indicator_style7 STYLE_DASHDOTDOT +#property indicator_width7 1 + +// +// KUMO ... + +// +// SENKOUSPANA ... + +// +#define senkouSpanABufferIndex 7 +double senkouSpanABuffer[]; + +// +// SENKOUSPANB ... + +// +#define senkouSpanBBufferIndex 8 +double senkouSpanBBuffer[]; + +// +// KUMOCLOUD ... + +// +#define kumoBufferIndex 7 + +// +#property indicator_label8 "X121_ICH Kumo" +#property indicator_type8 DRAW_FILLING +#property indicator_color8 clrAqua, clrMagenta +#property indicator_style8 STYLE_SOLID +#property indicator_width8 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +ENUM_SERIESMODE mTenkanSenTopMode = NULL; +ENUM_SERIESMODE mTenkanSenBottomMode = NULL; + +// +ENUM_SERIESMODE mKijunSenTopMode = NULL; +ENUM_SERIESMODE mKijunSenBottomMode = NULL; + +// +ENUM_SERIESMODE mSenkouSpanBTopMode = NULL; +ENUM_SERIESMODE mSenkouSpanBBottomMode = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + RemoveDraws(drawPrefix); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Ichimoku Kinko Hyo ... + (tenkanSenLength > 2 && + kijunSenLength > tenkanSenLength && + senkouSpanBLength > kijunSenLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ichimoku ... + result = MathMax(result, tenkanSenLength); + result = MathMax(result, kijunSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // ICHIMOKU ... + + // + // TENKANSEN ... + + // + ENUM_DRAW_TYPE tenkanSenDrawType = showTenkanSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tenkanSenBuffer, true); + SetIndexBuffer(tenkanSenBufferIndex, tenkanSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_SHOW_DATA, showTenkanSen); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_TYPE, tenkanSenDrawType); + + // + // KIJUNSEN ... + + // + ENUM_DRAW_TYPE kijunSenDrawType = showKijunSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenBuffer, true); + SetIndexBuffer(kijunSenBufferIndex, kijunSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_SHOW_DATA, showKijunSen); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_TYPE, kijunSenDrawType); + + // + // KIJUNSEN Plus ... + + // + ENUM_DRAW_TYPE kijunSenPlusDrawType = showKijunSenPlus ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenPlusBuffer, true); + SetIndexBuffer(kijunSenPlusBufferIndex, kijunSenPlusBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_SHIFT, kijunSenLength); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_DRAW_TYPE, kijunSenPlusDrawType); + + // + // KIJUNSEN Negative ... + + // + ENUM_DRAW_TYPE kijunSenNegativeDrawType = showKijunSenNegative ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenNegativeBuffer, true); + SetIndexBuffer(kijunSenNegativeBufferIndex, kijunSenNegativeBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_DRAW_TYPE, kijunSenNegativeDrawType); + + // + // CHIKOUSPAN ... + + // + ENUM_DRAW_TYPE chikouSpanDrawType = showChikouSpan ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(chikouSpanBuffer, true); + SetIndexBuffer(chikouSpanBufferIndex, chikouSpanBuffer, INDICATOR_DATA); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHOW_DATA, showChikouSpan); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_TYPE, chikouSpanDrawType); + + // + // SENKOUSPAN A and B ... + int shiftSize = shiftKumo ? kijunSenLength : 0; + + // + // SENKOUSPANA ... + ENUM_DRAW_TYPE senkouSpanADrawType = showSenkouSpanA ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(senkouABuffer, true); + SetIndexBuffer(senkouABufferIndex, senkouABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouABufferIndex, PLOT_SHOW_DATA, showSenkouSpanA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_DRAW_TYPE, senkouSpanADrawType); + + // + // SENKOUSPANB ... + ENUM_DRAW_TYPE senkouSpanBDrawType = showSenkouSpanB ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(senkouBBuffer, true); + SetIndexBuffer(senkouBBufferIndex, senkouBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_SHOW_DATA, showSenkouSpanB); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_DRAW_TYPE, senkouSpanBDrawType); + + // + // KUMO ... + + // + // SENKOUSPANA ... + ArraySetAsSeries(senkouSpanABuffer, true); + SetIndexBuffer(senkouSpanABufferIndex, senkouSpanABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // SENKOUSPANB ... + ArraySetAsSeries(senkouSpanBBuffer, true); + SetIndexBuffer(senkouSpanBBufferIndex, senkouSpanBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // KUMO ... + + // + ENUM_DRAW_TYPE kumoDrawType = showKumo ? DRAW_FILLING : DRAW_NONE; + + // + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kumoBufferIndex, PLOT_DRAW_TYPE, kumoDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // ICHIMOKU ... + + // + double topValue; + double bottomValue; + + // + // TENKANSEN ... + + // + // Extract Tenkan Sen Top/Bottom Calculation Mode based on User Input ... + if (mTenkanSenTopMode == NULL || mTenkanSenBottomMode == NULL) + { + // + switch (tenkanSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mTenkanSenTopMode = MODE_HIGH; + mTenkanSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mTenkanSenTopMode = MODE_OPEN; + mTenkanSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mTenkanSenTopMode, + tenkanSenLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mTenkanSenBottomMode, + tenkanSenLength, + bar_index); + + // + double tenkanSenValue = (topValue + bottomValue) / 2; + tenkanSenBuffer[bar_index] = tenkanSenValue; + + // + // KIJUNSEN ... + + // + // Extract Kijun Sen Top/Bottom Calculation Mode based on User Input ... + if (mKijunSenTopMode == NULL || mKijunSenBottomMode == NULL) + { + // + switch (kijunSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mKijunSenTopMode = MODE_HIGH; + mKijunSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mKijunSenTopMode = MODE_OPEN; + mKijunSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mKijunSenTopMode, + kijunSenLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mKijunSenBottomMode, + kijunSenLength, + bar_index); + + // + double kijunSenValue = (topValue + bottomValue) / 2; + kijunSenBuffer[bar_index] = kijunSenValue; + + // + kijunSenPlusBuffer[bar_index] = kijunSenValue; + kijunSenNegativeBuffer[bar_index] = kijunSenValue; + + // + // CHIKOUSPAN ... + double chikouSpanValue = GetAppliedPrice( + bar_index, + chikuoSpanAppliedTo); + chikouSpanBuffer[bar_index] = chikouSpanValue; + + // + // KUMO ... + + // + // SENKOUSPANA ... + double senkouSpanAValue = (tenkanSenValue + kijunSenValue) / 2; + senkouABuffer[bar_index] = senkouSpanAValue; + senkouSpanABuffer[bar_index] = senkouSpanAValue; + + // + // SENKOUSPANB ... + + // + // Extract Senkou Span B Top/Bottom Calculation Mode based on User Input ... + if (mSenkouSpanBTopMode == NULL || mSenkouSpanBBottomMode == NULL) + { + // + switch (senkouSpanBMode) + { + // + case X_XICH_HH_LL_MODE: + // + mSenkouSpanBTopMode = MODE_HIGH; + mSenkouSpanBBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mSenkouSpanBTopMode = MODE_OPEN; + mSenkouSpanBBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = GetHighestHigh( + _Symbol, + _Period, + mSenkouSpanBTopMode, + senkouSpanBLength, + bar_index); + + // + // Calculate Bottom ... + bottomValue = GetLowestLow( + _Symbol, + _Period, + mSenkouSpanBBottomMode, + senkouSpanBLength, + bar_index); + + // + double senkouSpanBValue = (topValue + bottomValue) / 2; + senkouBBuffer[bar_index] = senkouSpanBValue; + senkouSpanBBuffer[bar_index] = senkouSpanBValue; + + // + return; + if (ArraySize(senkouABuffer) > bar_index + kijunSenLength + 1) + { + // + // Detect Koumo Switch ... + bool isKumoSwitchBullish = + // + senkouABuffer[bar_index + kijunSenLength] > senkouBBuffer[bar_index + kijunSenLength] && + senkouABuffer[bar_index + kijunSenLength + 1] <= senkouBBuffer[bar_index + kijunSenLength + 1] + // + ; + + // + // Detect Koumo Switch ... + bool isKumoSwitchBearish = + // + senkouABuffer[bar_index + kijunSenLength] < senkouBBuffer[bar_index + kijunSenLength] && + senkouABuffer[bar_index + kijunSenLength + 1] >= senkouBBuffer[bar_index + kijunSenLength + 1] + // + ; + + // + datetime time = iTime( + _Symbol, + _Period, + bar_index); + + // + long chartID = ChartID(); + + // + if (isKumoSwitchBullish) + { + // + string vlName = "Kumo_Switch_Bullish_NOW" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + clrAqua, + STYLE_DASHDOT); + } + + // + if (isKumoSwitchBearish) + { + // + string vlName = "Kumo_Switch_Bearish_NOW" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + clrMagenta, + STYLE_DASHDOT); + } + } + + // + return; + if (ArraySize(senkouABuffer) > bar_index + 1) + { + // + // Detect Koumo Switch ... + bool isKumoSwitchBullish = + // + senkouABuffer[bar_index] > senkouBBuffer[bar_index] && + senkouABuffer[bar_index + 1] <= senkouBBuffer[bar_index + 1] + // + ; + + // + // Detect Koumo Switch ... + bool isKumoSwitchBearish = + // + senkouABuffer[bar_index] < senkouBBuffer[bar_index] && + senkouABuffer[bar_index + 1] >= senkouBBuffer[bar_index + 1] + // + ; + + // + datetime time = iTime( + _Symbol, + _Period, + bar_index); + + // + long chartID = ChartID(); + + // + if (isKumoSwitchBullish) + { + // + string vlName = "Kumo_Switch_Bullish_FUTURE" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + clrAqua, + STYLE_DASHDOT); + } + + // + if (isKumoSwitchBearish) + { + // + string vlName = "Kumo_Switch_Bearish_FUTURE" + (string)time; + + // + DrawVerticalLine( + chartID, + vlName, + 0, + time, + clrMagenta, + STYLE_DASHDOT); + } + } +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmc.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmc.mq5 new file mode 100644 index 0000000..8a4aa26 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmc.mq5 @@ -0,0 +1,469 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_MC MA Cross Indicator +// --------------------------------------------------- +// Name: X121_MC +// Description: Moving Average Crosses +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_MC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_MC" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Fast"; +input int fastMaLength = 9; // Length +input int fastMaShift = 0; // Shift +input ENUM_MA_METHOD fastMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE fastMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Slow"; +input int slowMaLength = 18; // Length +input int slowMaShift = 0; // Shift +input ENUM_MA_METHOD slowMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE slowMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Verifier"; +input int verifierMaLength = 50; // Length +input int verifierMaShift = 0; // Shift +input ENUM_MA_METHOD verifierMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE verifierMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Presentation"; +input bool showFastMa = true; // Show Fast +input bool showSlowMa = true; // Show Slow +input bool showVerifierMa = true; // Show Verifier + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +// PLOTTED Buffers ... + +// +// MA ... + +// +// FAST ... +#define fastMaBufferIndex 0 +double fastMaBuffer[]; + +// +#property indicator_label1 "X121_MC MA F" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// SLOW ... +#define slowMaBufferIndex 1 +double slowMaBuffer[]; + +// +#property indicator_label2 "X121_MC MA S" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrDarkOrange +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// VERIFIER ... +#define verifierMaBufferIndex 2 +double verifierMaBuffer[]; + +// +#property indicator_label3 "X121_MC MA V" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrDarkBlue +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int fastMaHandler = INVALID_HANDLE; +int slowMaHandler = INVALID_HANDLE; +int verifierMaHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // MA Initialization ... + + // + // FAST ... + fastMaHandler = iMA( + _Symbol, + _Period, + fastMaLength, + fastMaShift, + fastMaMethod, + fastMaAppliedTo); + if (fastMaHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + LogMessage(msg); + + // + return INIT_FAILED; + } + + // + // SLOW ... + slowMaHandler = iMA( + _Symbol, + _Period, + slowMaLength, + slowMaShift, + slowMaMethod, + slowMaAppliedTo); + if (slowMaHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + LogMessage(msg); + + // + return INIT_FAILED; + } + + // + // VERIFIER ... + verifierMaHandler = iMA( + _Symbol, + _Period, + verifierMaLength, + verifierMaShift, + verifierMaMethod, + verifierMaAppliedTo); + if (verifierMaHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + LogMessage(msg); + + // + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(fastMaHandler); + IndicatorRelease(slowMaHandler); + IndicatorRelease(verifierMaHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int fastMaCalculatedBars = BarsCalculated(fastMaHandler); + int slowMaCalculatedBars = BarsCalculated(slowMaHandler); + int verifierMaCalculatedBars = BarsCalculated(verifierMaHandler); + if (fastMaCalculatedBars < maxLength || + slowMaCalculatedBars < maxLength || + verifierMaCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFastMas = CopyBuffer(fastMaHandler, 0, 0, limit, fastMaBuffer); + int copiedSlowMas = CopyBuffer(slowMaHandler, 0, 0, limit, slowMaBuffer); + int copiedVerifierMas = CopyBuffer(verifierMaHandler, 0, 0, limit, verifierMaBuffer); + if (copiedFastMas <= 0 || + copiedSlowMas <= 0 || + copiedVerifierMas <= 0 + ) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Ma ... + (fastMaLength > 2 && + slowMaLength > fastMaLength && + verifierMaLength > slowMaLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ma ... + result = MathMax(result, fastMaLength); + result = MathMax(result, slowMaLength); + result = MathMax(result, verifierMaLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // MA ... + + // + // FAST ... + ENUM_DRAW_TYPE fastMaDrawType = showFastMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fastMaBuffer, true); + SetIndexBuffer(fastMaBufferIndex, fastMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_TYPE, fastMaDrawType); + + // + // SLOW ... + ENUM_DRAW_TYPE slowMaDrawType = showSlowMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(slowMaBuffer, true); + SetIndexBuffer(slowMaBufferIndex, slowMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_TYPE, slowMaDrawType); + + // + // VERIFIER ... + ENUM_DRAW_TYPE verifierMaDrawType = showVerifierMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(verifierMaBuffer, true); + SetIndexBuffer(verifierMaBufferIndex, verifierMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(verifierMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(verifierMaBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(verifierMaBufferIndex, PLOT_DRAW_TYPE, verifierMaDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmrb.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmrb.mq5 new file mode 100644 index 0000000..be26e52 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xmrb.mq5 @@ -0,0 +1,802 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_MRB MA Ribbon Indicator +// ----------------------------------------------------- +// Name: X121_MRB +// Description: Moving Average Ribbon +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_MRB Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_MRB" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Ribbon 1"; +input int fast1Length = 3; // Fast +input int slow1Length = 5; // Slow + +// +input group "Ribbon 2"; +input int fast2Length = 8; // Fast +input int slow2Length = 13; // Slow + +// +input group "Ribbon 3"; +input int fast3Length = 21; // Fast +input int slow3Length = 34; // Slow + +// +input group "Ribbon 4"; +input int fast4Length = 55; // Fast +input int slow4Length = 89; // Slow + +// +input group "Ribbon 5"; +input int fast5Length = 144; // Fast +input int slow5Length = 233; // Slow + +// +input group "Calculation Mode"; +input ENUM_MA_METHOD ribbonMode = MODE_EMA; // Calculation Mode +input ENUM_APPLIED_PRICE ribbonAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Presentation"; +input bool showFastMa = true; // Show Fast +input bool showSlowMa = true; // Show Slow +input bool showRibbon = false; // Show Ribbon + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 12 +#property indicator_plots 12 + +// +// PLOTTED Buffers ... + +// +// MA ... + +// +// FAST ... +#define fastMaBufferIndex 0 +double fastMaBuffer[]; + +// +#property indicator_label1 "X121_MRB F" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// SLOW ... +#define slowMaBufferIndex 1 +double slowMaBuffer[]; + +// +#property indicator_label2 "X121_MRB S" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// DATA Buffers ... + +// +// FAST ... + +// +#define fast1BufferIndex 2 +double fast1Buffer[]; + +// +#property indicator_label3 "X121_MRB 1 F" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAquamarine +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define fast2BufferIndex 3 +double fast2Buffer[]; + +// +#property indicator_label4 "X121_MRB 2 F" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAquamarine +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define fast3BufferIndex 4 +double fast3Buffer[]; + +// +#property indicator_label5 "X121_MRB 3 F" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAquamarine +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +#define fast4BufferIndex 5 +double fast4Buffer[]; + +// +#property indicator_label6 "X121_MRB 4 F" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrAquamarine +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +#define fast5BufferIndex 6 +double fast5Buffer[]; + +// +#property indicator_label7 "X121_MRB 5 F" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrAquamarine +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +// SLOW ... + +// +#define slow1BufferIndex 7 +double slow1Buffer[]; + +// +#property indicator_label8 "X121_MRB 1 S" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrPlum +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +#define slow2BufferIndex 8 +double slow2Buffer[]; + +// +#property indicator_label9 "X121_MRB 2 S" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrPlum +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 + +// +#define slow3BufferIndex 9 +double slow3Buffer[]; + +// +#property indicator_label10 "X121_MRB 3 S" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrPlum +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +// +#define slow4BufferIndex 10 +double slow4Buffer[]; + +// +#property indicator_label11 "X121_MRB 4 S" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrPlum +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define slow5BufferIndex 11 +double slow5Buffer[]; + +// +#property indicator_label12 "X121_MRB 5 S" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrPlum +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int fast1MaHandler = INVALID_HANDLE; +int fast2MaHandler = INVALID_HANDLE; +int fast3MaHandler = INVALID_HANDLE; +int fast4MaHandler = INVALID_HANDLE; +int fast5MaHandler = INVALID_HANDLE; + +// +int slow1MaHandler = INVALID_HANDLE; +int slow2MaHandler = INVALID_HANDLE; +int slow3MaHandler = INVALID_HANDLE; +int slow4MaHandler = INVALID_HANDLE; +int slow5MaHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initialize MAs ... + if (!InitializeMas()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + + // + IndicatorRelease(fast1MaHandler); + IndicatorRelease(fast2MaHandler); + IndicatorRelease(fast3MaHandler); + IndicatorRelease(fast4MaHandler); + IndicatorRelease(fast5MaHandler); + + // + IndicatorRelease(slow1MaHandler); + IndicatorRelease(slow2MaHandler); + IndicatorRelease(slow3MaHandler); + IndicatorRelease(slow4MaHandler); + IndicatorRelease(slow5MaHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + // + int fast1MaCalculatedBars = BarsCalculated(fast1MaHandler); + int fast2MaCalculatedBars = BarsCalculated(fast2MaHandler); + int fast3MaCalculatedBars = BarsCalculated(fast3MaHandler); + int fast4MaCalculatedBars = BarsCalculated(fast4MaHandler); + int fast5MaCalculatedBars = BarsCalculated(fast5MaHandler); + // + int slow1MaCalculatedBars = BarsCalculated(slow1MaHandler); + int slow2MaCalculatedBars = BarsCalculated(slow2MaHandler); + int slow3MaCalculatedBars = BarsCalculated(slow3MaHandler); + int slow4MaCalculatedBars = BarsCalculated(slow4MaHandler); + int slow5MaCalculatedBars = BarsCalculated(slow5MaHandler); + if ( + fast1MaCalculatedBars < maxLength || + fast2MaCalculatedBars < maxLength || + fast3MaCalculatedBars < maxLength || + fast4MaCalculatedBars < maxLength || + fast5MaCalculatedBars < maxLength || + slow1MaCalculatedBars < maxLength || + slow2MaCalculatedBars < maxLength || + slow3MaCalculatedBars < maxLength || + slow4MaCalculatedBars < maxLength || + slow5MaCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + // + int copiedFast1Mas = CopyBuffer(fast1MaHandler, 0, 0, limit, fast1Buffer); + int copiedFast2Mas = CopyBuffer(fast2MaHandler, 0, 0, limit, fast2Buffer); + int copiedFast3Mas = CopyBuffer(fast3MaHandler, 0, 0, limit, fast3Buffer); + int copiedFast4Mas = CopyBuffer(fast4MaHandler, 0, 0, limit, fast4Buffer); + int copiedFast5Mas = CopyBuffer(fast5MaHandler, 0, 0, limit, fast5Buffer); + // + int copiedSlow1Mas = CopyBuffer(slow1MaHandler, 0, 0, limit, slow1Buffer); + int copiedSlow2Mas = CopyBuffer(slow2MaHandler, 0, 0, limit, slow2Buffer); + int copiedSlow3Mas = CopyBuffer(slow3MaHandler, 0, 0, limit, slow3Buffer); + int copiedSlow4Mas = CopyBuffer(slow4MaHandler, 0, 0, limit, slow4Buffer); + int copiedSlow5Mas = CopyBuffer(slow5MaHandler, 0, 0, limit, slow5Buffer); + if ( + copiedFast1Mas <= 0 || + copiedFast2Mas <= 0 || + copiedFast3Mas <= 0 || + copiedFast4Mas <= 0 || + copiedFast5Mas <= 0 || + copiedSlow1Mas <= 0 || + copiedSlow2Mas <= 0 || + copiedSlow3Mas <= 0 || + copiedSlow4Mas <= 0 || + copiedSlow5Mas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Ma ... + (fast1Length > 2 && + fast2Length > fast1Length && + fast3Length > fast2Length && + fast4Length > fast3Length && + fast5Length > fast4Length && + slow1Length > fast1Length && + slow2Length > fast2Length && + slow3Length > fast3Length && + slow4Length > fast4Length && + slow5Length > fast5Length && + slow2Length > slow1Length && + slow3Length > slow2Length && + slow4Length > slow3Length && + slow5Length > slow4Length + // + ) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ma ... + + // + result = MathMax(fast1Length, fast2Length); + result = MathMax(result, fast3Length); + result = MathMax(result, fast4Length); + result = MathMax(result, fast5Length); + + // + result = MathMax(result, slow1Length); + result = MathMax(result, slow2Length); + result = MathMax(result, slow3Length); + result = MathMax(result, slow4Length); + result = MathMax(result, slow5Length); + + // + return result; +} + +// +// Initialize Ma Handlers ... +bool InitializeMas() +{ + // + bool result = false; + + // + fast1MaHandler = iMA( + _Symbol, + _Period, + fast1Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast2MaHandler = iMA( + _Symbol, + _Period, + fast2Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast3MaHandler = iMA( + _Symbol, + _Period, + fast3Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast4MaHandler = iMA( + _Symbol, + _Period, + fast4Length, + 0, + ribbonMode, + ribbonAppliedTo); + fast5MaHandler = iMA( + _Symbol, + _Period, + fast5Length, + 0, + ribbonMode, + ribbonAppliedTo); + + // + slow1MaHandler = iMA( + _Symbol, + _Period, + slow1Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow2MaHandler = iMA( + _Symbol, + _Period, + slow2Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow3MaHandler = iMA( + _Symbol, + _Period, + slow3Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow4MaHandler = iMA( + _Symbol, + _Period, + slow4Length, + 0, + ribbonMode, + ribbonAppliedTo); + slow5MaHandler = iMA( + _Symbol, + _Period, + slow5Length, + 0, + ribbonMode, + ribbonAppliedTo); + + // + result = + fast1MaHandler != INVALID_HANDLE && + fast2MaHandler != INVALID_HANDLE && + fast3MaHandler != INVALID_HANDLE && + fast4MaHandler != INVALID_HANDLE && + fast5MaHandler != INVALID_HANDLE && + slow1MaHandler != INVALID_HANDLE && + slow2MaHandler != INVALID_HANDLE && + slow3MaHandler != INVALID_HANDLE && + slow4MaHandler != INVALID_HANDLE && + slow5MaHandler != INVALID_HANDLE; + + // + if (!result) + { + // + string message = "Error Initializing Handlers ..."; + LogMessage(message); + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // FAST ... + ENUM_DRAW_TYPE fastDrawType = showFastMa ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(fastMaBuffer, true); + SetIndexBuffer(fastMaBufferIndex, fastMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_SHOW_DATA, showFastMa); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_TYPE, fastDrawType); + + // + // SLOW ... + ENUM_DRAW_TYPE slowDrawType = showSlowMa ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(slowMaBuffer, true); + SetIndexBuffer(slowMaBufferIndex, slowMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_SHOW_DATA, showSlowMa); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_TYPE, slowDrawType); + + // + // DATA ... + ENUM_DRAW_TYPE ribbonDrawType = showRibbon ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fast1Buffer, true); + SetIndexBuffer(fast1BufferIndex, fast1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast1BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast1BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast2Buffer, true); + SetIndexBuffer(fast2BufferIndex, fast2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast2BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast2BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast3Buffer, true); + SetIndexBuffer(fast3BufferIndex, fast3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast3BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast3BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast4Buffer, true); + SetIndexBuffer(fast4BufferIndex, fast4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast4BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast4BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast4BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast5Buffer, true); + SetIndexBuffer(fast5BufferIndex, fast5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast5BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast5BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast5BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow1Buffer, true); + SetIndexBuffer(slow1BufferIndex, slow1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow1BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow1BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow2Buffer, true); + SetIndexBuffer(slow2BufferIndex, slow2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow2BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow2BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow3Buffer, true); + SetIndexBuffer(slow3BufferIndex, slow3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow3BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow3BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow4Buffer, true); + SetIndexBuffer(slow4BufferIndex, slow4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow4BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow4BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow4BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow5Buffer, true); + SetIndexBuffer(slow5BufferIndex, slow5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow5BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow5BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow5BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Retireve Values ... + + // + double fast1Value = fast1Buffer[bar_index]; + double fast2Value = fast2Buffer[bar_index]; + double fast3Value = fast3Buffer[bar_index]; + double fast4Value = fast4Buffer[bar_index]; + double fast5Value = fast5Buffer[bar_index]; + + // + double slow1Value = slow1Buffer[bar_index]; + double slow2Value = slow2Buffer[bar_index]; + double slow3Value = slow3Buffer[bar_index]; + double slow4Value = slow4Buffer[bar_index]; + double slow5Value = slow5Buffer[bar_index]; + + // + double fastValue = (fast1Value + fast2Value + fast3Value + fast4Value + fast5Value) / 5; + fastMaBuffer[bar_index] = fastValue; + + // + double slowValue = (slow1Value + slow2Value + slow3Value + slow4Value + slow5Value) / 5; + slowMaBuffer[bar_index] = slowValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xppsr.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xppsr.mq5 new file mode 100644 index 0000000..e9b53df --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xppsr.mq5 @@ -0,0 +1,1214 @@ +///////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_PPSR Pivot Points Indicator +// --------------------------------------------------------- +// Name: X121_PPSR +// Description: Pivot Points +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_PPSR Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_PPSR" + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Level 1"; +input ENUM_X_PERIOD_METHOD l1Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l1Period = NULL; // Time Period +input ENUM_SERIESMODE l1HHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE l1LLMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Level 2"; +input ENUM_X_PERIOD_METHOD l2Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l2Period = NULL; // Time Period +input ENUM_SERIESMODE l2HHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE l2LLMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Level 3"; +input ENUM_X_PERIOD_METHOD l3Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l3Period = NULL; // Time Period +input ENUM_SERIESMODE l3HHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE l3LLMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Level 4"; +input ENUM_X_PERIOD_METHOD l4Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l4Period = NULL; // Time Period +input ENUM_SERIESMODE l4HHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE l4LLMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; + +// +input group "Support and Resistace Levels"; +input bool showSRLevel1 = true; // Show Level 1 +input bool showSRLevel2 = true; // Show Level 2 +input bool showSRLevel3 = true; // Show Level 3 +input bool showSRLevel4 = true; // Show Level 4 + +// +input group "Pivot Point Levels"; +input bool showPPLevel1 = true; // Show Level 1 Pivots +input bool showPPLevel2 = true; // Show Level 2 Pivots +input bool showPPLevel3 = true; // Show Level 3 Pivots +input bool showPPLevel4 = true; // Show Level 4 Pivots + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 24 +#property indicator_plots 24 + +// +// PLOTTED Buffers ... + +// +// LEVEL 1 ... + +// +// RESISTANCE ... + +// +#define l1RBufferIndex 0 +double l1RBuffer[]; + +// +#property indicator_label1 "X121_PPSR L1 R" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrGoldenrod +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +#define l1R1BufferIndex 1 +double l1R1Buffer[]; + +// +#property indicator_label2 "X121_PPSR L1 R1" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrGoldenrod +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +#define l1R2BufferIndex 2 +double l1R2Buffer[]; + +// +#property indicator_label3 "X121_PPSR L1 R2" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGoldenrod +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +// SUPPORT ... + +// +#define l1SBufferIndex 3 +double l1SBuffer[]; + +// +#property indicator_label4 "X121_PPSR L1 S" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLightGreen +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define l1S1BufferIndex 4 +double l1S1Buffer[]; + +// +#property indicator_label5 "X121_PPSR L1 S1" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrLightGreen +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +#define l1S2BufferIndex 5 +double l1S2Buffer[]; + +// +#property indicator_label6 "X121_PPSR L1 S2" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrLightGreen +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +// LEVEL 2 ... + +// +// RESISTANCE ... + +// +#define l2RBufferIndex 6 +double l2RBuffer[]; + +// +#property indicator_label7 "X121_PPSR L2 R" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrGoldenrod +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +#define l2R1BufferIndex 7 +double l2R1Buffer[]; + +// +#property indicator_label8 "X121_PPSR L2 R2" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrGoldenrod +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +#define l2R2BufferIndex 8 +double l2R2Buffer[]; + +// +#property indicator_label9 "X121_PPSR L2 R2" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrGoldenrod +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 + +// +// SUPPORT ... + +// +#define l2SBufferIndex 9 +double l2SBuffer[]; + +// +#property indicator_label10 "X121_PPSR L2 S" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrLightGreen +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +// +#define l2S1BufferIndex 10 +double l2S1Buffer[]; + +// +#property indicator_label11 "X121_PPSR L2 S1" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrLightGreen +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define l2S2BufferIndex 11 +double l2S2Buffer[]; + +// +#property indicator_label12 "X121_PPSR L2 S2" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrLightGreen +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// LEVEL 3 ... + +// +// RESISTANCE ... + +// +#define l3RBufferIndex 12 +double l3RBuffer[]; + +// +#property indicator_label13 "X121_PPSR L3 R" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrGoldenrod +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define l3R1BufferIndex 13 +double l3R1Buffer[]; + +// +#property indicator_label14 "X121_PPSR L3 R1" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrGoldenrod +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +#define l3R2BufferIndex 14 +double l3R2Buffer[]; + +// +#property indicator_label15 "X121_PPSR L3 R2" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGoldenrod +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +// SUPPORT ... + +// +#define l3SBufferIndex 15 +double l3SBuffer[]; + +// +#property indicator_label16 "X121_PPSR L3 S" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrLightGreen +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +#define l3S1BufferIndex 16 +double l3S1Buffer[]; + +// +#property indicator_label17 "X121_PPSR L3 S1" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrLightGreen +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +#define l3S2BufferIndex 17 +double l3S2Buffer[]; + +// +#property indicator_label18 "X121_PPSR L3 S2" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrLightGreen +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// LEVEL 4 ... + +// +// RESISTANCE ... + +// +#define l4RBufferIndex 18 +double l4RBuffer[]; + +// +#property indicator_label19 "X121_PPSR L4 R" +#property indicator_type19 DRAW_LINE +#property indicator_color19 clrGoldenrod +#property indicator_style19 STYLE_DOT +#property indicator_width19 1 + +// +#define l4R1BufferIndex 19 +double l4R1Buffer[]; + +// +#property indicator_label20 "X121_PPSR L4 R1" +#property indicator_type20 DRAW_LINE +#property indicator_color20 clrGoldenrod +#property indicator_style20 STYLE_DOT +#property indicator_width20 1 + +// +#define l4R2BufferIndex 20 +double l4R2Buffer[]; + +// +#property indicator_label21 "X121_PPSR L4 R2" +#property indicator_type21 DRAW_LINE +#property indicator_color21 clrGoldenrod +#property indicator_style21 STYLE_DOT +#property indicator_width21 1 + +// +// SUPPORT ... + +// +#define l4SBufferIndex 21 +double l4SBuffer[]; + +// +#property indicator_label22 "X121_PPSR L4 S" +#property indicator_type22 DRAW_LINE +#property indicator_color22 clrLightGreen +#property indicator_style22 STYLE_DOT +#property indicator_width22 1 + +// +#define l4S1BufferIndex 22 +double l4S1Buffer[]; + +// +#property indicator_label23 "X121_PPSR L4 S1" +#property indicator_type23 DRAW_LINE +#property indicator_color23 clrLightGreen +#property indicator_style23 STYLE_DOT +#property indicator_width23 1 + +// +#define l4S2BufferIndex 23 +double l4S2Buffer[]; + +// +#property indicator_label24 "X121_PPSR L4 S2" +#property indicator_type24 DRAW_LINE +#property indicator_color24 clrLightGreen +#property indicator_style24 STYLE_DOT +#property indicator_width24 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int currentPeriodSecconds = 0; + +// +int mL1Candles; +double mLastL1R; +double mLastL1S; +int mLastL1StartBarIndex = 0; +ENUM_SERIESMODE mL1HHMode = NULL; +ENUM_SERIESMODE mL1LLMode = NULL; +datetime mLastL1StartTime = NULL; +ENUM_TIMEFRAMES mL1Period = NULL; + +// +int mL2Candles; +double mLastL2R; +double mLastL2S; +int mLastL2StartBarIndex = 0; +ENUM_SERIESMODE mL2HHMode = NULL; +ENUM_SERIESMODE mL2LLMode = NULL; +datetime mLastL2StartTime = NULL; +ENUM_TIMEFRAMES mL2Period = NULL; + +// +int mL3Candles; +double mLastL3R; +double mLastL3S; +int mLastL3StartBarIndex = 0; +ENUM_SERIESMODE mL3HHMode = NULL; +ENUM_SERIESMODE mL3LLMode = NULL; +datetime mLastL3StartTime = NULL; +ENUM_TIMEFRAMES mL3Period = NULL; + +// +int mL4Candles; +double mLastL4R; +double mLastL4S; +int mLastL4StartBarIndex = 0; +ENUM_SERIESMODE mL4HHMode = NULL; +ENUM_SERIESMODE mL4LLMode = NULL; +datetime mLastL4StartTime = NULL; +ENUM_TIMEFRAMES mL4Period = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Do Initialization ... + + // + if (currentPeriodSecconds == 0) + { + currentPeriodSecconds = PeriodSeconds(_Period); + } + + // + // Find Level 1 Period ... + if (mL1Period == NULL) + { + // + if (l1Method == X_PERIOD_AUTO) + { + mL1Period = GetNearestTimeFrame(_Period); + } + else + { + mL1Period = l1Period; + } + + // + int level1PeriodSecconds = PeriodSeconds(mL1Period); + + // + mL1Candles = level1PeriodSecconds / currentPeriodSecconds; + + // + mL1HHMode = l1HHMode == NULL ? MODE_HIGH : l1HHMode; + mL1LLMode = l1LLMode == NULL ? MODE_LOW : l1LLMode; + } + + // + // Find Level 2 Period ... + if (mL2Period == NULL) + { + // + if (l2Method == X_PERIOD_AUTO) + { + mL2Period = GetMediestTimeFrame(_Period); + } + else + { + mL2Period = l2Period; + } + + // + int level2PeriodSecconds = PeriodSeconds(mL2Period); + + // + mL2Candles = level2PeriodSecconds / currentPeriodSecconds; + + // + mL2HHMode = l2HHMode == NULL ? MODE_HIGH : l2HHMode; + mL2LLMode = l2LLMode == NULL ? MODE_LOW : l2LLMode; + } + + // + // Find Level 3 Period ... + if (mL3Period == NULL) + { + // + if (l3Method == X_PERIOD_AUTO) + { + mL3Period = GetFarestTimeFrame(_Period); + } + else + { + mL3Period = l3Period; + } + + // + int level3PeriodSecconds = PeriodSeconds(mL3Period); + + // + mL3Candles = level3PeriodSecconds / currentPeriodSecconds; + + // + mL3HHMode = l3HHMode == NULL ? MODE_HIGH : l3HHMode; + mL3LLMode = l3LLMode == NULL ? MODE_LOW : l3LLMode; + } + + // + // Find Level 4 Period ... + if (mL4Period == NULL) + { + // + if (l4Method == X_PERIOD_AUTO) + { + mL4Period = GetHindmostTimeFrame(_Period); + } + else + { + mL4Period = l4Period; + } + + // + int level4PeriodSecconds = PeriodSeconds(mL4Period); + + // + mL4Candles = level4PeriodSecconds / currentPeriodSecconds; + + // + mL4HHMode = l4HHMode == NULL ? MODE_HIGH : l4HHMode; + mL4LLMode = l4LLMode == NULL ? MODE_LOW : l4LLMode; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + string comment = GenerateComment(); + Comment(comment); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Inputs ... + (l1Method != X_PERIOD_NOTHING && + (l1Period == NULL ? l1Method == X_PERIOD_AUTO : true)) + // + && + // + (l2Method != X_PERIOD_NOTHING && + (l2Period == NULL ? l2Method == X_PERIOD_AUTO : true)) + // + && + // + (l3Method != X_PERIOD_NOTHING && + (l3Period == NULL ? l3Method == X_PERIOD_AUTO : true)) + // + && + // + (l4Method != X_PERIOD_NOTHING && + (l4Period == NULL ? l4Method == X_PERIOD_AUTO : true)) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LEVEL 1 ... + ENUM_DRAW_TYPE l1DrawType = showSRLevel1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE l1PPDrawType = showPPLevel1 ? DRAW_LINE : DRAW_NONE; + + // + // RESISTANCE ... + ArraySetAsSeries(l1RBuffer, true); + SetIndexBuffer(l1RBufferIndex, l1RBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l1RBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1RBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l1RBufferIndex, PLOT_DRAW_TYPE, l1DrawType); + + ArraySetAsSeries(l1R1Buffer, true); + SetIndexBuffer(l1R1BufferIndex, l1R1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l1R1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1R1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l1R1BufferIndex, PLOT_DRAW_TYPE, l1PPDrawType); + + ArraySetAsSeries(l1R2Buffer, true); + SetIndexBuffer(l1R2BufferIndex, l1R2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l1R2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1R2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l1R2BufferIndex, PLOT_DRAW_TYPE, l1PPDrawType); + + // + // SUPPORT ... + ArraySetAsSeries(l1SBuffer, true); + SetIndexBuffer(l1SBufferIndex, l1SBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l1SBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1SBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l1SBufferIndex, PLOT_DRAW_TYPE, l1DrawType); + + ArraySetAsSeries(l1S1Buffer, true); + SetIndexBuffer(l1S1BufferIndex, l1S1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l1S1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1S1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l1S1BufferIndex, PLOT_DRAW_TYPE, l1PPDrawType); + + ArraySetAsSeries(l1S2Buffer, true); + SetIndexBuffer(l1S2BufferIndex, l1S2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l1S2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1S2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l1S2BufferIndex, PLOT_DRAW_TYPE, l1PPDrawType); + + // + // LEVEL 2 ... + ENUM_DRAW_TYPE l2DrawType = showSRLevel2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE l2PPDrawType = showPPLevel2 ? DRAW_LINE : DRAW_NONE; + + // + // RESISTANCE ... + ArraySetAsSeries(l2RBuffer, true); + SetIndexBuffer(l2RBufferIndex, l2RBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l2RBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2RBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l2RBufferIndex, PLOT_DRAW_TYPE, l2DrawType); + + ArraySetAsSeries(l2R1Buffer, true); + SetIndexBuffer(l2R1BufferIndex, l2R1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l2R1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2R1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l2R1BufferIndex, PLOT_DRAW_TYPE, l2PPDrawType); + + ArraySetAsSeries(l2R2Buffer, true); + SetIndexBuffer(l2R2BufferIndex, l2R2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l2R2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2R2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l2R2BufferIndex, PLOT_DRAW_TYPE, l2PPDrawType); + + // + // SUPPORT ... + ArraySetAsSeries(l2SBuffer, true); + SetIndexBuffer(l2SBufferIndex, l2SBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l2SBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2SBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l2SBufferIndex, PLOT_DRAW_TYPE, l2DrawType); + + ArraySetAsSeries(l2S1Buffer, true); + SetIndexBuffer(l2S1BufferIndex, l2S1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l2S1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2S1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l2S1BufferIndex, PLOT_DRAW_TYPE, l2PPDrawType); + + ArraySetAsSeries(l2S2Buffer, true); + SetIndexBuffer(l2S2BufferIndex, l2S2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l2S2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2S2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l2S2BufferIndex, PLOT_DRAW_TYPE, l2PPDrawType); + + // + // LEVEL 3 ... + ENUM_DRAW_TYPE l3DrawType = showSRLevel3 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE l3PPDrawType = showPPLevel3 ? DRAW_LINE : DRAW_NONE; + + // + // RESISTANCE ... + ArraySetAsSeries(l3RBuffer, true); + SetIndexBuffer(l3RBufferIndex, l3RBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l3RBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3RBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l3RBufferIndex, PLOT_DRAW_TYPE, l3DrawType); + + ArraySetAsSeries(l3R1Buffer, true); + SetIndexBuffer(l3R1BufferIndex, l3R1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l3R1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3R1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l3R1BufferIndex, PLOT_DRAW_TYPE, l3PPDrawType); + + ArraySetAsSeries(l3R2Buffer, true); + SetIndexBuffer(l3R2BufferIndex, l3R2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l3R2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3R2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l3R2BufferIndex, PLOT_DRAW_TYPE, l3PPDrawType); + + // + // SUPPORT ... + ArraySetAsSeries(l3SBuffer, true); + SetIndexBuffer(l3SBufferIndex, l3SBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l3SBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3SBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l3SBufferIndex, PLOT_DRAW_TYPE, l3DrawType); + + ArraySetAsSeries(l3S1Buffer, true); + SetIndexBuffer(l3S1BufferIndex, l3S1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l3S1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3S1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l3S1BufferIndex, PLOT_DRAW_TYPE, l3PPDrawType); + + ArraySetAsSeries(l3S2Buffer, true); + SetIndexBuffer(l3S2BufferIndex, l3S2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l3S2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3S2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l3S2BufferIndex, PLOT_DRAW_TYPE, l3PPDrawType); + + // + // LEVEL 4 ... + ENUM_DRAW_TYPE l4DrawType = showSRLevel4 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE l4PPDrawType = showPPLevel4 ? DRAW_LINE : DRAW_NONE; + + // + // RESISTANCE ... + ArraySetAsSeries(l4RBuffer, true); + SetIndexBuffer(l4RBufferIndex, l4RBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l4RBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l4RBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l4RBufferIndex, PLOT_DRAW_TYPE, l4DrawType); + + ArraySetAsSeries(l4R1Buffer, true); + SetIndexBuffer(l4R1BufferIndex, l4R1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l4R1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l4R1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l4R1BufferIndex, PLOT_DRAW_TYPE, l4PPDrawType); + + ArraySetAsSeries(l4R2Buffer, true); + SetIndexBuffer(l4R2BufferIndex, l4R2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l4R2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l4R2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l4R2BufferIndex, PLOT_DRAW_TYPE, l4PPDrawType); + + // + // SUPPORT ... + ArraySetAsSeries(l4SBuffer, true); + SetIndexBuffer(l4SBufferIndex, l4SBuffer, INDICATOR_DATA); + PlotIndexSetInteger(l4SBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l4SBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l4SBufferIndex, PLOT_DRAW_TYPE, l4DrawType); + + ArraySetAsSeries(l4S1Buffer, true); + SetIndexBuffer(l4S1BufferIndex, l4S1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l4S1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l4S1BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l4S1BufferIndex, PLOT_DRAW_TYPE, l4PPDrawType); + + ArraySetAsSeries(l4S2Buffer, true); + SetIndexBuffer(l4S2BufferIndex, l4S2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(l4S2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l4S2BufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(l4S2BufferIndex, PLOT_DRAW_TYPE, l4PPDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + XOHCL c = GetCandle(bar_index); + + // + int maxCandles = MathMax(mL1Candles, mL2Candles); + maxCandles = MathMax(maxCandles, mL3Candles); + maxCandles = MathMax(maxCandles, mL4Candles); + + // + double l1RValue = 0; + double l1SValue = 0; + double l1CloseValue = 0; + + // + double l2RValue = 0; + double l2SValue = 0; + double l2CloseValue = 0; + + // + double l3RValue = 0; + double l3SValue = 0; + double l3CloseValue = 0; + + // + double l4RValue = 0; + double l4SValue = 0; + double l4CloseValue = 0; + + // + double l1PPValue = 0; + double l1R1Value = 0; + double l1R2Value = 0; + double l1S1Value = 0; + double l1S2Value = 0; + + // + double l2PPValue = 0; + double l2R1Value = 0; + double l2R2Value = 0; + double l2S1Value = 0; + double l2S2Value = 0; + + // + double l3PPValue = 0; + double l3R1Value = 0; + double l3R2Value = 0; + double l3S1Value = 0; + double l3S2Value = 0; + + // + double l4PPValue = 0; + double l4R1Value = 0; + double l4R2Value = 0; + double l4S1Value = 0; + double l4S2Value = 0; + + // + // LEVEL 1 ... + + // + l1RValue = GetHighestHigh( + mL1Candles, + bar_index, + mL1HHMode); + l1SValue = GetLowestLow( + mL1Candles, + bar_index, + mL1LLMode); + l1CloseValue = GetLowestLow( + mL1Candles, + bar_index, + MODE_CLOSE); + + // + // Calculate Pivot Points ... + double l1Diff = MathAbs(l1RValue - l1SValue); + l1PPValue = (l1RValue + l1SValue + l1CloseValue) / 3; + + // + l1R1Value = (2 * l1PPValue) - l1SValue; + l1R2Value = l1PPValue + (l1Diff); + + // + l1S1Value = (2 * l1PPValue) - l1RValue; + l1S2Value = l1PPValue - l1Diff; + + // + // LEVEL 2 ... + + // + l2RValue = GetHighestHigh( + mL2Candles, + bar_index, + mL2HHMode); + l2SValue = GetLowestLow( + mL2Candles, + bar_index, + mL2LLMode); + l2CloseValue = GetLowestLow( + mL2Candles, + bar_index, + MODE_CLOSE); + + // + // Calculate Pivot Points ... + double l2Diff = MathAbs(l2RValue - l2SValue); + l2PPValue = (l2RValue + l2SValue + l2CloseValue) / 3; + + // + l2R1Value = (2 * l2PPValue) - l2SValue; + l2R2Value = l2PPValue + (l2Diff); + + // + l2S1Value = (2 * l2PPValue) - l2RValue; + l2S2Value = l2PPValue - l2Diff; + + // + // LEVEL 3 ... + + // + l3RValue = GetHighestHigh( + mL3Candles, + bar_index, + mL3HHMode); + l3SValue = GetLowestLow( + mL3Candles, + bar_index, + mL3LLMode); + l3CloseValue = GetLowestLow( + mL3Candles, + bar_index, + MODE_CLOSE); + + // + // Calculate Pivot Points ... + double l3Diff = MathAbs(l3RValue - l3SValue); + l3PPValue = (l3RValue + l3SValue + l3CloseValue) / 3; + + // + l3R1Value = (2 * l3PPValue) - l3SValue; + l3R2Value = l1PPValue + (l3Diff); + + // + l3S1Value = (2 * l3PPValue) - l3RValue; + l3S2Value = l3PPValue - l3Diff; + + // + // LEVEL 4 ... + + // + l4RValue = GetHighestHigh( + mL4Candles, + bar_index, + mL4HHMode); + l4SValue = GetLowestLow( + mL4Candles, + bar_index, + mL4LLMode); + l4CloseValue = GetLowestLow( + mL4Candles, + bar_index, + MODE_CLOSE); + + // + // Calculate Pivot Points ... + double l4Diff = MathAbs(l4RValue - l4SValue); + l4PPValue = (l4RValue + l4SValue + l4CloseValue) / 3; + + // + l4R1Value = (2 * l4PPValue) - l4SValue; + l4R2Value = l4PPValue + (l4Diff); + + // + l4S1Value = (2 * l4PPValue) - l4RValue; + l4S2Value = l4PPValue - l4Diff; + + // + // FILLING BUFFERS ... + + // + l1RBuffer[bar_index] = l1RValue; + l1R1Buffer[bar_index] = l1R1Value; + l1R2Buffer[bar_index] = l1R2Value; + + // + l1SBuffer[bar_index] = l1SValue; + l1S1Buffer[bar_index] = l1S1Value; + l1S2Buffer[bar_index] = l1S2Value; + + // + l2RBuffer[bar_index] = l2RValue; + l2R1Buffer[bar_index] = l2R1Value; + l2R2Buffer[bar_index] = l2R2Value; + + // + l2SBuffer[bar_index] = l2SValue; + l2S1Buffer[bar_index] = l2S1Value; + l2S2Buffer[bar_index] = l2S2Value; + + // + l3RBuffer[bar_index] = l3RValue; + l3R1Buffer[bar_index] = l3R1Value; + l3R2Buffer[bar_index] = l3R2Value; + + // + l3SBuffer[bar_index] = l3SValue; + l3S1Buffer[bar_index] = l3S1Value; + l3S2Buffer[bar_index] = l3S2Value; + + // + l4RBuffer[bar_index] = l4RValue; + l4R1Buffer[bar_index] = l4R1Value; + l4R2Buffer[bar_index] = l4R2Value; + + // + l4SBuffer[bar_index] = l4SValue; + l4S1Buffer[bar_index] = l4S1Value; + l4S2Buffer[bar_index] = l4S2Value; +} + +// +// Generate Comment String ... +string GenerateComment() +{ + // + string result = ""; + + // + result += "L1 P: " + EnumToString(mL1Period) + "\n"; + result += "L2 P: " + EnumToString(mL2Period) + "\n"; + result += "L3 P: " + EnumToString(mL3Period) + "\n"; + result += "L4 P: " + EnumToString(mL4Period); + + // + return result; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xpv.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xpv.mq5 new file mode 100644 index 0000000..c0d2a47 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xpv.mq5 @@ -0,0 +1,1124 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_PV Peaks and Vales Indicator +// ----------------------------------------------------------- +// Name: X121_PV +// Description: Market Peaks and Vales +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_PV Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_PV" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret Cycles"; +input int shortLength = 9; // Short Length +input int mediumLength = 17; // Medium Length +input int longLength = 26; // Long Length +input int hindLength = 35; // Hind Length + +// +input group "Trend"; +input int numOfShoulder = 10; // Number of Shoulders for Swings + +// +input group "Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; +input bool showPeaksAndVales = true; // Show Peaks and Vales +input bool showLevels = false; // Show Levels +input bool showTrend = false; // Show Trend +input bool showSRs = false; // Show Support and Resistance + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 14 +#property indicator_plots 12 + +// +// PEKSANDVALES ... + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "X121_PV PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "X121_PV VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define rBufferIndex 2 +double rBuffer[]; + +// +#define rColorBufferIndex 3 +double rColorBuffer[]; + +// +#property indicator_label3 "X121_PV R" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 clrAqua, CLR_NONE +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define sBufferIndex 4 +#define sBufferPlotIndex 3 +double sBuffer[]; + +// +#define sColorBufferIndex 5 +double sColorBuffer[]; + +// +#property indicator_label4 "X121_PV S" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 clrMagenta, CLR_NONE +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define sHHBufferIndex 6 +#define sHHBufferPlotIndex 4 +double sHHBuffer[]; + +// +#property indicator_label5 "X121_PV SHH" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrLightGray +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +#define sLLBufferIndex 7 +#define sLLBufferPlotIndex 5 +double sLLBuffer[]; + +// +#property indicator_label6 "X121_PV SLL" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrLightGray +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +#define mHHBufferIndex 8 +#define mHHBufferPlotIndex 6 +double mHHBuffer[]; + +// +#property indicator_label7 "X121_PV MHH" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrLightGray +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +#define mLLBufferIndex 9 +#define mLLBufferPlotIndex 7 +double mLLBuffer[]; + +// +#property indicator_label8 "X121_PV MLL" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrLightGray +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +#define lHHBufferIndex 10 +#define lHHBufferPlotIndex 8 +double lHHBuffer[]; + +// +#property indicator_label9 "X121_PV LHH" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrLightGray +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 + +// +#define lLLBufferIndex 11 +#define lLLBufferPlotIndex 9 +double lLLBuffer[]; + +// +#property indicator_label10 "X121_PV LLL" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrLightGray +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +// +#define hHHBufferIndex 12 +#define hHHBufferPlotIndex 10 +double hHHBuffer[]; + +// +#property indicator_label11 "X121_PV HHH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrLightGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define hLLBufferIndex 13 +#define hLLBufferPlotIndex 11 +double hLLBuffer[]; + +// +#property indicator_label12 "X121_PV HLL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrLightGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +double lastPeak; +double lastVale; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + RemoveDraws(drawPrefix); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Peaks and Vales ... + (shortLength > 2 && + mediumLength > shortLength && + longLength > mediumLength && + hindLength > longLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax(shortLength, mediumLength); + result = MathMax(result, longLength); + result = MathMax(result, hindLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RANGE ... + + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, 225); + // PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW_SHIFT, -20); + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, 225); + // PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW_SHIFT, 20); + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // SUPPORT and RESISTANCE ... + // + + // + // RESISTANCE ... + ArraySetAsSeries(rBuffer, true); + SetIndexBuffer(rBufferIndex, rBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(rBufferIndex, PLOT_SHOW_DATA, false); + + // + // RESISTANCE Color ... + ArraySetAsSeries(rColorBuffer, true); + SetIndexBuffer(rColorBufferIndex, rColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SUPPORT ... + ArraySetAsSeries(sBuffer, true); + SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // SUPPORT Color ... + ArraySetAsSeries(sColorBuffer, true); + SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX); + + // + ENUM_DRAW_TYPE zoneDrawType = showLevels ? DRAW_LINE : DRAW_NONE; + + // + // SHORT Buffers ... + + // + // HIGH ... + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // MEDIUM Buffer ... + + // + // HIGH ... + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LONG Buffer ... + + // + // HIGH ... + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // HIND Buffer ... + + // + // HIGH ... + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hHHBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); + + // + // LOW ... + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hLLBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, zoneDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate ... + + // + double rColorIDX = 1; + double sColorIDX = 1; + + // + // SHORT ... + + // + // HIGH ... + int sHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + shortLength, + bar_index); + double sHHValue = GetAppliedPrice( + sHHIndex, + hhMode); + + // + sHHBuffer[bar_index] = sHHValue; + + // + // LOW ... + int sLLIndex = iLowest( + _Symbol, + _Period, + llMode, + shortLength, + bar_index); + double sLLValue = GetAppliedPrice( + sLLIndex, + llMode); + + // + sLLBuffer[bar_index] = sLLValue; + + // + // MEDIUM ... + + // + // HIGH ... + int mHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + mediumLength, + bar_index); + double mHHValue = GetAppliedPrice( + mHHIndex, + hhMode); + + // + mHHBuffer[bar_index] = mHHValue; + + // + // LOW ... + int mLLIndex = iLowest( + _Symbol, + _Period, + llMode, + mediumLength, + bar_index); + double mLLValue = GetAppliedPrice( + mLLIndex, + llMode); + + // + mLLBuffer[bar_index] = mLLValue; + + // + // LONG ... + + // + // HIGH ... + int lHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + longLength, + bar_index); + double lHHValue = GetAppliedPrice( + lHHIndex, + hhMode); + + // + lHHBuffer[bar_index] = lHHValue; + + // + // LOW ... + int lLLIndex = iLowest( + _Symbol, + _Period, + llMode, + longLength, + bar_index); + double lLLValue = GetAppliedPrice( + lLLIndex, + llMode); + + // + lLLBuffer[bar_index] = lLLValue; + + // + // HIND ... + + // + // HIGH ... + int hHHIndex = iHighest( + _Symbol, + _Period, + hhMode, + hindLength, + bar_index); + double hHHValue = GetAppliedPrice( + hHHIndex, + hhMode); + + // + hHHBuffer[bar_index] = hHHValue; + + // + // LOW ... + int hLLIndex = iLowest( + _Symbol, + _Period, + llMode, + hindLength, + bar_index); + double hLLValue = GetAppliedPrice( + hLLIndex, + llMode); + + // + hLLBuffer[bar_index] = hLLValue; + + // + // RESISTANCE SUPPORT ... + + // + // RESISTANCE ... + double rValue = (sHHValue + mHHValue + lHHValue + hHHValue) / 4; + rBuffer[bar_index] = rValue; + + // + // SUPPORT ... + double sValue = (sLLValue + mLLValue + lLLValue + hLLValue) / 4; + sBuffer[bar_index] = sValue; + + // + // PEAKS and VALES ... + + // + // PEAKS ... + bool isPeak = rValue == hHHValue && + hHHValue == lHHValue && + lHHValue == mHHValue && + mHHValue == sHHValue; + // + if (isPeak && lastPeak != rValue) + { + // + if (showPeaksAndVales) + { + rColorIDX = 0; + } + + // + lastPeak = rValue; + peaksBuffer[bar_index] = lastPeak; + } + else + { + peaksBuffer[bar_index] = lastPeak; + } + + // + // VALES ... + bool isVale = sValue == hLLValue && + hLLValue == lLLValue && + lLLValue == mLLValue && + mLLValue == sLLValue; + + // + if (isVale && lastVale != sValue) + { + // + if (showPeaksAndVales) + { + sColorIDX = 0; + } + + // + lastVale = sValue; + valesBuffer[bar_index] = lastVale; + } + else + { + valesBuffer[bar_index] = lastVale; + } + + // + // Set Default Colors ... + + // + rColorBuffer[bar_index] = rColorIDX; + sColorBuffer[bar_index] = sColorIDX; + + // + // Find Swings ... + + // + // High ... + int hSwing1 = FindSwing( + _Symbol, + _Period, + MODE_HIGH, + numOfShoulder, + bar_index + 1); + + int hSwing2 = FindSwing( + _Symbol, + _Period, + MODE_HIGH, + numOfShoulder, + hSwing1 + 1); + + // + // High ... + int hSwing3 = FindSwing( + _Symbol, + _Period, + MODE_HIGH, + numOfShoulder, + hSwing2 + 1); + + // int hSwing4 = FindSwing( + // _Symbol, + // _Period, + // MODE_HIGH, + // numOfShoulder, + // hSwing3 + 1); + + // + // Low ... + int lSwing1 = FindSwing( + _Symbol, + _Period, + MODE_LOW, + numOfShoulder, + bar_index + 1); + + int lSwing2 = FindSwing( + _Symbol, + _Period, + MODE_LOW, + numOfShoulder, + lSwing1 + 1); + + int lSwing3 = FindSwing( + _Symbol, + _Period, + MODE_LOW, + numOfShoulder, + lSwing2 + 1); + + // int lSwing4 = FindSwing( + // _Symbol, + // _Period, + // MODE_LOW, + // numOfShoulder, + // lSwing3 + 1); + + // + if (bar_index < 50) + { + + // + bool isStrongResistance = + // + hHHBuffer[bar_index + 1] == hHHBuffer[bar_index + 2] && + hHHBuffer[bar_index + 2] == hHHBuffer[bar_index + 3] && + // + lHHBuffer[bar_index + 1] == lHHBuffer[bar_index + 2] && + lHHBuffer[bar_index + 2] == lHHBuffer[bar_index + 3] && + // + mHHBuffer[bar_index + 1] == mHHBuffer[bar_index + 2] && + mHHBuffer[bar_index + 2] == mHHBuffer[bar_index + 3] && + // + sHHBuffer[bar_index + 1] == sHHBuffer[bar_index + 2] && + sHHBuffer[bar_index + 2] == sHHBuffer[bar_index + 3] + // + ; + + // + bool isStrongSupport = + // + hLLBuffer[bar_index + 1] == hLLBuffer[bar_index + 2] && + hLLBuffer[bar_index + 2] == hLLBuffer[bar_index + 3] && + // + lLLBuffer[bar_index + 1] == lLLBuffer[bar_index + 2] && + lLLBuffer[bar_index + 2] == lLLBuffer[bar_index + 3] && + // + mLLBuffer[bar_index + 1] == mLLBuffer[bar_index + 2] && + mLLBuffer[bar_index + 2] == mLLBuffer[bar_index + 3] && + // + sLLBuffer[bar_index + 1] == sLLBuffer[bar_index + 2] && + sLLBuffer[bar_index + 2] == sLLBuffer[bar_index + 3] + // + ; + + // + if (isStrongResistance && showSRs) + { + // + DrawSupportResistance( + "R", + clrRed, + sHHBuffer[bar_index + 3], + bar_index + 3); + } + + // + if (isStrongSupport && showSRs) + { + // + DrawSupportResistance( + "S", + clrGreen, + sLLBuffer[bar_index + 3], + bar_index + 3); + } + } + + // + if (showTrend && bar_index < 20) + { + // + DrawSwing( + "High1", + MODE_HIGH, + clrAqua, + hSwing1, + hSwing2); + + // + DrawSwing( + "Low1", + MODE_LOW, + clrAqua, + lSwing1, + lSwing2); + + // + DrawSwing( + "High2", + MODE_HIGH, + clrMagenta, + hSwing2, + hSwing3); + + // + DrawSwing( + "Low2", + MODE_LOW, + clrMagenta, + lSwing2, + lSwing3); + } +} + +// +void DrawSwing( + string prefix, // Prefix ... + ENUM_SERIESMODE mode, // Swing Mode ... + color swingColor, // Color ... + int index1, // Index 1 ... + int index2 // Index 2 ... +) +{ + // + if (mode != MODE_HIGH && mode != MODE_LOW) + { + return; + } + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + index1); + + // + datetime time1 = GetCandleTime( + _Symbol, + _Period, + index1); + + // + XOHCL c2 = GetCandle( + _Symbol, + _Period, + index2); + + // + datetime time2 = GetCandleTime( + _Symbol, + _Period, + index2); + + // + double value1 = -1; + double value2 = -1; + + // + switch (mode) + { + // + case MODE_HIGH: + value1 = c1.high; + value2 = c2.high; + break; + + // + case MODE_LOW: + value1 = c1.low; + value2 = c2.low; + break; + } + + // + if (value1 == -1 || value2 == -1) + { + return; + } + + // + long chartId = ChartID(); + string tlName = prefix + "_" + "TrendLine"; + + // // + // if (IsDrawExists(tlName)) { + // RemoveDraw(tlName); + // } + + // + DrawTrendLine( + chartId, + tlName, + 0, + time2, + value2, + time1, + value1, + swingColor, + STYLE_DOT, + 3, + false, + false, + true); +} + +// +// Draw Support and Resistance ... +void DrawSupportResistance( + string prefix, // Prefix ... + color lColor, // Color ... + double price, // Support or Resistance price ... + int bar_index // Start Bar Index ... +) +{ + // + datetime time1 = GetCandleTime( + _Symbol, + _Period, + bar_index); + + // + datetime time2 = GetCandleTime( + _Symbol, + _Period, + bar_index - 1); + + // + long chartId = ChartID(); + string tlName = prefix + "_" + "TL" + "_" + (string)(NormalizePrice(price, _Symbol)); + + // + DrawTrendLine( + chartId, + tlName, + 0, + time1, + price, + time2, + price, + lColor, + STYLE_DOT, + 3, + false, + false, + true); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xsslc.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xsslc.mq5 new file mode 100644 index 0000000..bdfe5b2 --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xsslc.mq5 @@ -0,0 +1,453 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_SSLC SSL Channel +// ---------------------------------------------------- +// Name: X121_SSLC +// Description: SSL Channel Indicator +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_SSLC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_SSLC" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 30; // Length + +// +input group "Calculation"; +input ENUM_MA_METHOD method = MODE_SMA; // Method +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Applied To +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Applied To + +// +input group "Presentation"; +input bool showUp = true; // Show Up +input bool showDown = true; // Show Down + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 5 +#property indicator_plots 2 + +// +// PLOTTED Buffers ... + +// +#define upBufferIndex 0 +double upBuffer[]; + +// +#property indicator_label1 "X121_SSLC Up" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#define downBufferIndex 1 +double downBuffer[]; + +// +#property indicator_label2 "X121_SSLC Down" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// DATA Buffers ... + +// +#define upMaBufferIndex 2 +double upMaBuffer[]; + +// +#define downMaBufferIndex 3 +double downMaBuffer[]; + +// +#define kpiBufferIndex 4 +double kpiBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int upHandler = INVALID_HANDLE; +int downHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initialize Requierd Handlers ... + upHandler = iMA( + _Symbol, + _Period, + length, + 0, + method, + upAppliedTo); + downHandler = iMA( + _Symbol, + _Period, + length, + 0, + method, + downAppliedTo); + if (upHandler == INVALID_HANDLE || downHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + LogMessage(msg); + + // + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Release Indicators ... + IndicatorRelease(upHandler); + IndicatorRelease(downHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int upCalculatedBars = BarsCalculated(upHandler); + int downCalculatedBars = BarsCalculated(downHandler); + if (upCalculatedBars < maxLength || + downCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedUps = CopyBuffer(upHandler, 0, 0, limit, upMaBuffer); + int copiedDowns = CopyBuffer(downHandler, 0, 0, limit, downMaBuffer); + if (copiedUps <= 0 || + copiedDowns <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i, limit, rates_total, prev_calculated, close); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Inputs ... + (length > 2) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(result, length); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // UP ... + + // + ENUM_DRAW_TYPE upDrawType = showUp ? DRAW_LINE : DRAW_NONE; + + + ArraySetAsSeries(upBuffer, true); + SetIndexBuffer(upBufferIndex, upBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(upBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(upBufferIndex, PLOT_DRAW_TYPE, upDrawType); + + // + // DOWN ... + + // + ENUM_DRAW_TYPE downDrawType = showDown ? DRAW_LINE : DRAW_NONE; + + + ArraySetAsSeries(downBuffer, true); + SetIndexBuffer(downBufferIndex, downBuffer, INDICATOR_DATA); + PlotIndexSetInteger(downBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(downBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(downBufferIndex, PLOT_DRAW_TYPE, downDrawType); + + // + // DATA Buffers ... + + // + // UP MA ... + ArraySetAsSeries(upMaBuffer, true); + SetIndexBuffer(upMaBufferIndex, upMaBuffer, INDICATOR_CALCULATIONS); + + // + // DOWN MA ... + ArraySetAsSeries(downMaBuffer, true); + SetIndexBuffer(downMaBufferIndex, downMaBuffer, INDICATOR_CALCULATIONS); + + // + // KPI ... + ArraySetAsSeries(kpiBuffer, true); + SetIndexBuffer(kpiBufferIndex, kpiBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int limit, + int ratesTotal, + int prevCalculated, + const double &close[]) +{ + // + double upMaValue = upMaBuffer[bar_index]; + double downMaValue = downMaBuffer[bar_index]; + + // + double closeValue = close[bar_index]; + + // + double kpiValue; + if (closeValue > upMaValue) { + kpiValue = 1; + } else if (closeValue < downMaValue) { + kpiValue = -1; + } else { + kpiValue = kpiBuffer[bar_index + 1]; + } + + // + kpiBuffer[bar_index] = kpiValue; + + // + double upValue = kpiValue < 0 ? downMaValue : upMaValue; + upBuffer[bar_index] = upValue; + + // + double downValue = kpiValue < 0 ? upMaValue : downMaValue; + downBuffer[bar_index] = downValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtm.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtm.mq5 new file mode 100644 index 0000000..427af2b --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtm.mq5 @@ -0,0 +1,355 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121_XTM +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XTM Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "X121_XTM" + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 0, + X_XTM_BEARISH = 2, + X_XTM_NEUTURAL = 1, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int length = 35; // Length +input int shift = 0; // Shift + +// +input group "Calculations"; +input ENUM_MA_METHOD method = MODE_SMA; // Method +input ENUM_APPLIED_PRICE appliedTo = PRICE_LOW; // Applied To + +// +input group "Presentation"; +input bool showLine = true; // Show Line + +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 2 +#property indicator_plots 2 + +// +// maBuffer ... +#define maBufferIndex 0 +double maBuffer[]; + +#define maColorBufferIndex 1 +double maColorBuffer[]; + +// +#property indicator_label1 "X121 XTM" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int maHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initializing MA Handler ... + maHandler = iMA( + _Symbol, + _Period, + length, + shift, + method, + appliedTo); + if (maHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Ma Handler ..."; + Print(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(maHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = length; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showLine ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showLine); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtrnd.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtrnd.mq5 new file mode 100644 index 0000000..32e70cd --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Indicators/x-saherelm.x121.xtrnd.mq5 @@ -0,0 +1,1151 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_XTRND Trends Indicator +// ----------------------------------------------------------- +// Name: X121_XTRND +// Description: Market Trend Detector ... +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XTRND Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_XTRND" + +// +// XPERIOD Calculation Method ... +// USED For Multiple Time Frames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int cycleLength = 2; // Cycle Length to Check +input int numberOfVerifications = 2; // Number of Verifications + +// +input group "Calculation"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Detect Up +input ENUM_SERIESMODE llMode = MODE_LOW; // Detect Low + +// +input group "Cycles"; + +// +input group "Level 1"; +input ENUM_X_PERIOD_METHOD l1Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l1Period = NULL; // Time Period + +// +input group "Level 2"; +input ENUM_X_PERIOD_METHOD l2Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l2Period = NULL; // Time Period + +// +input group "Level 3"; +input ENUM_X_PERIOD_METHOD l3Method = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES l3Period = NULL; // Time Period + +// +input group "Presentation"; +input bool showConsolidations = false; // Show Consolidations +input bool showTrend = true; // Show Trend +input bool showL1Trends = false; // Show Cycle 1 Trend +input bool showL2Trends = false; // Show Cycle 2 Trend +input bool showL3Trends = false; // Show Cycle 3 Trend + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 16 +#property indicator_plots 16 + +// +// Higher High ... +#define hhBufferIndex 0 +#define hhPlotBufferIndex 0 +double hhBuffer[]; + +#define hhColorBufferIndex 1 +double hhColorBuffer[]; + +// +#property indicator_label1 "X121_XTRND U" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// Lower Low ... +#define llBufferIndex 2 +#define llPlotBufferIndex 1 +double llBuffer[]; + +#define llColorBufferIndex 3 +double llColorBuffer[]; + +// +#property indicator_label2 "X121_XTRND D" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// CYCLE 1 ... + +// +// Higher High ... +#define l1hhBufferIndex 4 +#define l1hhPlotBufferIndex 2 +double l1hhBuffer[]; + +#define l1hhColorBufferIndex 5 +double l1hhColorBuffer[]; + +// +#property indicator_label3 "X121_XTRND C1 U" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +// Lower Low ... +#define l1llBufferIndex 6 +#define l1llPlotBufferIndex 3 +double l1llBuffer[]; + +#define l1llColorBufferIndex 7 +double l1llColorBuffer[]; + +// +#property indicator_label4 "X121_XTRND C1 D" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// CYCLE 2 ... + +// +// Higher High ... +#define l2hhBufferIndex 8 +#define l2hhPlotBufferIndex 4 +double l2hhBuffer[]; + +#define l2hhColorBufferIndex 9 +double l2hhColorBuffer[]; + +// +#property indicator_label5 "X121_XTRND C2 U" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// Lower Low ... +#define l2llBufferIndex 10 +#define l2llPlotBufferIndex 5 +double l2llBuffer[]; + +#define l2llColorBufferIndex 11 +double l2llColorBuffer[]; + +// +#property indicator_label6 "X121_XTRND C2 D" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +// CYCLE 3 ... + +// +// Higher High ... +#define l3hhBufferIndex 12 +#define l3hhPlotBufferIndex 6 +double l3hhBuffer[]; + +#define l3hhColorBufferIndex 13 +double l3hhColorBuffer[]; + +// +#property indicator_label7 "X121_XTRND C3 U" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +// Lower Low ... +#define l3llBufferIndex 14 +#define l3llPlotBufferIndex 7 +double l3llBuffer[]; + +#define l3llColorBufferIndex 15 +double l3llColorBuffer[]; + +// +#property indicator_label8 "X121_XTRND C3 D" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int currentPeriodSecconds = 0; + +// +// CYCLE 1 ... +int mL1Candles; +int mL1PeriodSecconds = 0; +int mLastL1StartBarIndex = 0; +datetime mLastL1StartTime = NULL; +ENUM_TIMEFRAMES mL1Period = NULL; + +// +// CYCLE 2 ... +int mL2Candles; +int mL2PeriodSecconds = 0; +int mLastL2StartBarIndex = 0; +datetime mLastL2StartTime = NULL; +ENUM_TIMEFRAMES mL2Period = NULL; + +// +// CYCLE 3 ... +int mL3Candles; +int mL3PeriodSecconds = 0; +int mLastL3StartBarIndex = 0; +datetime mLastL3StartTime = NULL; +ENUM_TIMEFRAMES mL3Period = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initial Periods ... + InitialCycles(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (cycleLength > 0 && + numberOfVerifications > 0) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Peaks and Vales ... + result = MathMax( + cycleLength, + numberOfVerifications); + + // + return result; +} + +// +// Initial Multi Time Frame Cycles Periods ... +void InitialCycles() +{ + // + // Calculate Current Period Secconds ... + currentPeriodSecconds = PeriodSeconds(_Period); + + // + // Nearest ... + // Calculate Cycle 1 Requirements ... + if (mL1Period == NULL) + { + // + if (l1Method == X_PERIOD_AUTO) + { + mL1Period = GetNearestTimeFrame(_Period); + } + else + { + mL1Period = l1Period; + } + + // + mL1PeriodSecconds = PeriodSeconds(mL1Period); + + // + mL1Candles = mL1PeriodSecconds / currentPeriodSecconds; + } + + // + // Mediest ... + // Calculate Cycle 2 Requirements ... + if (mL2Period == NULL) + { + // + if (l2Method == X_PERIOD_AUTO) + { + mL2Period = GetMediestTimeFrame(_Period); + } + else + { + mL2Period = l2Period; + } + + // + mL2PeriodSecconds = PeriodSeconds(mL2Period); + + // + mL2Candles = mL2PeriodSecconds / currentPeriodSecconds; + } + + // + // Farest ... + // Calculate Cycle 3 Requirements ... + if (mL3Period == NULL) + { + // + if (l3Method == X_PERIOD_AUTO) + { + mL3Period = GetFarestTimeFrame(_Period); + } + else + { + mL3Period = l3Period; + } + + // + mL3PeriodSecconds = PeriodSeconds(mL3Period); + + // + mL3Candles = mL3PeriodSecconds / currentPeriodSecconds; + } +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showTrend ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(hhBuffer, true); + SetIndexBuffer(hhBufferIndex, hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hhPlotBufferIndex, PLOT_DRAW_TYPE, drawType); + + // + // COLOR Buffer ... + ArraySetAsSeries(hhColorBuffer, true); + SetIndexBuffer(hhColorBufferIndex, hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(llBuffer, true); + SetIndexBuffer(llBufferIndex, llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(llPlotBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(llPlotBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(llColorBuffer, true); + SetIndexBuffer(llColorBufferIndex, llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // CYCLES ... + + // + // NEAREST ... + + // + ENUM_DRAW_TYPE l1DrawType = showL1Trends ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l1hhBuffer, true); + SetIndexBuffer(l1hhBufferIndex, l1hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l1hhPlotBufferIndex, PLOT_SHOW_DATA, showL1Trends); + PlotIndexSetInteger(l1hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l1hhPlotBufferIndex, PLOT_DRAW_TYPE, l1DrawType); + + // + // COLOR Buffer ... + ArraySetAsSeries(l1hhColorBuffer, true); + SetIndexBuffer(l1hhColorBufferIndex, l1hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l1llBuffer, true); + SetIndexBuffer(l1llBufferIndex, l1llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l1llPlotBufferIndex, PLOT_SHOW_DATA, showL1Trends); + PlotIndexSetInteger(l1llPlotBufferIndex, PLOT_DRAW_TYPE, l1DrawType); + PlotIndexSetInteger(l1llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l1llColorBuffer, true); + SetIndexBuffer(l1llColorBufferIndex, l1llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIEST ... + + // + ENUM_DRAW_TYPE l2DrawType = showL2Trends ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l2hhBuffer, true); + SetIndexBuffer(l2hhBufferIndex, l2hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l2hhPlotBufferIndex, PLOT_SHOW_DATA, showL2Trends); + PlotIndexSetInteger(l2hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l2hhPlotBufferIndex, PLOT_DRAW_TYPE, l2DrawType); + + // + // COLOR Buffer ... + ArraySetAsSeries(l2hhColorBuffer, true); + SetIndexBuffer(l2hhColorBufferIndex, l2hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l2llBuffer, true); + SetIndexBuffer(l2llBufferIndex, l2llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l2llPlotBufferIndex, PLOT_SHOW_DATA, showL2Trends); + PlotIndexSetInteger(l2llPlotBufferIndex, PLOT_DRAW_TYPE, l2DrawType); + PlotIndexSetInteger(l2llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l2llColorBuffer, true); + SetIndexBuffer(l2llColorBufferIndex, l2llColorBuffer, INDICATOR_COLOR_INDEX); + + // + // FAREST ... + + // + ENUM_DRAW_TYPE l3DrawType = showL3Trends ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // HH Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l3hhBuffer, true); + SetIndexBuffer(l3hhBufferIndex, l3hhBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l3hhPlotBufferIndex, PLOT_SHOW_DATA, showL3Trends); + PlotIndexSetInteger(l3hhPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(l3hhPlotBufferIndex, PLOT_DRAW_TYPE, l3DrawType); + + // + // COLOR Buffer ... + ArraySetAsSeries(l3hhColorBuffer, true); + SetIndexBuffer(l3hhColorBufferIndex, l3hhColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LL Buffer ... + + // + // SERIES ... + ArraySetAsSeries(l3llBuffer, true); + SetIndexBuffer(l3llBufferIndex, l3llBuffer, INDICATOR_DATA); + + // + // PLOT Config ... + PlotIndexSetInteger(l3llPlotBufferIndex, PLOT_SHOW_DATA, showL3Trends); + PlotIndexSetInteger(l3llPlotBufferIndex, PLOT_DRAW_TYPE, l3DrawType); + PlotIndexSetInteger(l3llPlotBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // COLOR Buffer ... + ArraySetAsSeries(l3llColorBuffer, true); + SetIndexBuffer(l3llColorBufferIndex, l3llColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // HIGHER Highs ... + double hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + cycleLength, + bar_index); + + // + hhBuffer[bar_index] = hh; + + // + // LOWER Lows ... + double ll = GetLowestLow( + _Symbol, + _Period, + llMode, + cycleLength, + bar_index); + + // + llBuffer[bar_index] = ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double hhColorIDX = showConsolidations ? 1 : 0; + double llColorIDX = showConsolidations ? 1 : 0; + + // + // Calculate Cycle Changes ... + + // + int cycleCLength = cycleLength * numberOfVerifications; + bool isCycleCLengthPassed = MathAbs(ArraySize(hhBuffer) - bar_index) > cycleCLength + 1; + + // + if (isCycleCLengthPassed) + { + // + bool isLowestLowUp = true; // ll > llBuffer[bar_index + 1]; + bool isLowestLowDown = true; // ll < llBuffer[bar_index + 1]; + bool isHighsestHighUp = true; // hh > hhBuffer[bar_index + 1]; + bool isHighsestHighDown = true; // hh < hhBuffer[bar_index + 1]; + for (int i = bar_index; i < bar_index + cycleCLength; i++) + { + // + double iHH = hhBuffer[i]; + double iLL = llBuffer[i]; + + // + if (hh < iHH) + { + isHighsestHighUp = false; + } + else if (hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (ll < iLL) + { + isLowestLowUp = false; + } + else if (ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + hhColorIDX = 2; + llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + hhColorIDX = 3; + llColorIDX = 3; + } + } + + // + hhColorBuffer[bar_index] = hhColorIDX; + llColorBuffer[bar_index] = llColorIDX; + + // + // CYCLE 1 ... + + // + int l1cycleLength = cycleLength * mL1Candles; + + // + // HIGHER Highs ... + double l1hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + l1cycleLength, + bar_index); + + // + l1hhBuffer[bar_index] = l1hh; + + // + // LOWER Lows ... + double l1ll = GetLowestLow( + _Symbol, + _Period, + llMode, + l1cycleLength, + bar_index); + + // + l1llBuffer[bar_index] = l1ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double l1hhColorIDX = showConsolidations && showL1Trends ? 1 : 0; + double l1llColorIDX = showConsolidations && showL1Trends ? 1 : 0; + + // + // Calculate Cycle Changes ... + + // + int l1cycleCLength = l1cycleLength * numberOfVerifications; + bool isl1CycleCLengthPassed = MathAbs(ArraySize(l1hhBuffer) - bar_index) > l1cycleCLength + 1; + + // + if (isl1CycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + l1cycleCLength; i++) + { + // + double iHH = l1hhBuffer[i]; + double iLL = l1llBuffer[i]; + + // + if (l1hh < iHH) + { + isHighsestHighUp = false; + } + else if (l1hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (l1ll < iLL) + { + isLowestLowUp = false; + } + else if (l1ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + l1hhColorIDX = 2; + l1llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + l1hhColorIDX = 3; + l1llColorIDX = 3; + } + } + + // + l1hhColorBuffer[bar_index] = l1hhColorIDX; + l1llColorBuffer[bar_index] = l1llColorIDX; + + // + // CYCLE 2 ... + + // + int l2cycleLength = cycleLength * mL2Candles; + + // + // HIGHER Highs ... + double l2hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + l2cycleLength, + bar_index); + + // + l2hhBuffer[bar_index] = l2hh; + + // + // LOWER Lows ... + double l2ll = GetLowestLow( + _Symbol, + _Period, + llMode, + l2cycleLength, + bar_index); + + // + l2llBuffer[bar_index] = l2ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double l2hhColorIDX = showConsolidations && showL2Trends ? 1 : 0; + double l2llColorIDX = showConsolidations && showL2Trends ? 1 : 0; + + // + // Calculate Cycle Changes ... + + // + int l2cycleCLength = l2cycleLength * numberOfVerifications; + bool isl2CycleCLengthPassed = MathAbs(ArraySize(l2hhBuffer) - bar_index) > l2cycleCLength + 1; + + // + if (isl2CycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + l2cycleCLength; i++) + { + // + double iHH = l2hhBuffer[i]; + double iLL = l2llBuffer[i]; + + // + if (l2hh < iHH) + { + isHighsestHighUp = false; + } + else if (l2hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (l2ll < iLL) + { + isLowestLowUp = false; + } + else if (l2ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + l2hhColorIDX = 2; + l2llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + l2hhColorIDX = 3; + l2llColorIDX = 3; + } + } + + // + l2hhColorBuffer[bar_index] = l2hhColorIDX; + l2llColorBuffer[bar_index] = l2llColorIDX; + + // + // CYCLE 3 ... + + // + int l3cycleLength = cycleLength * mL3Candles; + + // + // HIGHER Highs ... + double l3hh = GetHighestHigh( + _Symbol, + _Period, + hhMode, + l3cycleLength, + bar_index); + + // + l3hhBuffer[bar_index] = l3hh; + + // + // LOWER Lows ... + double l3ll = GetLowestLow( + _Symbol, + _Period, + llMode, + l3cycleLength, + bar_index); + + // + l3llBuffer[bar_index] = l3ll; + + // + // Set Default Color ... + // in Consolidations use index 0 for CLR_NONE ... + double l3hhColorIDX = showConsolidations && showL3Trends ? 1 : 0; + double l3llColorIDX = showConsolidations && showL3Trends ? 1 : 0; + + // + // Calculate Cycle Changes ... + + // + int l3cycleCLength = l3cycleLength * numberOfVerifications; + bool isl3CycleCLengthPassed = MathAbs(ArraySize(l3hhBuffer) - bar_index) > l3cycleCLength + 1; + + // + if (isl3CycleCLengthPassed) + { + // + bool isLowestLowUp = true; + bool isLowestLowDown = true; + bool isHighsestHighUp = true; + bool isHighsestHighDown = true; + for (int i = bar_index; i < bar_index + l3cycleCLength; i++) + { + // + double iHH = l3hhBuffer[i]; + double iLL = l3llBuffer[i]; + + // + if (l3hh < iHH) + { + isHighsestHighUp = false; + } + else if (l3hh > iHH) + { + isHighsestHighDown = false; + } + + // + if (l3ll < iLL) + { + isLowestLowUp = false; + } + else if (l3ll > iLL) + { + isLowestLowDown = false; + } + } + + // + // Detect Trends and Change Colors ... + + // + if (isLowestLowUp && + isHighsestHighUp) + { + // + l3hhColorIDX = 2; + l3llColorIDX = 2; + } + + // + if (isLowestLowDown && + isHighsestHighDown) + { + // + l3hhColorIDX = 3; + l3llColorIDX = 3; + } + } + + // + l3hhColorBuffer[bar_index] = l3hhColorIDX; + l3llColorBuffer[bar_index] = l3llColorIDX; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/Test/x121.test.provider.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/Test/x121.test.provider.mq5 new file mode 100644 index 0000000..85b37ee --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/Test/x121.test.provider.mq5 @@ -0,0 +1,917 @@ +//////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTestPRVD Signal Provider Library +// -------------------------------------------------------- +// Name: XTestPRVD +// Description: XTestPRVD Signal provider ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Imports/Includes ... +// + +// +// Include Common Library ... +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// Include Logger Library ... +#include "../../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Alert Library ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" + +// +// Include Draw Library ... +#include "../../Libraries/x-saherelm.draw.lib.mq5" + +// +#include "../../Helpers/Test/x121.xpv.test.helper.mq5" +#include "../../Helpers/Test/x121.xmc.test.helper.mq5" +#include "../../Helpers/Test/x121.xmrb.test.helper.mq5" +#include "../../Helpers/Test/x121.xichi.test.helper.mq5" +#include "../../Helpers/Test/x121.xtrnd.test.helper.mq5" +#include "../../Helpers/Test/x121.xatrsl.test.helper.mq5" + +// +// END Imports/Includes ... +// + +// +// START Enum/Constant Definitions ... +// + +// +// Model Market Sence ... +struct X121MarketCondition +{ + // + // XPV ... + + // + bool isPVNewPeak; + bool isPVSamePeak; + bool isPVPeakBreakedUp; + bool isPVPeakBreakedDown; + + // + bool isPVNewVale; + bool isPVSameVale; + bool isPVValeBreakedUp; + bool isPVValeBreakedDown; + + // + // SSL Channel ... + bool isSSLUpOverDown; + bool isSSLUpUnderDown; + bool isSSLUpCrossedOverDown; + bool isSSLUpCrossedUnderDown; + + // + // XICHI ... + + // + // TNKIJ ... + bool isIchiTenkanSenOverKijunSen; + bool isIchiTenkanSenUnderKijunSen; + bool isIchiTenkanSenCrossedOverKijunSen; + bool isIchiTenkanSenCrossedUnderKijunSen; + + // + // KUMO ... + bool isIchiKumoBullish; + bool isIchiKumoBearish; + bool isIchiFutureKumoBullish; + bool isIchiFutureKumoBearish; + bool isIchiKumoSwitchedToBullish; + bool isIchiKumoSwitchedToBearish; + bool isIchiFutureKumoSwitchedToBullish; + bool isIchiFutureKumoSwitchedToBearish; + + // + // TNKUMO ... + bool isIchiTenkanSenOverSenkouSpanA; + bool isIchiTenkanSenOverSenkouSpanB; + bool isIchiTenkanSenCrossedOverSenkouSpanA; + bool isIchiTenkanSenCrossedOverSenkouSpanB; + bool isIchiTenkanSenUnderSenkouSpanA; + bool isIchiTenkanSenUnderSenkouSpanB; + bool isIchiTenkanSenCrossedUnderSenkouSpanA; + bool isIchiTenkanSenCrossedUnderSenkouSpanB; + + // + // KIJUMO ... + bool isIchiKijunSenOverSenkouSpanA; + bool isIchiKijunSenOverSenkouSpanB; + bool isIchiKijunSenCrossedOverSenkouSpanA; + bool isIchiKijunSenCrossedOverSenkouSpanB; + bool isIchiKijunSenUnderSenkouSpanA; + bool isIchiKijunSenUnderSenkouSpanB; + bool isIchiKijunSenCrossedUnderSenkouSpanA; + bool isIchiKijunSenCrossedUnderSenkouSpanB; + + // + // XTRND ... + + // + // CURRENT ... + bool isTrendBullish; + bool isTrendBearish; + bool isTrendConsolidation; + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + bool isTrendSwitchedToConsolidation; + + // + // LEVEL 1 ... + bool isTrendL1Bullish; + bool isTrendL1Bearish; + bool isTrendL1Consolidation; + bool isTrendL1SwitchedToBullish; + bool isTrendL1SwitchedToBearish; + bool isTrendL1SwitchedToConsolidation; + + // + // LEVEL 2 ... + bool isTrendL2Bullish; + bool isTrendL2Bearish; + bool isTrendL2Consolidation; + bool isTrendL2SwitchedToBullish; + bool isTrendL2SwitchedToBearish; + bool isTrendL2SwitchedToConsolidation; + + // + // LEVEL 3 ... + bool isTrendL3Bullish; + bool isTrendL3Bearish; + bool isTrendL3Consolidation; + bool isTrendL3SwitchedToBullish; + bool isTrendL3SwitchedToBearish; + bool isTrendL3SwitchedToConsolidation; + + // + // XMRB ... + + // + // MRIBBON ... + bool isRibbonBullish; + bool isRibbonBearish; + bool isRibbonSwitchedToBullish; + bool isRibbonSwitchedToBearish; + + // + // RIBOON 1 ... + bool isRibbon1Bullish; + bool isRibbon1Bearish; + bool isRibbon1SwitchedToBullish; + bool isRibbon1SwitchedToBearish; + + // + // RIBOON 2 ... + bool isRibbon2Bullish; + bool isRibbon2Bearish; + bool isRibbon2SwitchedToBullish; + bool isRibbon2SwitchedToBearish; + + // + // RIBOON 3 ... + bool isRibbon3Bullish; + bool isRibbon3Bearish; + bool isRibbon3SwitchedToBullish; + bool isRibbon3SwitchedToBearish; + + // + // RIBOON 4 ... + bool isRibbon4Bullish; + bool isRibbon4Bearish; + bool isRibbon4SwitchedToBullish; + bool isRibbon4SwitchedToBearish; + + // + // RIBOON 5 ... + bool isRibbon5Bullish; + bool isRibbon5Bearish; + bool isRibbon5SwitchedToBullish; + bool isRibbon5SwitchedToBearish; + + // + // XMC ... + bool isMCFastOverSlow; + bool isMCFastUnderSlow; + bool isMCFastCrossedOverSlow; + bool isMCFastCrossedUnderSlow; + bool isMCFastOverVerifier; + bool isMCFastUnderVerifier; + bool isMCFastCrossedOverVerifier; + bool isMCFastCrossedUnderVerifier; + bool isMCSlowOverVerifier; + bool isMCSlowUnderVerifier; + bool isMCSlowCrossedOverVerifier; + bool isMCSlowCrossedUnderVerifier; + + // + // XAMA ... + bool isXAMABullish; + bool isXAMABearish; + bool isXAMANeutural; + bool isXAMAChangedToBullish; + bool isXAMAChangedToBearish; + bool isXAMAChangedToNeutural; + + // + // XTM ... + bool isXTMBullish; + bool isXTMBearish; + bool isXTMNeutural; + bool isXTMChangedToBullish; + bool isXTMChangedToBearish; + bool isXTMChangedToNeutural; +} + +// +// END Enum/Constant Definitions ... +// + +// +// START Variables ... +// + +// +int mcclearHandler = INVALID_HANDLE; + +// +// END Variables ... +// + +// +// START Signal Provider Functions ... +// + +// +bool XTestPRVDOnInit() +{ + // + bool result = false; + + // + result = XATRSLHLPOnInit(); + if (!result) + { + return result; + } + + // + result = XICHIHLPOnInit(); + if (!result) + { + return result; + } + + // + result = XMCHLPOnInit(); + if (!result) + { + return result; + } + + // + result = XMRBHLPOnInit(); + if (!result) + { + return result; + } + + // + result = XPVHLPOnInit(); + if (!result) + { + return result; + } + + // + result = XTRNDHLPOnInit(); + if (!result) + { + return result; + } + + // + // Initial CCLear Handler ... + mcclearHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xcclear", + // + // Inputs ... + // + // CHARTSTYLE ... + "", + // + // Up Color ... + clrLime, + // + // Down Color ... + clrRed, + // + // Line mode and Doji candlestick Color ... + clrLime, + // + // Bullish Color ... + clrRed, + // + // Bearish Color ... + clrLime, + // + // Volumes Color ... + clrGreen, + // + // PRESENTATION ... + "", + true + // + ); + result = mcclearHandler != INVALID_HANDLE; + + // + return result; +} + +// +void XTestPRVDOnDeInit() +{ + // + XATRSLHLPOnDeInit(); + XICHIHLPOnDeInit(); + XMCHLPOnDeInit(); + XMRBHLPOnDeInit(); + XPVHLPOnDeInit(); + XTRNDHLPOnDeInit(); +} + +// +void XTestPRVDOnTick() +{ + XATRSLHLPReadBuffers(); + XICHIHLPReadBuffers(); + XMCHLPReadBuffers(); + XMRBHLPReadBuffers(); + XPVHLPReadBuffers(); + XTRNDHLPReadBuffers(); +} + +// +bool XTestPRVDProcessSignals(XSignal &result) +{ + // + bool mResult = false; + + // + // BUY ... + + // + Clean(result); + bool hasLongSignal = XTestPRVDHasLongSignal(result); + if (hasLongSignal) + { + // + mResult = true; + return mResult; + } + + // + // SELL ... + + // + Clean(result); + bool hasShortignal = XTestPRVDHasShortSignal(result); + if (hasShortignal) + { + // + mResult = true; + return mResult; + } + + // + return mResult; +} + +// +bool XTestPRVDHasLongSignal(XSignal &result) +{ + // + bool mResult = false; + return mResult; + + // + XOHCLSupRes supRes = XPVHLPFindCandleSupprtAndResistance(1, 6); + bool hasSupport = ArraySize(supRes.sup) > 0; + bool hasResistance = ArraySize(supRes.res) > 0; + + // + double r2r = 1.2; + double riskAmount = 0.005; + double entry = GetEntry( + _Symbol, + POSITION_TYPE_BUY); + double sl = entry - + (hasSupport + ? (supRes.sup[ArrayMaximum(supRes.sup)] - supRes.sup[ArrayMinimum(supRes.sup)]) + : hasResistance + ? (supRes.res[ArrayMaximum(supRes.res)] - supRes.res[ArrayMinimum(supRes.res)]) + : PointToPrice( + _Symbol, + 10)) + // + ; + + // + bool isXTestHasSignal = XTestPRVDHasLongCondition(); + if (isXTestHasSignal) + { + // + Add( + "XTest", + result.providers); + + // + result.r2r = 1.5; + + // + result.sl = atrslDownBuffer[1]; + } + + // + bool isXTRNDHasSignal = XTRNDHasLongCondition(); + if (isXTRNDHasSignal) + { + // + Add( + "XTRND", + result.providers); + } + + // + bool isXICHIHasSignal = XICHIHasLongCondition(); + if (isXICHIHasSignal) + { + // + Add( + "XICHI", + result.providers); + } + + // + mResult = + // + isXTRNDHasSignal + // + || + // + isXICHIHasSignal + // + ; + + // + if (mResult) + { + // + result.sl = sl; + result.r2r = r2r; + result.entry = entry; + result.symbol = _Symbol; + result.period = _Period; + result.riskAmount = riskAmount; + result.type = POSITION_TYPE_BUY; + result.supportAndResistance = supRes; + } + + // + return mResult; +} + +// +bool XTestPRVDHasShortSignal(XSignal &result) +{ + // + bool mResult = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + XOHCLSupRes supRes = XPVHLPFindCandleSupprtAndResistance(1, 6); + bool hasSupport = ArraySize(supRes.sup) > 0; + bool hasResistance = ArraySize(supRes.res) > 0; + + // + double r2r = 1.2; + double riskAmount = 0.005; + double entry = GetEntry( + _Symbol, + POSITION_TYPE_SELL); + double sl = entry + (supRes.res[ArrayMaximum(supRes.res)] - supRes.res[ArrayMinimum(supRes.res)]); + + // + bool isXTRNDHasSignal = XTRNDHasShortCondition(); + if (isXTRNDHasSignal) + { + // + Add( + "XTRND", + result.providers); + } + + // + bool isICHIHasSignal = XICHIHasShortCondition(); + if (isICHIHasSignal) + { + // + Add( + "XICHI", + result.providers); + } + + // + mResult = + // + isXTRNDHasSignal + // + // || + // // + // TODO: + // isICHIHasSignal + // + ; + + // + if (mResult) + { + // + result.sl = sl; + result.r2r = r2r; + result.entry = entry; + result.symbol = _Symbol; + result.period = _Period; + result.riskAmount = riskAmount; + result.type = POSITION_TYPE_SELL; + result.mode = X_ORDER_MODE_MARKET; + result.supportAndResistance = supRes; + + // + if (!hasSupport) + { + // + // When there is no any Provided Support for a Singal ... + // Place Pending Order instead of Market Order and use + // PV's LL Buffers as Supprt area ... + result.mode = X_ORDER_MODE_STOP; + double supportArea = XPVHLPGetMaxLL(1) - GetCandleShadow(c1); + result.entry = supportArea; + } + } + + // + return mResult; +} + +// +// TODO: Implement it ... +bool XTestPRVDForceCloseAllShorts() +{ + // + bool result = false; + + // // + // XOHCL c1 = GetCandle( + // _Symbol, + // _Period, + // 1); + + // // + // result = + // // + // c1.low < ichiKijunSenBuffer[1] && + // c1.high > ichiKijunSenBuffer[1] + // // + // ; + + // + return result; +} + +// +bool XTestPRVDHasLongCondition() +{ + // + bool result = false; + + // + return result; +} + +// +bool XTestPRVDHasShortCondition() +{ + // + bool result = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + + // + return result; +} + +// +// XTRND .. + +// +bool XTRNDForceCloseAllLongs() +{ + // + bool result = false; + + // + return result; +} + +// +bool XTRNDForceCloseAllShorts() +{ + // + bool result = false; + + // + return result; +} + +// +bool XTRNDHasLongCondition() +{ + // + bool result = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + + // + XIchiInfo ichi1 = XICHIHLPGetInfo(1); + + // + bool isTrendSwitchedToBullish = + // + ( + // + XTRNDHLPIsL3TrendSwitchedBullish(1) && + XTRNDHLPIsTrendBullish(1) && + XTRNDHLPIsL1TrendBullish(1) && + XTRNDHLPIsL2TrendBullish(1) + // + ) + // + || + // + ( + // + XTRNDHLPIsL2TrendSwitchedBullish(1) && + XTRNDHLPIsTrendBullish(1) && + XTRNDHLPIsL1TrendBullish(1) && + XTRNDHLPIsL3TrendBullish(1) + // + ) + // + || + // + ( + // + XTRNDHLPIsL1TrendSwitchedBullish(1) && + XTRNDHLPIsTrendBullish(1) && + XTRNDHLPIsL2TrendBullish(1) && + XTRNDHLPIsL3TrendBullish(1) + // + ) + // + ; + + // + bool signal1 = + // + isTrendSwitchedToBullish + // + ; + + // + result = + // + signal1 + // + ; + + // + return result; +} + +// +bool XTRNDHasShortCondition() +{ + // + bool result = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + + // + bool isTrendSwitchedToBearish = + // + ( + // + XTRNDHLPIsL3TrendSwitchedBearish(1) && + XTRNDHLPIsTrendBearish(1) && + XTRNDHLPIsL1TrendBearish(1) && + XTRNDHLPIsL2TrendBearish(1) + // + ) + // + || + // + ( + // + XTRNDHLPIsL2TrendSwitchedBearish(1) && + XTRNDHLPIsTrendBearish(1) && + XTRNDHLPIsL1TrendBearish(1) && + XTRNDHLPIsL3TrendBearish(1) && + XTRNDHLPIsTrendBearish(2) && + XTRNDHLPIsL1TrendBearish(2) && + XTRNDHLPIsL3TrendBearish(2) + // + ) + // + || + // + ( + // + XTRNDHLPIsL1TrendSwitchedBearish(1) && + XTRNDHLPIsTrendBearish(1) && + XTRNDHLPIsL2TrendBearish(1) && + XTRNDHLPIsL3TrendBearish(1) && + XTRNDHLPIsTrendBearish(2) && + XTRNDHLPIsL2TrendBearish(2) && + XTRNDHLPIsL3TrendBearish(2) && + XTRNDHLPIsTrendBearish(3) && + XTRNDHLPIsL2TrendBearish(3) && + XTRNDHLPIsL3TrendBearish(3) + // + ) + // + ; + + // + bool signal1 = + // + isTrendSwitchedToBearish + // + ; + + // + result = + // + signal1 + // + ; + + // + return result; +} + +// +// XICHI ... + +// +bool XICHIForceCloseAllShorts() +{ + // + bool result = false; + + // + return result; +} + +// +bool XICHIForceCloseAllLongs() +{ + // + bool result = false; + + // + return result; +} + +// +bool XICHIHasLongCondition() +{ + // + bool result = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + XIchiInfo info1 = XICHIHLPGetInfo(1); + + // + bool isKumoSwitchedToBullish = + // + XICHIHLPIsKumoSwitchedToBullish(1) + // + ; + + // + bool signal1 = + // + isKumoSwitchedToBullish && + c1.low > info1.tenkanSen && + info1.tenkanSen > info1.kijunSen && + info1.kijunSen > MathMax(info1.senkouSpanA, info1.senkouSpanB) + // + ; + + // + result = + // + signal1 + // + ; + + // + return result; +} + +// +bool XICHIHasShortCondition() +{ + // + bool result = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + XIchiInfo info1 = XICHIHLPGetInfo(1); + + // + bool isKumoSwitchedToBearish = + // + XICHIHLPIsKumoSwitchedToBearish(1) + // + ; + + // + bool signal1 = + // + isKumoSwitchedToBearish && + c1.high < info1.tenkanSen && + info1.tenkanSen < info1.kijunSen && + info1.kijunSen < MathMin(info1.senkouSpanA, info1.senkouSpanB) + // + ; + + // + result = + // + signal1 + // + ; + + // + return result; +} + +// +// END Signal Provider Functions ... +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/x.saherelm.x121.provider.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/x.saherelm.x121.provider.mq5 new file mode 100644 index 0000000..6da98ed --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Providers/x.saherelm.x121.provider.mq5 @@ -0,0 +1,1590 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Class Library +// ---------------------------------------------- +// Name: XSCX121P +// Description: X121 Signal Provider ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Classes/x-saherelm.xprovider.class.mq5" +#include "../Helpers/x-saherelm.x121.xpv.helper.mq5" +#include "../Helpers/x-saherelm.x121.xhk.helper.mq5" +#include "../Helpers/x-saherelm.x121.xmc.helper.mq5" +#include "../Helpers/x-saherelm.x121.xich.helper.mq5" +#include "../Helpers/x-saherelm.x121.xmrb.helper.mq5" +#include "../Helpers/x-saherelm.x121.xppsr.helper.mq5" +#include "../Helpers/x-saherelm.x121.xsslc.helper.mq5" +#include "../Helpers/x-saherelm.x121.xtrnd.helper.mq5" +#include "../Helpers/x-saherelm.x121.xatrsl.helper.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Base Class for All of our EA's ... +class XSCX121Provider : public XSCEABaseProvider +{ + // + // Public ... +public: + // + // Props ... + // + // Define Helpers ... + + // + // MC ... + XSCXMCHelper mMCHelper; + + // + // PV ... + XSCXPVHelper mPVHelper; + + // + // HKENASHI ... + XSCXHKHelper mHKHelper; + + // + // MRB ... + XSCXMRBHelper mMRBHelper; + + // + // ICHIMOKU ... + XSCXICHHelper mIchiHelper; + + // + // SSLC ... + XSCXSSLCHelper mSSLCHelper; + + // + // PPSR ... + XSCXPPSRHelper mPPSRHelper; + + // + // TRND ... + XSCXTRNDHelper mTRNDHelper; + + // + // ATRSL ... + XSCXATRSLHelper mATRSLHelper; + + // + // Constructor ... + void XSCX121Provider() : XSCEABaseProvider(){}; + void XSCX121Provider( + // + // Symbol ... + string symbol, + // + // Period ... + ENUM_TIMEFRAMES period + // + ) : XSCEABaseProvider(symbol, period) + { + // + mTag = "X121_Provider_" + mSymbol + "_" + ToString(mPeriod); + + // + mCTimerHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xct", + // + // Inputs ... + clrYellow, + CORNER_RIGHT_LOWER + // + ); + + // // + // ArraySetAsSeries(mEMA200Buffer, true); + // mEMA200Handler = iMA( + // mSymbol, + // mPeriod, + // 200, + // 0, + // MODE_EMA, + // PRICE_CLOSE); + + // // + // ArraySetAsSeries(mRSIBuffer, true); + // mRSIHandler = iRSI( + // mSymbol, + // mPeriod, + // 14, + // PRICE_CLOSE); + + // + // CCI Initialization ... + ArraySetAsSeries(mCCIBuffer, true); + mCCIHandler = iCCI( + mSymbol, + mPeriod, + 14, + PRICE_TYPICAL); + + // + // Instance Helpers ... + + // + // MC ... + mMCHelper = new XSCXMCHelper( + mSymbol, + mPeriod); + + // + // PV ... + mPVHelper = new XSCXPVHelper( + mSymbol, + mPeriod); + + // + // HIKENASHI ... + mHKHelper = new XSCXHKHelper( + mSymbol, + mPeriod); + + // + // MRB ... + mMRBHelper = new XSCXMRBHelper( + mSymbol, + mPeriod); + + // + // ICHIMOKU ... + mIchiHelper = new XSCXICHHelper( + mSymbol, + mPeriod); + + // + // SSLC ... + mSSLCHelper = new XSCXSSLCHelper( + mSymbol, + mPeriod); + + // + // PPSR ... + mPPSRHelper = new XSCXPPSRHelper( + mSymbol, + mPeriod); + + // + // TRND ... + mTRNDHelper = new XSCXTRNDHelper( + mSymbol, + mPeriod); + + // + // ATRSL ... + mATRSLHelper = new XSCXATRSLHelper( + mSymbol, + mPeriod); + } + + // + // Deconstructor ... + void ~XSCX121Provider() + { + // + IndicatorRelease(mCCIHandler); + IndicatorRelease(mCTimerHandler); + // IndicatorRelease(mRSIHandler); + // IndicatorRelease(mIchimokuHandler); + // IndicatorRelease(mEMA200Handler); + + // + // De construct Helpers ... + } + + // + virtual void ProcessBuffers() + { + // + mMCHelper.ReadBuffers(); + mPVHelper.ReadBuffers(); + mHKHelper.ReadBuffers(); + mMRBHelper.ReadBuffers(); + mSSLCHelper.ReadBuffers(); + mIchiHelper.ReadBuffers(); + mPPSRHelper.ReadBuffers(); + mTRNDHelper.ReadBuffers(); + mATRSLHelper.ReadBuffers(); + + // // + // /// EMA 200 ... + // CopyBuffer(mEMA200Handler, 0, 0, 10, mEMA200Buffer); + + // // + // /// RSI 14 ... + // CopyBuffer(mRSIHandler, 0, 0, 10, mRSIBuffer); + + // + // CCI 14 ... + CopyBuffer(mCCIHandler, 0, 0, 10, mCCIBuffer); + } + + // + virtual void ProcessTick() + { + ProcessSignals(); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // CCandle Timer ... + int mCTimerHandler; + + // // + // // EMA 200 ... + // int mEMA200Handler; + // double mEMA200Buffer[]; + + // // + // // RSI ... + // int mRSIHandler; + // double mRSIBuffer[]; + + // + // CCI ... + int mCCIHandler; + double mCCIBuffer[]; + + // + // Here we are Capture Conditions and Check Signals ... + // The Signals Must be Unique for each providers ... + void ProcessSignals() + { + // + XSignalInfo signal; + + // + // BUY ... + + // + Clean(signal); + bool hasLongSignal = HasLongSignal(signal); + if (hasLongSignal) + { + // + NotifyOnSignalEvent( + signal); + mWaitUntilNewCandle = true; + return; + } + + // + // SELL ... + + // + Clean(signal); + bool hasShortignal = HasShortSignal(signal); + if (hasShortignal) + { + // + NotifyOnSignalEvent( + signal); + mWaitUntilNewCandle = true; + return; + } + } + + // + // START Providers Signals ... + // + + // + // Check has Long Signal on Each Strategies ... + bool HasLongSignal(XSignalInfo &info) + { + // + bool result = false; + + // + double entry = GetEntry(POSITION_TYPE_BUY); + + // + bool isXMRBHasSignal = false; // XMRBHasLongCondition(); + if (isXMRBHasSignal) + { + // + Add( + "XMRB", + info.providers); + + // + info.r2r = 1.5; + + // + // info.sl = mATRSLHelper.downBuffer[1]; + } + + // + bool isXPVHasSignal = false; // XPVHasLongCondition(); + if (isXPVHasSignal) + { + // + Add( + "XPV", + info.providers); + + // + info.r2r = 1.4; + + // + double slValue = mPVHelper.sLLBuffer[1]; + // slValue -= PointToPrice( + // mSymbol, + // 5 + // ); + // info.sl = slValue; + info.sl = mATRSLHelper.downBuffer[1]; + } + + // + bool isXICHIHasSignal1 = false; // XICHIHasLongCondition1(); + if (isXICHIHasSignal1) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1.5; + + // + double llValue = GetLowestLow( + mSymbol, + mPeriod, + 3, + 0); + llValue -= PointToPrice( + mSymbol, + 5); + + // + info.sl = llValue; + } + + // + bool isXICHIHasSignal2 = false; // XICHIHasLongCondition2(); + if (isXICHIHasSignal2) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1; + + // + double llValue = GetLowestLow( + mSymbol, + mPeriod, + 3, + 0); + llValue -= PointToPrice( + mSymbol, + 5); + + // + info.sl = llValue; + } + + // + bool isXICHIHasSignal3 = false; // XICHIHasLongCondition3(); + if (isXICHIHasSignal3) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1.5; + + // + double llValue = GetLowestLow( + mSymbol, + mPeriod, + 3, + 0); + llValue -= PointToPrice( + mSymbol, + 5); + + // + info.sl = llValue; + } + + // + bool isXICHIHasSignal4 = XICHIHasLongCondition4(); + if (isXICHIHasSignal4) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1.5; + + // + double slValue = mATRSLHelper.downBuffer[1]; + slValue -= PointToPrice( + mSymbol, + 5); + + // + info.sl = slValue; + } + + // + result = + // + isXMRBHasSignal + // + || + // + isXPVHasSignal + // + || + // + isXICHIHasSignal1 + // + || + // + isXICHIHasSignal2 + // + || + // + isXICHIHasSignal3 + // + || + // + isXICHIHasSignal4 + // + ; + + // + if (result) + { + // + info.entry = entry; + info.symbol = mSymbol; + info.period = mPeriod; + info.type = POSITION_TYPE_BUY; + } + + // + return result; + } + + // + // Check has Short Signal on Each Strategies ... + bool HasShortSignal(XSignalInfo &info) + { + // + bool result = false; + + // + double entry = GetEntry(POSITION_TYPE_SELL); + + // + bool isXMRBHasSignal = false; // XMRBHasShortCondition(); + if (isXMRBHasSignal) + { + // + Add( + "XMRB", + info.providers); + + // + info.r2r = 1.5; + + // + // info.sl = mATRSLHelper.upBuffer[1]; + } + + // + bool isXPVHasSignal = false; // XPVHasShortCondition(); + if (isXPVHasSignal) + { + // + Add( + "XPV", + info.providers); + + // + info.r2r = 1.4; + + // + double slValue = mPVHelper.sHHBuffer[1]; + // slValue -= PointToPrice( + // mSymbol, + // 5 + // ); + // info.sl = slValue; + info.sl = mATRSLHelper.upBuffer[1]; + } + + // + bool isXICHIHasSignal1 = false; // XICHIHasShortCondition1(); + if (isXICHIHasSignal1) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1.5; + + // + double hhValue = GetHighestHigh( + mSymbol, + mPeriod, + 3, + 0); + hhValue += PointToPrice( + mSymbol, + 5); + + // + info.sl = hhValue; + } + + // + bool isXICHIHasSignal2 = false; // XICHIHasShortCondition2(); + if (isXICHIHasSignal2) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1; + + // + double hhValue = GetHighestHigh( + mSymbol, + mPeriod, + 3, + 0); + hhValue += PointToPrice( + mSymbol, + 5); + + // + info.sl = hhValue; + } + + // + bool isXICHIHasSignal3 = false; // XICHIHasShortCondition3(); + if (isXICHIHasSignal3) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1.5; + + // + double hhValue = GetHighestHigh( + mSymbol, + mPeriod, + 3, + 0); + hhValue += PointToPrice( + mSymbol, + 5); + + // + info.sl = hhValue; + } + + // + bool isXICHIHasSignal4 = XICHIHasShortCondition4(); + if (isXICHIHasSignal4) + { + // + Add( + "XICHI", + info.providers); + + // + info.r2r = 1.5; + + // + double slValue = mATRSLHelper.upBuffer[1]; + slValue += PointToPrice( + mSymbol, + 5); + + // + info.sl = slValue; + } + + // + result = + // + isXMRBHasSignal + // + || + // + isXPVHasSignal + // + || + // + isXICHIHasSignal1 + // + || + // + isXICHIHasSignal2 + // + || + // + isXICHIHasSignal3 + // + || + // + isXICHIHasSignal4 + // + ; + + // + if (result) + { + // + info.entry = entry; + info.symbol = mSymbol; + info.period = mPeriod; + info.type = POSITION_TYPE_SELL; + } + + // + return result; + } + + // + // START XMRB ... + + // + bool XMRBHasLongCondition() + { + // + bool result = false; + + // // + // XOHCL c1 = GetCandle( + // mSymbol, + // mPeriod, + // 1); + + // // + // XOHCL c2 = GetCandle( + // mSymbol, + // mPeriod, + // 2); + + // // + // double hhValue = GetHighestHigh( + // mSymbol, + // mPeriod, + // 5, + // 1); + // double llValue = GetLowestLow( + // mSymbol, + // mPeriod, + // 5, + // 1); + + // // + // // Find Fast Cross Over Slow ... + // bool isFastCrossOverSlow = + // mMRBHelper.fastBuffer[1] > mMRBHelper.slowBuffer[1] && + // mMRBHelper.fastBuffer[2] <= mMRBHelper.slowBuffer[2]; + + // // + // bool isTrendsUp = + // // + // // Trens by Other ... + // ( + // // + // ( + // // + // mMRBHelper.fast1Buffer[1] > mMRBHelper.slow1Buffer[1] && + // mMRBHelper.fast2Buffer[1] > mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] > mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] > mMRBHelper.slow4Buffer[1] && + // mMRBHelper.fast5Buffer[1] > mMRBHelper.slow5Buffer[1] + // // + // ) + // // + // || + // ( + // // + // mMRBHelper.fast1Buffer[1] > mMRBHelper.slow1Buffer[1] && + // mMRBHelper.fast2Buffer[1] > mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] > mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] > mMRBHelper.slow4Buffer[1] + // // + // ) + // // + // || + // ( + // // + // mMRBHelper.fast2Buffer[1] > mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] > mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] > mMRBHelper.slow4Buffer[1] && + // mMRBHelper.fast5Buffer[1] > mMRBHelper.slow5Buffer[1] + // // + // ) + // // + // ) + // // + // && + // // + // // Trends By Them ... + // ( + // // + // ( + // // + // mMRBHelper.fast2Buffer[1] > mMRBHelper.fast3Buffer[1] && + // mMRBHelper.fast3Buffer[1] > mMRBHelper.fast4Buffer[1] + // // + // ) + // // + // || + // // + // ( + // // + // mMRBHelper.fast3Buffer[1] > mMRBHelper.fast4Buffer[1] && + // mMRBHelper.fast4Buffer[1] > mMRBHelper.fast5Buffer[1] + // // + // ) + // // + // ) + // // + // ; + + // // + // bool isCyclesTrendsUp = + // ( + // // + // mMRBHelper.fast1Buffer[1] > mMRBHelper.slow1Buffer[1] && + // mMRBHelper.fast2Buffer[1] > mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] > mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] > mMRBHelper.slow4Buffer[1] && + // mMRBHelper.fast5Buffer[1] > mMRBHelper.slow5Buffer[1] + // // + // ) + // // + // && + // // + // !( + // // + // mMRBHelper.fast1Buffer[2] > mMRBHelper.slow1Buffer[2] && + // mMRBHelper.fast2Buffer[2] > mMRBHelper.slow2Buffer[2] && + // mMRBHelper.fast3Buffer[2] > mMRBHelper.slow3Buffer[2] && + // mMRBHelper.fast4Buffer[2] > mMRBHelper.slow4Buffer[2] && + // mMRBHelper.fast5Buffer[2] > mMRBHelper.slow5Buffer[2] + // // + // ) + // // + // ; + + // // + // bool candleCrossEMA200 = + // c1.open < mEMA200Buffer[1] && + // c1.close > mEMA200Buffer[1]; + + // // + // bool llCrossEMA200 = + // llValue < mEMA200Buffer[1] && + // hhValue > mEMA200Buffer[1]; + + // // + // bool candlesPullBack = + // // + // ( + // // + // mMRBHelper.fastBuffer[1] > mMRBHelper.slowBuffer[1] && + // mMRBHelper.fastBuffer[2] > mMRBHelper.slowBuffer[2] && + // mMRBHelper.fastBuffer[3] > mMRBHelper.slowBuffer[3] && + // // + // mMRBHelper.fastBuffer[1] > mMRBHelper.fastBuffer[2] && + // mMRBHelper.fastBuffer[2] > mMRBHelper.fastBuffer[3] && + // // + // c1.open < mMRBHelper.fastBuffer[1] && + // c1.close > mMRBHelper.fastBuffer[2] && + // // + // c2.open < mMRBHelper.fastBuffer[2] && + // c2.close < mMRBHelper.fastBuffer[2] && + // // + // MathMin(c1.high, c1.low) > mEMA200Buffer[1] && + // MathMin(c2.high, c2.low) > mEMA200Buffer[2] + // // + // ) + // // + // ; + + // // + // result = + // // + // (isTrendsUp && + // llCrossEMA200 && + // isFastCrossOverSlow) + // // + // || + // // + // (isTrendsUp && + // isCyclesTrendsUp && + // candleCrossEMA200) + // // + // // || + // // // + // // llCrossEMA200 + // // // + // || + // // + // candlesPullBack + // // + // ; + + // + return result; + } + + // + bool XMRBHasShortCondition() + { + // + bool result = false; + + // // + // XOHCL c1 = GetCandle( + // mSymbol, + // mPeriod, + // 1); + // XOHCL c2 = GetCandle( + // mSymbol, + // mPeriod, + // 2); + + // // + // double hhValue = GetHighestHigh( + // mSymbol, + // mPeriod, + // 5, + // 1); + // double llValue = GetLowestLow( + // mSymbol, + // mPeriod, + // 5, + // 1); + + // // + // // Find Fast Cross Under Slow ... + // bool isFastCrossUnderSlow = + // mMRBHelper.fastBuffer[1] < mMRBHelper.slowBuffer[1] && + // mMRBHelper.fastBuffer[2] >= mMRBHelper.slowBuffer[2]; + + // // + // bool isTrendsDown = + // // + // // Trens by Other ... + // ( + // // + // ( + // // + // mMRBHelper.fast1Buffer[1] < mMRBHelper.slow1Buffer[1] && + // mMRBHelper.fast2Buffer[1] < mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] < mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] < mMRBHelper.slow4Buffer[1] && + // mMRBHelper.fast5Buffer[1] < mMRBHelper.slow5Buffer[1] + // // + // ) + // // + // || + // ( + // // + // mMRBHelper.fast1Buffer[1] < mMRBHelper.slow1Buffer[1] && + // mMRBHelper.fast2Buffer[1] < mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] < mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] < mMRBHelper.slow4Buffer[1] + // // + // ) + // // + // || + // ( + // // + // mMRBHelper.fast2Buffer[1] < mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] < mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] < mMRBHelper.slow4Buffer[1] && + // mMRBHelper.fast5Buffer[1] < mMRBHelper.slow5Buffer[1] + // // + // ) + // // + // ) + // // + // && + // // + // // Trends By Them ... + // ( + // // + // ( + // // + // mMRBHelper.fast2Buffer[1] < mMRBHelper.fast3Buffer[1] && + // mMRBHelper.fast3Buffer[1] < mMRBHelper.fast4Buffer[1] + // // + // ) + // // + // || + // // + // ( + // // + // mMRBHelper.fast3Buffer[1] < mMRBHelper.fast4Buffer[1] && + // mMRBHelper.fast4Buffer[1] < mMRBHelper.fast5Buffer[1] + // // + // ) + // // + // ) + // // + // ; + + // // + // bool isCyclesTrendsDown = + // ( + // // + // mMRBHelper.fast1Buffer[1] < mMRBHelper.slow1Buffer[1] && + // mMRBHelper.fast2Buffer[1] < mMRBHelper.slow2Buffer[1] && + // mMRBHelper.fast3Buffer[1] < mMRBHelper.slow3Buffer[1] && + // mMRBHelper.fast4Buffer[1] < mMRBHelper.slow4Buffer[1] && + // mMRBHelper.fast5Buffer[1] < mMRBHelper.slow5Buffer[1] + // // + // ) + // // + // && + // // + // !( + // // + // mMRBHelper.fast1Buffer[2] < mMRBHelper.slow1Buffer[2] && + // mMRBHelper.fast2Buffer[2] < mMRBHelper.slow2Buffer[2] && + // mMRBHelper.fast3Buffer[2] < mMRBHelper.slow3Buffer[2] && + // mMRBHelper.fast4Buffer[2] < mMRBHelper.slow4Buffer[2] && + // mMRBHelper.fast5Buffer[2] < mMRBHelper.slow5Buffer[2] + // // + // ) + // // + // ; + + // // + // bool candleCrossEMA200 = + // c1.open > mEMA200Buffer[1] && + // c1.close < mEMA200Buffer[1]; + + // // + // bool hhCrossEMA200 = + // hhValue > mEMA200Buffer[1] && + // llValue < mEMA200Buffer[1]; + + // // + // bool candlesPullBack = + // // + // ( + // // + // mMRBHelper.fastBuffer[1] < mMRBHelper.slowBuffer[1] && + // mMRBHelper.fastBuffer[2] < mMRBHelper.slowBuffer[2] && + // mMRBHelper.fastBuffer[3] < mMRBHelper.slowBuffer[3] && + // // + // mMRBHelper.fastBuffer[1] < mMRBHelper.fastBuffer[2] && + // mMRBHelper.fastBuffer[2] < mMRBHelper.fastBuffer[3] && + // // + // c1.open > mMRBHelper.fastBuffer[1] && + // c1.close < mMRBHelper.fastBuffer[2] && + // // + // c2.open > mMRBHelper.slowBuffer[2] && + // c2.close > mMRBHelper.slowBuffer[2] && + // // + // MathMax(c1.high, c1.low) < mEMA200Buffer[1] && + // MathMax(c2.high, c2.low) < mEMA200Buffer[2] + // // + // ) + // // + // ; + + // // + // result = + // // + // (isTrendsDown && + // hhCrossEMA200 && + // isFastCrossUnderSlow) + // // + // || + // // + // (isTrendsDown && + // isCyclesTrendsDown && + // candleCrossEMA200) + // // + // // || + // // // + // // hhCrossEMA200 + // // // + // || + // // + // candlesPullBack + // // + // ; + + // + return result; + } + + // + // END XMRB ... + // + + // + // START XPV ... + // + + // + bool XPVHasLongCondition() + { + // + bool result = false; + + // + bool isSupportsHappens = + // + !mPVHelper.IsStrongSupport(1) && + mPVHelper.IsStrongSupport(2) && + mPVHelper.IsStrongSupport(3) + // + ; + + // + result = + // + false + // + // isSupportsHappens && + // isFeautureKumoBullish + // + ; + + // + return result; + } + + // + bool XPVHasShortCondition() + { + // + bool result = false; + + // + result = + !mPVHelper.IsStrongResistance(1) && + mPVHelper.IsStrongResistance(2) && + mPVHelper.IsStrongResistance(3); + + // + return result; + } + + // + // END XPV ... + // + + // + // START Ichimoku ... + // + + // + // CONDITION 1 ... + + // + // Long Condition 1 ... + bool XICHIHasLongCondition1() + { + // + bool result = false; + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + bool isTenkanSenCrossed = + mIchiHelper.IsTenkanSenCrossedOverKijunSen(1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + bool isCandleClosedOverCross = + c1.close > MathMax(info.tenkanSen, info.kijunSen); + + // + double ll = GetLowestLow( + mSymbol, + mPeriod, + 6, + 1); + bool isCandlesOverKumo = + ll > MathMax(info.senkouSpanA, info.senkouSpanB); + + // + result = + // + isTenkanSenCrossed && + isCandlesOverKumo && + isCandleClosedOverCross + // + ; + + // + return result; + } + + // + // Short Condition 1 ... + bool XICHIHasShortCondition1() + { + // + bool result = false; + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + bool isTenkanSenCrossed = + mIchiHelper.IsTenkanSenCrossedUnderKijunSen(1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + bool isCandleClosedUnderCross = + c1.close < MathMin(info.tenkanSen, info.kijunSen); + + // + double hh = GetHighestHigh( + mSymbol, + mPeriod, + 6, + 1); + bool isCandlesUnderKumo = + hh < MathMin(info.senkouSpanA, info.senkouSpanB); + + // + result = + // + isTenkanSenCrossed && + isCandlesUnderKumo && + isCandleClosedUnderCross + // + ; + + // + return result; + } + + // + // CONDITION 2 ... + + // + // Long Condition 2 ... + // Ichimoku and CCI ... + bool XICHIHasLongCondition2() + { + // + bool result = false; + + // + bool isCCICrossedOverNegative100 = + // + mCCIBuffer[1] > -100 && + mCCIBuffer[2] <= -100 + // + ; + + // + bool isTenkanSenOverKijunSen = + mIchiHelper.IsTenkanSenOverKijunSen(1); + + // + bool isKumoBullish = + mIchiHelper.IsKumoBullish(1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + double llValue = GetLowestLow( + mSymbol, + mPeriod, + 12, + 1); + bool isPriceOverKumo = + // + llValue > MathMax(info.senkouSpanA, info.senkouSpanB) + // + ; + + // + result = + // + isKumoBullish && + isPriceOverKumo && + isTenkanSenOverKijunSen && + isCCICrossedOverNegative100 + // + ; + + // + return result; + } + + // + // Short Condition 2 ... + // Ichimoku and CCI ... + bool XICHIHasShortCondition2() + { + // + bool result = false; + + // + bool isCCICrossedUnderPositive100 = + // + mCCIBuffer[1] < 100 && + mCCIBuffer[2] >= 100 + // + ; + + // + bool isTenkanSenUnderKijunSen = + mIchiHelper.IsTenkanSenUnderKijunSen(1); + + // + bool isKumoBearish = + mIchiHelper.IsKumoBearish(1); + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + XIchiInfo info = mIchiHelper.GetInfo(1); + double hhValue = GetHighestHigh( + mSymbol, + mPeriod, + 12, + 1); + bool isPriceUnderKumo = + // + c1.high < MathMin(info.senkouSpanA, info.senkouSpanB) && + hhValue < MathMin(info.senkouSpanA, info.senkouSpanB) + // + ; + + // + result = + // + isKumoBearish && + isPriceUnderKumo && + isTenkanSenUnderKijunSen && + isCCICrossedUnderPositive100 + // + ; + + // + return result; + } + + // + // CONDITIONS 3 ... + + // + // Long Condition 3 ... + bool XICHIHasLongCondition3() + { + // + bool result = false; + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + + // + bool isFutureKumoSwitchedToBullish = + mIchiHelper.IsKumoSwitchedToBullish(1, true); + + // + bool isCandleClosedOverFutureKumo = + c1.close > MathMax(info.senkouSpanAFuture, info.senkouSpanBFuture); + + // + result = + // + isCandleClosedOverFutureKumo && + isFutureKumoSwitchedToBullish + // + ; + + // + return result; + } + + // + // Short Condition 3 ... + bool XICHIHasShortCondition3() + { + // + bool result = false; + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + + // + bool isFutureKumoSwitchedToBearish = + mIchiHelper.IsKumoSwitchedToBearish(1, true); + + // + bool isCandleClosedUnderFutureKumo = + c1.close < MathMin(info.senkouSpanAFuture, info.senkouSpanBFuture); + + // + result = + // + isCandleClosedUnderFutureKumo && + isFutureKumoSwitchedToBearish + // + ; + + // + return result; + } + + // + // CONDITIONS 4 ... + + // + // Long Condition 4 ... + bool XICHIHasLongCondition4() + { + // + bool result = false; + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + + // + bool isSSLUpCrossedOverDown = + mSSLCHelper.IsUpCrossedOverDown(1); + + // + bool isCandleClosedOverKumo = + c1.low > MathMax(info.senkouSpanA, info.senkouSpanB); + + // + bool isKumoBullish = + mIchiHelper.IsKumoBullish(1); + + // + result = + // + isKumoBullish && + isSSLUpCrossedOverDown && + isCandleClosedOverKumo + // + ; + + // + return result; + } + + // + // Short Condition 4 ... + bool XICHIHasShortCondition4() + { + // + bool result = false; + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + XIchiInfo info = mIchiHelper.GetInfo(1); + + // + bool isSSLUpCrossedUnderDown = + mSSLCHelper.IsUpCrossedUnderDown(1); + + // + bool isCandleClosedUnderKumo = + c1.high < MathMin(info.senkouSpanA, info.senkouSpanB); + + // + bool isKumoBearish = + mIchiHelper.IsKumoBearish(1); + + // + result = + // + isKumoBearish && + isSSLUpCrossedUnderDown && + isCandleClosedUnderKumo + // + ; + + // + return result; + } + + // + // END Ichimoku ... + // + + // + // END Providers Signals ... + // +}; + +// +// START Definitions ... +// + +// +// Model Signal Providers Definitions ... +struct X121SignalProvider +{ + // + // Provider use Which Symbol ... + string symbol; + + // + // Provider use Which Time Frame ... + ENUM_TIMEFRAMES period; + + // + // Risk Amount Per Trades Related to Time Frames ... + // Percent of Available Balance ... + double riskAmount; + + // + // Desired Magic Number ... + ulong magicNumber; + + // + // Provider ... + XSCX121Provider provider; +}; + +// +// END Definitions ... +// + +// +// START Usefull Functions ... +// + +// +// Add Specific Provider to List ... +void Add( + X121SignalProvider &item, // item want to add + X121SignalProvider &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Generate Identifier Tag ... +string GenerateTag(X121SignalProvider &descriptor) +{ + // + string result = ""; + + // + result = descriptor.symbol + "_" + ToString(descriptor.period); + + // + return result; +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/x-saherelm.x121.chart.tools.lib.mq5 b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/x-saherelm.x121.chart.tools.lib.mq5 new file mode 100644 index 0000000..609c74b --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/x-saherelm.x121.chart.tools.lib.mq5 @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X12 Draw Library +// ------------------------------------------ +// Name: X121Draw +// Description: provides Draw Requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// START Chart Tools Functions ... +// + +// +string x121ToolsButtonName = "X121TOOLS"; + +// +// Calculate Button size ... +bool CalculateButtonSize( + XSize &result, // Holds Result ... + long chartID = 0, // Specified Chart ID ... + int step = 32 // Step Divider ... +) +{ + // + bool mResult = false; + + // + mResult = GetChartSize( + result, + chartID); + if (!mResult) + { + return mResult; + } + + // + // define the step for changing the button size + int x_step = (int)result.width / step; + int y_step = (int)result.height / step; + + // + // set the button coordinates and its size + int x = (int)result.width / step; + int y = (int)result.height / step; + + // + // int width = (int)result.width * 15 / 32; + // int height = (int)result.height * 15 / 32; + int width = (int)result.width / 32; + int height = (int)result.height / 32; + + // + result.x = x; + result.y = y; + result.w = width; + result.h = height; + result.wStep = x_step; + result.hStep = y_step; + + // + return mResult; +} + +// +// Draw Tools Button On Chart ... +bool DrawToolsButton( + long chartID = 0, // Specified Chart ID ... + int subWindow = 0, // Specified Chart's SubWindow ... + ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER // Specified Corner to Draw Button ... +) +{ + // + bool result = false; + + // + XSize size; + result = CalculateButtonSize( + size, + chartID); + if (!result) + { + return result; + } + + // + result = ButtonCreate( + chartID, + x121ToolsButtonName, + 0, + size.x, + size.y, + size.w, + size.y, + corner, + "Press", + "Arial", + 10, + clrBlack, + clrLightGray, + CLR_NONE, + false, // Pressed/Released ... + false, + false, + true, + 0); + + // + return result; +} + +// +bool ToggleToolsButtonState( + long chartID = 0, // Specified Chart ID ... + int subWindow = 0 // Specified Chart's SubWindow ... +) +{ + // + bool result = false; + + // + return result; +} + +// +// Prepare Chart Requirements ... +bool DrawTools( + long chartID = 0, // Specified Chart ID ... + int subWindow = 0 // Specified Chart's SubWindow ... +) +{ + // + bool result = false; + + // + result = DrawToolsButton( + chartID, + subWindow); + + // + // redraw the chart + if (result) + { + ChartRedraw(); + } + + // + return result; +} + +// +// Parse Chart Tools Events ... +void HandleToolsChartEvent( + long chartID, // Specified Chart ID ... + const int id, // event ID + const long &lparam, // long type event parameter + const double &dparam, // double type event parameter + const string &sparam // string type event parameter +) +{ + // + // OnClick ... + if (id == CHARTEVENT_CLICK) + { + // + // Toolls Btton Clicked ... + if (sparam == x121ToolsButtonName) + { + LogMessage("Tools Button Clicked ..."); + } + } +} + +// +// END Chart Tools Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Temp/supprot_resistance_sample.yaml b/MQLTestWorkspace/BKPS/Temp/supprot_resistance_sample.yaml new file mode 100644 index 0000000..27e265d --- /dev/null +++ b/MQLTestWorkspace/BKPS/Temp/supprot_resistance_sample.yaml @@ -0,0 +1,269 @@ +2024.04.01 06:30:00 XEA > Peaks and Vales +2024.04.01 06:30:00 XEA > Supprot and Resistance: +2024.04.01 06:30:00 R1: 1.07873 +2024.04.01 06:30:00 R2: 1.07986 +2024.04.01 06:30:00 +2024.04.01 06:30:00 S1: 1.07819 +2024.04.01 06:30:00 S2: 1.07743 +2024.04.01 06:30:00 +2024.04.01 06:30:00 +2024.04.01 06:30:00 XEA > +2024.04.01 06:30:00 XEA > Ichimoku Kinko Hyo +2024.04.01 06:30:00 XEA > Supprot and Resistance: +2024.04.01 06:30:00 R1: 1.0787149999999999 +2024.04.01 06:30:00 R2: 1.0788 +2024.04.01 06:30:00 +2024.04.01 06:30:00 S1: 0.0 +2024.04.01 06:30:00 S2: 0.0 + + +2024.04.01 15:30:00 XEA > Peaks and Vales +2024.04.01 15:30:00 XEA > Supprot and Resistance: +2024.04.01 15:30:00 R1: 1.07849 +2024.04.01 15:30:00 R2: 1.07903 +2024.04.01 15:30:00 +2024.04.01 15:30:00 S1: 0.0 +2024.04.01 15:30:00 S2: 0.0 +2024.04.01 15:30:00 +2024.04.01 15:30:00 +2024.04.01 15:30:00 XEA > +2024.04.01 15:30:00 XEA > Ichimoku Kinko Hyo +2024.04.01 15:30:00 XEA > Supprot and Resistance: +2024.04.01 15:30:00 R1: 1.0782349999999998 +2024.04.01 15:30:00 R2: 1.07844 +2024.04.01 15:30:00 +2024.04.01 15:30:00 S1: 0.0 +2024.04.01 15:30:00 S2: 0.0 + + +2024.04.01 16:20:00 XEA > Peaks and Vales +2024.04.01 16:20:00 XEA > Supprot and Resistance: +2024.04.01 16:20:00 R1: 1.07855 +2024.04.01 16:20:00 R2: 1.07903 +2024.04.01 16:20:00 +2024.04.01 16:20:00 S1: 0.0 +2024.04.01 16:20:00 S2: 0.0 +2024.04.01 16:20:00 +2024.04.01 16:20:00 +2024.04.01 16:20:00 XEA > +2024.04.01 16:20:00 XEA > Ichimoku Kinko Hyo +2024.04.01 16:20:00 XEA > Supprot and Resistance: +2024.04.01 16:20:00 R1: 1.078125 +2024.04.01 16:20:00 R2: 1.07817 +2024.04.01 16:20:00 +2024.04.01 16:20:00 S1: 0.0 +2024.04.01 16:20:00 S2: 0.0 + + + +2024.04.01 17:45:02 XEA > Peaks and Vales +2024.04.01 17:45:02 XEA > Supprot and Resistance: +2024.04.01 17:45:02 R1: 1.0781 +2024.04.01 17:45:02 R2: 1.07826 +2024.04.01 17:45:02 +2024.04.01 17:45:02 S1: 0.0 +2024.04.01 17:45:02 S2: 0.0 +2024.04.01 17:45:02 +2024.04.01 17:45:02 +2024.04.01 17:45:02 XEA > +2024.04.01 17:45:02 XEA > Ichimoku Kinko Hyo +2024.04.01 17:45:02 XEA > Supprot and Resistance: +2024.04.01 17:45:02 R1: 1.077985 +2024.04.01 17:45:02 R2: 1.078125 +2024.04.01 17:45:02 +2024.04.01 17:45:02 S1: 0.0 +2024.04.01 17:45:02 S2: 0.0 +2024.04.01 17:45:02 +2024.04.01 17:45:02 + + + +2024.04.01 18:15:00 XEA > Peaks and Vales +2024.04.01 18:15:00 XEA > Supprot and Resistance: +2024.04.01 18:15:00 R1: 1.07805 +2024.04.01 18:15:00 R2: 1.07853 +2024.04.01 18:15:00 +2024.04.01 18:15:00 S1: 0.0 +2024.04.01 18:15:00 S2: 0.0 +2024.04.01 18:15:00 +2024.04.01 18:15:00 +2024.04.01 18:15:00 XEA > +2024.04.01 18:15:00 XEA > Ichimoku Kinko Hyo +2024.04.01 18:15:00 XEA > Supprot and Resistance: +2024.04.01 18:15:00 R1: 1.07611 +2024.04.01 18:15:00 R2: 1.0763449999999999 +2024.04.01 18:15:00 +2024.04.01 18:15:00 S1: 0.0 +2024.04.01 18:15:00 S2: 0.0 +2024.04.01 18:15:00 +2024.04.01 18:15:00 + + +2024.04.01 18:25:00 XEA > Peaks and Vales +2024.04.01 18:25:00 XEA > Supprot and Resistance: +2024.04.01 18:25:00 R1: 1.07805 +2024.04.01 18:25:00 R2: 1.07853 +2024.04.01 18:25:00 +2024.04.01 18:25:00 S1: 0.0 +2024.04.01 18:25:00 S2: 0.0 +2024.04.01 18:25:00 +2024.04.01 18:25:00 +2024.04.01 18:25:00 XEA > +2024.04.01 18:25:00 XEA > Ichimoku Kinko Hyo +2024.04.01 18:25:00 XEA > Supprot and Resistance: +2024.04.01 18:25:00 R1: 1.07611 +2024.04.01 18:25:00 R2: 1.0763449999999999 +2024.04.01 18:25:00 +2024.04.01 18:25:00 S1: 0.0 +2024.04.01 18:25:00 S2: 0.0 +2024.04.01 18:25:00 +2024.04.01 18:25:00 + + +2024.04.02 01:50:02 XEA > Peaks and Vales +2024.04.02 01:50:02 XEA > Supprot and Resistance: +2024.04.02 01:50:02 R1: 1.07849 +2024.04.02 01:50:02 R2: 1.07903 +2024.04.02 01:50:02 +2024.04.02 01:50:02 S1: 1.07363 +2024.04.02 01:50:02 S2: 1.07342 +2024.04.02 01:50:02 +2024.04.02 01:50:02 +2024.04.02 01:50:02 XEA > +2024.04.02 01:50:02 XEA > Ichimoku Kinko Hyo +2024.04.02 01:50:02 XEA > Supprot and Resistance: +2024.04.02 01:50:02 R1: 1.074205 +2024.04.02 01:50:02 R2: 1.07428 +2024.04.02 01:50:02 +2024.04.02 01:50:02 S1: 1.0740675 +2024.04.02 01:50:02 S2: 1.074025 +2024.04.02 01:50:02 +2024.04.02 01:50:02 + + +2024.04.02 02:05:00 XEA > Peaks and Vales +2024.04.02 02:05:00 XEA > Supprot and Resistance: +2024.04.02 02:05:00 R1: 1.07416 +2024.04.02 02:05:00 R2: 1.0744 +2024.04.02 02:05:00 +2024.04.02 02:05:00 S1: 1.07366 +2024.04.02 02:05:00 S2: 0.0 +2024.04.02 02:05:00 +2024.04.02 02:05:00 +2024.04.02 02:05:00 XEA > +2024.04.02 02:05:00 XEA > Ichimoku Kinko Hyo +2024.04.02 02:05:00 XEA > Supprot and Resistance: +2024.04.02 02:05:00 R1: 1.074025 +2024.04.02 02:05:00 R2: 1.0740675 +2024.04.02 02:05:00 +2024.04.02 02:05:00 S1: 1.073385 +2024.04.02 02:05:00 S2: 0.0 +2024.04.02 02:05:00 +2024.04.02 02:05:00 + + +2024.04.02 03:35:00 XEA > Peaks and Vales +2024.04.02 03:35:00 XEA > Supprot and Resistance: +2024.04.02 03:35:00 R1: 1.07399 +2024.04.02 03:35:00 R2: 1.07425 +2024.04.02 03:35:00 +2024.04.02 03:35:00 S1: 0.0 +2024.04.02 03:35:00 S2: 0.0 +2024.04.02 03:35:00 +2024.04.02 03:35:00 +2024.04.02 03:35:00 XEA > +2024.04.02 03:35:00 XEA > Ichimoku Kinko Hyo +2024.04.02 03:35:00 XEA > Supprot and Resistance: +2024.04.02 03:35:00 R1: 1.073385 +2024.04.02 03:35:00 R2: 1.073705 +2024.04.02 03:35:00 +2024.04.02 03:35:00 S1: 0.0 +2024.04.02 03:35:00 S2: 0.0 +2024.04.02 03:35:00 +2024.04.02 03:35:00 + + +2024.04.02 06:25:00 XEA > Peaks and Vales +2024.04.02 06:25:00 XEA > Supprot and Resistance: +2024.04.02 06:25:00 R1: 1.07366 +2024.04.02 06:25:00 R2: 1.07512 +2024.04.02 06:25:00 +2024.04.02 06:25:00 S1: 1.07312 +2024.04.02 06:25:00 S2: 0.0 +2024.04.02 06:25:00 +2024.04.02 06:25:00 +2024.04.02 06:25:00 XEA > +2024.04.02 06:25:00 XEA > Ichimoku Kinko Hyo +2024.04.02 06:25:00 XEA > Supprot and Resistance: +2024.04.02 06:25:00 R1: 1.073485 +2024.04.02 06:25:00 R2: 1.0736249999999998 +2024.04.02 06:25:00 +2024.04.02 06:25:00 S1: 0.0 +2024.04.02 06:25:00 S2: 0.0 +2024.04.02 06:25:00 +2024.04.02 06:25:00 + + +2024.04.10 19:00:04 XEA > Peaks and Vales +2024.04.10 19:00:04 XEA > Supprot and Resistance: +2024.04.10 19:00:04 R1: 1.07795 +2024.04.10 19:00:04 R2: 1.08617 +2024.04.10 19:00:04 +2024.04.10 19:00:04 S1: 0.0 +2024.04.10 19:00:04 S2: 0.0 +2024.04.10 19:00:04 +2024.04.10 19:00:04 +2024.04.10 19:00:04 XEA > +2024.04.10 19:00:04 XEA > Ichimoku Kinko Hyo +2024.04.10 19:00:04 XEA > Supprot and Resistance: +2024.04.10 19:00:04 R1: 1.073705 +2024.04.10 19:00:04 R2: 1.07374 +2024.04.10 19:00:04 +2024.04.10 19:00:04 S1: 1.073275 +2024.04.10 19:00:04 S2: 1.0732050000000002 +2024.04.10 19:00:04 +2024.04.10 19:00:04 + + +2024.04.10 19:40:00 XEA > Peaks and Vales +2024.04.10 19:40:00 XEA > Supprot and Resistance: +2024.04.10 19:40:00 R1: 1.07742 +2024.04.10 19:40:00 R2: 1.08584 +2024.04.10 19:40:00 +2024.04.10 19:40:00 S1: 0.0 +2024.04.10 19:40:00 S2: 0.0 +2024.04.10 19:40:00 +2024.04.10 19:40:00 +2024.04.10 19:40:00 XEA > +2024.04.10 19:40:00 XEA > Ichimoku Kinko Hyo +2024.04.10 19:40:00 XEA > Supprot and Resistance: +2024.04.10 19:40:00 R1: 1.0732050000000002 +2024.04.10 19:40:00 R2: 1.073275 +2024.04.10 19:40:00 +2024.04.10 19:40:00 S1: 1.072805 +2024.04.10 19:40:00 S2: 0.0 +2024.04.10 19:40:00 +2024.04.10 19:40:00 + + +2024.04.11 03:10:00 XEA > Peaks and Vales +2024.04.11 03:10:00 XEA > Supprot and Resistance: +2024.04.11 03:10:00 R1: 1.07425 +2024.04.11 03:10:00 R2: 1.07542 +2024.04.11 03:10:00 +2024.04.11 03:10:00 S1: 0.0 +2024.04.11 03:10:00 S2: 0.0 +2024.04.11 03:10:00 +2024.04.11 03:10:00 +2024.04.11 03:10:00 XEA > +2024.04.11 03:10:00 XEA > Ichimoku Kinko Hyo +2024.04.11 03:10:00 XEA > Supprot and Resistance: +2024.04.11 03:10:00 R1: 1.074115 +2024.04.11 03:10:00 R2: 1.07416 +2024.04.11 03:10:00 +2024.04.11 03:10:00 S1: 1.0738750000000001 +2024.04.11 03:10:00 S2: 1.0738050000000001 +2024.04.11 03:10:00 +2024.04.11 03:10:00 + + diff --git a/MQLTestWorkspace/BKPS/Temp/xtm.old.mq5 b/MQLTestWorkspace/BKPS/Temp/xtm.old.mq5 new file mode 100644 index 0000000..a827587 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Temp/xtm.old.mq5 @@ -0,0 +1,361 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Indicator +// --------------------------------------------- +// Name: XTM +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTM Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTM" + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 1, + X_XTM_BEARISH = -1, + X_XTM_NEUTURAL = 0, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Makret"; +input int maPeriod = 35; // Period +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_LOW; // Applied To + +input group "Presentation"; +input bool showLine = true; // Show Line + +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 1 + +// +// maBuffer ... +#define maBufferIndex 0 +#define maColorBufferIndex 1 +#define stateBufferIndex 2 + +double maBuffer[]; +double maColorBuffer[]; +double stateBuffer[]; + +#property indicator_label1 "XTM" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int maHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // Initializing MA Handler ... + maHandler = iMA( + _Symbol, + _Period, + maPeriod, + maShift, + maMethod, + maAppliedTo); + if (maHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Ma Handler ..."; + LogMessage(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, maPeriod); + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (maPeriod >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ENUM_DRAW_TYPE drawType = showLine ? DRAW_COLOR_LINE : DRAW_NONE; + + // + string maBufferLabel = "XTM " + "(" + (string)maPeriod + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, drawType); + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showLine); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + + // + // State Buffer ... + ArraySetAsSeries(stateBuffer, true); + SetIndexBuffer(stateBufferIndex, stateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "(", maPeriod, ")"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Define State Value ... + // lineColorIndex == 0 => Bullish => 1; + // lineColorIndex == 1 => Neutural => 0; + // lineColorIndex == 2 => Bearish => -1; + double stateValue = + lineColorIndex == 0 ? X_XTM_BULLISH : lineColorIndex == 2 ? X_XTM_BEARISH + : X_XTM_NEUTURAL; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; + + // + // Set State Buffer Value ... + stateBuffer[bar_index] = stateValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Templates/Guard Handlers.mq5 b/MQLTestWorkspace/BKPS/Templates/Guard Handlers.mq5 new file mode 100644 index 0000000..47da2b6 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/Guard Handlers.mq5 @@ -0,0 +1,227 @@ + +// +// Close All Open Positions when Profit Summary is Reached ... +void HandleGridHedge() +{ + // + int openPositionsCount = xEATrade.PositionsCount(); + if (openPositionsCount <= 1 || + xEAMinProfitPerOpenPositionForHedging <= 0) + { + return; + } + + // + double requiredProfitForHedging = xEAMinProfitPerOpenPositionForHedging * openPositionsCount; + double accountProfit = xEATrade.GetPositionsProfit(); + if (accountProfit > 0 || MathAbs(accountProfit) < requiredProfitForHedging) + { + return; + } + + // + string comment = "Close since Grid Hedging ..."; + xEATrade.CloseAllPositions(comment); + + // + string msg = "Grid Hedging in Loss: " + (string)accountProfit; + LogMessage(msg); +} + +// +// Close All Open Positions when Profit Summary is Reached ... +void HandlePyramidHedge() +{ + // + int openPositionsCount = xEATrade.PositionsCount(); + if (openPositionsCount <= 1 || + xEAMinProfitPerOpenPositionForHedging <= 0) + { + return; + } + + // + double requiredProfitForHedging = xEAMinProfitPerOpenPositionForHedging * openPositionsCount; + double accountProfit = xEATrade.GetPositionsProfit(); + if (accountProfit < requiredProfitForHedging) + { + return; + } + + // + string comment = "Close since Pyramid Hedging ..."; + xEATrade.CloseAllPositions(comment); + + // + string msg = "Pyramid Hedging in Profit: " + (string)accountProfit; + LogMessage(msg); +} + +// +// Force Close Signals ... +void HandleForceClosing() +{ + // + int positionsCount = xEATrade.PositionsCount(); + int ordersCount = xEATrade.OrdersCount(); + if (positionsCount <= 0 || ordersCount <= 0) + { + return; + } + + // + X121ForceClose results[]; + xEAProvider.CanForceCloseShortSignals(results); + int resultsCount = ArraySize(results); + if (resultsCount <= 0) + { + return; + } + + // + for (int i = 0; i < resultsCount; i++) + { + // + X121ForceClose iForceClose = results[i]; + if (!iForceClose.force) + { + continue; + } + + // + XPosition iPositions[]; + xEATrade.GetPositions( + iPositions, + iForceClose.symbol, + iForceClose.period); + int iPositionsCount = ArraySize(iPositions); + if (iPositionsCount > 0) + { + // + for (int j = 0; j < iPositionsCount; j++) + { + // + XPosition jPosition = iPositions[j]; + bool isLong = IsLong(jPosition.type); + if (isLong) + { + continue; + } + + // + ENUM_X121_SIGNAL_PROVIDERS jProvider = ExtractProvider(jPosition); + string jProviderStr = ToString(jProvider); + if (jProviderStr != iForceClose.provider) + { + continue; + } + + // + string comment = "Force Close Signals ..."; + bool isClosed = xEATrade.Close(jPosition.ticket, comment); + if (isClosed) + { + // + string msg = "Position (" + (string)jPosition.ticket + ") Closed Due Force Event ..."; + LogMessage(msg); + } + } + } + + // + XOrder iOrders[]; + xEATrade.GetOrders( + iOrders, + iForceClose.symbol, + iForceClose.period, + ORDER_STATE_PLACED); + int iOrdersCount = ArraySize(iOrders); + if (iOrdersCount > 0) + { + // + bool isCanceled = xEATrade.CancelOrders(iOrders); + if (isCanceled) + { + // + string msg = "(" + (string)ordersCount + ") Canceled due Cycle Change ..."; + + // + LogMessage(msg); + } + } + } +} + +// +// Close a Position and it's Support Due to Profit ... +void HandleHedgeSupports() +{ + // + int positionsCount = xEATrade.PositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition positions[]; + xEATrade.GetPositions( + positions); + positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool hasSupport = xEATrade.HasSupport(iPosition.ticket); + if (!hasSupport) + { + continue; + } + + // + bool isClosed = xEATrade.ClosePositionAndSupports( + iPosition.ticket); + if (isClosed) + { + // + string msg = "Position and Supports Closed ..."; + LogMessage(msg); + } + } +} + + + + // + // Delete Specific Order of Support if Exists ... + ulong positionId = deal.positionId; + + // + XOrder supports[]; + bool hasSupport = xEATrade.GetSupportOrders( + positionId, + supports, + NULL, + NULL, + ORDER_STATE_PLACED); + if (hasSupport) + { + // + bool isCanceled = xEATrade.CancelOrders(supports); + + // + if (isCanceled) + { + // + string msg = "Close all Supports of (" + (string)positionId + ") Due to it's TakeProfit Event ..."; + LogMessage(msg); + } + } diff --git a/MQLTestWorkspace/BKPS/Templates/draw.support.resistance.mql5 b/MQLTestWorkspace/BKPS/Templates/draw.support.resistance.mql5 new file mode 100644 index 0000000..a221b3e --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/draw.support.resistance.mql5 @@ -0,0 +1,124 @@ + +// +void DrawSupportResistance( + int bar_index, + XOHCLSupRes &data, + string prefix = "", + color supportColor = clrLime, + color lowSupportColor = clrGreen, + color resistanceColor = clrRed, + color highResistanceColor = clrBrown) +{ + // + datetime barTime = GetCandleTime( + _Symbol, + _Period, + bar_index); + + // + datetime prevBarTime = GetCandleTime( + _Symbol, + _Period, + bar_index + 5); + + // + long chID = ChartID(); + int subWindiw = 0; + + // + string mPrefix = prefix + "_" + (string)barTime + "_"; + + // + // SUPPORT ... + + // + if (data.sup > 0) + { + // + string supTlName = mPrefix + "SUP_(" + (string)data.sup + ")"; + + // + // Draw Support ... + DrawTrendLine( + chID, + supTlName, + subWindiw, + prevBarTime, + data.sup, + barTime, + data.sup, + supportColor, + STYLE_DOT, + 1, + true); + } + + // + if (data.lowSup > 0) + { + // + string lowSupTlName = mPrefix + "LOW-SUP_(" + (string)data.lowSup + ")"; + + // + // Draw Low Support ... + DrawTrendLine( + chID, + lowSupTlName, + subWindiw, + prevBarTime, + data.lowSup, + barTime, + data.lowSup, + lowSupportColor, + STYLE_DOT, + 1, + true); + } + + // + // RESISTANCE ... + + // + if (data.res > 0) + { + // + string resTlName = mPrefix + "RES_(" + (string)data.res + ")"; + + // + // Draw Support ... + DrawTrendLine( + chID, + resTlName, + subWindiw, + prevBarTime, + data.res, + barTime, + data.res, + resistanceColor, + STYLE_DOT, + 1, + true); + } + + // + if (data.highRes > 0) + { + // + string highResTlName = mPrefix + "HIGH-RES_(" + (string)data.highRes + ")"; + + // + // Draw Low Support ... + DrawTrendLine( + chID, + highResTlName, + subWindiw, + prevBarTime, + data.highRes, + barTime, + data.highRes, + highResistanceColor, + STYLE_DOT, + 1, + true); + } +} diff --git a/MQLTestWorkspace/BKPS/Templates/how to use xtrnd helper.mq5 b/MQLTestWorkspace/BKPS/Templates/how to use xtrnd helper.mq5 new file mode 100644 index 0000000..6ad8b4e --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/how to use xtrnd helper.mq5 @@ -0,0 +1,30 @@ + + // + bool isTrendSwitchedBullish = mTRNDHelper.IsTrendSwitchedBullish(1); + if (isTrendSwitchedBullish) + { + LogMessage("isTrendSwitchedBullish"); + } + + // + bool isTrendSwitchedBearish = mTRNDHelper.IsTrendSwitchedBearish(1); + if (isTrendSwitchedBearish) + { + LogMessage("isTrendSwitchedBearish"); + } + + // + bool isTrendSwitchedConsolidation = mTRNDHelper.IsTrendSwitchedConsolidation(1); + if (isTrendSwitchedConsolidation) + { + LogMessage("isTrendSwitchedConsolidation"); + } + + // + if ( + isTrendSwitchedBullish || + isTrendSwitchedBearish || + isTrendSwitchedConsolidation) + { + LogMessage(" "); + } diff --git a/MQLTestWorkspace/BKPS/Templates/how-to-use.xichi.helper.mq5 b/MQLTestWorkspace/BKPS/Templates/how-to-use.xichi.helper.mq5 new file mode 100644 index 0000000..e5a5f6b --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/how-to-use.xichi.helper.mq5 @@ -0,0 +1,100 @@ + // + if (mIsNewCandle) + { + // + datetime barTime = iTime( + mSymbol, + mPeriod, + 0); + + // + datetime time = iTime( + mSymbol, + mPeriod, + 1); + + // + long chartID = ChartID(); + + // + int barIndex = 0; + + // // + // // Check Kumo Is Bullish On State ... + // bool isKumoBullish = + // // + // mIchiHelper.IsKumoBullish(barIndex + 1, true) + // // + // ; + + // // + // if (isKumoBullish) + // { + // // + // LogMessage("isKumoBullish"); + // LogMessage("TenkanSen: " + (string)mIchiHelper.tenkanSenBuffer[barIndex]); + // LogMessage("KijunSen: " + (string)mIchiHelper.kijunSenBuffer[barIndex]); + // LogMessage("SenkouSpan A: " + (string)mIchiHelper.senkouSpanABuffer[barIndex + 26]); + // LogMessage("SenkouSpan B: " + (string)mIchiHelper.senkouSpanBBuffer[barIndex + 26]); + // LogMessage(" "); + // } + + // // + // // Check Kumo Is Bearish On State ... + // bool isKumoBearish = + // // + // mIchiHelper.IsKumoBearish(barIndex + 1, true) + // // + // ; + + // // + // if (isKumoBearish) + // { + // // + // LogMessage("isKumoBearish"); + // LogMessage("TenkanSen: " + (string)mIchiHelper.tenkanSenBuffer[barIndex]); + // LogMessage("KijunSen: " + (string)mIchiHelper.kijunSenBuffer[barIndex]); + // LogMessage("SenkouSpan A: " + (string)mIchiHelper.senkouSpanABuffer[barIndex + 26]); + // LogMessage("SenkouSpan B: " + (string)mIchiHelper.senkouSpanBBuffer[barIndex + 26]); + // LogMessage(" "); + // } + + // // + // // Check Kumo Switched To Bullish On State ... + // bool isKumoSwitchedToBullish = + // // + // mIchiHelper.IsKumoSwitchedToBullish(barIndex + 1, true) + // // + // ; + + // // + // if (isKumoSwitchedToBullish) + // { + // // + // LogMessage("isKumoSwitchedToBullish"); + // LogMessage("TenkanSen: " + (string)mIchiHelper.tenkanSenBuffer[barIndex]); + // LogMessage("KijunSen: " + (string)mIchiHelper.kijunSenBuffer[barIndex]); + // LogMessage("SenkouSpan A: " + (string)mIchiHelper.senkouSpanABuffer[barIndex + 26]); + // LogMessage("SenkouSpan B: " + (string)mIchiHelper.senkouSpanBBuffer[barIndex + 26]); + // LogMessage(" "); + // } + + // // + // // Check Kumo Switched To Bearish On State ... + // bool isKumoSwitchedToBearish = + // // + // mIchiHelper.IsKumoSwitchedToBearish(barIndex + 1, true) + // // + // ; + + // if (isKumoSwitchedToBearish) + // { + // // + // LogMessage("isKumoSwitchedToBearish"); + // LogMessage("TenkanSen: " + (string)mIchiHelper.tenkanSenBuffer[barIndex]); + // LogMessage("KijunSen: " + (string)mIchiHelper.kijunSenBuffer[barIndex]); + // LogMessage("SenkouSpan A: " + (string)mIchiHelper.senkouSpanABuffer[barIndex + 26]); + // LogMessage("SenkouSpan B: " + (string)mIchiHelper.senkouSpanBBuffer[barIndex + 26]); + // LogMessage(" "); + // } + } diff --git a/MQLTestWorkspace/BKPS/Templates/ichimoku.test.short.signals.mq5 b/MQLTestWorkspace/BKPS/Templates/ichimoku.test.short.signals.mq5 new file mode 100644 index 0000000..42fe635 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/ichimoku.test.short.signals.mq5 @@ -0,0 +1,251 @@ +bool XTestPRVDHasShortCondition() +{ + // + bool result = false; + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + // + XOHCL c2 = GetCandle( + _Symbol, + _Period, + 2); + + // + XIchiInfo ichiInfo = XICHIHLPGetInfo(2); + + // + bool isCandleClosedUnderPsar = + // + c1.high < atrslSarBuffer[1] + // + ; + + // + bool isTrendSwitched = + // + XTRNDHLPIsTrendStronglyBearish(1) + // + ; + + // + bool isNewValeHappends = + // + XPVHLPIsVale(1) && + !XPVHLPIsVale(2) + // + ; + + // + bool isKumoBearish = + // + XICHIHLPIsKumoBearish(1) + // + ; + + // + bool isTenkanSenUnderKijunSen = + // + XICHIHLPIsTenkanSenUnderKijunSen(1) + // + ; + + // + bool isTenkanSenCrossedUnderKijunSen = + // + XICHIHLPIsTenkanSenCrossedUnderKijunSen(1) + // + ; + + // + bool isBullishKumoBreakout = + // + XICHIHLPIsKumoBullish(1) && + XICHIHLPIsKumoBullish(2) && + (c2.high > MathMax(ichiInfo.senkouSpanA, ichiInfo.senkouSpanB) && + c2.low < MathMin(ichiInfo.senkouSpanA, ichiInfo.senkouSpanB)) && + c1.high < MathMin(ichiInfo.senkouSpanA, ichiInfo.senkouSpanB) + // + ; + + // + bool isCandloClosedUnderTenkanSen = + // + c1.high < ichiInfo.tenkanSen + // + ; + + // + bool isKijunbSenUnderKumo = + // + ichiInfo.kijunSen < MathMin(ichiInfo.senkouSpanA, ichiInfo.senkouSpanB) + // + ; + + // + bool isChikouSpanFree = + // + c1.close < GetLowestLow( + _Symbol, + _Period, + 1, + 26) + // + ; + + // + bool isKumoSoFat = + // + MathAbs(ichiInfo.senkouSpanA - ichiInfo.senkouSpanB) > MathAbs(GetHighestHigh( + _Symbol, + _Period, + 1, + 17) - + GetLowestLow( + _Symbol, + _Period, + 1, + 17)) + // + ; + + // + bool isKijunSenInsideFutureKumo = + // + ichiInfo.kijunSen < MathMax(ichiInfo.senkouSpanAFuture, ichiInfo.senkouSpanBFuture) && + ichiInfo.kijunSen > MathMin(ichiInfo.senkouSpanAFuture, ichiInfo.senkouSpanBFuture) + // + ; + + // + bool isFutureKumoBearish = + // + XICHIHLPIsKumoBearish(1, true) + // && + // + // TODO: Remove this ... + // MathMax(ichiInfo.senkouSpanA, ichiInfo.senkouSpanB) < MathMax(ichiInfo.senkouSpanAFuture, ichiInfo.senkouSpanBFuture) + // + ; + + // + bool signal1 = + // + isKumoBearish && + isTrendSwitched && + isNewValeHappends && + isCandleClosedUnderPsar && + isTenkanSenUnderKijunSen + // + ; + + // + bool signal2 = + // + isKijunbSenUnderKumo && + isBullishKumoBreakout && + isTenkanSenUnderKijunSen && + isCandloClosedUnderTenkanSen + // + ; + + // + bool signal3 = + // + !isKumoSoFat && + isChikouSpanFree && + isFutureKumoBearish && + isKijunbSenUnderKumo && + !isKijunSenInsideFutureKumo && + isCandloClosedUnderTenkanSen && + isTenkanSenCrossedUnderKijunSen + // + ; + + // + result = + // + // signal1 + // // + // || + // + // signal2 + // // + // || + // + signal3 + // + ; + + // + return result; +} + + +/// + + + + // + XOHCL c1 = GetCandle( + _Symbol, + _Period, + 1); + // + XOHCL c2 = GetCandle( + _Symbol, + _Period, + 2); + + // + XIchiInfo ichiInfo = XICHIHLPGetInfo(1); + + // + bool isKumoSwitchedToBeraish = + // + XICHIHLPIsKumoSwitchedToBearish(1) + // + ; + + // + double ll9Value = GetLowestLow( + _Symbol, + _Period, + 9, + 1); + double hh9Value = GetHighestHigh( + _Symbol, + _Period, + 9, + 1); + bool isChikouSpanUnderPrice = + // + ichiInfo.chikouSpan < ll9Value && + ichiInfo.chikouSpan < hh9Value + // + ; + + // + bool isTenkanSenOverKijunSen = + // + XICHIHLPIsTenkanSenOverKijunSen(1) + // + ; + // + bool isPriceUnderTenkanSen = + c1.high < ichiInfo.tenkanSen; + + // + bool signal1 = + // + isChikouSpanUnderPrice && + isKumoSwitchedToBeraish && + (isTenkanSenOverKijunSen + ? isPriceUnderTenkanSen + : true) + + // + ; diff --git a/MQLTestWorkspace/BKPS/Templates/old.long.signals.mq5 b/MQLTestWorkspace/BKPS/Templates/old.long.signals.mq5 new file mode 100644 index 0000000..d00695a --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/old.long.signals.mq5 @@ -0,0 +1,79 @@ + // + bool result = false; + + // + double entry = GetEntry( + mSymbol, + POSITION_TYPE_BUY); + + // + XOHCL c0 = GetCandle( + mSymbol, + mPeriod, + 0); + double c0AppliedPrice = MathMin(c0.low, c0.open); + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + X121MarketConditions mConditions = GetMarketConditions(1); + + // + bool signal1 = + // + mConditions.xtrndInfo.l1ll == mConditions.xtrndInfo.l2ll && + mConditions.xtrndInfo.l1ll == mConditions.xtrndInfo.l3ll && + mConditions.xtrndInfo.l1ll == mConditions.xpvInfo.vale && + // + c0AppliedPrice == mConditions.xtrndInfo.l1ll + // && + // + // mConditions.xmrbInfo.isFastUnderSlow + // + ; + + // + if (signal1) + { + // + Add( + ToString(XPVF), + mConditions.signal.providers); + + // + mConditions.signal.r2r = 1.5; + mConditions.signal.riskAmount = 0.0001; + mConditions.signal.mode = X_ORDER_MODE_STOP; + mConditions.signal.entry = mConditions.xpvInfo.fl3; + mConditions.signal.sl = mConditions.xtrndInfo.l1ll; + mConditions.signal.tp = mConditions.xpvInfo.fl1; + } + + // + result = + // + false + // signal1 + // + ; + + // + if (result) + { + // + conditions = mConditions; + + // + conditions.signal.symbol = mSymbol; + conditions.signal.period = mPeriod; + conditions.signal.type = POSITION_TYPE_BUY; + + // + conditions.hasSignal = true; + } + + // + return result; diff --git a/MQLTestWorkspace/BKPS/Templates/old.short.signals.mq5 b/MQLTestWorkspace/BKPS/Templates/old.short.signals.mq5 new file mode 100644 index 0000000..f27cba0 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/old.short.signals.mq5 @@ -0,0 +1,130 @@ + // + // When Price going Down of Fibo 3 Level from Up ... + // Chandelier Exit Must Verify Short trade by providing Short Exit 1 and 2 ... + bool signal1 = + // + c1.close < mConditions.xpvInfo.fl3 && + // + mConditions.xcheInfo.shortExit1 > c1.open && + mConditions.xcheInfo.shortExit1 != EMPTY_VALUE && + // + mConditions.xcheInfo.shortExit2 > c1.open && + mConditions.xcheInfo.shortExit2 != EMPTY_VALUE && + // + !(mConditions.xtrndInfo.isTrendBullish || + mConditions.xtrndInfo.isL1TrendBullish || + mConditions.xtrndInfo.isL2TrendBullish || + mConditions.xtrndInfo.isL3TrendBullish) + // + ; + + + + X121MarketConditions m0Conditions = GetMarketConditions(0); + + // + bool signal1 = + // + mConditions.xtrndInfo.l1hh == mConditions.xtrndInfo.l2hh && + mConditions.xtrndInfo.l1hh == mConditions.xtrndInfo.l3hh && + mConditions.xtrndInfo.l1hh == mConditions.xpvInfo.peak && + // + c0AppliedPrice == mConditions.xtrndInfo.l1hh + // && + // + // mConditions.xmrbInfo.isFastUnderSlow + // + ; + + // + if (signal1) + { + // + Add( + ToString(XPVF), + mConditions.signal.providers); + + // + mConditions.signal.r2r = 1.5; + mConditions.signal.riskAmount = 0.0001; + mConditions.signal.mode = X_ORDER_MODE_STOP; + mConditions.signal.entry = mConditions.xpvInfo.fl1; + mConditions.signal.sl = mConditions.xtrndInfo.l1hh; + mConditions.signal.tp = mConditions.xpvInfo.fl3; + } + + // + double minVerifier = MathMin(m0Conditions.xhullInfo.up, m0Conditions.xhullInfo.down); + minVerifier = MathMin(minVerifier, m0Conditions.xmrbInfo.fast); + minVerifier = MathMin(minVerifier, m0Conditions.xmrbInfo.slow); + minVerifier = MathMin(minVerifier, m0Conditions.xsslcInfo.up); + minVerifier = MathMin(minVerifier, m0Conditions.xsslcInfo.down); + + // + bool signal2 = + // + (mConditions.xsslcInfo.isBearish && + mConditions.xmrbInfo.isFastUnderSlow && + mConditions.xhullInfo.isUpBearish && + mConditions.xhullInfo.isDownBearish) + // + && + // + !(m0Conditions.xsslcInfo.isBearish && + m0Conditions.xmrbInfo.isFastUnderSlow && + m0Conditions.xhullInfo.isUpBearish && + m0Conditions.xhullInfo.isDownBearish) + // + && + // + (mConditions.xtrndInfo.isTrendBearish && + (mConditions.xtrndInfo.isL1TrendBearish || + mConditions.xtrndInfo.isL2TrendBearish)) + // + && + // + c1.high < minVerifier + // + ; + + // + if (signal2) + { + // + Add( + ToString(XCHNL), + mConditions.signal.providers); + + // + mConditions.signal.r2r = 1.5; + mConditions.signal.riskAmount = 0.0001; + mConditions.signal.mode = X_ORDER_MODE_MARKET; + mConditions.signal.entry = entry; + mConditions.signal.sl = mConditions.xpvInfo.peak; + mConditions.signal.tp = mConditions.xpvInfo.vale; + } + + // + bool signal3 = + // + mConditions.xtrndInfo.isL3TrendSwitchedToBearish + // + ; + + // + if (signal3) + { + // + Add( + ToString(XTRND), + mConditions.signal.providers); + + // + mConditions.signal.r2r = 1.5; + mConditions.signal.riskAmount = 0.0001; + mConditions.signal.mode = X_ORDER_MODE_MARKET; + mConditions.signal.entry = entry; + mConditions.signal.sl = mConditions.xtrndInfo.l3hh; + mConditions.signal.tp = mConditions.xtrndInfo.l3ll; + } + diff --git a/MQLTestWorkspace/BKPS/Templates/open.support.positions.old.ea.mq5 b/MQLTestWorkspace/BKPS/Templates/open.support.positions.old.ea.mq5 new file mode 100644 index 0000000..96335e8 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/open.support.positions.old.ea.mq5 @@ -0,0 +1,181 @@ + +// +// Find Reversal Position Type ... +ENUM_POSITION_TYPE GetSupportPositionType(ENUM_POSITION_TYPE type) +{ + // + ENUM_POSITION_TYPE result = POSITION_TYPE_BUY; + + // + if (type == POSITION_TYPE_BUY) + { + result = POSITION_TYPE_SELL; + } + else + { + result = POSITION_TYPE_BUY; + } + + // + return result; +} + +// +// Check a Position Has Supportable or not ... +bool IsSupportablePosition(XPosition &position) +{ + // + bool result = false; + + // + if (StringLen(position.comment) <= 0) + { + return result; + } + + // + int supStrPos = StringFind( + position.comment, + mSupportPrefix + "("); + + // + result = supStrPos < 0; + + // + return result; +} + +// +// Check a Position has Support Position or not ... +bool HasSupportPosition(XPosition &position) +{ + // + bool result = false; + + // + int positionsCount = xEATrade.PositionsCount(); + + // + if (positionsCount <= 0 || + position.ticket == 0 || + StringLen(position.comment) <= 0) + { + return result; + } + + // + string supCommentStr = mSupportPrefix + "(" + (string)position.ticket + ")"; + + // + XPosition positions[]; + xEATrade.GetPositions(positions); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + int supCommentPos = StringFind( + iPosition.comment, + supCommentStr); + + // + result = supCommentPos >= 0; + if (result) + { + break; + } + } + + // + return result; +} + +// +// Open a Support Position based on Exists ... +void OpenSupportPosition(XPosition &position) +{ + // + bool isSupportable = IsSupportablePosition(position); + if (!isSupportable) + { + return; + } + + // + bool hasSupport = HasSupportPosition(position); + if (hasSupport) + { + return; + } + + // + ENUM_POSITION_TYPE type = GetSupportPositionType(position.type); + double entry = GetEntry( + position.symbol, + type); + + // + bool isLong = IsLong(type); + + // + double tpPrice = PipsToPrice( + position.symbol, + 10); + double slPrice = PipsToPrice( + position.symbol, + 5); + + // + double tp = 0; + // isLong + // ? entry + tpPrice + // : entry - tpPrice; + + // + double sl = 0; + // isLong + // ? entry - slPrice + // : entry + slPrice; + + // + string comment = mSupportPrefix + "(" + (string)position.ticket + ")"; + + // + bool isPositionOpen = false; + // + // Open Signal Position ... + if (isLong) + { + // + isPositionOpen = xEATrade.Buy( + position.symbol, + position.period, + position.volume, + entry, + sl, + tp, + comment); + } + else + { + // + isPositionOpen = xEATrade.Sell( + position.symbol, + position.period, + position.volume, + entry, + sl, + tp, + comment); + } + + // + if (isPositionOpen) + { + // + LogMessage("Open Support Psition for: " + position.comment); + } +} diff --git a/MQLTestWorkspace/BKPS/Templates/short.sl.calc.test.mql5 b/MQLTestWorkspace/BKPS/Templates/short.sl.calc.test.mql5 new file mode 100644 index 0000000..f6d7a20 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/short.sl.calc.test.mql5 @@ -0,0 +1,62 @@ + + // // + // int prevBearish = + // XTRNDHLPFindNextTrendSwitchedBearish(1); + // XOHCL cPrevBearish = GetCandle( + // _Symbol, + // _Period, + // prevBearish); + + // // + // int prevBullish = + // XTRNDHLPFindNextTrendSwitchedBearish(1); + // XOHCL cPrevBullish = GetCandle( + // _Symbol, + // _Period, + // prevBullish); + + // // + // double changeRate = XATRSLHLPGetChangeRate(1); + // double rangeChangeRate = XATRSLHLPGetRangeChangeRate(2); + // double atrValue = atrslUpBuffer[1]; + // if (changeRate > rangeChangeRate) + // { + // atrValue = atrslUpBuffer[2]; + // } + + // + // double hhValue = GetHighestHigh( + // _Symbol, + // _Period, + // 3, + // 1); + + // + // double mrbValue = MathMax(mrbFastBuffer[1], mrbSlowBuffer[1]); + + // + // atrslUpBuffer[1]; + // ichiKijunSenBuffer[1]; + // MathMin(cPrevBullish.high, cPrevBearish.high); + // double hh9Value = + // GetHighestHigh( + // _Symbol, + // _Period, + // 1, + // 9); + + // + // int prevSwingHigh = FindSwing( + // _Symbol, + // _Period, + // MODE_HIGH, + // 5, + // 1); + + // // + // double s1 = XPVHLPGetLastStrongSupport(1); + // double s2 = XPVHLPGetLastStrongSupport(2); + + // // + // double r1 = XPVHLPGetLastStrongResistance(1); + // double r2 = XPVHLPGetLastStrongResistance(2); diff --git a/MQLTestWorkspace/BKPS/Templates/static.indicator.helper.library.mql5 b/MQLTestWorkspace/BKPS/Templates/static.indicator.helper.library.mql5 new file mode 100644 index 0000000..a86246a --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/static.indicator.helper.library.mql5 @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XHLP Indicator Helper for Signal Providers +// -------------------------------------------------------------------------- +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +///////////////////////////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Includes ... +// + +// +// Includes ... +#include "../../Libraries/x-saherelm.alert.lib.mq5" +#include "../../Libraries/x-saherelm.models.lib.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes ... +// + +// +// START Constants/Enums ... +// + +// +// END Constants/Enums ... +// + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +bool XHLPOnInit() { + // + bool result = false; + + // + return result; +} + +// +void XHLPOnDeInit() { + // + // Release Indicators ... +} + +// +void XHLPReadBuffers() { + // +} + +// +// END Handler Functions ... +// + +// +// START Helper Functions ... +// + +// +// END Helper Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Templates/trader.generate.support.signals.mq5 b/MQLTestWorkspace/BKPS/Templates/trader.generate.support.signals.mq5 new file mode 100644 index 0000000..0b2d946 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/trader.generate.support.signals.mq5 @@ -0,0 +1,129 @@ + + // + // Support Signals ... + void GenerateSupportSignals( + XSignal &result[], // Hold Result ... + const XSignal &source // Source Signal to Use for Generation ... + ) + { + // + // Here we must Prepare all Signals ... + + // + Clean(result); + + // + if (source.entry <= 0 || + (ArraySize(source.supportAndResistance.sup) == 0 && + ArraySize(source.supportAndResistance.res) == 0)) + { + return; + } + + // + double priceOf10Points = PointToPrice( + source.symbol, + 10); + + // + double tmpSupRes[]; + int supResCount = ArraySize(source.supportAndResistance.sup) + + ArraySize(source.supportAndResistance.res); + ArrayResize( + tmpSupRes, + supResCount); + ArrayCopy( + tmpSupRes, + source.supportAndResistance.sup); + ArrayCopy( + tmpSupRes, + source.supportAndResistance.res, + 0, + ArraySize(source.supportAndResistance.sup) - 1); + + // + bool isLong = IsLong(source.type); + + // + ENUM_POSITION_TYPE signalReverseType = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + // Template Variables ... + double sl; + double tp; + double entry; + ENUM_POSITION_TYPE type; + ENUM_X_ORDER_MODES mode; + double r2r = 1.5; + double volume = NormalizeVolume( + source.volume, // * 1.5, + source.symbol); + string symbol = source.symbol; + ENUM_TIMEFRAMES period = source.period; + double riskAmount = source.riskAmount; // * 1.5; + + // + XSignal tmpSignal; + Clean(tmpSignal); + + // + // since SL is Lower Sup or Higher Res ... + // we have to add a Reversal Support for SL ... + if (source.sl > 0) + { + // + // Sl Type Signals are Reversal ... + type = signalReverseType; + + // + // Finding Entry Price ... + entry = source.sl - priceOf10Points; + sl = !isLong + ? FindLesserThanValue(entry, tmpSupRes) + : FindBiggerThanValue(entry, tmpSupRes); + double riskPrice = sl > 0 + ? MathAbs(entry - sl) + : MathAbs(entry - priceOf10Points); + double riskPoint = PriceToPoint( + symbol, + riskPrice); + double rewardPoint = r2r * riskPoint; + double rewardPrice = PointToPrice( + symbol, + rewardPoint); + tp = !isLong + ? entry + rewardPrice + : entry - rewardPrice; + + // + mode = X_ORDER_MODE_STOP; + + // + // Fill ... + tmpSignal.sl = sl; + tmpSignal.tp = tp; + tmpSignal.r2r = r2r; + tmpSignal.type = type; + tmpSignal.mode = mode; + tmpSignal.entry = entry; + tmpSignal.symbol = symbol; + tmpSignal.volume = volume; + tmpSignal.period = period; + tmpSignal.riskAmount = riskAmount; + + // + Add( + tmpSignal, + result); + Clean(tmpSignal); + } + + // + // add MidTerm Support Signal ... + // TODO: + + // + // TODO: Implement another Support Scenarios ... + } diff --git a/MQLTestWorkspace/BKPS/Templates/x-121.indicator.template.mq5 b/MQLTestWorkspace/BKPS/Templates/x-121.indicator.template.mq5 new file mode 100644 index 0000000..d9183a6 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/x-121.indicator.template.mq5 @@ -0,0 +1,253 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XHULL Indicator +// --------------------------------------------- +// Name: XHULL +// Description: Hull Trend Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XHull Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XHull" +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.ex5 b/MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..20a8c83ccaf4cd6a4b67f6df3f87337d3858a78e GIT binary patch literal 8122 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 HaQXiLZ*Ovf literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.mq5 b/MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.mq5 new file mode 100644 index 0000000..e660058 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/x-saherelm.chart_drawing.template.mq5 @@ -0,0 +1,164 @@ +////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121_ICH Ichimoku Time Teory +// ------------------------------------------------------ +// Name: X121_ICH_ +// Description: +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_ICH Timing" + +// +#property strict +#property indicator_chart_window + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121_ICH_T" + +// +// Ichimoku Golden Numbers ... +enum ENUM_X_ICHIMOKU_GOLDEN_NUMBERS +{ + X_ICH_BASE = 9, + X_ICH_GOLDEN = 17, + X_ICH_CYCLE = 26, + X_ICH_PERIOD = 35, + X_ICH_STAR = 45, + X_ICH_MED = 52, + X_ICH_LONG = 63, + X_ICH_FULL = 72 +}; + +// +// END Constants ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +// Indicator Chart ID ... +string mIndicatorId; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Assign a hopefully-unique ID to the indicator so that it can later remove itself + mIndicatorId = ShortName + "." + IntegerToString(GetMicrosecondCount()); + IndicatorSetString(INDICATOR_SHORTNAME, mIndicatorId); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculations ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + return rates_total; +} + +// +// Handle Chart Events ... +void OnChartEvent( + const int id, // event ID + const long &lparam, // long type event parameter + const double &dparam, // double type event parameter + const string &sparam // string type event parameter +) +{ +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Remove Indicator From Chart ... +void RemoveIndicator() +{ + ChartIndicatorDelete(0, 0, mIndicatorId); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Templates/x-saherelm.xxhelper.indicator.template.mq5 b/MQLTestWorkspace/BKPS/Templates/x-saherelm.xxhelper.indicator.template.mq5 new file mode 100644 index 0000000..2ecba4c --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/x-saherelm.xxhelper.indicator.template.mq5 @@ -0,0 +1,151 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCBaseHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Constructor ... + void XSCHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) : XSCBaseHelper(symbol, period) + { + // + } + + // + // Deconstructor ... + void ~XSCHelper() + { + } + + // + // START Properties ... + // + + // + // Symbol ... + string GetSymbol() + { + return mSymbol; + } + + // + // Period ... + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Tag ... + string GetTag() + { + return mTag; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Initial Indicator Handler ... + virtual bool Init(); + + // + // Reading Buffers based on Given Bar Index ... + virtual void ReadBuffers( + int barIndex // Given Bar Index + ); + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Indicator Handler ... + int mHandler; + + // + // Tag Identifier ... + string mTag; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Templates/x.helper.implementation.class.template.mq5 b/MQLTestWorkspace/BKPS/Templates/x.helper.implementation.class.template.mq5 new file mode 100644 index 0000000..852dc0e --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/x.helper.implementation.class.template.mq5 @@ -0,0 +1,435 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXPVHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Index of Lines ... +enum ENUM_XPV_BUFFERS +{ + // + // Main Requirements ... + XPV_PEAKS_LINE = 0, + XPV_VALES_LINE = 1, +}; + +// +// Retrieve Info Model ... +struct XPVInfo +{ + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + // Bar Index ... + int barIndex; + + // + // Peak Value ... + double peak; + + // + // Vales Value ... + double vale; + + // + // Conditions ... + + // + // Determines New Peaks Happens ... + bool isNewPeak; + + // + // Determines New Vales Happens ... + bool isNewVale; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Helping Indicators Requirements ... +class XSCXPVHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + + // + // Constructor ... + void XSCXPVHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + // + // Indicator Properties ... + // + // Market ... + // + // Short Length ... + int shortLength = 9, + // + // Medium Length + int mediumLength = 17, + // + // Long Length ... + int longLength = 26, + // + // Hind Length ... + int hindLength = 35, + // + // Detection Mode ... + // + // Highest High Calculation Method ... + ENUM_SERIESMODE hhMode = MODE_HIGH, + // + // Lowest Low Calculation Method ... + ENUM_SERIESMODE llMode = MODE_LOW, + // + // Presentations ... + // + // Show Peaks and Vales ... + bool showPeaksAndVales = false, + // + // Show Levels ... + bool showLevels = false + // + ) : XSCBaseHelper(symbol, period) + { + // + // Indicator Properties ... + mHHMode = hhMode; + mLLMode = llMode; + mLongLength = longLength; + mHindLength = hindLength; + mShowLevels = showLevels; + mShortLength = shortLength; + mMediumLength = mediumLength; + mShowPeaksAndVales = showPeaksAndVales; + + // + Init(); + } + + // + // Deconstructor ... + void ~XSCXPVHelper() + { + } + + // + // START Properties ... + // + + // + // Show Levels ... + bool ShowLevels( + bool show // Show or Hide Levels + ) + { + // + bool result = false; + + // + if (mShowLevels == show) + { + return true; + } + + // + mShowLevels = show; + result = Init(); + + // + return result; + } + + // + // Show Peaks and Vales ... + bool ShowPeaksAnVales( + bool show // Show or Hide Levels + ) + { + // + bool result = false; + + // + if (mShowPeaksAndVales == show) + { + return true; + } + + // + mShowPeaksAndVales = show; + result = Init(); + + // + return result; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + void PrepareTag() + { + mTag = "" + GetTagPrefix(); + } + + // + // Initial Indicator Handler ... + bool Init() + { + // + bool result = false; + + // + // Validate Args ... + result = + // + (mShortLength > 2 && + mMediumLength > mShortLength && + mLongLength > mMediumLength && + mHindLength > mLongLength) + // + ; + if (!result) + { + return false; + } + + // + // Initialize Handler ... + mHandler = iCustom( + // + mSymbol, + mPeriod, + "x-saherelm.x121.xpv", + // + // Inputs ... + // + // Market ... + "", + // + // Short Length ... + mShortLength, + // + // Medium Length + mMediumLength, + // + // Long Length ... + mLongLength, + // + // Hind Length ... + mHindLength, + // + // Detection Mode ... + "", + // + // Highest High Calculation Method ... + mHHMode, + // + // Lowest Low Calculation Method ... + mLLMode, + // + // Presentations ... + "", + // + // Show Peaks and Vales ... + mShowPeaksAndVales, + // + // Show Levels ... + mShowLevels + // + ); + result = mHandler != INVALID_HANDLE; + + // + return result; + } + + // + // Reading Buffers based on Given Bar Index ... + void Calculate( + int barIndex // Given Bar Index + ) + { + // + // PEAKS ... + CopyBuffer( + mHandler, + XPV_PEAKS_LINE, + barIndex, + mLoopbackBars, + peaksBuffer); + + // + // VALES ... + CopyBuffer( + mHandler, + XPV_VALES_LINE, + barIndex, + mLoopbackBars, + valesBuffer); + } + + // + // Retrieve Info at Specific Bar Index ... + XPVInfo GetInfo( + int barIndex // Given Bar Index + ) + { + // + XPVInfo result; + + // + if (barIndex < 0) + { + return result; + } + + // + // Do Calculations ... + Calculate(barIndex); + + // + // Generate Candle Time ... + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex + ); + + // + // Fill Result ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barTime = barTime;; + result.barIndex = barIndex; + + // + result.peak = peaksBuffer[barIndex]; + result.vale = valesBuffer[barIndex]; + + // + result.isNewPeak = + peaksBuffer[barIndex] != peaksBuffer[barIndex + 1]; + result.isNewVale = + valesBuffer[barIndex] != valesBuffer[barIndex + 1]; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Indicator Properties ... + // + // Market ... + // + // Short Length ... + int mShortLength; + // + // Medium Length + int mMediumLength; + // + // Long Length ... + int mLongLength; + // + // Hind Length ... + int mHindLength; + // + // Detection Mode ... + // + // Highest High Calculation Method ... + ENUM_SERIESMODE mHHMode; + // + // Lowest Low Calculation Method ... + ENUM_SERIESMODE mLLMode; + // + // Presentations ... + // + // Show Peaks and Vales ... + bool mShowPeaksAndVales; + // + // Show Levels ... + bool mShowLevels; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/Templates/xpv.find.supres.old.mq5 b/MQLTestWorkspace/BKPS/Templates/xpv.find.supres.old.mq5 new file mode 100644 index 0000000..8b174ad --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/xpv.find.supres.old.mq5 @@ -0,0 +1,310 @@ + +// +XOHCLSupRes XPVHLPFindCandleSupprtAndResistance( + int bar_index, // Bar Index ... + int verifications = 4 // Number of Verifications ... +) +{ + // + XOHCLSupRes result = {}; + result.res = 0; + result.highRes = 0; + result.sup = 0; + result.lowSup = 0; + + // + XOHCL cBar = GetCandle( + _Symbol, + _Period, + bar_index); + + // + int tries = 0; + int lastBar = bar_index; + while ( + result.res == 0 || + result.highRes == 0 || + result.sup == 0 || + result.lowSup == 0) + { + // + int bar = XPVHLPFindSupportBar(lastBar); + double val = XPVHLPFindSupportValue(lastBar); + + // + int bar1 = XPVHLPFindResistanceBar(lastBar); + double val1 = XPVHLPFindResistanceValue(lastBar); + + // + if (result.res == 0 && result.highRes == 0 && val > cBar.high && val1 > cBar.high) + { + // + result.res = MathMin(val, val1); + result.highRes = MathMax(val, val1); + } + else if (result.sup == 0 && result.lowSup == 0 && val < cBar.low && val1 < cBar.low) + { + // + result.sup = MathMax(val, val1); + result.lowSup = MathMin(val, val1); + } + else if (val > cBar.high) + { + // + if (result.res == 0 || result.highRes == 0) + { + // + if (result.res == 0) + { + result.res = val; + } + else if (val > result.res) + { + result.highRes = val; + } + else if (val < result.res) + { + // + result.highRes = result.res; + result.res = val; + } + } + } + else if (val < cBar.low) + { + // + if (result.sup == 0 || result.lowSup == 0) + { + // + if (result.sup == 0) + { + result.sup = val; + } + else if (val < result.sup) + { + result.lowSup = val; + } + else if (val > result.sup) + { + // + result.lowSup = result.sup; + result.sup = val; + } + } + } + else if (val1 > cBar.high) + { + // + if (result.res == 0 || result.highRes == 0) + { + // + if (result.res == 0) + { + result.res = val1; + } + else if (val1 > result.res) + { + result.highRes = val1; + } + else if (val1 < result.res) + { + // + result.highRes = result.res; + result.res = val1; + } + } + } + else if (val1 < cBar.low) + { + // + if (result.sup == 0 || result.lowSup == 0) + { + // + if (result.sup == 0) + { + result.sup = val1; + } + else if (val1 < result.sup) + { + result.lowSup = val1; + } + else if (val1 > result.sup) + { + // + result.lowSup = result.sup; + result.sup = val1; + } + } + } + + // + if (tries >= verifications) + { + break; + } + + // + lastBar = MathMin(bar, bar1); + tries++; + } + + // + return result; +} + + + + +// +int XPVHLPFindSupportBar( + int bar_index, // Bar Index ... + int verifications = 4 // Number of Verifications ... +) +{ + // + int result = -1; + + // + int mVerified = 0; + int idx = bar_index; + bool founded = false; + double lastValue = 0; + while (!founded) + { + // + XPVHLPReadBuffers(idx); + bool isSupport = XPVHLPIsStrongSupport(idx); + if (isSupport) + { + // + if (lastValue != pvLLLBuffer[idx]) + { + // + lastValue = pvLLLBuffer[idx]; + mVerified = 0; + } + else if (lastValue == pvLLLBuffer[idx]) + { + mVerified++; + } + } + else + { + mVerified = 0; + } + + // + idx++; + + // + founded = mVerified >= verifications; + if (founded) + { + result = idx; + break; + } + } + + // + return result; +} + +// +double XPVHLPFindSupportValue( + int bar_index, // Bar Index ... + int verifications = 4 // Number of Verifications ... +) +{ + // + double result = 0; + + // + int supportBar = XPVHLPFindSupportBar(bar_index, verifications); + if (supportBar < -1) + { + return result; + } + + // + return pvSLLBuffer[bar_index]; + + // + return result; +} + +// +int XPVHLPFindResistanceBar( + int bar_index, // Bar Index ... + int verifications = 4 // Number of Verifications ... +) +{ + // + int result = -1; + + // + int mVerified = 0; + int idx = bar_index; + bool founded = false; + double lastValue = 0; + while (!founded) + { + // + XPVHLPReadBuffers(idx); + bool isSupport = XPVHLPIsStrongResistance(idx); + if (isSupport) + { + // + if (lastValue != pvLHHBuffer[idx]) + { + // + lastValue = pvLHHBuffer[idx]; + mVerified = 0; + } + else if (lastValue == pvLHHBuffer[idx]) + { + mVerified++; + } + } + else + { + mVerified = 0; + } + + // + idx++; + + // + founded = mVerified >= verifications; + if (founded) + { + result = idx; + break; + } + } + + // + return result; +} + +// +double XPVHLPFindResistanceValue( + int bar_index, // Bar Index ... + int verifications = 4 // Number of Verifications ... +) +{ + // + double result = 0; + + // + int supportBar = XPVHLPFindResistanceBar(bar_index, verifications); + if (supportBar < -1) + { + return result; + } + + // + return pvSHHBuffer[bar_index]; + + // + return result; +} diff --git a/MQLTestWorkspace/BKPS/Templates/xpv.helper.test.tools.mq5 b/MQLTestWorkspace/BKPS/Templates/xpv.helper.test.tools.mq5 new file mode 100644 index 0000000..99784e7 --- /dev/null +++ b/MQLTestWorkspace/BKPS/Templates/xpv.helper.test.tools.mq5 @@ -0,0 +1,164 @@ + +// +// Find Last Strong Support ... +double XPVHLPGetLastStrongSupport( + int bar_index, // Bar Index ... + int length // LoopBack ... +) +{ + // + double result = 0; + + // + bool isBarIndexSupport = XPVHLPIsStrongSupport(bar_index); + if (isBarIndexSupport) + { + length += bar_index; + } + + // + if (!XPVHLPIsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (XPVHLPIsStrongSupport(i)) + { + // + result = mpvSLLBuffer[i]; + break; + } + } + + // + return result; +} + +// +// Find Last Strong Resistance ... +double XPVHLPGetLastStrongResistance( + int bar_index, // Bar Index ... + int length // LoopBack ... +) +{ + // + double result = 0; + + // + bool isBarIndexResistance = XPVHLPIsStrongResistance(bar_index); + if (isBarIndexResistance) + { + length += bar_index; + } + + // + if (!XPVHLPIsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (XPVHLPIsStrongResistance(i)) + { + // + result = mpvSHHBuffer[i]; + break; + } + } + + // + return result; +} + +// +// Find Strong Support Break Stop ... +bool XPVHLPIsSupportBreakedStop( + int bar_index, // Bar Index ... + int length // LoopBack ... +) +{ + // + bool result = false; + + // + bool isBaIndexSupport = XPVHLPIsStrongSupport(bar_index); + if (isBaIndexSupport) + { + return result; + } + + // + if (!XPVHLPIsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + bool isAllStrongSupport = true; + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (!XPVHLPIsStrongSupport(i) && isAllStrongSupport) + { + // + isAllStrongSupport = false; + break; + } + } + + // + result = !isBaIndexSupport && isAllStrongSupport; + + // + return result; +} + +// +// Find Strong Resistance Break Stop ... +bool XPVHLPIsResistanceBreakedStop( + int bar_index, // Bar Index ... + int length // LoopBack ... +) +{ + // + bool result = false; + + // + bool isBaIndexResistance = XPVHLPIsStrongResistance(bar_index); + if (isBaIndexResistance) + { + return result; + } + + // + if (!XPVHLPIsValidArraySize(bar_index + length + 1)) + { + return result; + } + + // + bool isAllStrongResistance = true; + for (int i = bar_index; i < bar_index + length; i++) + { + // + if (!XPVHLPIsStrongResistance(i) && isAllStrongResistance) + { + // + isAllStrongResistance = false; + break; + } + } + + // + result = !isBaIndexResistance && isAllStrongResistance; + + // + return result; +} diff --git a/MQLTestWorkspace/Classes/x-saherelm.http.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.http.class.mq5 new file mode 100644 index 0000000..e28342d --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.http.class.mq5 @@ -0,0 +1,385 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCHttp +// Description: provides all HTTP requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +enum X_HTTP_METHOD +{ + X_HTTP_GET, + X_HTTP_POST +}; + +// +// Convert enum to String ... +string ToString(X_HTTP_METHOD method) +{ + // + string result = ""; + + // + switch (method) + { + // + case X_HTTP_GET: + result = "GET"; + break; + + // + case X_HTTP_POST: + result = "POST"; + break; + } + + // + return result; +} + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Manage Account ... +class XSCHttp +{ + // + // Public ... +public: + // + // Constructor ... + void XSCHttp() + { + XSCHttp("", 10000); + } + void XSCHttp( + string path, // Base Folder to Store Data + int timeout // base timeout for Requests + ) + { + // + Path(path); + Timeout(timeout); + } + + // + // Deconstructor ... + void ~XSCHttp() + { + } + + // + // START Getter(s)/Setter(s) ... + // + + // + // Path ... + void Path(string value) + { + mPath = value; + } + + string Path() + { + return mPath; + } + + // + // Timeout ... + void Timeout(int value) + { + mTimeout = value; + } + + // + int Timeout() + { + return mTimeout; + } + + // + // Error ... + int Error() + { + return mError; + } + + // + // Response ... + string Response() + { + return mResponse; + } + + // + // END Getter(s)/Setter(s) ... + // + + // + // START Provided Functions ... + // + + // + // Send Global Request ... + int SendRequest( + X_HTTP_METHOD method, // Httm Request Method + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 + ) + { + // + int result = -1; + + // + string strMethod = ToString(method); + if (StringLen(strMethod) == 0) + { + return result; + } + + // + // Reset State ... + ResetState(); + + // + result = WebRequest( + strMethod, + url, + headers, + timeout, + payload, + response, + responseHeaders); + + // + if (result < 0) + { + mError = GetLastError(); + } + else + { + mResponse = CharArrayToString(response); + } + + // + return result; + } + + // + // Get Request ... + int GetRequest( + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 + ) + { + // + int result = SendRequest( + X_HTTP_GET, + url, + headers, + payload, + response, + responseHeaders, + timeout); + + // + return result; + } + + // + // Post Request ... + int PostRequest( + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 + ) + { + // + int result = SendRequest( + X_HTTP_POST, + url, + headers, + payload, + response, + responseHeaders, + timeout); + + // + return result; + } + + // + // Handle Download Specific URL Content to Specific Path and File Name ... + bool Download( + string url, // the URL address which going to download + string fileName // Specify Destination file name to Store Response + ) + { + // + bool result = false; + + // + string filePath = GetFilePath(fileName); + string cookie = NULL; + string referer = NULL; + int timeout = Timeout(); + + // + char payload[]; + string headers; + char response[]; + string responseHeaders; + + // + // Send Request ... + int requestResult = GetRequest( + url, + headers, + payload, + response, + responseHeaders, + timeout); + + // + // Define File Handler ... + int mFileHandler = FileOpen( + filePath, + FILE_WRITE | FILE_BIN); + if (mFileHandler == INVALID_HANDLE) + { + // + mError = GetLastError(); + return result; + } + + // + // Write Response to File ... + uint writed = FileWriteArray( + mFileHandler, + response, + 0, + ArraySize(response)); + FileFlush(mFileHandler); + FileClose(mFileHandler); + + // + result = writed > 0; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Destintion Folder Path ... + string mPath; + + // + // WEB Request Timeout Value ... + int mTimeout; + + // + // WEB Request's Response ... + string mResponse; + + // + // Error Value ... + int mError; + + // + // Private ... +private: + // + // Reset Errors State ... + void ResetState() + { + // + // Reset Errors ... + mError = -1; + mResponse = ""; + ResetLastError(); + } + + // + // Generate Full File Path ... + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + Path() + "\\" + fileName + // + ; + + // + return result; + } +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.ex5 b/MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..86ed2007f10ad6fb817c1dd752b1551dd5cd9dee GIT binary patch literal 10406 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.mq5 new file mode 100644 index 0000000..4a423b0 --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.x121.provider.class.mq5 @@ -0,0 +1,1788 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCX121Provider +// Description: X121 Signal Provider ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Classes/x-saherelm.xprovider.class.mq5" +#include "../Helpers/x-saherelm.x121.xct.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xcc.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xhk.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xtm.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xpv.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xama.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xmrb.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xche.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xich.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xtrnd.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xsslc.helper.class.mq5" +#include "../Helpers/x-saherelm.x121.xhull.helper.class.mq5" + +// +// Seriallizer Library ... +#include "../Libraries/x-saherelm.seriallizer.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// Here we Have to Define an Input Structure Model +// for Provider Class to Handle Helpers Definitions ... +struct X121ProviderInputs +{ + // + // XCT ... + // Candle Timer ... + XCTInputs xctConfig; + + // + // XCC ... + // Candle Styling ... + XCCInputs xccConfig; + + // + // XHK ... + // HikenAshi Candle Representing ... + XHKInputs xhkConfig; + + // + // XTM ... + // Trend Magic ... + XTMInputs xtmConfig; + + // + // XPV ... + // Peaks And Vales ... + XPVInputs xpvConfig; + + // + // XAMA ... + // Adaptive Moving Average ... + XAMAInputs xamaConfig; + + // + // XMRB ... + // Moving Average Ribbon ... + XMRBInputs xmrbConfig; + + // + // XCHE ... + // Chandelier Exit Points ... + XCHEInputs xcheConfig; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + XICHInputs xichConfig; + + // + // XTRND ... + // Trend Detector ... + XTRNDInputs xtrndConfig; + + // + // XSSLC ... + // SSL Channel ... + XSSLCInputs xsslcConfig; + + // + // XHULL ... + // Hull Trend Detection Channel ... + XHULLInputs xhullConfig; +}; + +// +// Model Market Sense based On Current Captured conditions ... +struct X121MarketConditions +{ + // + // Commonly Used Info ... + + // + // Symbol ... + string symbol; + + // + // Period ... + ENUM_TIMEFRAMES period; + + // + // Bar Time ... + datetime barTime; + + // + XCandleRemains barRemains; + + // + // Bar Index ... + int barIndex; + + // + // Check Current Market Condition has Signal or not ... + bool hasSignal; + + // + // If has any Signal, Models it's related info here ... + XSignal signal; + + // + // Support and Resistances ... + // if provides Signal ... + XOHCLSupRes supportResistances; + + // + // Change Price Steps ... + double momentumStep; + + // + // INDICATORS Market Sense ... + + // + // XCT ... + // there is not any Info provided here ... + + // + // XCC ... + // there is not any Info provided here ... + + // + // XHK ... + XHKInfo xhkInfo; + + // + // XTM ... + XTMInfo xtmInfo; + + // + // XPV ... + XPVInfo xpvInfo; + + // + // XAMA ... + XAMAInfo xamaInfo; + + // + // XMRB ... + XMRBInfo xmrbInfo; + + // + // XCHE ... + XCHEInfo xcheInfo; + + // + // XICH ... + XICHInfo xichInfo; + + // + // XTRND ... + XTRNDInfo xtrndInfo; + + // + // XSSLC ... + XSSLCInfo xsslcInfo; + + // + // XHULL ... + XHULLInfo xhullInfo; +}; + +// +// Notified a Signal was Appears ... +typedef void (*TOnSignalConditions)( + X121MarketConditions &info); + +// +// All Available Signal Types ... +enum ENUM_X121_SIGNAL_PROVIDERS +{ + NONE, // NONE ... + XPVF, // Peakse and Vales Using Fibo ... + XCHNL, // SSL Channel and MRB Signals ... + XTRND, // Trend Base ... +}; + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Base Class for All of our EA's ... +class XSCX121Provider : public XSCEABaseProvider +{ + // + // Public ... +public: + // + // Props ... + X121ProviderInputs providedConfig; + X121ProviderInputs currentConfig; + X121ProviderInputs cleanConfig; + + // + // Indicator Helper Classes Instance ... + + // + // XCT ... + XSCXCTHelper *mXCTHelper; + + // + // XCC ... + XSCXCCHelper *mXCCHelper; + + // + // XHK ... + XSCXHKHelper *mXHKHelper; + + // + // XTM ... + XSCXTMHelper *mXTMHelper; + + // + // XPV ... + XSCXPVHelper *mXPVHelper; + + // + // XAMA ... + XSCXAMAHelper *mXAMAHelper; + + // + // XMRB ... + XSCXMRBHelper *mXMRBHelper; + + // + // XCHE ... + XSCXCHEHelper *mXCHEHelper; + + // + // XICH ... + XSCXICHHelper *mXICHHelper; + + // + // XTRND ... + XSCXTRNDHelper *mXTRNDHelper; + + // + // XSSLC ... + XSCXSSLCHelper *mXSSLCHelper; + + // + // XHULL ... + XSCXHULLHelper *mXHULLHelper; + + // + // Hull Pivot Points ... + double upZonePivots[]; + double downZonePivots[]; + + // + // Peaks and Vales Verifications Number ... + double peaksPivots[]; + double valesPivots[]; + + // + double ichPivots[]; + + // + double fiboPivots[]; + + // + int pvConsequences; + + // + // Constructor ... + void XSCX121Provider( + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period // Trading Time Frame ... + ) + { + // + mMinPivots = 100; + pvConsequences = 26; + mDisableXPVFShort = false; + mDisableXPVFLong = false; + + // + PrepareTag(); + } + + // + // Deconstructor ... + void ~XSCX121Provider() + { + // + IndicatorRelease(mCTimerHandler); + + // + // De construct Helpers ... + delete mXCTHelper; + delete mXCCHelper; + delete mXHKHelper; + delete mXTMHelper; + delete mXPVHelper; + delete mXAMAHelper; + delete mXMRBHelper; + delete mXCHEHelper; + delete mXICHHelper; + delete mXTRNDHelper; + delete mXSSLCHelper; + delete mXHULLHelper; + } + + // + int GetMinPivots() { + return mMinPivots; + } + + // + virtual void PrepareTag() + { + mTag = "X121Provider((" + mSymbol + ")(" + ToString(mPeriod) + ")"; + } + + // + virtual bool Init() + { + // + bool result = false; + + // + // Instantiate all Indicators Helper Classes ... + + // + // XCT ... + mXCTHelper = new XSCXCTHelper( + mSymbol, + mPeriod); + result = mXCTHelper.SetConfig(currentConfig.xctConfig); + if (!result) + { + return result; + } + + // + // XCC ... + mXCCHelper = new XSCXCCHelper( + mSymbol, + mPeriod); + result = mXCCHelper.SetConfig(currentConfig.xccConfig); + if (!result) + { + return result; + } + + // + // XHK ... + mXHKHelper = new XSCXHKHelper( + mSymbol, + mPeriod); + result = mXHKHelper.SetConfig(currentConfig.xhkConfig); + if (!result) + { + return result; + }; + + // + // XTM ... + mXTMHelper = new XSCXTMHelper( + mSymbol, + mPeriod); + result = mXTMHelper.SetConfig(currentConfig.xtmConfig); + if (!result) + { + return result; + }; + + // + // XPV ... + mXPVHelper = new XSCXPVHelper( + mSymbol, + mPeriod); + result = mXPVHelper.SetConfig(currentConfig.xpvConfig); + if (!result) + { + return result; + }; + + // + // XAMA ... + mXAMAHelper = new XSCXAMAHelper( + mSymbol, + mPeriod); + result = mXAMAHelper.SetConfig(currentConfig.xamaConfig); + if (!result) + { + return result; + }; + + // + // XMRB ... + mXMRBHelper = new XSCXMRBHelper( + mSymbol, + mPeriod); + result = mXMRBHelper.SetConfig(currentConfig.xmrbConfig); + if (!result) + { + return result; + }; + + // + // XCHE ... + mXCHEHelper = new XSCXCHEHelper( + mSymbol, + mPeriod); + result = mXCHEHelper.SetConfig(currentConfig.xcheConfig); + if (!result) + { + return result; + }; + + // + // XICH ... + mXICHHelper = new XSCXICHHelper( + mSymbol, + mPeriod); + result = mXICHHelper.SetConfig(currentConfig.xichConfig); + if (!result) + { + return result; + }; + + // + // XTRND ... + mXTRNDHelper = new XSCXTRNDHelper( + mSymbol, + mPeriod); + result = mXTRNDHelper.SetConfig(currentConfig.xtrndConfig); + if (!result) + { + return result; + }; + + // + // XSSLC ... + mXSSLCHelper = new XSCXSSLCHelper( + mSymbol, + mPeriod); + result = mXSSLCHelper.SetConfig(currentConfig.xsslcConfig); + if (!result) + { + return result; + }; + + // + // XHULL ... + mXHULLHelper = new XSCXHULLHelper( + mSymbol, + mPeriod); + result = mXHULLHelper.SetConfig(currentConfig.xhullConfig); + if (!result) + { + return result; + }; + + // + return result; + } + + // + virtual int GetMaxLength() + { + // + int result = -1; + + // + result = MathMax(result, mXCTHelper.GetMaxLength()); + result = MathMax(result, mXCCHelper.GetMaxLength()); + result = MathMax(result, mXHKHelper.GetMaxLength()); + result = MathMax(result, mXTMHelper.GetMaxLength()); + result = MathMax(result, mXPVHelper.GetMaxLength()); + result = MathMax(result, mXAMAHelper.GetMaxLength()); + result = MathMax(result, mXMRBHelper.GetMaxLength()); + result = MathMax(result, mXCHEHelper.GetMaxLength()); + result = MathMax(result, mXICHHelper.GetMaxLength()); + result = MathMax(result, mXTRNDHelper.GetMaxLength()); + result = MathMax(result, mXSSLCHelper.GetMaxLength()); + result = MathMax(result, mXHULLHelper.GetMaxLength()); + + // + return result; + } + + // + virtual int GetCalculatedBars() + { + // + int result = -1; + + // + int mXCTBars = mXCTHelper.GetCalculatedBars(); + int mXCCBars = mXCCHelper.GetCalculatedBars(); + int mXHKBars = mXHKHelper.GetCalculatedBars(); + int mXTMBars = mXTMHelper.GetCalculatedBars(); + int mXPVBars = mXPVHelper.GetCalculatedBars(); + int mXAMABars = mXAMAHelper.GetCalculatedBars(); + int mXMRBBars = mXMRBHelper.GetCalculatedBars(); + int mXCHEBars = mXCHEHelper.GetCalculatedBars(); + int mXICHBars = mXICHHelper.GetCalculatedBars(); + int mXTRNDBars = mXTRNDHelper.GetCalculatedBars(); + int mXSSLCBars = mXSSLCHelper.GetCalculatedBars(); + int mXHULLBars = mXHULLHelper.GetCalculatedBars(); + + // + int min = MathMin(mXCTBars, mXCCBars); + min = MathMin(min, mXHKBars); + min = MathMin(min, mXTMBars); + min = MathMin(min, mXPVBars); + min = MathMin(min, mXAMABars); + min = MathMin(min, mXMRBBars); + min = MathMin(min, mXCHEBars); + min = MathMin(min, mXICHBars); + min = MathMin(min, mXTRNDBars); + min = MathMin(min, mXSSLCBars); + min = MathMin(min, mXHULLBars); + + // + int max = MathMax(mXCTBars, mXCCBars); + max = MathMax(max, mXHKBars); + max = MathMax(max, mXTMBars); + max = MathMax(max, mXPVBars); + max = MathMax(max, mXAMABars); + max = MathMax(max, mXMRBBars); + max = MathMax(max, mXCHEBars); + max = MathMax(max, mXICHBars); + max = MathMax(max, mXTRNDBars); + max = MathMax(max, mXSSLCBars); + max = MathMax(max, mXHULLBars); + + // + result = min; + + // + return result; + } + + // + virtual void ProcessBuffers() + { + UpdatePivotPoints(); + } + + // + virtual bool ProcessTick(X121MarketConditions &conditions) + { + // + if (CanIgnoreTick()) { + return false; + } + + // + return ProcessSignals(conditions); + } + + // + X121ProviderInputs GetConfig() + { + // + X121ProviderInputs result; + + // + result = currentConfig; + + // + return result; + } + + // + bool SetConfig(X121ProviderInputs &config) + { + // + bool result = false; + + // + PrepareConfig(config); + + // + result = Init(); + + // + return result; + } + + // + bool ResetDefaultConfig() + { + // + bool result = SetConfig(providedConfig); + + // + return result; + } + + // + bool ShowCleanConfig() + { + // + currentConfig = cleanConfig; + + // + bool result = Init(); + + // + return result; + } + + // + bool ShowDefaultConfig() + { + // + currentConfig = providedConfig; + + // + bool result = Init(); + + // + return result; + } + + // + // Generate Market Sense ... + X121MarketConditions GetMarketConditions( + int barIndex // Specified Bar Index + ) + { + // + X121MarketConditions result; + + // + // Fill Common Data ... + result.symbol = mSymbol; + result.period = mPeriod; + result.barIndex = barIndex; + + // + datetime barTime = GetCandleTime( + mSymbol, + mPeriod, + barIndex); + result.barTime = barTime; + + // + int remainedCandle = barIndex > 0 + ? barIndex - 1 + : barIndex; + GetCandleRemainsTime( + result.barRemains, + mSymbol, + mPeriod, + remainedCandle); + + // + result.xhkInfo = mXHKHelper.GetInfo(barIndex); + result.xtmInfo = mXTMHelper.GetInfo(barIndex); + result.xpvInfo = mXPVHelper.GetInfo(barIndex); + result.xamaInfo = mXAMAHelper.GetInfo(barIndex); + result.xmrbInfo = mXMRBHelper.GetInfo(barIndex); + result.xcheInfo = mXCHEHelper.GetInfo(barIndex); + result.xichInfo = mXICHHelper.GetInfo(barIndex); + result.xtrndInfo = mXTRNDHelper.GetInfo(barIndex); + result.xsslcInfo = mXSSLCHelper.GetInfo(barIndex); + result.xhullInfo = mXHULLHelper.GetInfo(barIndex); + + // + return result; + } + + // + // TODO: Complete this ... + XOHCLSupRes GetSupportsAndResistances( + XSignal &signal, // Signal + int requirements = 10) + { + // + XOHCLSupRes result; + + // + int totalBars = Bars( + mSymbol, + mPeriod); + + // + int idx = 0; + + // + while ( + idx < totalBars - 17 || + ArraySize(result.sup) < requirements || + ArraySize(result.res) < requirements) + { + // + // Here we Try to Find Support and Resistances ... + + // + idx++; + } + + // + return result; + } + + // + bool GuardCheck(XGuard &guards[]) + { + // + bool result = false; + + // + Clean(guards); + + // + // Implement Guards Check ... + + // + return result; + } + + // + // Add Specific On SignalConditions Event Handler ... + int AddOnSignalConditionEventHandler(TOnSignalConditions handler) + { + // + ArrayResize( + mSignalConditionsEventHandlers, + ArraySize(mSignalConditionsEventHandlers) + 1); + + // + int result = ArraySize(mSignalConditionsEventHandlers) - 1; + mSignalConditionsEventHandlers[result] = handler; + + // + return result; + } + + // + // Remove All On Signal Event Handler ... + void ReoveOnSignalEventHandlers() + { + // + ArrayFree(mSignalConditionsEventHandlers); + } + + // + // Notify a Signal Found on all Event Listeners ... + void NotifyOnSignalConditionsEvent(X121MarketConditions &info) + { + // + int listenerCount = ArraySize(mSignalConditionsEventHandlers); + if (listenerCount <= 0) + { + return; + } + + // + // Loop Through Listeners ... + for (int i = 0; i < listenerCount; i++) + { + // + TOnSignalConditions listener = mSignalConditionsEventHandlers[i]; + + // + listener(info); + } + } + + // + void ProccessPivotPoints() + { + // + if (mStartPivotScan) + { + return; + } + + // + mStartPivotScan = true; + + // + int maxLength = GetMaxLength(); + int cBars = GetCalculatedBars(); + int scanSize = cBars - maxLength - 1; + for (int i = 1; i < scanSize; i++) + { + // + UpdatePivotPoints(i); + + // + int pivotsCount = CountPivots(); + if (pivotsCount >= mMinPivots) + { + break; + } + } + } + + // + int CountPivots() + { + // + int pivotSizes[]; + int upZoneCount = ArraySize(upZonePivots); + if (upZoneCount > 0) + { + // + Add( + upZoneCount, + pivotSizes); + } + + // + int downZoneCount = ArraySize(downZonePivots); + if (downZoneCount > 0) + { + // + Add( + downZoneCount, + pivotSizes); + } + + // + int peaksCount = ArraySize(peaksPivots); + if (peaksCount > 0) + { + // + Add( + peaksCount, + pivotSizes); + } + + // + int valesCount = ArraySize(valesPivots); + if (valesCount > 0) + { + // + Add( + valesCount, + pivotSizes); + } + + // + int fibsCount = ArraySize(fiboPivots); + if (fibsCount > 0) + { + // + Add( + fibsCount, + pivotSizes); + } + + // + int ichsCount = ArraySize(ichPivots); + if (ichsCount > 0) + { + // + Add( + ichsCount, + pivotSizes); + } + + // + int result = ArraySize(pivotSizes) > 0 + ? pivotSizes[ArrayMaximum(pivotSizes)] + : 0; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // CCandle Timer ... + int mCTimerHandler; + + // + // Signal Event Handlers ... + TOnSignalConditions mSignalConditionsEventHandlers[]; + + // + // Make Provided Config in Clean Style ... + void PrepareConfig(X121ProviderInputs &config) + { + // + cleanConfig = config; + + // + // XCT ... + // Candle Timing ... + cleanConfig.xctConfig.showCandleTime = false; + + // + // XCC ... + // Candle Styling ... + cleanConfig.xccConfig.showCandles = true; + + // + // XHK ... + // HikenAshi Candle Representing ... + cleanConfig.xhkConfig.drawCandles = false; + cleanConfig.xhkConfig.drawCandleLines = false; + + // + // XTM ... + // Trend Magic ... + cleanConfig.xtmConfig.showLine = false; + + // + // XPV ... + // Peaks And Vales ... + cleanConfig.xpvConfig.showPeaksAndVales = false; + cleanConfig.xpvConfig.showLevels = false; + cleanConfig.xpvConfig.showFibo1Levels = false; + cleanConfig.xpvConfig.showFibo2Levels = false; + cleanConfig.xpvConfig.showFibo3Levels = false; + + // + // XAMA ... + // Adaptive Moving Average ... + cleanConfig.xamaConfig.showLine = false; + + // + // XMRB ... + // Moving Average Ribbon ... + cleanConfig.xmrbConfig.showFastMa = false; + cleanConfig.xmrbConfig.showSlowMa = false; + cleanConfig.xmrbConfig.showRibbon = false; + + // + // XCHE ... + // Chandelier Exit Points ... + cleanConfig.xcheConfig.showLongExit1Line = false; + cleanConfig.xcheConfig.showShortExit1Line = false; + cleanConfig.xcheConfig.showLongExit2Line = false; + cleanConfig.xcheConfig.showShortExit2Line = false; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + cleanConfig.xichConfig.showTenkanSen = false; + cleanConfig.xichConfig.showKijunSen = false; + cleanConfig.xichConfig.showKijunSenPlus = false; + cleanConfig.xichConfig.showKijunSenNegative = false; + cleanConfig.xichConfig.showChikouSpan = false; + cleanConfig.xichConfig.showSenkouSpanA = false; + cleanConfig.xichConfig.showSenkouSpanB = false; + cleanConfig.xichConfig.showKumo = false; + + // + // XTRND ... + // Trend Detector ... + cleanConfig.xtrndConfig.showConsolidations = false; + cleanConfig.xtrndConfig.showTrend = false; + cleanConfig.xtrndConfig.showL1Trend = false; + cleanConfig.xtrndConfig.showL2Trend = false; + cleanConfig.xtrndConfig.showL3Trend = false; + + // + // XSSLC ... + // SSL Channel ... + cleanConfig.xsslcConfig.showUp = false; + cleanConfig.xsslcConfig.showDown = false; + + // + // XHULL ... + // Hull Trend Detection Channel ... + cleanConfig.xhullConfig.showUpZone = false; + cleanConfig.xhullConfig.showDownZone = false; + + // + providedConfig = config; + currentConfig = config; + } + + // + int mMinPivots; + bool mStartPivotScan; + bool mDisableXPVFLong; + bool mDisableXPVFShort; + double mLastMomentumStep; + + // + // Find Required Pivots for Support and Resistance ... + void UpdatePivotPoints( + int barIndex = 1 // Specified Candle ... + ) + { + // + mXCTHelper.Calculate(barIndex); + mXCCHelper.Calculate(barIndex); + mXHKHelper.Calculate(barIndex); + mXTMHelper.Calculate(barIndex); + mXPVHelper.Calculate(barIndex); + mXAMAHelper.Calculate(barIndex); + mXMRBHelper.Calculate(barIndex); + mXCHEHelper.Calculate(barIndex); + mXICHHelper.Calculate(barIndex); + mXTRNDHelper.Calculate(barIndex); + mXSSLCHelper.Calculate(barIndex); + mXHULLHelper.Calculate(barIndex); + + // + // Detect Peask and Vales Pivots ... + + // + // Detect Hull Pivots ... + // find Hull Trend Changes ... + int idx = 1; + bool isHullUpChanged = + // + ( + // + (XHULL_ZONE_STATES)mXHULLHelper.upStateBuffer[idx] == XHULL_STATE_BULLISH && + (XHULL_ZONE_STATES)mXHULLHelper.upStateBuffer[idx + 1] != XHULL_STATE_BULLISH + // + ) + // + || + // + ( + // + (XHULL_ZONE_STATES)mXHULLHelper.upStateBuffer[idx] == XHULL_STATE_BEARISH && + (XHULL_ZONE_STATES)mXHULLHelper.upStateBuffer[idx + 1] != XHULL_STATE_BEARISH + // + ) + // + ; + + // + bool isHullDownChanged = + // + ( + // + (XHULL_ZONE_STATES)mXHULLHelper.downStateBuffer[idx] == XHULL_STATE_BULLISH && + (XHULL_ZONE_STATES)mXHULLHelper.downStateBuffer[idx + 1] != XHULL_STATE_BULLISH + // + ) + // + || + // + ( + // + (XHULL_ZONE_STATES)mXHULLHelper.downStateBuffer[idx] == XHULL_STATE_BEARISH && + (XHULL_ZONE_STATES)mXHULLHelper.downStateBuffer[idx + 1] != XHULL_STATE_BEARISH + // + ) + // + ; + + // + // Find Change State ... + if (isHullUpChanged || + isHullDownChanged) + { + // + AddIfNotExists( + mXHULLHelper.upBuffer[idx], + upZonePivots); + + // + AddIfNotExists( + mXHULLHelper.downBuffer[idx], + downZonePivots); + } + + // + // Find Momentom Step ... + if (isHullUpChanged && + isHullDownChanged) + { + // + mLastMomentumStep = MathAbs(mXHULLHelper.upBuffer[idx] - mXHULLHelper.downBuffer[idx]); + mLastMomentumStep = NormalizePrice( + mLastMomentumStep, + mSymbol); + } + + // + // Find Peaks and Vales ... + double selectedFib1 = mXPVHelper.fl1Buffer[idx]; + double selectedFib2 = mXPVHelper.fl2Buffer[idx]; + double selectedFib3 = mXPVHelper.fl3Buffer[idx]; + double selectedPeak = mXPVHelper.peaksBuffer[idx]; + double selectedVale = mXPVHelper.valesBuffer[idx]; + + // + double selectedTenkanSen = mXICHHelper.tenkanSenBuffer[idx]; + double selectedKijunSen = mXICHHelper.kijunSenBuffer[idx]; + + // + int fib1Verified = 0; + int fib2Verified = 0; + int fib3Verified = 0; + int peaksVerified = 0; + int valesVerified = 0; + int kijunSenVerified = 0; + int tenkanSenVerified = 0; + int senkouSpanAVerified = 0; + int senkouSpanBVerified = 0; + for (int i = barIndex + 1; i < pvConsequences + barIndex + 1; i++) + { + // + int idx = i - barIndex; + + // + // PEAKS and VALES ... + + // + if (selectedPeak == mXPVHelper.peaksBuffer[idx]) + { + peaksVerified++; + } + else + { + peaksVerified = 0; + } + + // + if (selectedVale == mXPVHelper.valesBuffer[idx]) + { + valesVerified++; + } + else + { + valesVerified = 0; + } + + // + if (selectedFib1 == mXPVHelper.fl1Buffer[idx]) + { + fib1Verified++; + } + else + { + fib1Verified = 0; + } + + // + if (selectedFib2 == mXPVHelper.fl2Buffer[idx]) + { + fib2Verified++; + } + else + { + fib2Verified = 0; + } + + // + if (selectedFib3 == mXPVHelper.fl3Buffer[idx]) + { + fib3Verified++; + } + else + { + fib3Verified = 0; + } + + // + // ICHIMOKU Kinko Hyo ... + + // + if (selectedTenkanSen == mXICHHelper.tenkanSenBuffer[idx]) + { + tenkanSenVerified++; + } + else + { + tenkanSenVerified = 0; + } + + // + if (selectedKijunSen == mXICHHelper.kijunSenBuffer[idx]) + { + kijunSenVerified++; + } + else + { + kijunSenVerified++; + } + } + + // + if (peaksVerified >= pvConsequences) + { + // + AddIfNotExists( + selectedPeak, + peaksPivots); + } + + // + if (valesVerified >= pvConsequences) + { + // + AddIfNotExists( + selectedVale, + valesPivots); + } + + // + if (fib1Verified >= pvConsequences) + { + // + AddIfNotExists( + selectedFib1, + fiboPivots); + } + + // + if (fib2Verified >= pvConsequences) + { + // + AddIfNotExists( + selectedFib2, + fiboPivots); + } + + // + if (fib3Verified >= pvConsequences) + { + // + AddIfNotExists( + selectedFib3, + fiboPivots); + } + + // + if (tenkanSenVerified >= pvConsequences) + { + // + AddIfNotExists( + selectedTenkanSen, + ichPivots); + } + + // + if (kijunSenVerified >= pvConsequences) + { + // + AddIfNotExists( + selectedKijunSen, + ichPivots); + } + + // // + // if (senkouSpanAVerified >= pvConsequences) + // { + // // + // AddIfNotExists( + // selectedSenkouSpanA, + // ichPivots); + // } + + // // + // if (senkouSpanBVerified >= pvConsequences) + // { + // // + // AddIfNotExists( + // selectedSenkouSpanB, + // ichPivots); + // } + } + + // + void FillPivotPoints( + double &result[]) + { + // + Clean(result); + + // + int pCount = CountPivots(); + if (pCount <= 0) + { + return; + } + + // + AddsIfNotExists( + upZonePivots, + result); + + // + AddsIfNotExists( + downZonePivots, + result); + + // + AddsIfNotExists( + peaksPivots, + result); + + // + AddsIfNotExists( + valesPivots, + result); + + // + AddsIfNotExists( + fiboPivots, + result); + + // + AddsIfNotExists( + ichPivots, + result); + } + + // + // Here we are Capture Conditions and Check Signals ... + // The Signals Must be Unique for each providers ... + bool ProcessSignals(X121MarketConditions &conditions) + { + // + X121MarketConditions mConditions = GetMarketConditions(1); + + // + // BUY ... + + // + Clean(mConditions.signal); + bool hasLongSignal = HasLongSignal(mConditions); + if (hasLongSignal) + { + // + NotifyOnSignalEvent( + mConditions.signal); + NotifyOnSignalConditionsEvent(mConditions); + mWaitUntilNewCandle = true; + + // + conditions = mConditions; + return true; + } + + // + // SELL ... + + // + Clean(mConditions.signal); + bool hasShortignal = HasShortSignal(mConditions); + if (hasShortignal) + { + // + NotifyOnSignalEvent( + mConditions.signal); + NotifyOnSignalConditionsEvent(mConditions); + mWaitUntilNewCandle = true; + + // + conditions = mConditions; + return true; + } + + // + return false; + } + + // + // Check has Long Signal on Each Strategies ... + bool HasLongSignal(X121MarketConditions &conditions) + { + // + bool result = false; + + // + double entry = GetEntry( + mSymbol, + POSITION_TYPE_BUY); + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + double pivots[]; + FillPivotPoints(pivots); + XOHCLSupRes supRes = ExtractSupportAndResistance( + 1, + pivots, + 15); + X121MarketConditions mConditions = GetMarketConditions(1); + + // + mXPVHelper.Calculate(1); + + // + Clean(mConditions.signal); + + // + // XPVF Signal Provider ... + bool xPVFSignal = false; + if (!mDisableXPVFLong) + { + // + xPVFSignal = + // + mConditions.xpvInfo.isNewPeak && + mXPVHelper.peaksBuffer[0] < mXPVHelper.peaksBuffer[1] && + mXPVHelper.valesBuffer[0] == mXPVHelper.valesBuffer[1] + // + ; + + // + if (xPVFSignal) + { + // + Add( + ToString(XPVF), + mConditions.signal.providers); + + // + mConditions.signal.r2r = 1.5; + mConditions.signal.riskAmount = 0.005; + mConditions.signal.mode = X_ORDER_MODE_MARKET; + mConditions.signal.entry = entry; + mConditions.signal.sl = 0; // mXCHEHelper.longExit2[1]; + mConditions.signal.tp = 0; + + // + // mConditions.signal.calculateTP = true; + // mConditions.signal.useRiskAmountAsVolume = false; + // mConditions.signal.useSupportAndResistance = true; + + // + // mDisableXPVFLong = true; + // mDisableXPVFShort = false; + } + } + + // + result = + // + xPVFSignal + // + ; + + // + if (result) + { + // + conditions = mConditions; + + // + conditions.supportResistances = supRes; + conditions.momentumStep = mLastMomentumStep; + + // + conditions.signal.symbol = mSymbol; + conditions.signal.period = mPeriod; + conditions.signal.type = POSITION_TYPE_BUY; + + // + conditions.hasSignal = true; + } + + // + return result; + } + + // + // Check has Short Signal on Each Strategies ... + bool HasShortSignal(X121MarketConditions &conditions) + { + // + bool result = false; + + // + double entry = GetEntry( + mSymbol, + POSITION_TYPE_SELL); + + // + XOHCL c1 = GetCandle( + mSymbol, + mPeriod, + 1); + + // + double pivots[]; + FillPivotPoints(pivots); + XOHCLSupRes supRes = ExtractSupportAndResistance( + 1, + pivots, + 15); + + // + X121MarketConditions mConditions = GetMarketConditions(1); + + // + mXPVHelper.Calculate(1); + + // + Clean(mConditions.signal); + + // + // XPVF Signal Provider ... + bool xPVFSignal = false; + if (!mDisableXPVFShort) + { + // + xPVFSignal = + // + mConditions.xpvInfo.isNewVale && + mXPVHelper.valesBuffer[0] > mXPVHelper.valesBuffer[1] && + mXPVHelper.peaksBuffer[0] == mXPVHelper.peaksBuffer[1] + // + ; + + // + if (xPVFSignal) + { + // + Add( + ToString(XPVF), + mConditions.signal.providers); + + // + mConditions.signal.r2r = 1.5; + mConditions.signal.riskAmount = 0.005; + mConditions.signal.mode = X_ORDER_MODE_STOP; + mConditions.signal.entry = entry; + mConditions.signal.sl = 0; + mConditions.signal.tp = mXPVHelper.valesBuffer[1]; + + // + mConditions.signal.calculateTP = true; + mConditions.signal.useRiskAmountAsVolume = false; + mConditions.signal.useSupportAndResistance = true; + + // + // mDisableXPVFShort = true; + // mDisableXPVFLong = false; + } + } + + // + result = + // + xPVFSignal + // + ; + + // + if (result) + { + // + conditions = mConditions; + + // + conditions.supportResistances = supRes; + conditions.momentumStep = mLastMomentumStep; + + // + conditions.signal.symbol = mSymbol; + conditions.signal.period = mPeriod; + conditions.signal.type = POSITION_TYPE_SELL; + + // + conditions.hasSignal = true; + } + + // + return result; + } +}; + +// +// START Definitions ... +// + +// +// Model Signal Providers Definitions ... +struct X121SignalProvider +{ + // + // Provider use Which Symbol ... + string symbol; + + // + // Provider use Which Time Frame ... + ENUM_TIMEFRAMES period; + + // + // Risk Amount Per Trades Related to Time Frames ... + // Percent of Available Balance ... + double riskAmount; + + // + // Desired Magic Number ... + ulong magicNumber; + + // + // Provider ... + XSCX121Provider *provider; +}; + +// +// END Definitions ... +// + +// +// START Usefull Functions ... +// + +// +// Add Specific Provider to List ... +void Add( + X121SignalProvider &item, // item want to add + X121SignalProvider &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Generate Identifier Tag ... +string GenerateTag(X121SignalProvider &descriptor) +{ + // + string result = ""; + + // + result = descriptor.symbol + "," + ToString(descriptor.period); + + // + return result; +} + +// +// Converts a Signal provider to String ... +string ToString(ENUM_X121_SIGNAL_PROVIDERS provider) +{ + return EnumToString(provider); +} + +// +// convert an String to Signal provider ... +ENUM_X121_SIGNAL_PROVIDERS ToProvider(string provider) +{ + // + ENUM_X121_SIGNAL_PROVIDERS result = NONE; + + // + if (ToString(NONE) == provider) + { + result = NONE; + } + else if (ToString(XPVF) == provider) + { + result = XPVF; + } + else if (ToString(XCHNL) == provider) + { + result = XCHNL; + } + else if (ToString(XTRND) == provider) + { + result = XTRND; + } + + // + return result; +} + +// +// Extract Provider Type from Signal Commnet ... +ENUM_X121_SIGNAL_PROVIDERS ExtractPositionProvider(XPosition &position) +{ + // + ENUM_X121_SIGNAL_PROVIDERS result = NONE; + + // + string providerStr = + ExtractString( + position.comment, + XProviderToken + "(", + ")"); + if (StringLen(providerStr) <= 0) + { + return result; + } + + // + result = ToProvider(providerStr); + + // + return result; +} + +// +// Generate Provider String for Using in Positions Comment ... +// NOTE: if there is more than One Provider, it takes first +// provider as main and the others used to increase volume ... +string GenerateProvidersString(XSignal &signal) +{ + // + string result = ""; + + // + int providersCount = ArraySize(signal.providers); + if (providersCount <= 0) + { + return result; + } + + // + result = XProviderToken + "(" + signal.providers[0] + ")"; + + // + return result; +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.x121.xea.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.x121.xea.class.mq5 new file mode 100644 index 0000000..a9926c5 --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.x121.xea.class.mq5 @@ -0,0 +1,443 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCX121EA +// Description: an Expert Class which +// used X121 Setup ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Classes/x-saherelm.xea.class.mq5" +#include "../Libraries/x-saherelm.x121.draw.lib.mq5" +#include "../Classes/x-saherelm.x121.provider.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// an Expert Advisor Class by X121Provider ... +class XSCX121EA : public XSCBaseEA +{ + // + // Public ... +public: + // + // Props ... + XSCX121Provider *mProvider; + + // + // Constructor ... + void XSCX121EA( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + ulong magic, // Magic Number + int slippage, // Slippgae + OnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler + OnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + OnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler + OnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler + OnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler + OnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler + TOnSignalConditions onSignalConditions = NULL // On SignalConditions Event Handler + ) : XSCBaseEA(symbol, + period, + magic, + slippage, + onStopLossTriggered, + onTakeProfitTriggered, + onDealsChangedHandler, + onOrdersChangedHandler, + onPositionsChangedHandler, + onTradeStateChangedHandler) + { + // + mOnSignalConditions = onSignalConditions; + + // + InitProvider(); + } + + // + // DeConstructor ... + void ~XSCX121EA() + { + delete mProvider; + } + + // + // START Inheritance Functions ... + // + + // + void PrepareTag() + { + mTag = "X121EA:" + mSymbol + "," + ToString(mPeriod) + (string)mMagic; + } + + // + bool CheckGuard(XGuard &guards[]) + { + return mProvider.GuardCheck(guards); + } + + // + bool SignalCheck(XSignal &signals[]) + { + // + // Detect Pivot Points ... + int foundedPivots = mProvider.CountPivots(); + int reuiredPivots = mProvider.GetMinPivots(); + if (foundedPivots < reuiredPivots) + { + // + mProvider.ProccessPivotPoints(); + + // + LogMessage("Founding Pivots: " + ToString(foundedPivots) + "/" + ToString(reuiredPivots)); + return false; + } + + // + X121MarketConditions conditions; + bool result = mProvider.ProcessTick(conditions); + + // + if (result) + { + // + // TODO: Here we Do all Signal Preparations such as TP/SL Calculations + // or Support and Resistance usage or Volume Calculations ... + // then pass prepared Signal to Execution ... + + // + ulong mTicket = MathRand() * 100000; + + // + DrawSignal( + mTicket, + conditions.signal); + + // + DrawSupportResistance( + 0, + conditions.supportResistances, + conditions.signal.providers[0]); + + // + // IGNORE SIGNAL EXECUTTION ... + return false; + + // + Add( + conditions.signal, + signals); + } + + // + return result; + } + + // + // END Inheritance Functions ... + // + + // + // START Provided Actions ... + // + + // + // END Provided Actions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + X121ProviderInputs mProviderConfig; + TOnSignalConditions mOnSignalConditions; + + // + // Actions ... + + // + // Prepare Default Configurations for X121Provider Setup ... + void PrepareProviderConfig() + { + // + // XCT ... + // Candle Timing ... + mProviderConfig.xctConfig.clr = clrBlueViolet; + mProviderConfig.xctConfig.corner = CORNER_RIGHT_UPPER; + mProviderConfig.xctConfig.showCandleTime = true; + + // + // XCC ... + // Candle Styling ... + mProviderConfig.xccConfig.upColor = clrLime; + mProviderConfig.xccConfig.downColor = clrRed; + mProviderConfig.xccConfig.lineColor = clrLime; + mProviderConfig.xccConfig.bearishColor = clrRed; + mProviderConfig.xccConfig.bullishColor = clrLime; + mProviderConfig.xccConfig.volumesColor = clrGreen; + mProviderConfig.xccConfig.showCandles = true; + + // + // XHK ... + // HikenAshi Candle Representing ... + mProviderConfig.xhkConfig.drawCandleLines = false; + + // + // XTM ... + // Trend Magic ... + mProviderConfig.xtmConfig.length = 35; + mProviderConfig.xtmConfig.shift = 0; + mProviderConfig.xtmConfig.method = MODE_SMA; + mProviderConfig.xtmConfig.appliedTo = PRICE_LOW; + mProviderConfig.xtmConfig.showLine = false; + + // + // XPV ... + // Peaks And Vales ... + mProviderConfig.xpvConfig.shortLength = 9; + mProviderConfig.xpvConfig.mediumLength = 17; + mProviderConfig.xpvConfig.longLength = 26; + mProviderConfig.xpvConfig.hindLength = 35; + mProviderConfig.xpvConfig.fiboLevel1 = 0.382; + mProviderConfig.xpvConfig.fiboLevel2 = 0.5; + mProviderConfig.xpvConfig.fiboLevel3 = 0.618; + mProviderConfig.xpvConfig.hhMode = MODE_HIGH; + mProviderConfig.xpvConfig.llMode = MODE_LOW; + mProviderConfig.xpvConfig.showPeaksAndVales = false; + mProviderConfig.xpvConfig.showLevels = false; + mProviderConfig.xpvConfig.showFibo1Levels = false; + mProviderConfig.xpvConfig.showFibo2Levels = false; + mProviderConfig.xpvConfig.showFibo3Levels = false; + + // + // XAMA ... + // Adaptive Moving Average ... + mProviderConfig.xamaConfig.length = 52; + mProviderConfig.xamaConfig.fastEMA = 2; + mProviderConfig.xamaConfig.slowEMA = 30; + mProviderConfig.xamaConfig.maShift = 0; + mProviderConfig.xamaConfig.appliedTo = PRICE_LOW; + mProviderConfig.xamaConfig.showLine = false; + + // + // XMRB ... + // Moving Average Ribbon ... + mProviderConfig.xmrbConfig.fast1Length = 3; + mProviderConfig.xmrbConfig.slow1Length = 5; + mProviderConfig.xmrbConfig.fast2Length = 8; + mProviderConfig.xmrbConfig.slow2Length = 13; + mProviderConfig.xmrbConfig.fast3Length = 21; + mProviderConfig.xmrbConfig.slow3Length = 34; + mProviderConfig.xmrbConfig.fast4Length = 55; + mProviderConfig.xmrbConfig.slow4Length = 89; + mProviderConfig.xmrbConfig.fast5Length = 144; + mProviderConfig.xmrbConfig.slow5Length = 233; + mProviderConfig.xmrbConfig.ribbonMode = MODE_EMA; + mProviderConfig.xmrbConfig.ribbonAppliedTo = PRICE_CLOSE; + mProviderConfig.xmrbConfig.showFastMa = false; + mProviderConfig.xmrbConfig.showSlowMa = false; + mProviderConfig.xmrbConfig.showRibbon = false; + + // + // XCHE ... + // Chandelier Exit Points ... + mProviderConfig.xcheConfig.length = 35; + mProviderConfig.xcheConfig.loopback = 26; + mProviderConfig.xcheConfig.multiplier1 = 3; + mProviderConfig.xcheConfig.multiplier2 = 3.5; + mProviderConfig.xcheConfig.upAppliedTo = PRICE_HIGH; + mProviderConfig.xcheConfig.downAppliedTo = PRICE_LOW; + mProviderConfig.xcheConfig.showLongExit1Line = false; + mProviderConfig.xcheConfig.showShortExit1Line = false; + mProviderConfig.xcheConfig.showLongExit2Line = false; + mProviderConfig.xcheConfig.showShortExit2Line = false; + + // + // XICH ... + // Ichimopku Kinko Hyo ... + mProviderConfig.xichConfig.tenkanSenLength = 9; + mProviderConfig.xichConfig.tenkanSenMode = X_XICH_HH_LL_MODE; + mProviderConfig.xichConfig.kijunSenLength = 26; + mProviderConfig.xichConfig.kijunSenMode = X_XICH_HH_LL_MODE; + mProviderConfig.xichConfig.senkouSpanBLength = 52; + mProviderConfig.xichConfig.senkouSpanBMode = X_XICH_HH_LL_MODE; + mProviderConfig.xichConfig.chikuoSpanAppliedTo = PRICE_CLOSE; + mProviderConfig.xichConfig.showTenkanSen = false; + mProviderConfig.xichConfig.showKijunSen = false; + mProviderConfig.xichConfig.showKijunSenPlus = false; + mProviderConfig.xichConfig.showKijunSenNegative = false; + mProviderConfig.xichConfig.showChikouSpan = false; + mProviderConfig.xichConfig.showSenkouSpanA = false; + mProviderConfig.xichConfig.showSenkouSpanB = false; + mProviderConfig.xichConfig.showKumo = false; + mProviderConfig.xichConfig.shiftKumo = true; + + // + // XTRND ... + // Trend Detector ... + mProviderConfig.xtrndConfig.cycleLength = 2; + mProviderConfig.xtrndConfig.numberOfVerifications = 2; + mProviderConfig.xtrndConfig.hhMode = MODE_HIGH; + mProviderConfig.xtrndConfig.llMode = MODE_LOW; + mProviderConfig.xtrndConfig.l1Method = X_PERIOD_AUTO; + mProviderConfig.xtrndConfig.l1Period = NULL; + mProviderConfig.xtrndConfig.l2Method = X_PERIOD_AUTO; + mProviderConfig.xtrndConfig.l2Period = NULL; + mProviderConfig.xtrndConfig.l3Method = X_PERIOD_AUTO; + mProviderConfig.xtrndConfig.l3Period = NULL; + mProviderConfig.xtrndConfig.showConsolidations = false; + mProviderConfig.xtrndConfig.showTrend = false; + mProviderConfig.xtrndConfig.showL1Trend = false; + mProviderConfig.xtrndConfig.showL2Trend = false; + mProviderConfig.xtrndConfig.showL3Trend = false; + + // + // XSSLC ... + // SSL Channel ... + mProviderConfig.xsslcConfig.length = 36; + mProviderConfig.xsslcConfig.method = MODE_SMA; + mProviderConfig.xsslcConfig.upAppliedTo = PRICE_HIGH; + mProviderConfig.xsslcConfig.downAppliedTo = PRICE_LOW; + mProviderConfig.xsslcConfig.showUp = false; + mProviderConfig.xsslcConfig.showDown = false; + + // + // XHULL ... + // Hull Trend Detection Channel ... + mProviderConfig.xhullConfig.length = 72; + mProviderConfig.xhullConfig.divisor = 2; + mProviderConfig.xhullConfig.upAppliedTo = PRICE_HIGH; + mProviderConfig.xhullConfig.downAppliedTo = PRICE_LOW; + mProviderConfig.xhullConfig.showUpZone = false; + mProviderConfig.xhullConfig.showDownZone = false; + + // + // Default Configs For Different States ... + bool showPV = true; + bool showHK = true; + bool showCHE = true; + bool showTRND = true; + bool simpleIchi = true; + + // + if (showHK) + { + // + // Hiken Ashi ... + mProviderConfig.xccConfig.showCandles = false; + mProviderConfig.xhkConfig.drawCandles = true; + } + if (showPV) + { + // + // Peaks and Vales ... + mProviderConfig.xpvConfig.showFibo1Levels = true; + mProviderConfig.xpvConfig.showFibo2Levels = true; + mProviderConfig.xpvConfig.showFibo3Levels = true; + mProviderConfig.xpvConfig.showPeaksAndVales = true; + } + if (simpleIchi) + { + // + // Simple Ichimoku Kinko Hyo ... + mProviderConfig.xichConfig.showKijunSen = true; + mProviderConfig.xichConfig.showTenkanSen = true; + mProviderConfig.xichConfig.showSenkouSpanA = true; + mProviderConfig.xichConfig.showSenkouSpanB = true; + } + if (showCHE) + { + // + // Chandelier Exit ... + mProviderConfig.xcheConfig.showLongExit1Line = true; + mProviderConfig.xcheConfig.showLongExit2Line = true; + mProviderConfig.xcheConfig.showShortExit1Line = true; + mProviderConfig.xcheConfig.showShortExit2Line = true; + } + if (showTRND) + { + // + // Show Trend ... + mProviderConfig.xtrndConfig.showL1Trend = true; + mProviderConfig.xtrndConfig.showL2Trend = true; + mProviderConfig.xtrndConfig.showL3Trend = true; + } + } + + // + // Initialize X121Provider ... + void InitProvider() + { + // + PrepareProviderConfig(); + + // + mProvider = new XSCX121Provider( + mSymbol, + mPeriod); + + // + if (mOnSignalConditions != NULL) + { + // + // Attach Event Handlers ... + mProvider.AddOnSignalConditionEventHandler(mOnSignalConditions); + } + + // + // Initialize Provider ... + mProvider.SetConfig(mProviderConfig); + } +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xaccount.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xaccount.class.mq5 new file mode 100644 index 0000000..4425f0b --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xaccount.class.mq5 @@ -0,0 +1,398 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAccount +// Description: provides all Account requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Manage Account ... +class XSCAccount +{ + // + // Public ... +public: + // + // Constructor ... + void XSCAccount() + { + // + mAccountInfo = new CAccountInfo(); + } + + // + // Deconstructor ... + void ~XSCAccount() + { + } + + // + // START Provided Functions ... + // + + // + // User Account ... + long GetUserAccount() + { + return mAccountInfo.Login(); + } + + // + // Account Leverage ... + long GetLeverage() + { + return mAccountInfo.Leverage(); + } + + // + // Get Trade Expert State ... + bool CanExpertTrade() + { + return mAccountInfo.TradeExpert(); + } + + // + // User Account Trade Mopde (ENUM_ACCOUNT_TRADE_MODE) ... + // -------------------------- + // ACCOUNT_TRADE_MODE_DEMO + // ACCOUNT_TRADE_MODE_CONTEST + // ACCOUNT_TRADE_MODE_REAL + ENUM_ACCOUNT_TRADE_MODE GetTradeMode() + { + return mAccountInfo.TradeMode(); + } + + // + // Get Account Balance ... + double GetBalance() + { + return mAccountInfo.Balance(); + } + + // + // Get the amount of give Credit ... + double GetCredit() + { + return mAccountInfo.Credit(); + } + + // + // Get the amount of current Profit on account ... + double GetProfit() + { + return mAccountInfo.Profit(); + } + + // + // Get the amount of current Equity on account ... + double GetEquity() + { + return mAccountInfo.Equity(); + } + + // + // Get the amount of reserved Margin ... + double GetMargin() + { + return mAccountInfo.Margin(); + } + + // + // Get the amount of free Margin ... + double GetFreeMargin() + { + return mAccountInfo.FreeMargin(); + } + + // + // Get the Level of Margin ... + double GetMarginLevel() + { + return mAccountInfo.MarginLevel(); + } + + // + // Get the Level Of Margin for a Deposit ... + double GetMarginCall() + { + return mAccountInfo.MarginCall(); + } + + // + // Get the Level of Margin for Stop out ... + double GetMarginStopOut() + { + return mAccountInfo.MarginStopOut(); + } + + // + // Get the Client Name ... + string GetName() + { + return mAccountInfo.Name(); + } + + // + // Get the Trade Server Name ... + string GetServerName() + { + return mAccountInfo.Server(); + } + + // + // Get deposit Currency Name ... + string GetCurrency() + { + return mAccountInfo.Currency(); + } + + // + // Get the Company Name that serves an Account ... + string GetCompany() + { + return mAccountInfo.Company(); + } + + // + // Calculate Profits for the current account based on passed parameters ... + double CalculateTradeProfit( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry, // open price + double exit // close price + ) + { + // + double result = mAccountInfo.OrderProfitCheck( + symbol, + type, + volume, + entry, + exit); + + // + return result; + } + + // + // Calculate amount of margin which required for trade operation ... + double CalculateMarging( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry // open price + ) + { + // + double result = mAccountInfo.MarginCheck( + symbol, + type, + volume, + entry); + + // + return result; + } + + // + // Calculate amount of free margin left after trade operation ... + double CalculateFreeMarging( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry // open price + ) + { + // + double result = mAccountInfo.FreeMarginCheck( + symbol, + type, + volume, + entry); + + // + return result; + } + + // + // Calculate the Maximum possible volume of trade operation ... + double CalculateMaxVolume( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double entry, // open price + double percent = 100 // percent of available margin + ) + { + // + double result = mAccountInfo.MaxLotCheck( + symbol, + type, + entry, + percent); + + // + return result; + } + + // + // Calculate Point Value for Given Symbol based on Account ... + double GetPointValue( + string symbol // trading symbol + ) + { + // + double result = 0; + + // + double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); + double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); + double point = SymbolInfoDouble(symbol, SYMBOL_POINT); + + // + double ticksPerPoint = tickSize / point; + + // + result = tickValue / ticksPerPoint; + + // + return result; + } + + // + // Calculate Risk Amount based on account Currency by Providing: + // Points and Volume ... + double CalculateRiskAmount( + string symbol, // trading symbol + double points, // amount of Risk Points + double volume // position Volume + ) + { + // + double result = 0; + + // + double pointValue = GetPointValue(symbol); + + // + result = pointValue * volume * points; + + // + return result; + } + + // + // Calculate Risk Points based on account Currency by Providing: + // Volume and Amount ... + double CalculateRiskPoints( + string symbol, // trading symbol + double volume, // position Volume + double amount // amount of Risk based on Account Currency + ) + { + // + double result = 0; + + // + double pointValue = GetPointValue(symbol); + + // + result = amount / (pointValue * volume); + + // + return result; + } + + // + // Calculate Volume based on account Currency by Providing: + // Amount and Risk Points ... + double CalculateVolume( + string symbol, // trading symbol + double amount, // amount of Risk based on Account Currency + double points // amount of Risk Points + ) + { + // + double result = 0; + + // + points = + points <= 0 + ? 10 + : points; + + // + double pointValue = GetPointValue(symbol); + + // + result = amount / (pointValue * points); + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xdatacollector.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xdatacollector.class.mq5 new file mode 100644 index 0000000..f24164d --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xdatacollector.class.mq5 @@ -0,0 +1,1582 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCDataCollector +// Description: provides all Data Collection requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Supported Data Types ... +enum ENUM_X_XDATACOLLECTOR_TYPES +{ + X_DATA_COLLECTOR_SIGNAL, + X_DATA_COLLECTOR_SUPRES, + X_DATA_COLLECTOR_POSITION, + X_DATA_COLLECTOR_DEAL, + X_DATA_COLLECTOR_LOG, +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "x-saherelm.xtrade.class.mq5" +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class Definition ... +class XSCDataCollector +{ + // + // Public ... +public: + // + // Constructor ... + void XSCDataCollector() + { + // + XSCDataCollector("XDataCollector"); + + // + DefineTokens(); + } + void XSCDataCollector( + string path // Base Folder to Store Data + ) + { + // + // Set Properties ... + + // + Path(path); + + // + DefineTokens(); + } + + // + // Deconstructor ... + void ~XSCDataCollector() + { + } + + // + // START Getter(s)/Setter(s) ... + // + + // + // Path ... + void Path(string value) + { + mPath = value; + } + + string Path() + { + return mPath; + } + + // + // END Getter(s)/Setter(s) ... + // + + // + // START Provided Functions ... + // + + // + // Clean Exists Collected Data ... + void CleanStore() + { + // + ENUM_X_XDATACOLLECTOR_TYPES types[]; + RetrieveAllAvailableTypes(types); + int typesCount = ArraySize(types); + if (typesCount <= 0) + { + return; + } + + // + ResetLastError(); + + // + for (int i = 0; i < typesCount; i++) + { + // + ENUM_X_XDATACOLLECTOR_TYPES iType = types[i]; + string typeFilePath = GenerateTypeFilePath(iType); + + // + bool isExist = FileIsExist(typeFilePath); + if (isExist) + { + FileDelete(typeFilePath); + } + } + } + + // + // Add Specific Deal ... + void CollectDeal(const XDeal &deal) + { + // + string content = ToStringFormat(deal); + if (StringLen(content) <= 0) + { + return; + } + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_DEAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Deals ... + void ExtreactDeals(XDeal &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_DEAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + XDeal deal = ToDeal(content); + + // + Add( + deal, + result); + } + + // + FileClose(mFileHandler); + } + + // + // Add Specific Signal ... + void CollectSignal(const XSignal &signal) + { + // + string content = ToStringFormat(signal); + if (StringLen(content) <= 0) + { + return; + } + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_SIGNAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + LogMessage("Error: " + (string)GetLastError()); + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Signals ... + void ExtreactSignals(XSignal &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_SIGNAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + XSignal signal = ToSignal(content); + + // + Add( + signal, + result); + } + + // + FileClose(mFileHandler); + } + + // + // Add Specific Position ... + void CollectPosition(const XPosition &position) + { + // + string content = ToStringFormat(position); + if (StringLen(content) <= 0) + { + return; + } + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_POSITION); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Positions ... + void ExtreacPositions(XPosition &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_POSITION); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + XPosition position = ToPosition(content); + + // + Add( + position, + result); + } + + // + FileClose(mFileHandler); + } + + // + // SUPPORT and RESISTANCE ... + void CollectSupRes(const XOHCLSupRes &item) + { + } + + // + void ExtractSupReses(XOHCLSupRes &result[]) + { + } + + // + // Add Specific Log ... + void CollectLog(string log) + { + // + if (StringLen(log) <= 0) + { + return; + } + + // + string content = ExtractTypePath(X_DATA_COLLECTOR_LOG) + + "[" + log + "]"; + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_LOG); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Logs ... + void ExtractLogs(string &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_LOG); + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_LOG); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + string log = ExtractString( + content, + typeIdentifier + "[", + "]"); + + // + if (StringLen(log) > 0) + { + // + Add( + log, + result); + } + } + + // + FileClose(mFileHandler); + } + + // + // TYPE Specific Casting Functions ... + + // + // Signal ... + + // + // Convert to it's String Representation ... + string ToStringFormat(const XSignal &signal) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_SIGNAL) + + "[" + + mProvidersToken + "(" + ToString(signal.providers) + ")" + + mSymbolToken + "(" + signal.symbol + ")" + + mPeriodToken + "(" + ToString(signal.period) + ")" + + mTypeToken + "(" + (string)((int)signal.type) + ")" + + mModeToken + "(" + (string)((int)signal.mode) + ")" + + mEntryToken + "(" + (string)signal.entry + ")" + + mRiskAmountToken + "(" + (string)signal.riskAmount + ")" + + mTPToken + "(" + (string)signal.tp + ")" + + mSLToken + "(" + (string)signal.sl + ")" + + mR2rToken + "(" + (string)signal.r2r + ")" + + mVolumeToken + "(" + (string)signal.volume + ")" + + mSupportResistanceToken + "(" + ToStringFormat(signal.supportAndResistance) + ")" + + "]"; + + // + return result; + } + + // + // Converts an string to XSignal ... + XSignal ToSignal(string content) + { + // + XSignal result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_SIGNAL); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string signalContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(signalContent) == 0) + { + return result; + } + + // + // Providers ... + string providersStr = ExtractString( + signalContent, + mProvidersToken + "(", + ")"); + if (StringLen(providersStr) > 0) + { + // + string providers[]; + StringSplit( + providersStr, + StringGetCharacter(",", 0), + providers); + + // + ArrayCopy( + result.providers, + providers); + } + + // + // Symbol ... + string symbolStr = ExtractString( + signalContent, + mSymbolToken + "(", + ")"); + if (StringLen(symbolStr) > 0) + { + result.symbol = symbolStr; + } + + // + // Period ... + string periodStr = ExtractString( + signalContent, + mPeriodToken + "(", + ")"); + if (StringLen(periodStr) > 0) + { + // + ENUM_TIMEFRAMES period = ToPeriod(periodStr); + + // + result.period = period; + } + + // + // Type ... + string typeStr = ExtractString( + signalContent, + mTypeToken + "(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)((int)typeStr); + + // + result.type = type; + } + + // + // Mode ... + string modeStr = ExtractString( + signalContent, + mModeToken + "(", + ")"); + if (StringLen(modeStr) > 0) + { + // + ENUM_X_ORDER_MODES mode = (ENUM_X_ORDER_MODES)((int)modeStr); + + // + result.mode = mode; + } + + // + // Entry ... + string entryStr = ExtractString( + signalContent, + mEntryToken + "(", + ")"); + if (StringLen(entryStr) > 0) + { + // + double entry = (double)entryStr; + + // + result.entry = entry; + } + + // + // RiskAmount ... + string raStr = ExtractString( + signalContent, + mRiskAmountToken + "(", + ")"); + if (StringLen(raStr) > 0) + { + // + double ra = (double)raStr; + + // + result.riskAmount = ra; + } + + // + // TP ... + string tpStr = ExtractString( + signalContent, + mTPToken + "(", + ")"); + if (StringLen(tpStr) > 0) + { + // + double tp = (double)tpStr; + + // + result.tp = tp; + } + + // + // SL ... + string slStr = ExtractString( + signalContent, + mSLToken + "(", + ")"); + if (StringLen(slStr) > 0) + { + // + double sl = (double)slStr; + + // + result.sl = sl; + } + + // + // R2R ... + string r2rStr = ExtractString( + signalContent, + mR2rToken + "(", + ")"); + if (StringLen(r2rStr) > 0) + { + // + double r2r = (double)r2rStr; + + // + result.r2r = r2r; + } + + // + // Volume ... + string volumeStr = ExtractString( + signalContent, + mVolumeToken + "(", + ")"); + if (StringLen(volumeStr) > 0) + { + // + double volume = (double)volumeStr; + + // + result.volume = volume; + } + + // + // SupportResistance ... + string supportResistanceStr = ExtractString( + signalContent, + mSupportResistanceToken + "(", + ")"); + if (StringLen(supportResistanceStr) > 0) + { + // + XOHCLSupRes supRes = ToSupRes(supportResistanceStr); + + // + result.supportAndResistance = supRes; + } + + // + return result; + } + + // + // Deal ... + + // + // Convert to it's String Representation ... + string ToStringFormat(const XDeal &deal) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_DEAL) + + "[" + + mMagicToken + "(" + (string)deal.magic + ")" + + mPositionIDToken + "(" + (string)deal.positionId + ")" + + mTicketToken + "(" + (string)deal.ticket + ")" + + mSymbolToken + "(" + (string)deal.symbol + ")" + + mOrderToken + "(" + (string)deal.order + ")" + + mTimeToken + "(" + (string)deal.time + ")" + + mPriceToken + "(" + (string)deal.price + ")" + + mProfitToken + "(" + (string)deal.profit + ")" + + mSwapToken + "(" + (string)deal.swap + ")" + + mCommissionToken + "(" + (string)deal.commission + ")" + + mVolumeToken + "(" + (string)deal.volume + ")" + + mCommentToken + "(" + (string)deal.comment + ")" + + mTypeToken + "(" + (string)((int)deal.type) + ")" + + mEntryToken + "(" + (string)((int)deal.entry) + ")" + + mReasonToken + "(" + (string)((int)deal.reason) + ")" + + "]"; + + // + return result; + } + + // + // Converts an string to XDeal ... + XDeal ToDeal(string content) + { + // + XDeal result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_DEAL); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string dealContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(dealContent) == 0) + { + return result; + } + + // + // Magic ... + string magicStr = ExtractString( + dealContent, + mMagicToken + "(", + ")"); + if (StringLen(magicStr) > 0) + { + // + ulong magic = (ulong)magicStr; + + // + result.magic = magic; + } + + // + // PositionID ... + string posIDStr = ExtractString( + dealContent, + mPositionIDToken + "(", + ")"); + if (StringLen(posIDStr) > 0) + { + // + ulong posID = (ulong)posIDStr; + + // + result.positionId = posID; + } + + // + // Ticket ... + string ticketStr = ExtractString( + dealContent, + mTicketToken + "(", + ")"); + if (StringLen(ticketStr) > 0) + { + // + ulong ticket = (ulong)ticketStr; + + // + result.ticket = ticket; + } + + // + // Symbol ... + string symbolStr = ExtractString( + dealContent, + mSymbolToken + "(", + ")"); + if (StringLen(symbolStr) > 0) + { + result.symbol = symbolStr; + } + + // + // Order ... + string orderStr = ExtractString( + dealContent, + mOrderToken + "(", + ")"); + if (StringLen(orderStr) > 0) + { + // + ulong order = (ulong)orderStr; + + // + result.order = order; + } + + // + // Time ... + string timeStr = ExtractString( + dealContent, + mTimeToken + "(", + ")"); + if (StringLen(timeStr) > 0) + { + // + datetime time = StringToTime(timeStr); + + // + result.time = time; + } + + // + // Price ... + string priceStr = ExtractString( + dealContent, + mPriceToken + "(", + ")"); + if (StringLen(priceStr) > 0) + { + // + double price = (double)priceStr; + + // + result.price = price; + } + + // + // Profit ... + string profitStr = ExtractString( + dealContent, + mProfitToken + "(", + ")"); + if (StringLen(profitStr) > 0) + { + // + double profit = (double)profitStr; + + // + result.profit = profit; + } + + // + // Swap ... + string swapStr = ExtractString( + dealContent, + mSwapToken + "(", + ")"); + if (StringLen(swapStr) > 0) + { + // + double swap = (double)swapStr; + + // + result.swap = swap; + } + + // + // Commission ... + string commissionStr = ExtractString( + dealContent, + mCommissionToken + "(", + ")"); + if (StringLen(commissionStr) > 0) + { + // + double commission = (double)commissionStr; + + // + result.commission = commission; + } + + // + // Volume ... + string volumeStr = ExtractString( + dealContent, + mVolumeToken + "(", + ")"); + if (StringLen(volumeStr) > 0) + { + // + double volume = (double)volumeStr; + + // + result.volume = volume; + } + + // + // Comment ... + string commentStr = ExtractString( + dealContent, + mCommentToken + "(", + ")"); + if (StringLen(commentStr) > 0) + { + result.comment = commentStr; + } + + // + // Type ... + string typeStr = ExtractString( + dealContent, + mTypeToken + "(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_DEAL_TYPE type = (ENUM_DEAL_TYPE)((int)typeStr); + + // + result.type = type; + } + + // + // Entry ... + string entryStr = ExtractString( + dealContent, + mEntryToken + "(", + ")"); + if (StringLen(entryStr) > 0) + { + // + ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)((int)entryStr); + + // + result.entry = entry; + } + + // + // Reason ... + string reasonStr = ExtractString( + dealContent, + mReasonToken + "(", + ")"); + if (StringLen(reasonStr) > 0) + { + // + ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)((int)reasonStr); + + // + result.reason = reason; + } + + // + return result; + } + + // + // SUPPORT and RESISTANCES ... + string ToStringFormat(const XOHCLSupRes &item) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_SUPRES) + + "[" + + mResToken + "(" + ToString(item.res) + ")" + + mSupToken + "(" + ToString(item.sup) + ")" + + "]"; + + // + return result; + } + + // + XOHCLSupRes ToSupRes(string content) + { + // + XOHCLSupRes result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_SUPRES); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string mainContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(mainContent) == 0) + { + return result; + } + + // + // Res ... + string resStr = ExtractString( + mainContent, + mResToken + "(", + ")"); + if (StringLen(resStr) > 0) + { + // + double res[]; + string parts[]; + StringSplit( + resStr, + StringGetCharacter(",", 0), + parts); + + // + int partsCount = ArraySize(parts); + if (partsCount > 0) + { + // + for (int i = 0; i < partsCount; i++) + { + // + string iPart = parts[i]; + + // + Add( + double(iPart), + result.res); + } + } + } + + // + // Sup ... + string supStr = ExtractString( + mainContent, + mSupToken + "(", + ")"); + if (StringLen(supStr) > 0) + { + // + double sup[]; + string parts[]; + StringSplit( + supStr, + StringGetCharacter(",", 0), + parts); + + // + int partsCount = ArraySize(parts); + if (partsCount > 0) + { + // + for (int i = 0; i < partsCount; i++) + { + // + string iPart = parts[i]; + + // + Add( + double(iPart), + result.sup); + } + } + } + + // + return result; + } + + // + // Position ... + + // + // Convert to it's String Representation ... + string ToStringFormat(const XPosition &position) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_POSITION) + + "[" + + mMagicToken + "(" + (string)position.magic + ")" + + mTicketToken + "(" + (string)position.ticket + ")" + + mSymbolToken + "(" + (string)position.symbol + ")" + + mPeriodToken + "(" + (string)((int)position.period) + ")" + + mTypeToken + "(" + (string)((int)position.type) + ")" + + mTPToken + "(" + (string)position.tp + ")" + + mSLToken + "(" + (string)position.sl + ")" + + mProfitToken + "(" + (string)position.profit + ")" + + mEntryToken + "(" + (string)position.entry + ")" + + mPriceToken + "(" + (string)position.price + ")" + + mSwapToken + "(" + (string)position.swap + ")" + + mCommissionToken + "(" + (string)position.commission + ")" + + mVolumeToken + "(" + (string)position.volume + ")" + + mOpenAtToken + "(" + (string)position.openAt + ")" + + mCommentToken + "(" + (string)position.comment + ")" + + "]"; + + // + return result; + } + + // + // Converts an string to XPosition ... + XPosition ToPosition(string content) + { + // + XPosition result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_POSITION); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string positionContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(positionContent) == 0) + { + return result; + } + + // + // Magic ... + string magicStr = ExtractString( + positionContent, + mMagicToken + "(", + ")"); + if (StringLen(magicStr) > 0) + { + // + ulong magic = (ulong)magicStr; + + // + result.magic = magic; + } + + // + // Ticket ... + string ticketStr = ExtractString( + positionContent, + mTicketToken + "(", + ")"); + if (StringLen(ticketStr) > 0) + { + // + ulong ticket = (ulong)ticketStr; + + // + result.ticket = ticket; + } + + // + // Symbol ... + string symbolStr = ExtractString( + positionContent, + mSymbolToken + "(", + ")"); + if (StringLen(symbolStr) > 0) + { + result.symbol = symbolStr; + } + + // + // Period ... + string periodStr = ExtractString( + positionContent, + mPeriodToken + "(", + ")"); + if (StringLen(periodStr) > 0) + { + // + ENUM_TIMEFRAMES period = ToPeriod(periodStr); + + // + result.period = period; + } + + // + // Type ... + string typeStr = ExtractString( + positionContent, + mTypeToken + "(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)((int)typeStr); + + // + result.type = type; + } + + // + // TP ... + string tpStr = ExtractString( + positionContent, + mTPToken + "(", + ")"); + if (StringLen(tpStr) > 0) + { + // + double tp = (double)tpStr; + + // + result.tp = tp; + } + + // + // SL ... + string slStr = ExtractString( + positionContent, + mSLToken + "(", + ")"); + if (StringLen(slStr) > 0) + { + // + double sl = (double)slStr; + + // + result.sl = sl; + } + + // + // Profit ... + string profitStr = ExtractString( + positionContent, + mProfitToken + "(", + ")"); + if (StringLen(profitStr) > 0) + { + // + double profit = (double)profitStr; + + // + result.profit = profit; + } + + // + // Entry ... + string entryStr = ExtractString( + positionContent, + mEntryToken + "(", + ")"); + if (StringLen(entryStr) > 0) + { + // + double entry = (double)entryStr; + + // + result.entry = entry; + } + + // + // Price ... + string priceStr = ExtractString( + positionContent, + mPriceToken + "(", + ")"); + if (StringLen(priceStr) > 0) + { + // + double price = (double)priceStr; + + // + result.price = price; + } + + // + // Swap ... + string swapStr = ExtractString( + positionContent, + mSwapToken + "(", + ")"); + if (StringLen(swapStr) > 0) + { + // + double swap = (double)swapStr; + + // + result.swap = swap; + } + + // + // Commission ... + string commissionStr = ExtractString( + positionContent, + mCommissionToken + "(", + ")"); + if (StringLen(commissionStr) > 0) + { + // + double commission = (double)commissionStr; + + // + result.commission = commission; + } + + // + // Volume ... + string volumeStr = ExtractString( + positionContent, + mVolumeToken + "(", + ")"); + if (StringLen(volumeStr) > 0) + { + // + double volume = (double)volumeStr; + + // + result.volume = volume; + } + + // + // OpenAt ... + string openAtStr = ExtractString( + positionContent, + mOpenAtToken + "(", + ")"); + if (StringLen(openAtStr) > 0) + { + // + datetime openAt = StringToTime(openAtStr); + + // + result.openAt = openAt; + } + + // + // Comment ... + string commentStr = ExtractString( + positionContent, + mCommentToken + "(", + ")"); + if (StringLen(commentStr) > 0) + { + result.comment = commentStr; + } + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Destintion Folder Path ... + string mPath; + + // + void DefineTokens() + { + + // + // Define Required Variables ... + + // + // Define Some Modifier Tokens for Type Castings ... + mProvidersToken = "PVS"; + mSymbolToken = "SBL"; + mPeriodToken = "PR"; + mTypeToken = "TYP"; + mModeToken = "MD"; + mEntryToken = "EN"; + mRiskAmountToken = "RA"; + mTPToken = "TP"; + mSLToken = "SL"; + mR2rToken = "RR"; + mVolumeToken = "VL"; + + // + mMagicToken = "MGK"; + mTicketToken = "TK"; + mProfitToken = "PFT"; + mPriceToken = "CPR"; + mSwapToken = "SWP"; + mCommissionToken = "CMS"; + mOpenAtToken = "ODT"; + mCommentToken = "CMN"; + + // + mPositionIDToken = "PID"; + mOrderToken = "ORD"; + mTimeToken = "TDT"; + mReasonToken = "RSN"; + + // + mResToken = "RES"; + mSupToken = "SUP"; + mSupportResistanceToken = "SUPRES"; + } + + // + // Private ... +private: + // + // Generate Full File Path ... + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + Path() + "\\" + fileName + // + ; + + // + return result; + } + + // + // Extract Each Type Specific File Name ... + string ExtractTypePath(ENUM_X_XDATACOLLECTOR_TYPES type) + { + // + string typeStr = EnumToString(type); + + // + string typeParts[]; + StringSplit( + typeStr, + StringGetCharacter("_", 0), + typeParts); + + // + string result = typeParts[ArraySize(typeParts) - 1]; + + // + return result; + } + + // + string GenerateTypeFilePath(ENUM_X_XDATACOLLECTOR_TYPES type) + { + // + string name = ExtractTypePath(type) + ".txt"; + + // + string result = GetFilePath(name); + + // + return result; + } + + // + // Retrieve all available data types ... + void RetrieveAllAvailableTypes(ENUM_X_XDATACOLLECTOR_TYPES &result[]) + { + // + ArrayFree(result); + ArrayResize(result, 0); + + // + Add( + X_DATA_COLLECTOR_LOG, + result); + + // + Add( + X_DATA_COLLECTOR_DEAL, + result); + + // + Add( + X_DATA_COLLECTOR_SIGNAL, + result); + + // + Add( + X_DATA_COLLECTOR_SUPRES, + result); + + // + Add( + X_DATA_COLLECTOR_POSITION, + result); + } + + // + // Define Some Modifier Tokens for Type Castings ... + string mProvidersToken; + string mSymbolToken; + string mPeriodToken; + string mTypeToken; + string mModeToken; + string mEntryToken; + string mRiskAmountToken; + string mTPToken; + string mSLToken; + string mR2rToken; + string mVolumeToken; + + // + string mMagicToken; + string mTicketToken; + string mProfitToken; + string mPriceToken; + string mSwapToken; + string mCommissionToken; + string mOpenAtToken; + string mCommentToken; + + // + string mPositionIDToken; + string mOrderToken; + string mTimeToken; + string mReasonToken; + + // + string mResToken; + string mSupToken; + string mSupportResistanceToken; +}; + +// +// START Usefull Functions ... +// +void Add(ENUM_X_XDATACOLLECTOR_TYPES type, + ENUM_X_XDATACOLLECTOR_TYPES &types[]) +{ + // + ArrayResize( + types, + ArraySize(types) + 1); + + // + types[ArraySize(types) - 1] = type; +} +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xea.class.ex5 b/MQLTestWorkspace/Classes/x-saherelm.xea.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..a52c19f34bb8dc8b6ffcacaa1324b4a3dc9ac818 GIT binary patch literal 9654 zcmdUTV{j%wv+f()Ha523*tYHD4L7#Av2EMgXk*(>Hn#2E;O=+sJ^xPCy?^i1HPby$ z&rDT!*Hm?lgf=IH6QBfD7!vRgV1UE_(*LplH;RmRKm*}AmTe0P6rX{v<^Rq9U-kdF z#~T&^_|N#CAc_WSTa7W`*v)<7Zz?9|+=z_e@97@zLnmNN4NLxv*U4H20l7_S@t?C| z00)30zzg6Eum)HHtN^Y6QUDu(<=M&wJNdM<5u>zR>Rh#91cK$!G zhQ+L;HhpN=vZ85ry7M2TeltGONsm zV-!~8+U>FL}yO!xSq}AF4yUu3=*IxMAtOIN=CWV zRhDD5j1Yn|ZYJ9OY%uGbh^n&tI1iYEO$Jzo`lm4ZT%=s?7+J`6^fVvu#=q+``gji` zaALxnD7qTMoiiMv=G- zE)N`G$G~Tq&!f_nxeYHy_l`&n%rBJf1qxf6sk*o3c)PXiNn7~|)6?zY6OIA+;DUm% zA1)a=8Zkc4!aTVv#!>=m7(0ASNVzV+aW&)XIT}B2x?j1PZ753RMB=+7{pj@GL){Iu zu;k`OeQL_<5x=H?wD)m3BGD@kK;0WIn>r@-?Qh+|^n9V(aK1TLE>qlpPA=^+#?r1l z&;$-812RbD1-G^XEzlxh^I@0g7qVt z*@fdtLu0j?w=Sw&GNkO6I2gLJvwsuRV|?D?rqB!o8P{Y&%SFqCD{xRQUIMM;x8*g2 z=e2_aZYQ0}Vu8$`<7JpGw-YEi?fq+hcFnG|<1CMb2b+v|OwcFHw&F;not~4ce<2V( zmlEEZq2d+`-(%(yOwGtXs!Oml1S+o8ByZUFdt(mDJ7OMv+p{v;zI|vk;#@lJDFTUM zY+H*3HW3fnPg6oTB{J3ZcCs2Ujn$w4C%3xU3? z?0yFPC2TWRk=ota5b@mM#-az$FPP5aIgG6m4rO}76fyBzR3Up;Bfr~m7|9S*^J8h6xh`_FUZVte$uW}5_7TAU%pGtc#r>05aHdtfGg|aq z|GD$mIZ(=7(3uy(?gvRCV=v38ciX4z-yvdyuSnviPTH`2>N9-iz{O>xM1=U4syBrm zcVJHp_80gxZKw2LKPxLJwz&SHa;V?4zLh3bXxiO51CgnUS$ZfBrB{x|XChe^^{qLS z)r{@O)ip-X5XVp7MdsWNGRDn>u2P|dAw`bz^v&g7)s8{y!cl=!1lxR!GPoQj{xHQt z7ELZDj9XYYn4)}nDJ(c>&et(e(J(A_73R2GyxR_R; zy8}hU_s9)WRPikV=5LpRBMSuYYGff_J(_K%e)E;NN*QAPx$GsNkJaB;ySI86{?TQ* z;Xj*3T-i096YfYLg z?RAw94TWRTeq-_?2}BOku}|=p!jW7aeX-20{6@kh5kjnLWCkfeZXq|3TnE<>U+%h1 zSUop(Bp35qmtO~x!eOWL)6ec1Vv9J{5~2U1^f%Q->_a}g zp;B{CZnZ;Ojp-o&F()TRi`wfOuL0cAcS%A$;lBM#6eb|4?exy^QgtR+UeoRPz2cv2 zU@9;zB<)*q?z3hpA4FWF(x!E@G+V7_cf_8OteO15p*eSJdBp?oui;;g#PQ8a&t7gv zcRkl-ep0Pm_<3N}y9jdz6|ubKDFj=5C36Ioa^dY=!)xQ{bjm%IcLv{_gP;*!@qAHt z*q`8KlO3V!3lVbpSzu2mCD+lXb_Vc~%6|0x8y^YEO!t4<1Pc-a|_D`HQ zQ7MArR@tk;(2PcG58{f2e2P~%#k|wMP~k-BqtxF9sxuo#X==Xy-bycSJ%TG0p0K1+ zemTD8YWynP*B0h>dbRkNS|#1j&v^`vFYjli3;H#q+%q`{QHh`Y$>$`#zI6mS^`xcz z9IFak{{khWcUo;x;d5>Ae+14{H|J%iJ3!KKuim5;Gh@JCOJt}Ry>N)ESc{bLOf}y* zxp>^O;>g$RNLHTJTbjQ}SOFpk2dR-h+{PQn??l`@BlUNCU4h;Ym?q$al#~9plACu3 zkr|E%-<9L`Pw91(MLcHT*xTa1HFm$9^J-eC?wA1ZCe&(z+(VzJd)~9yr!+?Rhz-i` ztd|YDeK%k1eyL1K7~thgmx=&6Pkah#B@a73x1~JSotwW+V>vFU7Q(U58FI%8n|SDE zsN`3AY^0Oy9e%3g^Nl-Eq3IHgfNlDO-(BYpsDhM8+VrZyw%gyHsMa-T|3oaglVxCa zH#MW}lWk}l_b6oRH#PspyYLgvl6P0g^5j;j`Jm%~ z5B$1Sr>4w3O~a&Q8~1kdWC+l9CIDCT)w|o!Ec=L>McHU*HTv=M1f>e;cczY|_n9)o zX7ItY%` z>Ul*tvQb(>9}?5<2Jo{dEkb^!eXTG_d6MoF^1EivqGlS0Oz7TPYzB_iCUGyS?Lo=M+7?Z?S9)Ir&f2AdtNc=8DC`)(Y_{93Us(jlaWO}O_nQ#)|9HBqh zNk3*l)rk)fUo`qwcPQqRoz0K1y|pybt`=2#t?VGEY%HghQ8;8fJ>4`yIQiL={j3Z? z%TK>CN*U)yo__r(%{E*CN=fvq8c~gH9LA$|77X-t357-!XuMqxl|kyZF`yrf%D@hG z!M0JRqfC!c^We7$|TfMPj{LaUax!?)K1I-<2X4%cwpD_d}Af(X}>YB2= zqVc62PG8uJ`Qj%(&Ftzn)y<-UH|8Rk*Y7d^Px#P*Px~>!stXVg?Fg_-astgjQ$G=j}yuLdxU8yR?e= z%d)2kO|5(8iJY_pmg|Zh{PmN~maHnjgn?z3@YjQxV6W|)5XGNAoabSmgyspIKoo-DzcCzW&2Mm&)k6-J z%n2zVMGDK5*PB*pffIy7F~JNO!Fm^$F-0$AsE)uHQz_Ye^c zJt(iQ`HW+VthHhNTW2B+*%noRyj=1$Cze{eA>ubxPWG}H#GPhk13M<7ozr`7BLR}Z6}OzN27-kV zIlA#fFt8?Rbj`F^1-~<`UP)j7poQ7<;JBq>SfjUK*-|2Gt++FI(cz>1^l#rEo((Fq z%fTPr_RkwWTzai$?`1}~OJXNVjSv(iUU zUuf4FhSifP^%-`{5Ozbw)S!9>@hAv$Ve1Z&&A}AkWjp$kNyWPVsFD34Azuk+k`906&KlTo3aM%q1NBN7a%ra`)DNRysUw05FzCJ4`EFZ? z<*ZYy-}w!i;my1JCW)e66;zkyUnMwe@hh*buy`W;P0HYJV5JM3?q zY#N)Ai9++vmQrb!`~4f*KJn4rZ-C6zPlI%U7+hR3ZZQ0zfSoNOD>$_Zba=Z_kVB~C z=-HimYu1#>n`Ry(CbjvosjCrYWGqptCi*Ctg%0nZsbk8#89|~oP;lcmNyw*E96BsY zxR_OEDLC|O0#Cbo44%iH9qaen5^y06OIf6-EXsso*`bcFYpOn^)|~kW8nyd4$(Q13mdO~Tb|uLulzJ}gdwV2t3URyPz}5^ zcYEy3orVr+t|nYHOVUwNQ51eqMoW0VavAyoB#n(_B}kXie+Y3rQj8kPGf{_j8+qN2 z-Ccalk=8|M25ta#03C9lsRkp}^x)K%bYZGemhrZc(RMVDfv^J^*o_``B5Km~mr1+s z#K>iSSitBB^>pX}56H|oQeadncXHMWJC57uIkf|7Hw-3w#GSoy7J=lXOvx%j*4mGR z8n>zdtG7gyXm_-04mX0@H+~SM@>11(n;q^|{%ekS2b(ytS&s)+U}-MhzWkm_Y!pyC zZcX)GfF;X<#9YTV{I{vVRD;1oM;KwJtygJZ%n(>)C;vx0K}Fb)Yz<=Pr0?Ddw2G|D zw-biLCflK1B%>q2!AWf6X=vrxFCLMEyFdLP(3C`_JRILK-u?&Uf&@DnuclnM>i4!3 zT({(ld5enelK}eCK5|J8a85eL(|w|6uDH@8_=_y}sAbZrZQA2&KAi7As}$(m{tCI_|9=v(9DXi}JERypNG32Uy$E-Qy4+WH6hxV<=dydJ)Jb zmapqZ>E9d@`9ffaHftPK)ihE2e|RVL+;wP`TpnS%GMmTEU5@U;CimJnxYQEg~mw55M+N9405@Cs1z=WbpB!t zPvlGl9HuCCpQeh|umL#Cyrk-8ol#H^)4OPj%T+Ht_}%^B_d9rv;Z> z>=YG>-;Vc9f;62eu{bZ~>Sl#>-41KWL^Y!;uuGT z;pU!>>4g&V!*fV+q#4EDex53+mCkF+{`RY>-!tyCe6V-`pLe@H&bY(8_+>tK>(7cc z{~PxiU+3vt4@y>#Hw5#lci)r-O)#&FEsg_9s83!Pt1b6hndBeyw}$X0F0M13A}G@S zVE;qCH%odB2fT!aE2Z}$c!ud`CtYLS2A#+Yp48Z_R^0dgT@K|;ag9l^_0$jN)h?RS zS9HmfBNja!QttGbl~atX%pYA%34*Gcqoy+ng9<-od<^qB&aI%;j_{G|J z=hCP5CoZ$ylloDdgH>0U25W!#`$;89$g!}hUlymz8~3J4aDUq!H-f7WIz!Y?nVFkB zW#0~nO|E4W*R>!(D~*G!GLqF#IYkdUZpNTmhq6YN23O!~4kA}-G%pSnmNgS_LpwkM zwteAPBqy`G6i{0Ev<$Vd0i6;Ab`Tfy!wn&Yp2$tMPrj)K^)XKcKU#gXACmZjyg;!7 z>@Lty?U??PzOUGey;=Oampe`+;lf}@YQKs+{qE`U3DZeT%kKV zx%5<}nR2PN*^8novIbbb-q^}o12!t79+>^r?DjEi}c4XNV`_aVU5T{ExOe||1NwyVvZw*fi$5r(FrBa@o0w3Eh%GpO| zLTH&p&?Z{RQw7qT!bri?%WD0g3n`TukCS#P+a@usZF>Zh6F_1-*UCR(Z=mBD=>xYfRw*Ey+y1Z(s_J+tp?$rn)GmE3f? zMDQ^Nv0tBz-4w5zVBLPpB< z{(YC(ehoLiE?bZCnAVYH!vf<@h)S6LDP2s$MmT3>*#%zWrLmfsxojKI!{XrK1) zLqVbG)?5ocG7-~n%8D=_39Pk{8^WC@jZv9;O}A(D(+aI;;%od?K3jjq`dZd){K}2m zsD2d`RhjW|jy{9!!L#Nde8e(U3EwLM8?CvKRJqkz88O=F`B`K$CPM}+aGn}qi+YAz z7q%FB)oE%&&K%$*+0F0o5eRLk{o?POqMR_d=U5-uEAzqP<*K9W# z7yig*rrx3Ol4On_XU%v$wj*FO5f^RQBDfwj`kp0}(Xs3^S*=wB2;!+#LL+y?Uc=|n zx~MWQ9*bx_-1tJPg21%LtY`V2anjNsmtJzKe3{ugkqJqWen%#l?eh^}BG*EbBI=~i zkj8xXA}{w5$0KIBAj}lhGB&iAnOLyxRol@6e~8B4IVRY^q0i8g5W$octD-fTl&(yE zRejGE?bfgDrOoQ+WJ=WJQ9;$A!lV4}>n4iZ?)Aq=@x7;zugkvjlfB=k(*Wu1Ruh>v zW&>tI$|vNuf{r|C#ht{v7N;uU(-etOg_cyTgp!lvhVl(aO*7oCksYvlX@>D>WXboh zxs_(8=ikJ~sKm&MlvbbpJN~9gEFW*;%Hh+=L?Rzp7^qX486~liKlkkV_|0d5{^Gq# z;}}NTqJ zsyKOdc!lA9m3U#8?l#oc9#T}bsS_v!E)(Kl>4`^;G^3MpQPs<9!C~0y8rzpt3aYs@ zQhu)}mtgmC*!AK4IO|qEnLQRLG(qWhhe=s3xN+rkv|JHCGj+NLwPGI5mt)DpmcWKa z+`lfE*co%^m%cR=2jyf$`X4oi38zLtw^3D(l_T_c)bkxK(o*ycxc~Ig!sPoUU+uk->$`8Tm9r z!kyX9$-~XM=Dq{nbbYMJGmv$BP9GN{B9q6%{EzuXnuf_H{2H7ElYYKasCe|GAhUi# zV}f-{WtPT8{jTACq*KI>I_7}ml|ON$~*V^m~vt4<)`j63E%yncqdk$$F@Qj`npb$X{t+Tc$uiQCw zlFqY{7%Wl7P*R;gIp=pl6*TP(g!cyDNo(o=m&4hG3>xKZHhg2;Z&b+Lyp!4=6F$t@ zg|(c;(*5n~C7Ic_KqNvn#dGq!QC10(-^W${WjC5gfUQ>ZHQo~#wDUbkqs_~UjPcx! z*kl%p$k`?YfCn|Yi;vPtpS-@5kn$}PbvJcguD;a)$`+E%pOs@Nxt0>1PbTMjp^L7ek$Z!WG6v5 zVaMl@BpryLeJ+W5an5r#wvbSM#bw2sL@rQm&DBnLUMjxfeS3evcDnxjsM@H%QmSrK zf8-5VEhQ|7o?1E!;u>fxI(@sM*SgZ$?nUJvPC?`NXgs8QcIAm0WkH4)G(w@O8~r6V zSb;0Q=V^Sha%?u~`4r~8HscvZ%o&jFWgl^bUK^WFWTsX0wnB6X_5IgGEE_DV8@LYX|dMEtn{J|ItgyM&)7=&w1kC?$i&$sKZ7YA8)_&A zM+{A@z$$IMy2pPQ%F{Y+;$ous=3ptF@(e$NVX%4tFHZ5jiu#vCm|79d4Fy5eYc4ir zS^s5=HxLO~!WkJqt%Jf=;@8kZSr-)JVM$P)d~%Q>j*^mn&WEn7HJ22h4!vq19tOYS z!i57CXa4J4f&53QuK6f67XKC7fKJ&kcq zCd71o z>S#FUf$^PxZ_I`Xje+_g>xz=$j%qR3d`}8E&r{-)liSWwucEF3StVkA<$7zkZ4YVX zcyGozlJsz92A!UCm=Va*LG}ay4Op9iybMn1xnkyaZwTm=r6( zI>^mf+Zs+vctv=$+D3E!V=|E?3Q3uq^C@FZj^8@BC)a(TwcPZz>k46+tvfF?^h%dw b*b|u{P3GIJXVyS+Wv0bfzlMfx^4I?YIm~DG literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/Classes/x-saherelm.xea.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xea.class.mq5 new file mode 100644 index 0000000..92dbc7f --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xea.class.mq5 @@ -0,0 +1,814 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseEA +// Description: provides all Base EA requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Classes/x-saherelm.xaccount.class.mq5" +#include "../Classes/x-saherelm.xprovider.class.mq5" +#include "../Libraries/x-saherelm.seriallizer.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Handle base requirements ... +// for indicators ... +class XSCBaseEA +{ + // + // Public ... +public: + // + // Props ... + XSCTrade *mTrader; + XSCAccount *mAccount; + + // + bool isNewHour; + bool isNewDay; + bool isNewWeek; + bool isNewMonth; + bool isNewCandle; + + // + bool isInTestMode; + + // + bool mWaitsUntilNewCandle; + + // + // Constructor ... + void XSCBaseEA( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Time Frame + ulong magic, // Magic Number + int slippage, // Slippgae + OnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler + OnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + OnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler + OnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler + OnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler + OnTradeStateChanged onTradeStateChangedHandler = NULL // On Trade State Changed Event Handler + ) + { + // + mSymbol = symbol; + mPeriod = period; + + // + mMagic = magic; + mSlippage = slippage; + + // + mOnStopLossTriggered = onStopLossTriggered; + mOnTakeProfitTriggered = onTakeProfitTriggered; + mOnDealsChangedHandler = onDealsChangedHandler; + mOnOrdersChangedHandler = onOrdersChangedHandler; + mOnPositionsChangedHandler = onPositionsChangedHandler; + mOnTradeStateChangedHandler = onTradeStateChangedHandler; + + // + // Reset Timings ... + ResetTiming(); + + // + InitRequirements(); + } + + // + // Deconstructor ... + void ~XSCBaseEA() + { + // + delete mTrader; + delete mAccount; + } + + // + // START Properties ... + // + + // + // Symbol ... + string GetSymbol() + { + return mSymbol; + } + + // + // Period ... + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Tag ... + string GetTag() + { + return mTag; + } + + // + ulong GetMagic() + { + return mMagic; + } + + // + int GetSlippage() + { + return mSlippage; + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() + { + mTag = "XEA" + mSymbol + "," + ToString(mPeriod) + (string)mMagic; + } + + // + // Handle Chart Events ... + virtual void OnChartEvent( + const int id, // event ID + const long &lparam, // long type event parameter + const double &dparam, // double type event parameter + const string &sparam // string type event parameter + ) + { + } + + // + // Check any Registered Providers Signalling ... + virtual bool SignalCheck(XSignal &signals[]) { + return false; + } + + // + // Check for any Custom Guard Actions Guard Actions ... + virtual bool CheckGuard(XGuard &guards[]) { + return false; + } + + // + // NOTE: you have to call these Functions on Static Classes to Handle Works ... + + // + // Handle StopLoss Event ... + virtual void OnStopLossTriggered(const XDeal &deal) {} + + // + // Handle TakeProfit Event ... + virtual void OnTakeProfitTriggered(const XDeal &deal) {} + + // + // Handle Deals Changed Event ... + virtual void OnDealsChangedHandler(int count) {} + + // + // Handle Order Changed Event ... + virtual void OnOrdersChangedHandler(int count) {} + + // + // Handle Position Changed Event ... + virtual void OnPositionsChangedHandler(int count) {} + + // + // Handle Trade State Changed ... + virtual void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) {} + + // + // Implemented Actions ... + + // + // OnTick Handler ... + void OnTick() + { + // + // First Check Guards .... + XGuard guards[]; + bool hasGuard = CheckGuard(guards); + if (hasGuard) { + DoGuards(guards); + } + + // + XSignal signals[]; + bool hasSignal = SignalCheck(signals); + if (hasSignal) { + mTrader.ExecuteSignals(signals); + } + } + + // + // Handle On Trade ... + void OnTrade() + { + // + XOnTradeHandlerState state = mTrader.HandleOnTrade(); + + // + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return; + } + + // + // STATE ... + + // + // Notfy Trade State Changed Event ... + OnTradeStateChangedHandler(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + OnDealsChangedHandler(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + mTrader.GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + OnTakeProfitTriggered(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + OnStopLossTriggered(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + OnOrdersChangedHandler(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + OnPositionsChangedHandler(state.newPositions); + } + } + + // + // Retrieve Dept Of Market ... + void OnBookEvent(const string &symbol) + { + // + // TODO: Implement this ... + } + + // + // TOOLS ... + // + void GetPositions( + XPosition &result[], // Hold Result ... + string symbol = NULL, // Trading Symbol ... + ENUM_POSITION_TYPE type = NULL, // Trading Type ... + ENUM_TIMEFRAMES period = NULL // Trading Period ... + ) + { + // + Clean(result); + + // + int positionsCount = mTrader.PositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition positions[]; + mTrader.GetPositions( + positions, + symbol, + period); + positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return; + } + + // + if (type == NULL) + { + // + ArrayResize( + result, + ArraySize(positions)); + + // + for (int i = 0; i < positionsCount; i++) + { + // + Add( + positions[i], + result); + } + + // + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (type == NULL || iPosition.type == type) + { + // + Add( + iPosition, + result); + } + } + } + void GetPositions( + XPosition &result[], // Hold Result ... + string symbol = NULL, // Trading Symbol ... + ENUM_POSITION_TYPE type = NULL, // Trading Type ... + ENUM_TIMEFRAMES period = NULL, // Trading Period ... + string provider = NULL // Signal Provider ... + ) + { + // + Clean(result); + + // + bool hasSymbol = !(symbol == NULL || StringLen(symbol) == 0); + bool hasProvider = !(provider == NULL || StringLen(provider) == 0); + + // + int positionsCount = mTrader.PositionsCount(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition positions[]; + mTrader.GetPositions( + positions, + symbol, + period); + positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return; + } + + // + if (!hasProvider && type == NULL) + { + // + ArrayResize( + result, + ArraySize(positions)); + + // + for (int i = 0; i < positionsCount; i++) + { + // + Add( + positions[i], + result); + } + + // + return; + } + + // + if (type == NULL) + { + // + ArrayResize( + result, + ArraySize(positions)); + + // + for (int i = 0; i < positionsCount; i++) + { + // + Add( + positions[i], + result); + } + + // + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + string iProvider = ExtractProvider(iPosition.comment); + if (hasProvider && iProvider != provider) + { + continue; + } + + // + if (type == NULL || iPosition.type == type) + { + // + Add( + iPosition, + result); + } + } + } + + // + // GUARD Handlers ... + + // + // Parse Recievd Guards and Do them ... + void DoGuards(XGuard &guards[]) + { + int guardsCount = ArraySize(guards); + if (guardsCount <= 0) + { + return; + } + + // + for (int i = 0; i < guardsCount; i++) + { + // + XGuard iGuard = guards[i]; + + // + switch (iGuard.action) + { + // + // Hedge In Profit Specified Positions ... + case X_GUARD_ACTION_HEDGE: + HandleGuardHedgeAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Trail Stop Loss in Specified Positions ... + case X_GUARD_ACTION_TRAIL_STOP: + HandleGuardTrailingStopAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period, + iGuard.dblPayLoad); + break; + + // + // Force Close Specified Positions ... + case X_GUARD_ACTION_FORCE_CLOSE: + HandleGuardForceCloseAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Generate and Place Support Signals ... + case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL: + HandleGuardAddSupportPositionAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Delete All Placed Pending Orders ... + case X_GUARD_ACTION_CANCEL_PENDING_ORDERS: + HandleGuardCancelPendingOrdersAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + } + } + } + + // + // Close All Specified Provider's Positions in Profit Summary ... + void HandleGuardHedgeAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double minProfitForHedging = 1 // Specified Profit for Hedge ... + ) + { + // + } + + // + // Force Close Specified Set Of Position ... + void HandleGuardForceCloseAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ulong ticket = 0 // Specific Ticket + ) + { + // + string comment = ""; + + // + // Close All Positions ... + if (ticket == 0) + { + // + XPosition positions[]; + GetPositions( + positions, + symbol, + type, + period, + provider); + if (ArraySize(positions) <= 0) + { + return; + } + + // + comment = provider + " Force Close Guard ..."; + + // + mTrader.ClosePositions( + positions, + comment); + } + // + // Close Specific Position ... + else + { + // + XPosition position; + bool hasPosition = mTrader.GetPosition( + position, + ticket); + + // + if (hasPosition) + { + // + comment = provider + "(" + ToString(ticket) + ")" + " Force Close Guard ..."; + + // + mTrader.Close( + ticket, + comment); + } + } + + // + if (StringLen(comment) > 0) + { + LogMessage(comment); + } + } + + // + // Trailing Specified Set Of Positions Stop Losses ... + void HandleGuardTrailingStopAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double sl // Desired SL Value ... + ) + { + // + // TODO: Implement this ... + } + + // + // Add Support Signal for Specified Positions ... + void HandleGuardAddSupportPositionAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + // + // TODO: Implement this ... + } + + // + // Cancel all Placed Orders ... + void HandleGuardCancelPendingOrdersAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + // + // TODO: Implement this ... + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + string GetTagPrefix() + { + // + string result = "(" + mSymbol + ")(" + ToString(mPeriod) + ")"; + + // + return result; + } + + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // ExpertAdviser MAgic Number ... + ulong mMagic; + + // + // Slipppage ... + int mSlippage; + + // + // Tag Identifier ... + string mTag; + + // + // Private ... +private: + // + // Define Requirements ... + + // + // XSCTrade Event Handlers ... + OnStopLoss mOnStopLossTriggered; + OnTakeProfit mOnTakeProfitTriggered; + OnDealsChanged mOnDealsChangedHandler; + OnOrdersChanged mOnOrdersChangedHandler; + OnPositionsChanged mOnPositionsChangedHandler; + OnTradeStateChanged mOnTradeStateChangedHandler; + + // + // Initi Requirements ... + void InitRequirements() + { + // + // Account Manager ... + mAccount = new XSCAccount(); + + // + // Trader ... + mTrader = new XSCTrade( + mSlippage, + mMagic); + + // + // Attach Event Handlers ... + + // + if (mOnStopLossTriggered != NULL) + { + mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered); + } + + // + if (mOnTakeProfitTriggered != NULL) + { + mTrader.AddOnTakeProfitEventHandler(mOnTakeProfitTriggered); + } + + // + if (mOnDealsChangedHandler != NULL) + { + mTrader.AddOnDealsChangedEventHandler(mOnDealsChangedHandler); + } + + // + if (mOnOrdersChangedHandler != NULL) + { + mTrader.AddOnOrdersChangedEventHandler(mOnOrdersChangedHandler); + } + + // + if (mOnPositionsChangedHandler != NULL) + { + mTrader.AddOnPositionsChangedEventHandler(mOnPositionsChangedHandler); + } + + // + if (mOnTradeStateChangedHandler != NULL) + { + mTrader.AddOnTradeStateChangedEventHandler(mOnTradeStateChangedHandler); + } + } +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xhelper.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xhelper.class.mq5 new file mode 100644 index 0000000..d9cea8b --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xhelper.class.mq5 @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseHelper +// Description: provides all Base Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Handle base requirements ... +// for indicators ... +class XSCBaseHelper +{ + // + // Public ... +public: + // + // Constructor ... + void XSCBaseHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) + { + // + mSymbol = symbol; + mPeriod = period; + + // + LoopBack(52); + } + + // + // Deconstructor ... + void ~XSCBaseHelper() + { + IndicatorRelease(mHandler); + } + + // + // START Properties ... + // + + // + // Loopback Bars ... + void LoopBack(int value) + { + mLoopbackBars = value; + } + + int Loopback() + { + return mLoopbackBars; + } + + // + // Symbol ... + string GetSymbol() + { + return mSymbol; + } + + // + // Period ... + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Tag ... + string GetTag() + { + return mTag; + } + + // + // Retrieve Bars ... + int GetBars() + { + // + int result = + Bars( + mSymbol, + mPeriod); + + // + return result; + } + + // + int GetCalculatedBars() + { + return BarsCalculated(mHandler); + } + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + + // + // Prepare Tag ... + virtual void PrepareTag() {} + + // + // Reading Buffers based on Given Bar Index ... + virtual void Calculate( + int barIndex // Given Bar Index + ); + + // + // Retrieve MAx Required Length for Calculations ... + virtual int GetMaxLength(); + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + string GetTagPrefix() + { + // + string result = "(" + mSymbol + ")(" + ToString(mPeriod) + ")"; + + // + return result; + } + + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Indicator Handler ... + int mHandler; + + // + // Number Of Items Read Per Tick ... + int mLoopbackBars; + + // + // Tag Identifier ... + string mTag; + + // + // Private ... +private: + // +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xnotifier.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xnotifier.class.mq5 new file mode 100644 index 0000000..0c653eb --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xnotifier.class.mq5 @@ -0,0 +1,295 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCNotifier +// Description: provides all Base Notification requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// a Notification Model ... +typedef void (*OnMessage)( + string, // action ... + string // payload ... +); + +// +struct XNotifierEventListener +{ + string action; + OnMessage listeners[]; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Handle base requirements ... +// for indicators ... +class XSCNotifier +{ + // + // Public ... +public: + // + // Constructor ... + void XSCNotifier() + { + } + + // + // Deconstructor ... + void ~XSCNotifier() + { + } + + // + // START Properties ... + // + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + bool AddEventListener( + string action, // Specific Action ... + OnMessage listener // Specific Listener ... + ) + { + // + bool result = false; + + // + int aIndex = FindActionIndex(action); + if (aIndex < 0) + { + // + // Create a New Structure ... + XNotifierEventListener model; + + // + model.action = action; + + // + Add( + listener, + model.listeners); + + // + Add( + model, + mEventListeners); + + // + result = true; + } + else + { + // + // Just Add Listener to Exists model ... + Add( + listener, + mEventListeners[aIndex].listeners); + + // + result = true; + } + + // + return result; + } + + // + bool NotifyEvent( + string action, // action ... + string payload // payload ... + ) + { + // + bool result = false; + + // + int actionIndex = FindActionIndex(action); + result = actionIndex >= 0; + if (!result) + { + return result; + } + + // + int aListenersCount = ArraySize(mEventListeners[actionIndex].listeners); + result = aListenersCount > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < aListenersCount; i++) + { + // + OnMessage iListener = mEventListeners[actionIndex].listeners[i]; + + // + // Call Listener ... + iListener( + action, + payload); + } + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + + // + // Private ... +private: + // + XNotifierEventListener mEventListeners[]; + + // + // Find Specific Actions Index in Registered Event Listeners ... + int FindActionIndex(string action) + { + // + int result = -1; + + // + int listenersCount = ArraySize(mEventListeners); + if (listenersCount <= 0) + { + return result; + } + + // + for (int i = 0; i < listenersCount; i++) + { + // + XNotifierEventListener iModel = mEventListeners[i]; + + // + if (iModel.action == action) + { + // + result = i; + break; + } + } + + // + return result; + } +}; + +// +// START Usefull Functions ... +// + +// +void Clean( + OnMessage &buffer[] // Buffer ... +) +{ + // + ArrayFree(buffer); + + // + ArrayResize( + buffer, + 0); +} +void Clean( + XNotifierEventListener &buffer[] // Buffer ... +) +{ + // + ArrayFree(buffer); + + // + ArrayResize( + buffer, + 0); +} + +// +void Add( + OnMessage item, // Item ... + OnMessage &buffer[] // Buffer ... +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XNotifierEventListener &item, // Item ... + XNotifierEventListener &buffer[] // Buffer ... +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xprovider.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xprovider.class.mq5 new file mode 100644 index 0000000..e60bb27 --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xprovider.class.mq5 @@ -0,0 +1,304 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCEABaseProvider +// Description: provides base requirements for +// Specific Sgnal Provider ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Definitions ... +// + +// +// Notified a Signal was Appears ... +typedef void (*OnSignal)( + XSignal &signal); + +// +// Notified a Guard Appears ... +typedef void (*OnGuard)(XGuard &guard); + +// +// END Definitions ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Base Class for All of our EA's ... +class XSCEABaseProvider +{ + // + // Public ... +public: + // + // Constructor ... + void XSCEABaseProvider() + { + mSymbol = _Symbol; + mPeriod = _Period; + } + void XSCEABaseProvider( + string symbol, + ENUM_TIMEFRAMES period) + { + // + mSymbol = symbol; + mPeriod = period; + + // + mTag = mSymbol + "," + ToString(mPeriod); + + // + mIsInTestMode = IsRunningOnTestMode(); + } + + // + // Deconstructor ... + void ~XSCEABaseProvider() + { + } + + // + bool CanIgnoreTick() { + // + mIsNewCandle = IsNewCandle( + mSymbol, + mPeriod); + bool result = mIsInTestMode + ? !mIsNewCandle + : !mIsNewCandle && mWaitUntilNewCandle; + + // + return result; + } + + // + // Prepare State ... + void OnTick() + { + // + mIsNewCandle = IsNewCandle( + mSymbol, + mPeriod); + mCanIgnoreTick = mIsInTestMode + ? !mIsNewCandle + : !mIsNewCandle && mWaitUntilNewCandle; + + // + ProcessBuffers(); + + // + if (mCanIgnoreTick) + { + return; + } + + // + mWaitUntilNewCandle = false; + + // + ProcessTick(); + } + + // + virtual void PrepareTag(); + + // + // Initialize Indicators and Requirements ... + virtual bool Init(); + + // + virtual int GetMaxLength(); + + // + virtual int GetCalculatedBars(); + + // + // Handle Update Buffers ... + virtual void ProcessBuffers() + { + return; + } + + // + // Handle On Tick Event ... + virtual void ProcessTick() + { + return; + } + + // + // Check for Guards ... + virtual bool GuardCheck(XGuard &guards[]); + + // + // Add Specific On Signal Event Handler ... + int AddOnSignalEventHandler(OnSignal handler) + { + // + ArrayResize( + mSignalEventHandlers, + ArraySize(mSignalEventHandlers) + 1); + + // + int result = ArraySize(mSignalEventHandlers) - 1; + mSignalEventHandlers[result] = handler; + + // + return result; + } + + // + // Remove All On Signal Event Handler ... + void ReoveOnSignalEventHandlers() + { + // + ArrayFree(mSignalEventHandlers); + } + + // + // Notify a Signal Found on all Event Listeners ... + void NotifyOnSignalEvent(XSignal &info) + { + // + int listenerCount = ArraySize(mSignalEventHandlers); + if (listenerCount <= 0) + { + return; + } + + // + // Loop Through Listeners ... + for (int i = 0; i < listenerCount; i++) + { + // + OnSignal listener = mSignalEventHandlers[i]; + + // + listener(info); + } + } + + // + // Protected ... +protected: + // + string mSymbol; + + // + ENUM_TIMEFRAMES mPeriod; + + // + string mTag; + + // + bool mIsNewCandle; + bool mIsInTestMode; + bool mCanIgnoreTick; + bool mWaitUntilNewCandle; + + // + // Private ... +private: + // + // Signal Event Handlers ... + OnSignal mSignalEventHandlers[]; +}; + +// +// START Definitions ... +// + +// +// Model Signal Providers Definitions ... +struct XBaseSignalProvider +{ + // + // Provider use Which Symbol ... + string symbol; + + // + // Provider use Which Time Frame ... + ENUM_TIMEFRAMES period; + + // + // Risk Amount Per Trades Related to Time Frames ... + // Percent of Available Balance ... + double riskAmount; + + // + // Desired Magic Number ... + ulong magicNumber; +}; + +// +struct XLastSignal +{ + datetime at; + string provider; +}; + +// +// END Definitions ... +// + +// +// START Usefull Functions ... +// + +// +// Add Specific Provider to List ... +void Add( + XBaseSignalProvider &item, // item want to add + XBaseSignalProvider &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Classes/x-saherelm.xtrade.class.mq5 b/MQLTestWorkspace/Classes/x-saherelm.xtrade.class.mq5 new file mode 100644 index 0000000..87694fa --- /dev/null +++ b/MQLTestWorkspace/Classes/x-saherelm.xtrade.class.mq5 @@ -0,0 +1,4111 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCTrade +// Description: provides all Trade requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +// Model an Open Position ... +struct XPosition +{ + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Position Comment ... + string comment; +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long pocitionID; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string smybol; + + // + // Order Comment ... + string comment; +}; + +// +// Model a Deal ... +struct XDeal +{ + // + // the ID of the Expert Advisor, that executed the deal ... + ulong magic; + + // + // the ID of position, in which the deal was involved ... + ulong positionId; + + // + // Ticket ... + ulong ticket; + + // + // the name of the deal symbol ... + string symbol; + + // + // order by which the deal is executed ... + ulong order; + + // + // the time of deal execution ... + datetime time; + + // + // Deal price ... + double price; + + // + // the financial result of the deal (in deposit currency) ... + double profit; + + // + // the amount of swap when position is closed ... + double swap; + + // + // the amount of commission of the deal ... + double commission; + + // + // the volume of deal ... + double volume; + + // + // the deal comment ... + string comment; + + // + // the deal type ... + // ------------------------------------------------------------------ + // DEAL_TYPE_BUY => Buy ... + // DEAL_TYPE_SELL => Sell ... + // DEAL_TYPE_BUY_CANCELED => Canceled buy deal ... + // There can be a situation when a previously executed buy deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ... + // + // DEAL_TYPE_SELL_CANCELED => Canceled sell deal ... + // There can be a situation when a previously executed sell deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation + // + // DEAL_TYPE_BALANCE => Balance ... + // DEAL_TYPE_CREDIT => Credit ... + // DEAL_TYPE_CHARGE => Additional charge ... + // DEAL_TYPE_CORRECTION => Correction ... + // DEAL_TAX => Tax charges ... + // DEAL_TYPE_BONUS => Bonus ... + // DEAL_TYPE_INTEREST => Interest rate ... + // DEAL_DIVIDEND => Dividend operations... + // DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ... + // DEAL_TYPE_COMMISSION => Additional commission ... + // DEAL_TYPE_COMMISSION_DAILY => Daily commission ... + // DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ... + // DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ... + // DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission + ENUM_DEAL_TYPE type; + + // + // the deal direction ... + // ---------------------------------- + // DEAL_ENTRY_IN => Entry in ... + // DEAL_ENTRY_OUT => Entry out ... + // DEAL_ENTRY_INOUT => Reverse ... + // DEAL_ENTRY_OUT_BY => Close a position by an opposite one ... + ENUM_DEAL_ENTRY entry; + + // + // deal reson ... + // --------------------- + // DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ... + // DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ... + // DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ... + // DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ... + // DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ... + // DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ... + // DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ... + // DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ... + // DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ... + // DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ... + ENUM_DEAL_REASON reason; +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerState +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; +}; + +// +typedef void (*OnDealsChanged)(int count); + +// +typedef void (*OnOrdersChanged)(int count); + +// +typedef void (*OnPositionsChanged)(int count); + +// +typedef void (*OnStopLoss)(const XDeal &deal); +typedef void (*OnTakeProfit)(const XDeal &deal); + +// +typedef void (*OnTradeStateChanged)(const XOnTradeHandlerState &state); + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.seriallizer.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// XCTrade Base Class ... +class XSCTradeBase : public CTrade +{ +public: + // + // Modify Specific Position, by Specific Comment ... + bool PositionModify( + const string symbol, // Symbol + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!SelectPosition(symbol)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + bool PositionModify( + const ulong ticket, // Position Ticket + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.position = ticket; + m_request.symbol = PositionGetString(POSITION_SYMBOL); + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + + // + // Close Specific Position, by Specific Comment ... + bool PositionClose( + const string symbol, // Symbol + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + bool partial_close = false; + int retry_count = 10; + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + do + { + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specify Comment ... + m_request.comment = comment; + + // + // check volume + double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + if (m_request.volume > max_volume) + { + // + m_request.volume = max_volume; + partial_close = true; + } + else + { + partial_close = false; + } + + // + // hedging? just send order + if (IsHedging()) + { + return (OrderSend(m_request, m_result)); + } + + // + // order send + if (!OrderSend(m_request, m_result)) + { + // + if (--retry_count != 0) + { + continue; + } + + // + if (retcode == TRADE_RETCODE_DONE_PARTIAL) + { + m_result.retcode = retcode; + } + + // + return (false); + } + + // + //--- WARNING. If position volume exceeds the maximum volume allowed for deal, + //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, + //--- but partially. It is decreased by the maximum volume allowed for deal. + if (m_async_mode) + { + break; + } + + // + retcode = TRADE_RETCODE_DONE_PARTIAL; + if (partial_close) + { + Sleep(1000); + } + } while (partial_close); + + // + // succeed + return (true); + } + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } + + // + // Partial Close Specific Position, by Specific Comment ... + bool PositionClosePartial( + const string symbol, // Symbol + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // hedging? just send order + return (OrderSend(m_request, m_result)); + } + bool PositionClosePartial( + const ulong ticket, // Position Ticket + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } +}; + +// +// END Overrides ... +// + +// +// a Class for Manage Trades ... +class XSCTrade +{ + // + // Public ... +public: + // + // Constructor ... + void XSCTrade( + int slippage, // Specify Slippage + ulong magicNumber // Specify Magic Number + ) + { + // + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mPeriodPrefix = "PR"; + + // + mTrader = new XSCTradeBase(); + + // + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + // Prepare Trade Event Materials ... + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + } + + // + // Deconstructor ... + void ~XSCTrade() + { + } + + // + // START Event Processing ... + // + + // + // This Must be Called Every time OnTrade Event Happening ... + XOnTradeHandlerState HandleOnTrade() + { + // + // Handle OnTrade Event ... + XOnTradeHandlerState state = {}; + HandleOnTradeEvent(state); + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return state; + } + + // + // STATE ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(state.newPositions); + } + + // + return state; + } + + // + // Process On Trade Requirement + void HandleOnTradeEvent( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + if (mScanStarted) + { + ProcessOnTradeContext(result); + } + else + { + InitOnTradeContext(); + } + } + + // + // Event Emitters ... + + // + // STATE Changed ... + + // + // Clear Trade State Changed Event Handlers ... + void ClearOnTradeStateChangedEventHandlers() + { + // + ArrayFree(mTradeStateChangedEventHandlers); + + // + ArrayResize(mTradeStateChangedEventHandlers, 0); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnTradeStateChangedEventHandler(OnTradeStateChanged handler) + { + // + ArrayResize( + mTradeStateChangedEventHandlers, + ArraySize(mTradeStateChangedEventHandlers) + 1); + + // + mTradeStateChangedEventHandlers[ArraySize(mTradeStateChangedEventHandlers) - 1] = handler; + } + + // + // DEALS ... + + // + // Clear Deals Changed Event Handlers ... + void ClearOnDealsChangedEventHandlers() + { + // + ArrayFree(mDealsChangedEventHandlers); + + // + ArrayResize(mDealsChangedEventHandlers, 0); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnDealsChangedEventHandler(OnDealsChanged handler) + { + // + ArrayResize( + mDealsChangedEventHandlers, + ArraySize(mDealsChangedEventHandlers) + 1); + + // + mDealsChangedEventHandlers[ArraySize(mDealsChangedEventHandlers) - 1] = handler; + } + + // + // ORDERS ... + + // + // Clear Orders Changed Event Handlers ... + void ClearOnOrdersChangedEventHandlers() + { + // + ArrayFree(mOrdersChangedEventHandlers); + + // + ArrayResize(mOrdersChangedEventHandlers, 0); + } + + // + // Add New Orders Changed Event Handler ... + void AddOnOrdersChangedEventHandler(OnOrdersChanged handler) + { + // + ArrayResize( + mOrdersChangedEventHandlers, + ArraySize(mOrdersChangedEventHandlers) + 1); + + // + mOrdersChangedEventHandlers[ArraySize(mOrdersChangedEventHandlers) - 1] = handler; + } + + // + // POSITIONS ... + + // + // Clear Positions Changed Event Handlers ... + void ClearOnPositionsChangedEventHandlers() + { + // + ArrayFree(mPositionsChangedEventHandlers); + + // + ArrayResize(mPositionsChangedEventHandlers, 0); + } + + // + // Add New Positions Changed Event Handler ... + void AddOnPositionsChangedEventHandler(OnPositionsChanged handler) + { + // + ArrayResize( + mPositionsChangedEventHandlers, + ArraySize(mPositionsChangedEventHandlers) + 1); + + // + mPositionsChangedEventHandlers[ArraySize(mPositionsChangedEventHandlers) - 1] = handler; + } + + // + // TPSL ... + + // + // Clear Stop Loss Event Handlers ... + void ClearOnStopLossEventHandlers() + { + // + ArrayFree(mStopLossEventHandlers); + + // + ArrayResize(mStopLossEventHandlers, 0); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnStopLossEventHandler(OnStopLoss handler) + { + // + ArrayResize( + mStopLossEventHandlers, + ArraySize(mStopLossEventHandlers) + 1); + + // + mStopLossEventHandlers[ArraySize(mStopLossEventHandlers) - 1] = handler; + } + + // + // Clear Take Profit Event Handlers ... + void ClearOnTakeProfitEventHandlers() + { + // + ArrayFree(mTakeProfitEventHandlers); + + // + ArrayResize(mTakeProfitEventHandlers, 0); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnTakeProfitEventHandler(OnTakeProfit handler) + { + // + ArrayResize( + mTakeProfitEventHandlers, + ArraySize(mTakeProfitEventHandlers) + 1); + + // + mTakeProfitEventHandlers[ArraySize(mTakeProfitEventHandlers) - 1] = handler; + } + + // + // END Event Processing ... + // + + // + // START Provided Functions ... + // + + // + // Count Currently Open Positions ... + int PositionsCount( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + int result = 0; + + // + int allPositions = 0; + int longPositions = 0; + int shortPositions = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + allPositions++; + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + longPositions++; + } + else + { + shortPositions++; + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + allPositions++; + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + longPositions++; + } + else + { + shortPositions++; + } + + // + continue; + } + } + } + + // + // Specify Result ... + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + result = allPositions; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == POSITION_TYPE_BUY) + { + result = longPositions; + } + else + { + result = shortPositions++; + } + } + else if (StringLen(symbol) > 0) + { + // + result = allPositions; + } + else if (type != NULL) + { + // + if (type == POSITION_TYPE_BUY) + { + result = longPositions; + } + else + { + result = shortPositions; + } + } + + // + return result; + } + + // + // Retrieve Max In Profit Position Ticket ... + ulong GetMaxInProfitPosition( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + ulong result = -1; + + // + double profit = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + double positionAbsProfit = MathAbs(positionProfit); + if (positionProfit <= 0) + { + continue; + } + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Retrieve Max In DrawDown Position Ticket ... + ulong GetMaxInDrawDownPosition( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + ulong result = -1; + + // + double profit = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + double positionAbsProfit = MathAbs(positionProfit); + if (positionProfit >= 0) + { + continue; + } + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + else + { + // + if (profit < positionAbsProfit) + { + // + result = positionTicket; + profit = positionAbsProfit; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Retrieve Specific Position's Profit ... + double GetPositionProfit( + const ulong ticket // Specified Position Ticket + ) + { + // + double result = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + result = mPositionInfo.Profit(); + break; + } + + // + return result; + } + + // + // Retrieve Specific Position's OpenDate ... + datetime GetPositionOpenDate( + const ulong ticket // Specified Position Ticket + ) + { + // + datetime result = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + result = mPositionInfo.Time(); + break; + } + + // + return result; + } + + // + // Retrieve Specific Position's Comment ... + string GetPositionComment( + const ulong ticket // Specified Position Ticket + ) + { + // + string result = ""; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + result = mPositionInfo.Comment(); + break; + } + + // + return result; + } + + // + // Retrieve All Open Positions Profit ... + double GetPositionsProfit( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + double result = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + result += positionProfit; + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + result += positionProfit; + } + else + { + result += positionProfit; + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + result += positionProfit; + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + result += positionProfit; + } + else + { + result += positionProfit; + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Find Oldes Position ... + ulong GetOldestPosition( + string symbol = "", // Specified Symbol + ENUM_POSITION_TYPE type = NULL // Specified Type + ) + { + // + ulong result = 0; + + // + int age = 0; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + + // + string positionSymbol = mPositionInfo.Symbol(); + + // + double positionProfit = mPositionInfo.Profit(); + double positionAbsProfit = MathAbs(positionProfit); + if (positionProfit >= 0) + { + continue; + } + + // + ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType(); + + // + string positionComment = mPositionInfo.Comment(); + ENUM_TIMEFRAMES positionPeriod = ExtractPositionPeriod(positionComment); + + // + // Calculate Position's Age ... + datetime positionOpenTime = mPositionInfo.Time(); + + // + // Retrieve Trade Open Bar Index based on Current Period ... + int positionOpenBarIndex = iBarShift( + positionSymbol, + positionPeriod, + positionOpenTime); + + // + // Calculate Trade Life ... + int positionAge = MathAbs(0 - positionOpenBarIndex); + + // + if ( + type == NULL && + StringLen(symbol) <= 0) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + + // + continue; + } + else if ( + type != NULL && + StringLen(symbol) > 0) + { + // + if (type == positionType && + symbol == positionSymbol) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + else + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + + // + continue; + } + } + else if (StringLen(symbol) > 0) + { + // + if (positionSymbol == symbol) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + + // + continue; + } + } + else if (type != NULL) + { + // + if (type == positionType) + { + // + if (type == POSITION_TYPE_BUY) + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + else + { + // + if (age < positionAge) + { + // + age = positionAge; + result = positionTicket; + } + } + + // + continue; + } + } + } + + // + return result; + } + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = "" // comment + ) + { + // + bool result = false; + + // + string mPeriodStr = GeneratePositionPeriodComment(period); + + // + comment += mPeriodStr; + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = "" // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + if (tp <= 0 && sl <= 0) + { + result = false; + return result; + } + + // + // Use Position Comment when there isn't new One ... + if (StringLen(comment) == 0) + { + comment = GetPositionComment(ticket); + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment); + + // + return result; + } + + // + // Close Position By Ticket ... + bool Close( + ulong ticket, // Position Ticket + string comment = "" // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + // Try to Select Position ... + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + // Close Position By Specific Comment ... + result = mTrader.PositionClose( + ticket, + mSlippage, + comment); + + // + return result; + } + + // + // Close All Positions ... + void CloseAllPositions( + string comment = "" // Close Position By Specific Comment + ) + { + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + Close( + positionTicket, + comment); + } + } + + // + // Close Partial By Ticket ... + bool ClosePartial( + ulong ticket, // Position Ticket + double volume, // Volume Size for Partial Closing + string comment = "" // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume, + mSlippage, + comment); + + // + return result; + } + + // + // Find Position Open Bar Index ... + int GetPositionOpenBarIndex( + const ulong ticket // position ticket + ) + { + // + int result = -1; + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong positionTicket = mPositionInfo.Ticket(); + if (positionTicket != ticket) + { + continue; + } + + // + string symbol = mPositionInfo.Symbol(); + datetime openAt = mPositionInfo.Time(); + string comment = mPositionInfo.Comment(); + ENUM_TIMEFRAMES period = ExtractPositionPeriod(comment); + + // + result = iBarShift( + symbol, + period, + openAt); + } + + // + return result; + } + + // + bool GetPosition( + XPosition &position, // Holds result ... + ulong ticket // Required Position Ticket ... + ) + { + // + bool result = false; + + // + XPosition positions[]; + GetPositions(positions); + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + result = iPosition.ticket == ticket; + if (!result) + { + continue; + } + + // + position = iPosition; + break; + } + + // + return result; + } + + // + // Retrieve Positions as an Array ... + void GetPositions( + XPosition &result[] // Hold Result ... + ) + { + // + Clean(result); + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + ulong magic = mPositionInfo.Magic(); + ulong ticket = mPositionInfo.Ticket(); + string symbol = mPositionInfo.Symbol(); + datetime openAt = mPositionInfo.Time(); + double swap = mPositionInfo.Swap(); + double sl = mPositionInfo.StopLoss(); + double tp = mPositionInfo.TakeProfit(); + double profit = mPositionInfo.Profit(); + double volume = mPositionInfo.Volume(); + string comment = mPositionInfo.Comment(); + double entry = mPositionInfo.PriceOpen(); + double price = mPositionInfo.PriceCurrent(); + double commission = mPositionInfo.Commission(); + ENUM_POSITION_TYPE type = mPositionInfo.PositionType(); + ENUM_TIMEFRAMES period = ExtractPositionPeriod(comment); + + // + XPosition iPosition = {}; + + // + iPosition.tp = tp; + iPosition.sl = sl; + iPosition.swap = swap; + iPosition.type = type; + iPosition.magic = magic; + iPosition.entry = entry; + iPosition.price = price; + iPosition.ticket = ticket; + iPosition.symbol = symbol; + iPosition.period = period; + iPosition.volume = volume; + iPosition.openAt = openAt; + iPosition.profit = profit; + iPosition.comment = comment; + iPosition.commission = commission; + + // + Add( + iPosition, + result); + } + } + + // + void GetPositions( + XPosition &result[], // Hold Result ... + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period // Trading Period ... + ) + { + // + Clean(result); + + // + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return; + } + + // + XPosition allPositions[]; + GetPositions(allPositions); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + if (symbol != iPosition.symbol) + { + continue; + } + + // + ENUM_TIMEFRAMES positionPeriod = ExtractPositionPeriod(iPosition.comment); + if (period != positionPeriod) + { + continue; + } + + // + Add( + iPosition, + result); + } + } + + // + // Execute a Signal ... + bool ExecuteSignal( + XSignal &signal, // Signal ... + string comment = "", // Position Comment ... + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime ... + datetime expiration = 0 // order expiration time + ) + + { + // + bool result = false; + + // + double currentEntry = GetEntry( + signal.symbol, + signal.type); + bool isLong = IsLong(signal.type); + + // + ResetLastError(); + + // + if (signal.mode == X_ORDER_MODE_MARKET) + { + // + // Execute MArket Orders ... + if (isLong) + { + // + result = Buy( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + signal.sl, + signal.tp, + comment); + } + else + { + // + result = Sell( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + signal.sl, + signal.tp, + comment); + } + } + else if (signal.mode == X_ORDER_MODE_LIMIT) + { + // + // Execute Limit Orders ... + + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? signal.entry < currentEntry + : signal.entry > currentEntry; + if (!result) + { + return result; + } + + // + // Check Expiration Date ... + result = (lifetime == ORDER_TIME_SPECIFIED || lifetime == ORDER_TIME_SPECIFIED_DAY) + ? expiration > 0 + : true; + if (!result) + { + return result; + } + + // + if (isLong) + { + // + result = BuyLimit( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + signal.sl, + signal.tp, + lifetime, + expiration, + comment); + } + else + { + // + result = SellLimit( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + signal.sl, + signal.tp, + lifetime, + expiration, + comment); + } + } + else if (signal.mode == X_ORDER_MODE_STOP) + { + // + // Execute Stop Orders ... + + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? signal.entry > currentEntry + : signal.entry < currentEntry; + if (!result) + { + return result; + } + + // + // Check Expiration Date ... + result = (lifetime == ORDER_TIME_SPECIFIED || lifetime == ORDER_TIME_SPECIFIED_DAY) + ? expiration > 0 + : true; + if (!result) + { + return result; + } + + // + if (isLong) + { + // + result = BuyStop( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + signal.sl, + signal.tp, + lifetime, + expiration, + comment); + } + else + { + // + result = SellStop( + signal.symbol, + signal.period, + signal.volume, + signal.entry, + signal.sl, + signal.tp, + lifetime, + expiration, + comment); + } + } + + // + if (!result) + { + // + LogMessage("Error: " + (string)GetLastError() + ", " + GetErrorDescription(GetLastError())); + } + + // + return result; + } + + // + // Execute a Collection of Signals ... + int ExecuteSignals( + const XSignal &signals[], // an Array of Signals ... + string comment = "", // Position Comment ... + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime ... + datetime expiration = 0 // order expiration time + ) + { + // + int result = 0; + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isExecuted = ExecuteSignal( + iSignal, + comment, + lifetime, + expiration); + + // + if (isExecuted) + { + result++; + } + } + + // + return result; + } + + // + // Retrieve in Profit Positions ... + void GetInProfitPositions( + XPosition &result[] // Hold Result ... + ) + { + // + Clean(result); + + // + XPosition allPositions[]; + GetPositions(allPositions); + int positionsCount = ArraySize(allPositions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + if (iPosition.profit > 0) + { + Add( + iPosition, + result); + } + } + } + + // + // Retrieve in Drawdown Positions ... + void GetInDrawdownPositions( + XPosition &result[] // Hold Result ... + ) + { + // + Clean(result); + + // + XPosition allPositions[]; + GetPositions(allPositions); + int positionsCount = ArraySize(allPositions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + if (iPosition.profit < 0) + { + Add( + iPosition, + result); + } + } + } + + // + // Close a Collection Of Positions ... + void ClosePositions( + XPosition &positions[], // Positions to Close ... + string comment = "" // Specified Comment ... + ) + { + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + Close( + iPosition.ticket, + comment); + } + } + + // + // Retrieve All Orders ... + void GetOrders( + XOrder &result[], // Holdes Result .... + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period, // Trading TimeFrame ... + ENUM_ORDER_STATE state = NULL // Order State ... + ) + { + // + Clean(result); + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return; + } + + // + // Since Orders may be so more than positions ... + // start Orders Collectiong Loops reverse ... + for (int i = ordersCount - 1; i >= 0; i--) + { + // + if (!mOrderInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mOrderInfo.Magic() != mMagicNumber) + { + continue; + } + + // + // Reading Order Info ... + long magic = mOrderInfo.Magic(); + double sl = mOrderInfo.StopLoss(); + ulong ticket = mOrderInfo.Ticket(); + double tp = mOrderInfo.TakeProfit(); + string oSymbol = mOrderInfo.Symbol(); + string comment = mOrderInfo.Comment(); + long pocitionID = mOrderInfo.PositionId(); + double openPrice = mOrderInfo.PriceOpen(); + datetime setupAt = mOrderInfo.TimeSetup(); + datetime executedAt = mOrderInfo.TimeDone(); + ENUM_ORDER_STATE oState = mOrderInfo.State(); + ENUM_ORDER_TYPE type = mOrderInfo.OrderType(); + double currentPrice = mOrderInfo.PriceCurrent(); + datetime expiredAt = mOrderInfo.TimeExpiration(); + double initialVolume = mOrderInfo.VolumeInitial(); + double currentVolume = mOrderInfo.VolumeCurrent(); + double stopLimitPrice = mOrderInfo.PriceStopLimit(); + ENUM_ORDER_TYPE_TIME lifetime = mOrderInfo.TypeTime(); + ENUM_ORDER_TYPE_FILLING filling = mOrderInfo.TypeFilling(); + + // + if (StringLen(symbol) > 0 && symbol != oSymbol) + { + continue; + } + + // + ENUM_TIMEFRAMES oPeriod = ExtractPositionPeriod(comment); + if (period != NULL && period != oPeriod) + { + continue; + } + + // + if (state != NULL && oState != state) + { + continue; + } + + // + // Now Create an instance of XOrder struct and fill it by + // retrieved data, and add it to results ... + XOrder iOrder = {}; + + // + iOrder.sl = sl; + iOrder.tp = tp; + iOrder.type = type; + iOrder.magic = magic; + iOrder.state = oState; + iOrder.ticket = ticket; + iOrder.smybol = oSymbol; + iOrder.setupAt = setupAt; + iOrder.comment = comment; + iOrder.filling = filling; + iOrder.lifetime = lifetime; + iOrder.expiredAt = expiredAt; + iOrder.openPrice = openPrice; + iOrder.pocitionID = pocitionID; + iOrder.executedAt = executedAt; + iOrder.currentPrice = currentPrice; + iOrder.initialVolume = initialVolume; + iOrder.currentVolume = currentVolume; + iOrder.stopLimitPrice = stopLimitPrice; + + // + Add( + iOrder, + result); + } + } + + // + int OrdersCount() + { + return OrdersTotal(); + } + + // + // Cancel Specific Orders ... + bool CancelOrders( + XOrder &orders[]) + { + // + bool result = false; + + // + int ordersCount = ArraySize(orders); + if (ordersCount <= 0) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + bool isDeleted = mTrader.OrderDelete(iOrder.ticket); + if (isDeleted && !result) + { + result = isDeleted; + } + } + + // + return result; + } + + // + // Retrieve All Deals ... + void GetDeals(XDeal &result[]) + { + // + Clean(result); + + // + int dealsCount = HistoryDealsTotal(); + if (dealsCount <= 0) + { + return; + } + + // + for (int i = dealsCount - 1; i >= 0; i--) + { + // + if (!mDealInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mDealInfo.Magic() != mMagicNumber) + { + continue; + } + + // + // Reading Order Info ... + double swap = mDealInfo.Swap(); + ulong magic = mDealInfo.Magic(); + ulong order = mDealInfo.Order(); + ulong ticket = mDealInfo.Ticket(); + datetime time = mDealInfo.Time(); + double price = mDealInfo.Price(); + string symbol = mDealInfo.Symbol(); + double profit = mDealInfo.Profit(); + double volume = mDealInfo.Volume(); + string comment = mDealInfo.Comment(); + ulong positionId = mDealInfo.PositionId(); + ENUM_DEAL_ENTRY entry = mDealInfo.Entry(); + double commission = mDealInfo.Commission(); + ENUM_DEAL_TYPE type = mDealInfo.DealType(); + ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + XDeal iDeal = {}; + + // + iDeal.swap = swap; + iDeal.time = time; + iDeal.type = type; + iDeal.magic = magic; + iDeal.entry = entry; + iDeal.order = order; + iDeal.price = price; + iDeal.ticket = ticket; + iDeal.symbol = symbol; + iDeal.profit = profit; + iDeal.volume = volume; + iDeal.reason = reason; + iDeal.comment = comment; + iDeal.positionId = positionId; + iDeal.commission = commission; + + // + Add( + iDeal, + result); + } + } + + // + // Generate String Representation Of Position's Time Frame ... + string GeneratePositionPeriodComment(ENUM_TIMEFRAMES period) + { + // + string result = mPeriodPrefix + "(" + ToString(period) + ")"; + + // + return result; + } + + // + // Extract Position Time Frame From it's Comment ... + ENUM_TIMEFRAMES ExtractPositionPeriod(string comment) + { + // + ENUM_TIMEFRAMES result = _Period; + + // + if (StringLen(comment) <= 0) + { + return result; + } + + // + string periodStr = ExtractString( + comment, + mPeriodPrefix + "(", + ")"); + if (StringLen(periodStr) <= 0) + { + return result; + } + + // + result = ToPeriod(periodStr); + + // + return result; + } + + // + // Retrieve Last Open Position Ticket ... + ulong GetLastOpenPositionTicket() + { + // + ulong result = 0; + + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + result = PositionGetTicket(PositionsTotal() - 1); + + // + return result; + } + + // + // Retrieve Last Placed Order Ticket ... + ulong GetLastPlacedOrderTicket() + { + // + ulong result = 0; + + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + if (mOrderInfo.SelectByIndex(ordersCount - 1)) + { + result = mOrderInfo.Ticket(); + } + + // + return result; + } + + // + // SUPPORT Signals ... + + // + // Find an Specific Position Has Support Signal Or not ... + bool HasSupport(ulong ticket) + { + // + bool result = false; + + // + int count = PositionsCount(); + if (count <= 1) + { + return result; + } + + // + XPosition position; + result = GetPosition( + position, + ticket); + if (!result) + { + return result; + } + + // + XPosition positions[]; + GetPositions(positions); + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + string supportTicketStr = ExtractParentTicketOfSupport(iPosition.comment); + if (StringLen(supportTicketStr) == 0) + { + continue; + } + + // + ulong parentTicket = (ulong)supportTicketStr; + + // + result = + parentTicket == ticket && + iPosition.ticket != parentTicket; + if (result) + { + break; + } + } + + // + return result; + } + + // + // Get All Support Positions for Specific Position ... + bool GetSupportPositions( + ulong ticket, // Parent Position Ticket + XPosition &supports[] // Holds Result ... + ) + { + // + bool result = false; + + // + Clean(supports); + + // + int count = PositionsCount(); + if (count <= 0) + { + return result; + } + + // + XPosition parentPosition; + bool positionExist = GetPosition( + parentPosition, + ticket); + if (!positionExist) + { + return result; + } + + // + bool hasSupport = HasSupport(ticket); + if (!hasSupport) + { + return result; + } + + // + XPosition positions[]; + GetPositions(positions); + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.ticket == ticket) + { + continue; + } + + // + string pTicketStr = ExtractParentTicketOfSupport(iPosition.comment); + if (StringLen(pTicketStr) <= 0) + { + continue; + } + + // + ulong pTicket = (ulong)pTicketStr; + if (pTicket != ticket) + { + continue; + } + + // + Add( + iPosition, + supports); + } + + // + result = ArraySize(supports) > 0; + + // + return result; + } + + // + bool GetSupportOrders( + ulong ticket, // Parent Position Ticket + XOrder &supports[], // Holds Result ... + string symbol, // Trading Symbol ... + ENUM_TIMEFRAMES period, // Trading TimeFrame ... + ENUM_ORDER_STATE state = NULL // Order State ... + ) + { + // + bool result = false; + + // + Clean(supports); + + // + XOrder orders[]; + GetOrders( + orders, + symbol, + period, + state); + int ordersCount = ArraySize(orders); + result = ordersCount > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + string pTicketStr = ExtractParentTicketOfSupport(iOrder.comment); + if (StringLen(pTicketStr) == 0) + { + continue; + } + + // + ulong pTicket = (ulong)pTicketStr; + if (pTicket != ticket) + { + continue; + } + + // + Add( + iOrder, + supports); + } + + // + result = ArraySize(supports) > 0; + + // + return result; + } + + // + // Generate SL Support Signal ... + bool GenerateSLSupportSignal( + XSignal &signal, // Holds Result .... + ulong ticket, // Specific Position Ticket ... + double slGapPoint = 10, // Which Distance to SL for Enabling Signal ... + double volumeMultiplier = 2 // Support Signals Volume Multiplier ... + ) + { + // + bool result = false; + + // + int count = PositionsCount(); + if (count <= 0) + { + return result; + } + + // + bool hasSupport = HasSupport(ticket); + if (hasSupport) + { + return result; + } + + // + XPosition position; + result = GetPosition( + position, + ticket); + if (!result) + { + return result; + } + + // + bool isLong = + IsLong(position.type); + + // + string symbol = position.symbol; + ENUM_TIMEFRAMES period = ExtractPositionPeriod(position.comment); + double volume = position.volume * volumeMultiplier; + volume = NormalizeVolume( + volume, + symbol); + + ENUM_POSITION_TYPE type = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_STOP; + + // + double slGapPrice = PointToPrice( + symbol, + slGapPoint); + double riskPrice = MathAbs(position.entry - position.sl); + + // + double entry = + isLong + ? position.sl + slGapPrice + : position.sl - slGapPrice; + entry = NormalizePrice(entry, symbol); + + // + double sl = + isLong + ? entry + riskPrice + : entry - riskPrice; + sl = NormalizePrice(sl, symbol); + + // + double tp = + isLong + ? entry - riskPrice + : entry + riskPrice; + tp = NormalizePrice(tp, symbol); + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = symbol; + signal.period = period; + + // + return result; + } + + // + // Close a Position and it's Supports on a Profit ... + bool ClosePositionAndSupports( + ulong ticket, // Position Ticket + double minProfit = 4 // Minimum Profit For Closing + ) + { + // + bool result = false; + + // + if (minProfit <= 0) + { + return result; + } + + // + int count = PositionsCount(); + if (count <= 0) + { + return result; + } + + // + XPosition position; + bool isExist = GetPosition( + position, + ticket); + if (!isExist) + { + return result; + } + + // + bool hasSupport = HasSupport(ticket); + if (!hasSupport) + { + return result; + } + + // + XPosition supports[]; + hasSupport = GetSupportPositions( + ticket, + supports); + int supportsCount = ArraySize(supports); + if (!hasSupport || supportsCount <= 0) + { + return result; + } + + // + double profitSummary = 0; + for (int i = 0; i < supportsCount; i++) + { + // + XPosition iSupport = supports[i]; + + // + profitSummary += iSupport.profit; + } + + // + result = profitSummary > 0 && profitSummary >= minProfit; + if (!result) + { + return result; + } + + // + Add( + position, + supports); + + // + string comment = "Close Position (" + (string)ticket + ") and it's Supports in Profit: " + (string)profitSummary + " ..."; + ClosePositions( + supports, + comment); + + // + if (result) + { + LogMessage(comment); + } + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... + + // + // EVENTS Handlers Notifiers ... + + // + // STATE ... + void NotifyTradeStateChangeEvent(const XOnTradeHandlerState &state) + { + // + int count = ArraySize(mTradeStateChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + OnTradeStateChanged iHandler = mTradeStateChangedEventHandlers[i]; + iHandler(state); + } + } + + // + // DEALS ... + void NotifyDealsChangeEvent(int changes) + { + // + int count = ArraySize(mDealsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + OnDealsChanged iHandler = mDealsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // ORDERS ... + void NotifyOrdersChangeEvent(int changes) + { + // + int count = ArraySize(mOrdersChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + OnOrdersChanged iHandler = mOrdersChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // POSITIONS ... + void NotifyPositionsChangeEvent(int changes) + { + // + int count = ArraySize(mPositionsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + OnPositionsChanged iHandler = mPositionsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // TPSL ... + + // + void NotifyStopLossEvent(const XDeal &deal) + { + // + int count = ArraySize(mStopLossEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + OnStopLoss iHandler = mStopLossEventHandlers[i]; + iHandler(deal); + } + } + + // + void NotifyTakeProfitEvent(const XDeal &deal) + { + // + int count = ArraySize(mTakeProfitEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + OnTakeProfit iHandler = mTakeProfitEventHandlers[i]; + iHandler(deal); + } + } + +private: + // + // using deviation, it must be in Point ... + int mSlippage; + + // + // using magic number ... + ulong mMagicNumber; + + // + // using CTrade instance ... + XSCTradeBase mTrader; + + // + // Deals Info ... + CDealInfo mDealInfo; + + // + // Order Info ... + COrderInfo mOrderInfo; + + // + // using PositionInfo instance ... + CPositionInfo mPositionInfo; + + // + // ADDITIONAL Data ... + + // + string mPeriodPrefix; + + // + // START Trade Processing ... + // + + // + int mDaysForRead; + + // + // set the limits of the trade history on the global scope ... + + // + // // start date for trade history in cache ... + datetime mStartDate; + + // + // end date for trade history in cache ... + datetime mEndDate; + + // + // global OnTrade counters ... + + // + // number of active orders ... + int mOrdersCount; + + // + // number of open positions ... + int mPositionsCount; + + // + // number of deals in the trade history cache ... + int mDealsCount; + + // + // number of orders in the trade history cache ... + int mHistoryOrdersCount; + + // + // flag of counter relevance ... + bool mScanStarted; + + // + // Check Statrt Date In Trade History ... + void CheckStartDateInTradeHistory() + { + // + // initial interval, if we were to start working right now .. + datetime currStart = TimeCurrent() - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + + // + // make sure that the start limit of the trade history has not gone + // more than 1 day over the intended date ... + if (currStart - mStartDate > PeriodSeconds(PERIOD_D1)) + { + // + // correct the start date of history to be loaded in the cache ... + mStartDate = currStart; + + // + // now reload the trade history for the updated interval ... + HistorySelect(mStartDate, mEndDate); + + // + // correct the deal and order counters in history for further comparison + mHistoryOrdersCount = HistoryOrdersTotal(); + mDealsCount = HistoryDealsTotal(); + } + } + + // + // Process On Trade Context ... + void ProcessOnTradeContext( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + mEndDate = TimeCurrent(); + + // + ResetLastError(); + + // + // download trading history from the specified interval to the program cache ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current values ... + int currOrders = OrdersTotal(); + int currPositions = PositionsTotal(); + int currDeals = HistoryDealsTotal(); + int currHistoryOrders = HistoryOrdersTotal(); + + // + // Orders ... + // check if the number of active orders has been changed ... + if (currOrders != mOrdersCount) + { + // + // number of active orders has been changed ... + result.hasNewOrder = true; + result.newOrders = currOrders - mOrdersCount; + + // + // update the value ... + mOrdersCount = currOrders; + } + + // + // Positions ... + // changes in the number of open positions ... + if (currPositions != mPositionsCount) + { + // + // number of open positions has been changed ... + result.hasNewPosition = true; + result.newPositions = currPositions - mPositionsCount; + + // + // update the value ... + mPositionsCount = currPositions; + } + + // + // Deals ... + // changes in the number of deals in the trade history cache ... + if (currDeals != mDealsCount) + { + // + // number of deals in the trade history cache has been changed ... + result.hasNewDeal = true; + result.newDeals = currDeals - mDealsCount; + + // + // update the value ... + mDealsCount = currDeals; + } + + // + // History Orders ... + // changes in the number of history orders in the trade history cache ... + if (currHistoryOrders != mHistoryOrdersCount) + { + // + // number of history orders in the trade history cache has been changed ... + result.hasNewHistoryOrder = true; + result.newHistoryOrders = currHistoryOrders - mHistoryOrdersCount; + + // + // update the value ... + mHistoryOrdersCount = currHistoryOrders; + } + + // + // checking if it is necessary to change the limits of the trade history to be requested in cache ... + CheckStartDateInTradeHistory(); + } + + // + // Reset On Trade Scanner Context ... + void ResetOnTradeContext() + { + // + mEndDate = TimeCurrent(); + mStartDate = mEndDate - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + } + + // + // Initial Context Of Trade Scanner ... + void InitOnTradeContext() + { + // + ResetLastError(); + + // + mOrdersCount = OrdersTotal(); + mPositionsCount = PositionsTotal(); + + // + // load history ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current value ... + mDealsCount = HistoryDealsTotal(); + mHistoryOrdersCount = HistoryOrdersTotal(); + + // + mScanStarted = true; + } + + // + // Deals Changed Event Handlers ... + OnDealsChanged mDealsChangedEventHandlers[]; + + // + // Orders Changed Event Handlers ... + OnOrdersChanged mOrdersChangedEventHandlers[]; + + // + // Positions Changed Event Handlers ... + OnPositionsChanged mPositionsChangedEventHandlers[]; + + // + // Trade State Changed Event Handlers ... + OnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + // TPSL ... + OnStopLoss mStopLossEventHandlers[]; + OnTakeProfit mTakeProfitEventHandlers[]; + + // + // END Trade Processing ... + // +}; + +// +// START Usefull Functions ... +// + +// +// Add Specific XPosition to Specified Array ... +void Add( + XDeal &item, + XDeal &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XOrder &item, + XOrder &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XPosition &item, + XPosition &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Clear All Items Inside Array ... +void Clean(XDeal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clean(XOrder &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void Clean(XPosition &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +// Generate Identifier Tag ... +string GenerateTag(XSignal &info) +{ + // + string result = ""; + + // + result = info.symbol + "," + ToString(info.period); + + // + return result; +} + +// +// Convert Position to Signal ... +XSignal ToSignalInfo( + XPosition &position) +{ + // + XSignal result; + + // + result.tp = position.tp; + result.sl = position.sl; + result.type = position.type; + result.entry = position.entry; + result.symbol = position.symbol; + result.period = position.period; + result.volume = position.volume; + + // + return result; +} + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/Experts/x-saherelm.xea.ex5 b/MQLTestWorkspace/Experts/x-saherelm.xea.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..009ab5f862b5e839ce80c44677434ef5e2955334 GIT binary patch literal 447484 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