From efa8818dbba4491d52d02270aca79cfb4982df60 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 25 Jan 2024 04:08:38 +0330 Subject: [PATCH] Initial Commit ... --- .gitkeep | 0 .../EX5/Experts/x-saherelm.test.ea.ex5 | Bin 0 -> 201454 bytes .../x-saherelm.xchlh.oscillator.ex5 | Bin 0 -> 48004 bytes .../x-saherelm.xchma.oscillator.ex5 | Bin 0 -> 49154 bytes .../Indicators/x-saherelm.xobd.oscillator.ex5 | Bin 0 -> 11052 bytes .../Indicators/x-saherelm.xrsi.oscillator.ex5 | Bin 0 -> 17482 bytes .../Indicators/x-saherelm.xtd.oscillator.ex5 | Bin 0 -> 18384 bytes .../Indicators/x-saherelm.xtm.indicator.ex5 | Bin 0 -> 12832 bytes .../EX5/Libraries/x-saherelm.alert.lib.ex5 | Bin 0 -> 7392 bytes .../EX5/Libraries/x-saherelm.class.lib.ex5 | Bin 0 -> 7564 bytes .../EX5/Libraries/x-saherelm.common.lib.ex5 | Bin 0 -> 4944 bytes .../EX5/Libraries/x-saherelm.draw.lib.ex5 | Bin 0 -> 6304 bytes .../EX5/Libraries/x-saherelm.http.lib.ex5 | Bin 0 -> 4574 bytes .../EX5/Libraries/x-saherelm.log.lib.ex5 | Bin 0 -> 5906 bytes .../EX5/Libraries/x-saherelm.models.lib.ex5 | Bin 0 -> 4932 bytes .../EX5/Libraries/x-saherelm.nn.lib.ex5 | Bin 0 -> 4374 bytes ...x-saherelm.xchlh.oscillator.helper.lib.ex5 | Bin 0 -> 33778 bytes ...x-saherelm.xchma.oscillator.helper.lib.ex5 | Bin 0 -> 32648 bytes .../x-saherelm.xobd.oscillator.helper.lib.ex5 | Bin 0 -> 6726 bytes .../x-saherelm.xrsi.oscillator.helper.lib.ex5 | Bin 0 -> 14368 bytes .../x-saherelm.xtd.oscillator.helper.lib.ex5 | Bin 0 -> 7998 bytes ...saherelm.xtest.provider.indicators.lib.ex5 | Bin 0 -> 79708 bytes .../x-saherelm.xtest.provider.inputs.lib.ex5 | Bin 0 -> 11266 bytes .../x-saherelm.xtest.provider.lib.ex5 | Bin 0 -> 83324 bytes .../x-saherelm.xtm.indicator.helper.lib.ex5 | Bin 0 -> 8864 bytes .../MQ5/Experts/x-saherelm.test.ea.mq5 | 192 + .../x-saherelm.xchlh.oscillator.mq5 | 838 + .../x-saherelm.xchma.oscillator.mq5 | 1153 ++ .../Indicators/x-saherelm.xobd.oscillator.mq5 | 328 + .../Indicators/x-saherelm.xrsi.oscillator.mq5 | 358 + .../Indicators/x-saherelm.xtd.oscillator.mq5 | 465 + .../Indicators/x-saherelm.xtm.indicator.mq5 | 349 + .../MQ5/Libraries/x-saherelm.alert.lib.mq5 | 197 + .../MQ5/Libraries/x-saherelm.class.lib.mq5 | 3991 +++++ .../MQ5/Libraries/x-saherelm.common.lib.mq5 | 3584 ++++ .../MQ5/Libraries/x-saherelm.draw.lib.mq5 | 2220 +++ .../MQ5/Libraries/x-saherelm.http.lib.mq5 | 177 + .../MQ5/Libraries/x-saherelm.log.lib.mq5 | 161 + .../MQ5/Libraries/x-saherelm.models.lib.mq5 | 187 + .../MQ5/Libraries/x-saherelm.nn.lib.mq5 | 258 + ...x-saherelm.xchlh.oscillator.helper.lib.mq5 | 925 ++ ...x-saherelm.xchma.oscillator.helper.lib.mq5 | 1535 ++ .../x-saherelm.xobd.oscillator.helper.lib.mq5 | 417 + .../x-saherelm.xrsi.oscillator.helper.lib.mq5 | 424 + .../x-saherelm.xtd.oscillator.helper.lib.mq5 | 917 ++ ...saherelm.xtest.provider.indicators.lib.mq5 | 2316 +++ .../x-saherelm.xtest.provider.inputs.lib.mq5 | 82 + .../x-saherelm.xtest.provider.lib.mq5 | 1073 ++ .../x-saherelm.xtm.indicator.helper.lib.mq5 | 319 + EURUSD-5M-V0.1/Version.txt | 1 + README.md | 11 + XAUUSD-15M-V1.0/Ex4/Experts/x-saherelm.ea.ex4 | Bin 0 -> 122876 bytes .../Ex4/Indicators/x-saherelm.ma.ex4 | Bin 0 -> 9556 bytes .../Ex4/Indicators/x-saherelm.xrange.ex4 | Bin 0 -> 10704 bytes .../Ex4/Indicators/x-saherelm.xtpow.ex4 | Bin 0 -> 12694 bytes .../Ex4/Libraries/x-saherelm.dialog.ex4 | Bin 0 -> 21464 bytes .../Ex4/Libraries/x-saherelm.draw.lib.ex4 | Bin 0 -> 7218 bytes .../Libraries/x-saherelm.indicator.lib.ex4 | Bin 0 -> 8046 bytes .../Ex4/Libraries/x-saherelm.lib.ex4 | Bin 0 -> 7270 bytes .../Ex4/Libraries/x-saherelm.log.lib.ex4 | Bin 0 -> 5064 bytes .../Ex4/Libraries/x-saherelm.models.lib.ex4 | Bin 0 -> 4890 bytes .../Ex4/Libraries/x-saherelm.signal.lib.ex4 | Bin 0 -> 19232 bytes .../Ex4/Libraries/x-saherelm.x.signal.lib.ex4 | Bin 0 -> 11452 bytes .../Libraries/x-saherelm.xr.signal.lib.ex4 | Bin 0 -> 10450 bytes .../Libraries/x-saherelm.xtpw.signal.lib.ex4 | Bin 0 -> 11350 bytes XAUUSD-15M-V1.0/MQ4/Experts/x-saherelm.ea.mq4 | 1116 ++ .../MQ4/Indicators/x-saherelm.ma.mq4 | 173 + .../MQ4/Indicators/x-saherelm.xrange.mq4 | 294 + .../MQ4/Indicators/x-saherelm.xtpow.mq4 | 275 + .../MQ4/Libraries/x-saherelm.dialog.mq4 | 110 + .../MQ4/Libraries/x-saherelm.draw.lib.mq4 | 2010 +++ .../Libraries/x-saherelm.indicator.lib.mq4 | 450 + .../MQ4/Libraries/x-saherelm.lib.mq4 | 1695 ++ .../MQ4/Libraries/x-saherelm.log.lib.mq4 | 91 + .../MQ4/Libraries/x-saherelm.models.lib.mq4 | 155 + .../MQ4/Libraries/x-saherelm.signal.lib.mq4 | 1756 ++ .../MQ4/Libraries/x-saherelm.x.signal.lib.mq4 | 1063 ++ .../Libraries/x-saherelm.xr.signal.lib.mq4 | 1142 ++ .../Libraries/x-saherelm.xtpw.signal.lib.mq4 | 1332 ++ XAUUSD-15M-V1.0/Version.txt | 1 + XEU5-0/Classes/.gitkeep | 0 XEU5-0/Classes/x-saherelm.class.lib.mq5 | 10286 ++++++++++++ XEU5-0/Classes/x-saherelm.nn.lib.mq5 | 258 + XEU5-0/Documents/.gitkeep | 0 XEU5-0/Documents/Reports/.gitkeep | 0 XEU5-0/Documents/Settings/.gitkeep | 0 XEU5-0/Documents/Settings/xeu5ea.set | Bin 0 -> 7562 bytes XEU5-0/Documents/Settings/xeu5ea.vbb.set | Bin 0 -> 7562 bytes XEU5-0/Documents/Settings/xeu5ea.vbd.set | Bin 0 -> 7562 bytes .../Settings/xeu5ea_just_xtam_and_xstfi.set | Bin 0 -> 18988 bytes ...5ea_just_xtam_and_xstfi_xtam_signaller.set | Bin 0 -> 18988 bytes .../Settings/xeu5ea_xtam_signaller.final.set | Bin 0 -> 18990 bytes .../xeu5ea_xtam_signaller_longs.final.set | Bin 0 -> 18992 bytes .../xeu5ea_xtam_signaller_shorts.final.set | Bin 0 -> 18992 bytes .../Settings/xeu5ea_xtsfi_signaller.final.set | Bin 0 -> 7576 bytes .../xeu5ea_xtsfi_signaller_longs.final.set | Bin 0 -> 8324 bytes .../xeu5ea_xtsfi_signaller_shorts.final.set | Bin 0 -> 7578 bytes XEU5-0/Documents/Settings/xts.tpl | Bin 0 -> 7966 bytes XEU5-0/Experts/.gitkeep | 0 XEU5-0/Experts/x-saherelm.xeu5.ea.ex5 | Bin 0 -> 191218 bytes XEU5-0/Experts/x-saherelm.xeu5.ea.mq5 | 347 + XEU5-0/Helpers/.gitkeep | 0 .../x-saherelm.xama.indicator.helper.lib.mq5 | 607 + ...x-saherelm.xchlh.oscillator.helper.lib.mq5 | 1032 ++ ...x-saherelm.xchma.oscillator.helper.lib.mq5 | 2229 +++ .../x-saherelm.xfi.oscillator.helper.lib.mq5 | 358 + .../x-saherelm.xlh.indicator.helper.lib.mq5 | 668 + .../x-saherelm.xobd.indicator.helper.lib.mq5 | 249 + .../x-saherelm.xrsi.oscillator.helper.lib.mq5 | 433 + .../x-saherelm.xtd.oscillator.helper.lib.mq5 | 931 ++ .../x-saherelm.xtm.indicator.helper.lib.mq5 | 598 + .../x-saherelm.xts.oscillator.helper.lib.mq5 | 1179 ++ XEU5-0/Indicators/.gitkeep | 0 .../Indicators/x-saherelm.xama.indicator.mq5 | 353 + .../x-saherelm.xchlh.oscillator.mq5 | 753 + .../x-saherelm.xchma.oscillator.mq5 | 1153 ++ .../Indicators/x-saherelm.xfi.oscillator.mq5 | 317 + .../Indicators/x-saherelm.xlh.indicator.mq5 | 346 + .../Indicators/x-saherelm.xobd.indicator.mq5 | 390 + .../Indicators/x-saherelm.xrsi.oscillator.mq5 | 397 + .../Indicators/x-saherelm.xtd.oscillator.mq5 | 465 + .../Indicators/x-saherelm.xtm.indicator.mq5 | 349 + .../Indicators/x-saherelm.xts.oscillator.mq5 | 558 + XEU5-0/Libraries/.gitkeep | 0 XEU5-0/Libraries/x-saherelm.alert.lib.mq5 | 200 + XEU5-0/Libraries/x-saherelm.common.lib.mq5 | 4429 +++++ XEU5-0/Libraries/x-saherelm.draw.lib.mq5 | 2345 +++ XEU5-0/Libraries/x-saherelm.http.lib.mq5 | 177 + XEU5-0/Libraries/x-saherelm.log.lib.mq5 | 261 + XEU5-0/Libraries/x-saherelm.models.lib.mq5 | 438 + XEU5-0/Providers/.gitkeep | 0 ...-saherelm.xeu5.provider.indicators.lib.mq5 | 9201 +++++++++++ .../x-saherelm.xeu5.provider.inputs.lib.mq5 | 321 + .../x-saherelm.xeu5.provider.lib.mq5 | 1370 ++ XEU5-0/Settings/.gitkeep | 0 XEU5-0/Templates/.gitkeep | 0 .../FundedNext.XEU5.Guarded.Signals.txt | 548 + XEU5/Classes/.gitkeep | 0 XEU5/Classes/x-saherelm.class.lib.mq5 | 10316 ++++++++++++ XEU5/Classes/x-saherelm.nn.lib.mq5 | 258 + XEU5/Classes/x-saherelm.provider.lib.mq5 | 4430 +++++ XEU5/Documents/.gitkeep | 0 XEU5/Documents/Reports/.gitkeep | 0 XEU5/Documents/Settings/.gitkeep | 0 XEU5/Experts/.gitkeep | 0 XEU5/Experts/x-saherelm.xeu5.ea.mq5 | 347 + XEU5/Helpers/.gitkeep | 0 .../x-saherelm.xama.indicator.helper.lib.mq5 | 607 + ...x-saherelm.xchlh.oscillator.helper.lib.mq5 | 1032 ++ ...x-saherelm.xchma.oscillator.helper.lib.mq5 | 2229 +++ .../x-saherelm.xfi.oscillator.helper.lib.mq5 | 358 + .../x-saherelm.xlh.indicator.helper.lib.mq5 | 668 + .../x-saherelm.xobd.indicator.helper.lib.mq5 | 249 + .../x-saherelm.xrsi.oscillator.helper.lib.mq5 | 433 + .../x-saherelm.xtd.oscillator.helper.lib.mq5 | 931 ++ .../x-saherelm.xtm.indicator.helper.lib.mq5 | 598 + .../x-saherelm.xts.oscillator.helper.lib.mq5 | 1179 ++ XEU5/Indicators/.gitkeep | 0 XEU5/Indicators/x-saherelm.xama.indicator.mq5 | 353 + .../x-saherelm.xchlh.oscillator.mq5 | 753 + .../x-saherelm.xchma.oscillator.mq5 | 1153 ++ XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 | 317 + XEU5/Indicators/x-saherelm.xlh.indicator.mq5 | 346 + XEU5/Indicators/x-saherelm.xobd.indicator.mq5 | 390 + .../Indicators/x-saherelm.xrsi.oscillator.mq5 | 397 + XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 | 465 + XEU5/Indicators/x-saherelm.xtm.indicator.mq5 | 349 + XEU5/Indicators/x-saherelm.xts.oscillator.mq5 | 558 + XEU5/Libraries/.gitkeep | 0 XEU5/Libraries/x-saherelm.alert.lib.mq5 | 200 + XEU5/Libraries/x-saherelm.common.lib.mq5 | 4429 +++++ XEU5/Libraries/x-saherelm.draw.lib.mq5 | 2345 +++ XEU5/Libraries/x-saherelm.http.lib.mq5 | 177 + XEU5/Libraries/x-saherelm.log.lib.mq5 | 261 + XEU5/Libraries/x-saherelm.models.lib.mq5 | 438 + XEU5/Providers/.gitkeep | 0 ...-saherelm.xeu5.provider.indicators.lib.mq5 | 13599 ++++++++++++++++ .../x-saherelm.xeu5.provider.inputs.lib.mq5 | 280 + .../x-saherelm.xeu5.provider.lib.mq5 | 1370 ++ XEU5/Settings/.gitkeep | 0 XEU5/Settings/xeu5.longs.vbb.set | Bin 0 -> 7584 bytes XEU5/Settings/xeu5.shorts.vbb.set | Bin 0 -> 7584 bytes XEU5/Settings/xeu5.vbb.set | Bin 0 -> 7566 bytes XEU5/Templates/.gitkeep | 0 184 files changed, 129502 insertions(+) create mode 100644 .gitkeep create mode 100644 EURUSD-5M-V0.1/EX5/Experts/x-saherelm.test.ea.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xchlh.oscillator.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xchma.oscillator.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xobd.oscillator.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xrsi.oscillator.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xtd.oscillator.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xtm.indicator.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.alert.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.class.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.common.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.draw.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.http.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.log.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.models.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.nn.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xchma.oscillator.helper.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xobd.oscillator.helper.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtd.oscillator.helper.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtest.provider.indicators.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtest.provider.inputs.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtest.provider.lib.ex5 create mode 100644 EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtm.indicator.helper.lib.ex5 create mode 100644 EURUSD-5M-V0.1/MQ5/Experts/x-saherelm.test.ea.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xobd.oscillator.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.class.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.common.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.http.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.log.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.models.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.nn.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xobd.oscillator.helper.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.indicators.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.inputs.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.lib.mq5 create mode 100644 EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 EURUSD-5M-V0.1/Version.txt create mode 100644 README.md create mode 100644 XAUUSD-15M-V1.0/Ex4/Experts/x-saherelm.ea.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Indicators/x-saherelm.ma.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Indicators/x-saherelm.xrange.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Indicators/x-saherelm.xtpow.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.dialog.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.draw.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.indicator.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.log.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.models.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.signal.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.x.signal.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.xr.signal.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.xtpw.signal.lib.ex4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Experts/x-saherelm.ea.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.ma.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xrange.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xtpow.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.dialog.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.draw.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.indicator.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.log.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.models.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.signal.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.x.signal.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xr.signal.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xtpw.signal.lib.mq4 create mode 100644 XAUUSD-15M-V1.0/Version.txt create mode 100644 XEU5-0/Classes/.gitkeep create mode 100644 XEU5-0/Classes/x-saherelm.class.lib.mq5 create mode 100644 XEU5-0/Classes/x-saherelm.nn.lib.mq5 create mode 100644 XEU5-0/Documents/.gitkeep create mode 100644 XEU5-0/Documents/Reports/.gitkeep create mode 100644 XEU5-0/Documents/Settings/.gitkeep create mode 100644 XEU5-0/Documents/Settings/xeu5ea.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea.vbb.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea.vbd.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_just_xtam_and_xstfi.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_just_xtam_and_xstfi_xtam_signaller.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_xtam_signaller.final.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_xtam_signaller_longs.final.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_xtam_signaller_shorts.final.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller.final.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller_longs.final.set create mode 100644 XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller_shorts.final.set create mode 100644 XEU5-0/Documents/Settings/xts.tpl create mode 100644 XEU5-0/Experts/.gitkeep create mode 100644 XEU5-0/Experts/x-saherelm.xeu5.ea.ex5 create mode 100644 XEU5-0/Experts/x-saherelm.xeu5.ea.mq5 create mode 100644 XEU5-0/Helpers/.gitkeep create mode 100644 XEU5-0/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 XEU5-0/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 XEU5-0/Indicators/.gitkeep create mode 100644 XEU5-0/Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 XEU5-0/Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 XEU5-0/Libraries/.gitkeep create mode 100644 XEU5-0/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 XEU5-0/Libraries/x-saherelm.common.lib.mq5 create mode 100644 XEU5-0/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 XEU5-0/Libraries/x-saherelm.http.lib.mq5 create mode 100644 XEU5-0/Libraries/x-saherelm.log.lib.mq5 create mode 100644 XEU5-0/Libraries/x-saherelm.models.lib.mq5 create mode 100644 XEU5-0/Providers/.gitkeep create mode 100644 XEU5-0/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 create mode 100644 XEU5-0/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 create mode 100644 XEU5-0/Providers/x-saherelm.xeu5.provider.lib.mq5 create mode 100644 XEU5-0/Settings/.gitkeep create mode 100644 XEU5-0/Templates/.gitkeep create mode 100644 XEU5-0/Templates/FundedNext.XEU5.Guarded.Signals.txt create mode 100644 XEU5/Classes/.gitkeep create mode 100644 XEU5/Classes/x-saherelm.class.lib.mq5 create mode 100644 XEU5/Classes/x-saherelm.nn.lib.mq5 create mode 100644 XEU5/Classes/x-saherelm.provider.lib.mq5 create mode 100644 XEU5/Documents/.gitkeep create mode 100644 XEU5/Documents/Reports/.gitkeep create mode 100644 XEU5/Documents/Settings/.gitkeep create mode 100644 XEU5/Experts/.gitkeep create mode 100644 XEU5/Experts/x-saherelm.xeu5.ea.mq5 create mode 100644 XEU5/Helpers/.gitkeep create mode 100644 XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 XEU5/Indicators/.gitkeep create mode 100644 XEU5/Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 XEU5/Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 XEU5/Libraries/.gitkeep create mode 100644 XEU5/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 XEU5/Libraries/x-saherelm.common.lib.mq5 create mode 100644 XEU5/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 XEU5/Libraries/x-saherelm.http.lib.mq5 create mode 100644 XEU5/Libraries/x-saherelm.log.lib.mq5 create mode 100644 XEU5/Libraries/x-saherelm.models.lib.mq5 create mode 100644 XEU5/Providers/.gitkeep create mode 100644 XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 create mode 100644 XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 create mode 100644 XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 create mode 100644 XEU5/Settings/.gitkeep create mode 100644 XEU5/Settings/xeu5.longs.vbb.set create mode 100644 XEU5/Settings/xeu5.shorts.vbb.set create mode 100644 XEU5/Settings/xeu5.vbb.set create mode 100644 XEU5/Templates/.gitkeep diff --git a/.gitkeep b/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/EURUSD-5M-V0.1/EX5/Experts/x-saherelm.test.ea.ex5 b/EURUSD-5M-V0.1/EX5/Experts/x-saherelm.test.ea.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..107055b8c3356c0897ed861f4586269c997a5860 GIT binary patch literal 201454 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 D17;-} literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xchlh.oscillator.ex5 b/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xchlh.oscillator.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..619de7708e427b11442ebbc93ff9a8c4945effa9 GIT binary patch literal 48004 zcmdS9Q>-{n>@Rq1+qP}nwr$(CZQHhO`+SdW+xz=(b~m~EaNlnyZKjw>+CEG&{fKI? zf;a*^!V7=^AOHXW0vv+?{4ccdB0@xJ>hCpajcGnXoBj2_IR8_~{{M#mSO0(R@qz#V z_#YMkf&EYZuLR}#2q2Bs>ViYt0YxB!$3!nD$=XF7qv6dAE$%F0Yx+N@ zgaPaU8~{84oB%8V%mFL_TmT3Fm;f05V`c!F|MtoNhW}Yj|MQCi*Z|o6XORR@`A-V} zXS4e+`hPtCC)59A?DAg)oB_B1=>J>J|6jhQ|98H0|JCLH>)#!|NEf- zjd#m$N2HE_n)n2>2yjC67V{7b)SAI*053^{hK8m0afw3}(i2f9v%yF~4@D*yMx9o< z&VD$bPM9e+PDmMH#K<+R_~rKCji1%2^P_}WGgF5p(5fGm%cmf-{WjUl5`qO#DIL7V z+dW8XBZE{j$G`nv-#L*H6Sz&|*W>}|bEj~ToasPyH}bKUGkv!Tx-ov2i>dV(5xg7l zcyF*xq(+8Fj zlz_{R5Ajb@$^+BWM21)DTYSs(!G_MZ$G;0|NF!a{jFeX-i?7Gxi^9pji)n&v57dLQ z$?6kLu82)K`>FXAjI0?MnvJbKhXCDjc!)|lf!RAFiivO_W z`$KlYuvxn=TJ*K1(Nznb_=mh^4+XyWfjCW7o-dGdsN$ zwLobesDyvu{sVQIW3)=0;#69~L?Kh{C(>>XXFT}3#;rbV-_-vcDJ5I>JW5gV0Ry0z zKubcCgxpJ|3q6;Y-@R*=faV7*0Q1jXp;50JHXs zC{4o?Q2P2g67UdeJzDPIagVz76!>9I$bDONbbU3MU`DDRZ{~y2LtI$nNma~_I#W43 zRmg{{5h|*Tc0vR_Jrp+wtdMm8_=|;#79+Mr@y#N>r3>Qb8oe`SM^uT#;dC$X^L&`5 zctEJ@$BqR$ko+bU%4H+Lw-_5lz5pz{zo_x=ao_tjba{)EIqb=2v%SWQin@FF4UYrj z&l-RXuQunZ#CLo24xbD=Pj(8_Ix|MP^WNjvq(_t{lyP7qoE-BojnLOvu`{NG;5JmB zd^Pk$Y;PLA_!K6#V|Bob9})vF0)k4+If9>Ay%V2$`Av#ov$j|7Dge2!yE7Bd_arjn z3_m)eD9?p4$qU68I z#vj}DKpSZ-rKo(u0Zvfm#U8^1*W2E8N2(UU8*Sp298O5$my7`n$f7hZ3?pSA*(;`n z$P(-zCx83DYF`a`Vjo3foqEr(G^S97stVP&_Yyl%BY%7Gm65TBU_5^#@@UkNIaK)* z!|7);#q8n;F(}NClFB_m+6Qjb7fi*ZRRWWg5j1h1{(Az|tX(F&NnEUgBKgdaw56A| zaZKclz6IhjR^dAcL{xI|d$v-ck(sx!HZ4{@L4fW(8 z&*afNjpJs({)DQY79PFB<^kG?ZV#8RbiDPAW7$5|d<;xK@p{>UaI1!E$Hdx~>5dBH zifTo6&d}KM89SCvQ};P6xO+MKj`c9s?&fjP?4cugP$g*lWkYZ@u`-BKsy_5sDjBS# z;v(x49>CI}^L(4qu?OKx16>6~{I(b2DY84KHwhCG-5GbUvip|VDQ@t{1#VSnfW3PL z>rtY66%lf<7%7^}=dHq&=dt0n*PhmoU&k8fCv)@ZDfo8B;b7yNK;*Q-}~ zz7Ul{j^2+QJjk|fMZ^u9BH~lrB*q~73!9_A_KRN>dN*xfnOzwXTpc+^j9#JXY%4QoXRV@J^)b^!lSK@Rjo z%7b3Roq6=M^3Bara2C?ZfKS|bdqbs2rkPD7f^fEb3oF#u-96pSZqps8IAZX-lTQq4 z`7BL2>7l|OJ%O>_QFC1VKh_iR@@^sPMFGc3Am|DvgrvnR+{ZlPSb(2d=%0JwR7--H z?VmDv1OSf!?~g_GwvJ2UZqcvA!r!k*mVgyf2z$1c@$ejGd6PDqL#GzGZ2nk<+UJut zw#^}#&hRph_F`hMjCLAnfSWNdoL?B^X32`EXJxT+r9-Flm9Tk_%+vmuzH1gT0;$nnAzI$FI_jmAD(nxS6X(MYSEm!$2>00opk#`d$fe-z zafka6bXC~^ zW`(mZ?n||b-hgw6=T)rRgu=JU=_wIWu{8)-S{@#SxVz~|oY@#`gpZ^@Pf{Rkx1zLS zIqW)#e(l8;a2yj_V=Bb`_!i(EJd&L329T{*6u43n?JHb;dl>M?9Vio8Fs2gcRW>=SYb}mpwtr5%_>~YSKQ)`GqQ#A)QnN%C5lAjY>q<+5gB<( z@rm?lsYhmDUWBmJ`|aQ)2d9(~H{M1&X_C}AcFH{EQ%{RA)Ekz`onAzsMiL`=%t$zOGLrXYwHK4f^mkxX=U);>A?tI!cyG1NKX{@ ze~V(=4^0ayh8WN2K+`SXgwLO0cEaG- z)^cx*pS1@i8udf_c5K=5c4@quzVod<-`|$I#a}xYUoWu`AnyeGVVqJ1-&0cal;ixDyOat zryM7`C^ZHMb=bP4dNd^RZ2IH#FG-OaEq0OD?tD(19_0t~;0PuKq-`OVX!I|DiVZ() z$_|~f=2jLp$a}t*)6#8BKVhuU`bJCZHI6K7Ou)XDJ{3~LieD5zajCNKY;7McbMW-yqU_jsaqEG zjF}${R2h&Oop1()0y&3sUa+v&6R!Ue$NdGvm~-?!(}@p?fcP8YK6~Au3P5fB~TE=~IF7C)|fLq~BtJw$dnf3B{G0TA-;X*k7DIC<h-bLod z-nl1)9i@N8twND6hfvs9058s8L)b%)uWnM}>&F!<+SYCUhe?xD%WtYUP;aHV<7QSj z=G*zRA0;s87Vq!sss3X738FpO3~I)bZi$`C44QSej{BR=I0z4rYBr~VILKg`t942m zHD_lYH11U)6#eAw`2pgtZ`4qjU5)xbCFph|N8bBvyREu;HT=;kY>A0Gp)@U-C+1lu zx)(kn{cx4@xXAB7lg@OAl~nFgt0(Kj<1$Bu!>>KeZjpY+-6R93KN=FCsy>Km>-gDr z<8E!JE^3uD(@KbQ%jyzjiLq90AY7s>n6G5Aly(C|KVx8+K5PVpJR$-w11EuwxA$R^q4tpEUnJ6RHDEw{}x-j0rN?u4a zyek@l%X)MX4BRC&qixia3qPq)#7{II?No9`D?wvF1*bwd2+Sw}4Jv$l{B;RyZt&8y z%i<*pNO&B=1iDEVW0rUp=znisRAD1-IfeF~4Y{YoI%V)TFx3EKgGf>ZbdOK&JkqIZ z{>jH3+x{#XA-UMqwIQCA^prMh)bsI)UIE)cRxVWWKybCixzP8Hl}g;)M5HrbxFfK6 zkA=%F8b`J7>d|`iSamlHa!la5wnprvq3v$CyAA2iLn=1KkpNUaTFrVXn8M@TwzfDM zihcTi^go?7l=_N#;e4|}bKIu7(ARNH%INAyXXrjKMZD@OG$g^s>M48-s-E5US(xB! z0G&82rY#*U1sG=>7;A4127#96)4LuO^rE$*7an<75qtvz*B^1QbX3h$7@hnuw+iG7 z!9pJ0h9kV%4Nj<(B8%*r6+@5LCkQA@92d#9Fyfht>>By-zybc}fl3?k)w(D@tP;r@ zvii$q?ajp=%R&2qsqqh&83)K1;K%M!F@&(m0CocHMU0xCj^XM5mg6(S3|j9QBaXQA zgcSStBDS}BtApgft3D^rGikyQHPb?gzELwrW!BQLWndCXqrjj4LcEDHW*(uTnMW_d zorP{*Fp%41Tkz|AP!P?pNTpH!OpTZCn9V-t2kt3B!NMTMmvOw$_lDK$}(Awb1f)EOXwOG-dJZ zhZ&g$w`jKbh|tKh4Jcb-the;6f*`*-t~T26ooGcm1?{S#85JZxF?$naIOD{SddGZd zF1v$}jdG)DzQ%W*s%~uVt#7|uSf3GoSB_cd-eWG>3Ffcf)sG`gDx3o9Fbe?HUu5m^ z#rKfeanZhmzR4i89s|-Yd>=5?kMU(a1^hu+^u{aJqzL{Yk5Jm&yFN`!FajYr;BO$L zWONG_bWPE7Z6P@{i<=&g{$gOf6J8|`7871g8=$doTmZV}@X-621rQTU1xeD*PxK|`#^u=Z1QD) zSKlv1WH&t9L+sBqMRR2xku+HG9u_#8%?@MQ~)oEWr!7v1C%v ztF&t!^d%1b`>T!=p|5LTl1RCi8_cEt6OGmI??(F5EfBueI7v%h&dv8B_WyQjp7t_J zs5AYjXs61n$)Tw%otYoZj|s0|RO&F!q`$&Wl{+a%9h4Z`lDiUj3L-Y4BcbE;X`q=H z8pS;x0DhLJIBsR--^CXi1pn+)@$>-9o?vcoLJKLG8SJM8B?b0}czQ-geGYWYTW_rJ zPvWhfHc3pY$M35aL8{@mf>$IiuF^vL;*xDlqAgOB{wLpaB)&8&XTp=+ii9(Uc43Tv z0s6x}lq>#tnMn5<4a>q1a;wM1NG5{3koc9ICQ_Gf^l{{e>NA2j)7D_38T~KPiMW^8 zeThj>4Wh1h>bi)nsoFczc-e%6jQ?--k>Jr8IVAOl=I$7liqgC;s~uDQG-;?;i|v%G z@-e<>K^}C2H7I`we)i(GYM)9|jd1pwle_X6*qSCwssJKaFJv+Iaj4>?H}|1Y5K?mH zP@^TCqg*Od-JQr@&(S$lqmIZKl!yp^xO#7R5CToAo0ISIfVZLMx2Qqhs-C5Z3QwyiKE1DZoS+`8)Ouf2d9@I)uPk}6{?69=%tuA7M%2j-e@VOm<|qTq+6ggg|>ztgK(d&8z^ zMT*M$zCKa1f>kA4t(SrLqP06%r^56~ZFWE%Otr{%JJw_fQ>0e0GN|N<-x_odm{gy^ z_v#k6A_FpaceMc}bQ^{S)t%ss3TApnsf`Oe!)N1cnw9at?qC=G=n= zs>}^$QB+ajQbQ4~9Y$!9fPZ*?bj9)Z#V^Y;8nEOIc6_K%RL`(FUTD!jvG7@(z&EM8 z!po$XSGk5dsM@2^D4YsN_0*C9gbmX_7W>1iCXXzPCZ-{~dPbUmJZY`aa>eHg{)8q_ z;|DfgOh$oM3;kJLohs2f9%ZG$w1Z7=}}go9-&BDHvmVV@AaP^F#iep>gLfd~@Y4(cTqw!SGb9);#T3y1xgAAn(`s->(E5rw9>nM(c{tP+Nr zsY1@)->Oje_2r#@nVg+cRjFl}#!wJE`K+%-##@h$B9pCPY5C-^a<{T`BF%}wSSqv4 z1?N5|NRlVzAOf&b4}~Uxv^%;*x$X$hrkBEd-T7_1&>m^^zPva^7QGq!d1#bl$In<@ zC|Ee%FW&p!bVxuKyixoe-9zG5;Dl0o(@rdQ%$~3cIS!mni|Tw2L*rC>iHHj|h9G0{ zmsjfY`yDo|z_zpH-GJ0?3H(VFQ_Pu5WrQ#W@mU|+!SsWifKKc%(f!!al?E7lhWOQpp#0}7idF<{0TMYcLKwmZ}??#1P9inP0 zyRBjpIWM&##Jo9*>L~P1V-U3#zVjp+gqrR`&>kkcHR^USXw^!b35m{D&!!v+F3nOy zF0a=+MJQA|x}p`~uvnfdbv~_2*5hfIB0yDDG!8@Lid;lDOA(@CMvT)BPKBY0s7e=G z3ymXvkNO>KWCjrqn%08l`dsIVaQ%C+0%j__b6%P_Byuv1&nZGp=28cFtVx1m9k>xz zk8wo?H!g~@7<7T{l(GW-24Yu*r^K4}C+Zr^!22(U(K*E>`e zK=v2VjdAYi=-VY!{Nx=L@V)IMAMMmVqbG4_!3)<(&ugz+@+H?e@r1@XMSItW(6!@S zc~Zo`FOc=K_GO|FBKkWWkPU?V!DE~K{V~&%+vAala!wT3Kc8j`pCptm-`n~8V}Xgi z3)H-jjDMiRpJvW6^P+az1Eh^Zp)&K%yoK$`&bnr#F%dTjlN)PNk`bP&%X6CH0F57G zhNopn9p$hu_`v$t$QH^|g_V;lg-vYi~Cr{7g$@31=PfKwFe@BOy z^leXIhCa>VZ6VHNa~s0mxV^3pKR}tk z7HZauvzA-DdOH8U7l=F%KeDDCmfxRM827`EFLL%Ln~Wc~1OejHb&=RDwbIVKr)xV! z3Fje9fVwThf~Js{H?nZYrMU_H!?Yu^=2E(w!cs7+@k63JTuI}ktU6;T{5cRYW}@!rXq0?@Bpm-L1my~1h_#D9CJfN>`d&>DsreFgu*tFDp?k$z z_l%7MwjH|qZ%&&(KklXJSKLDWNo6%U5^e>cJS^!Nk$LgLXt>B&5}5ZJ=Dbb%>GdVL zOxL2m);DXCb_F|EB?ZuO-1*Q~ zPn^VAL4&chRM((O;j$S{=k1DT>1Tk0VW~b-emAh32jKt5;E@2T^g|%V-w0nCmsTh0 zj5I!^tWGScc*+^G_s%`BW?fJb{X7u47X<7w4X51l2;F{8MF)r?pr&?ilzhE9qGTtK zcQdHgHMAHVn>&+`8f|b~^ah^7G04>C-79SoF9#1fY&H>dE$C&}L2au!@p|GI-N9Sf zOXz&0(@^*jI35Nk(bnC~*4TW9hX{6+R%Ps!9`)u!O9~%-J9R!|u&W{*hC7M$oKS}6$Z^D%WDuuiST$C(CY4l1B6({ zEUqNPCarTBgAM*sSNBzle{aGiw%}u+ogEN^S}6gy6jz$%hG89$uZFpAu|g5ShdsN< zcJRJ_$i;t0r;S!%irnx3Qqd1Cnf_im5DR3SCHED3cH#64R}a z!ivyqVBXFD8V3{dB z=5GhSffzaU?Pou9?s?4g4+o)>zS^)TJ~!WGZ%uq;QQ2^p+A>!2D9V^^G2yX$WMe_D zZTn3^fO}b&DD?%D;e6lO;VZV@Rhpl-LfnPN?^e6V45;oY-1Y{|djru;rEg=D)#ht&otWBs0eM6;-A`Swe9%SmZr(1nF1#H;@zh z%t0#Yc_PIsL3;GG{9LU^oU?0~Id?y9jjw-JQ$b9wB(T~AWU-$cGeBGJ#WdI>+K_x_!sC# z^O3tCRD5tRnbWvbSpEKYjL6KCx!{8URx1$tSlU>FQ;=is)o>G=H&FV7|r>)$=1#4=4FCjv~?r4mk$(b#;<&m(Lz%(n=Sje`h}(B756teApk!%q5rm z#bx<5_+6{cXR8`&rm=+EtWorJVnWeB&l=;m2+N!WKyy~T=gYy&wby9nG-q~23`f|2 z!X_n%G!HA7QFMZ8Ju4_Fo82J$-2Z(=E<~isai!TL0B_kXU;%+_u`CBXFrCL-RiZz9 z0pLjNjJh&6)E5U>`jI@cOszIT{aL6)`19ss3ty|{-tabPmEeE8qylIKU4qVoqJ|H= zPw9F%607YqRIOt8xH+pgH8*Lqa!1Xi32=nu-5MKVCW>@86?MKcT37lUZ5VhdDWkC- zejbE)bQz&>CwDU{#%Mn;@kL`COYkqG$m?vfAe4SpO+q4CFBNXHW=WgYCgq7J9ekhE zsjES69At$?GOihxMT?6wih3h# z6%6{0<>gb?dRv(CW?Nj1{JE~Nei%lYC$>ArFE4FCXcn=9TiAk?(S5e|?+%&`FEyP( zygI{MpIOHP%Gmp@cX=d)pf`R}i&tFui)8KDyw*S}A*CEFJq@R?wI>-k(|UCa%zjwo(UEhibrOF8q~1)$-a|ypj6xpB)pP zS491^$e~rlNjer%lNX(*8H?at%-n>;b0(L(pp~c!Fv0LddW8*m)*;}pUBAb%kX|iJ z@W4FhIpGQu))=mz_EQIG?msz^%i*q5#n?#Y@RH+5*Ks7(_w-KJ;$29R76JRs?^_n* zTNtmRq5vOYvN$A-~BfOE?6=q6ZyC9#~~0S5`9uhaN}cH z<0c>Fu&?}D*HJah=ivdB0}2nA%dgbtVsQ}$&RS3rJx&EAQJ`vOO z+NGT*txl+)^b&bdxC}Z$2~~?_lzMA!AJx-T*_`HRsXz6wKCXRH;xC}TO}=xB7q-10 z*orWy^>_g4kQb8nC3LyXn8rf;WDx$%=*3ih?8qM?NwJ3!TmhKyFZTxcfTRMcSvhgI zlfE?{t=zPS6q2G3D+pHXY=dS$%hep}&I>x%;blef6#ekTNPL}sm`G`V8_OG4;w(BHCx9kJ%aK>j+9 zq<*gck|r0BMa{mBxNwKavq>8{47x>p-5NX)%ufw!Ts{?!yyKhzY6O0}R%{tsFr4B(cqCYuZ6b7aK*)-)< zZ-bw)JG4U>?K!~FZh82oh8ojeWVJ%#^uj}qYyqv9;V!qs@(mS%03(`8%F%$&fZh3S zuYEaaOT|>1?_3;>$p?b2z1AY2ZP!_H|7~b%ik-A38v6ciZx{^D>}0;9-9C!+=19q! z5s1v=DwG%8RK*wuDOs6js%q0GMNRMY;3EKtFjea?Um5aRYyJigl*g@i?gwf>t8{)j zFnb%z09;mYjl%x#s)`_nPTGS&dkd}-ckpo?rNlMr*&*dW+!EjU5b6gzoME~ffWF7J zbXE6)`Ogx;kJ-pC5ojctC};Ov9Bj(DI#oCnn54FP=&uGXx86WxXvg2QcywAcVlYN>k-|&sw zgbL^9uP{vBU+%rAf`a=vWhJGyx=kgxC&M6cdU$OGfbIAjrZ1leHPHiQss#SoG03t#fG}aFf=FWB^JUcy z;R=D3yz@)9kc)N|jE94`Cih-GA8xoQFQL<&V3wRWH1qcAR#i579t?pf#-D{fR0`ZE zGv-;e5;GVW&+)ewfg;-?yCK{ zp(OaE`MWsJ&U3cV##PI$G-ZCp$nfDlUTNNs%-fugHUaiNG)zt&9 zha0wtv8yY?Q$MteiRN2}Iw?F}L9+FpuVQ5a+)^U`7{7CXG(CM(=9I+n=nu>-KvkAj&ZskP^_+{MavEqDkF{B zo91ra$tvsh9oU^;-*c^j(N)6;4z$h?AUl%!&?2aK zF!IUak}d2o&%$>4=g{91ao_kujg%PWYt>NA;r$n6k4?njj$7R0s@wwM%9<_e!_<9c zw}}9Y9BF8F_Zgwe`g-eENjPRVBc5#(Kwyv$d21!edSzlY>RK4(fy{CBnlP6?vj`LGipk)^S0$D9`ETh<((Z{N zqNLi45i{Ayy)}J`$rTJxK1=t#n}}gZZ1h8zh`!Y(1B>7`nJi_wDGT(EEbqa5<1z5^ znD4bwZQO(;SuMCcC>WIkXk;l9?j4ZBwxE;F9F+lZau?w= zSIlLxGRh~7fjf{ow`n;S0u|{LRekdpM&=8qdtO9*YB8&&eablnLVmmQCXD!nXC3Z*U&`de=fkG*fJ{B}*9uL>5zt2kWcR|@0T2yP zCKUIs7YaVBu&=;u`;Ii}ZP~;Q130uQ3yg%V*%+-U<815%RDPD9N6aL#K5Tk}N)bE^ zIG-DskLVN8P?Y0hVSTRP7_ak)4v@6u^Ijn0_1|vOLyS6`Y&i~73FIrP zjDjyjQFThir&=Hb{JqUvyARf`)j5*lS`F@m=~IK5~B;HV1k_?<^Dy zLSwAoG*+-y-vj<4ep0Z#XXz>Jrmi|(;|d24Ob2h4Lz@^F52QP|FS(H2Klkbl?*Yk{ zy?8bzO^~sboZ+~cA2HTB{>k3>$Hh!~=>7*AO>0NwG^PGrmV)oDcu4)F`*3%{Mpnht z$2Hu#UgfNXCCxn?yEUc`FH;P@cDO*RoB5%J1^XFT4eE?oic4i;!Gg1&fT+M%yZ0Y<;7gLrGz{zQ9WRSKYUnje52|ZL0XPOS;5AN zXR}usoY-EbKG;M^U2*HY4%P^|JVc}IKvpkEzjCv-Cmi{trts!jjC1+EpKs{ zM|b#~m`s#JVDxgMQ-W+4j4fv{f6^8x)6*jMV1CZNr2du5a_R{ry{F^( z)bENV!25XFi(5975*M?E9awQ|!z3B~rNpKU#EY?u@u z9>Oq7Bjq!7C7PVLmFRd{9-cuNJf79>9{O^{K4ISJo1+|}R8if%Q6<7ZQ176|0M_=* zo3s;rJGnvs<1!jf73;PFw}K0EFB!%ogzJOpy{A&0M zW^w&bI{^hp5@@1GAi}KgLHRdGBidRPiZa8-IM26(gnaD@<9NujvEC1|@qt>V2=VPE z3CP!Zl0)jC+=g3<5kGz#8sX2%l6cYoU-#Lw|X2GOWknP-7F8r8&KAwi6>{ z_fryVV^RAvS-o2kOf{Rjl&RT5X0s+i8~ls&(wJ#>0?Ek@5QEssvH6v!Is;E_^SI*0 z`&S%)5Ie$<1-w#onvFV774jQQseirX7Q6ge3{mGOj=wp`?_%>!l2TSzjSG6=jE{8a^$nY+v4=_v&>mXy3f>QN@Bx6LV&ZOpeN z$c3e2`u+Vo4w&UjZzJ~dA>YgaK<|rw*_UnvSE0)Njs;)XKP9OXiKPf~h;^L+K(&Kf z2v50<=D7{8QpH6zqa2JQWO=Ra-Y)H@j9*Yp)+*IyuqWG9&Jv8iq7%jbx zQRo5ncekQw4w{NlmhBs*g5c{;wFi$pgO8Pv#?!ArNOP|prnf~83@~g8ie&k!@gJ$? zhL1u9$6`)Or!Q`uTk;clMbxBjON*_c6o&_Twa4%TpouP$R9Fg4%7vEJ;Wr^K5fd{) zZ{}VhP5lFi;%+7*#tHwOGP-iSgGk#M3N?0;l{Y_{5)B!!K|Sn1_?ZmgF|Bbo@NrTb z{xgYG(I)9QQb$wC3Q@zJzz(%(PWjg6dFs0Ui&_405$s0oc~=e2RL#YR*b?4cJPPdy zU^7j;27$+CUM&PNH;}}lBwcH&c1-}epC#VwrDzA!X`G~gx6Q;JKzP{=7p^A>v z51)PJ%ebE0j&^?uk!sMxp_ubK;D@?0NZ=74lZHL{Rgscn9x~ojI&hi9hjoav{rC*? z;cI_yNQ^6M^up<|q5}zjP*kZm8|_k?Tb7!8_7;0qB|UTp>(Dn5W$}UEPt9B!*HrU2 zOtu4<6a5k^VvD#CvnQY7sdO(?FgohiXCyaX4!WQ6<*YJquMU+v`90$vrXCDf;|5t-no5Sr?@#{hBt;C@zaHBrC{P zO&Cv;7z44TcQ{z|lv)x9WM{oinn}E21?!^NpLI+4F zId|+k+@nqGs<$^=9}fLopU$d0xM=Z>@wA?Ee&VOn(RtRu&IfyDjq{y3nKVDy|J1V= zY^iE%>bdGtg^U*uFJN@;^+0sT+T`7HwiM{<*@0S-PQS*S=#gSXyWpB9t=bA0x+UNx zYd@0g(qk%)HWm)maJa_ei?a_G64;0K*OT}{&mPy5l?63c2==&>pKopP&XR#p4+Jv_ zg)d$nhO3tZubvug00MwwwSgD8m%LToAJ?ZJYDCZC>zJ!dE;oMZP0BYQc!S1PyKXoR z9NeSEFk|ZD)WyU?9H-!CML5Q8d<-N>hD_VjOFI3-e64%zcqLxRO%NTh8YSF?y^Q8k zA}wPhLFN@V+R9wbY^iCD-sY#f%Fj4#`yto;^^XcUT`w<*aoxIBL&0kHP_U~;se3qfY?z0oR@0!=R%>_|2Z7!~mOHI)? zS~8ZxTVtq7@(hwHZ*e|gvzAxbli@%m30i;C$?NN+u~DIx*S+VKUV78ks=0VLl6>>$ zXo(!PdjM^%>}k*7k1a+UAtP3Czequ1ecb`>_H@StSr_4-0vPbd!apt0jfstnL^&pt ze3>G+Eqss3@g9cK?U)a>nPXk>FvRZV9fzT;Z`&m4eI4tui*1CK?sB@2Z(4eYY7b|2 zQ1|hc;ShHsvmULOYfnD`E%`)Ng!an~%uBFW%xP>|2m^XFcT zsLX1@{HWWzX!$0nlE}ecqqVEZHYHDm-W037G&86Xg|SrWOCsJrZjdg6Ka+~>0CfYX z_9vtZ0&61>H&C5JsRYIHVg!)3b*`Z|Y|mfjAVt6b&TE=vYNS9Q@}WjcB6$jNmXU<^ z2HU7A&Z@(1#m}`*#~O`34{zOp_go3EXK|Nv@~QRn&WtdB^V9 z7|H(n0K|08nAqtJV|P5}(Y4b$zJ{8tZ}|O|rUDxKgPW1qJmzPLV#k=EcI?T3XAm5| zm#e=4qBe*?g-ant6=+xUx=ap6nAM!dMFwg}!U{h+3M%$l1 zi==@7y{lW3*7>)=qjgdaJ%40=Sfc+oBTV!rxi@% zA~|?h-xwaQla;q94VOK2&DuG8m4K3R>$)UJd!AVPEXY>*aaNcXw7kt;iHD^afU7`o zCct}%`R#`pGB6ltf_{`NDqsa=9!KMeSrv5D$AjLYp*FNlz7wb8x2M2sTx>aBg=}u6Vt^TaMz$vS5uF)QrFA(b1)2oevN6 zi5)4x2uZFUWsoXNkYi8=1XD>Ci3+xIye@XxPujZu~WgWbi z3>+|Zfvu7bS+8{(+iwm$SL8wAGm%1_SWBqR#Zs~Sy|A3-^hGaSt_rmPCqGE1|D28} zh7eTKN>+#bG95(DR{I6$lrg(QB`GD0s4X-@Gf5Qt@pJ!7Pgpp|)jCO5IlKQs z#2t1NoeEmYo-MCG0ZX*o0Qi;~l;n7@fvr@W&B<)2gbZWs6}Bv58Aj)+S1-5Fq|=m0 zodvs#tTo4FkLj<+F;K6`4t^%a|3%q5uvyk^+nO1+ZQEvsjSSni9T~Q58yU83+qNAU zj>x-m@AK8!=T_aPs(!(E)||7C(fZq3A1md7Gtmrc^YX}R*rCk0bbhsWE|Y4IK48-L zGc4vAE^^Tn*7s_;IngkYI5c{RQHm15T(8 zYhMmrGj65di6TD{NO5k=s~i%n1z7h{KjME1G0dSK?4bmJ`HnAJjy&=)hLY? zzK&vWgJszAG7a=Hmi|#?++b%o2Fi8Ltx0et-a;gwGrM4->oo+fj`;SKV|t&PX#GG@+}pY2iBE8azX|c zt(lfqEETydn}X4H%Xxc(r((c*=LqB2rAo{eWkE^MkvdKf`T}a8YN@x0Bgf(F{313Q z|Di!TB8t0NQslRGBZSA(%?mZ=n28efu3O^IA{#we3=t*CWpZR3IdfF6EJHPyH#~We zGb>??!f=0iH{!08Cs_Ml81Jc>AKPPwnH_=55W^c%iM6n4fo|vZ2_^@I(M}ynmX^*Z zAqBq@hUX8{x!bm)BdiA|ezkdT%O)iOYe>L>$sqq(5F>84zz%l3WoSx28h!0=j##XHD3jeT37PP$L11h2P!hn8Vpn z4w+)UkUR#T(8cvvA_Q)ci`R*`wv{5;K+r6Kor@zUs89Cc|@v576(XMF-R#buFX^+v{cOn>#t121a@38Kdf8l$4iv04O_^U@~w zmm7s3=`3;EZ-HeRfs|zd^R?QVpQvZ4h+~s|hwtuiMt0h4Mn0CjN`5w!N?D8bC&F#< zGHfnOdmYIV6uZwQrRv7pbB(mOQaCaa0P!HXYK$s6%|xHBpXU4-(PgmKN^k)OO`}H{ zA%`JeP2EcvhVCMsz=OP(4ZTN*=Q~j}5N~dt=CEB{9!Z8^(fhq8f;2zGUSua|T=}tZ zf@A1xU1|H`Ak4hN{d)q1AZEMfLQq>mZJ)4RnZVRwG6*j#+Q8BezMcwO986t*D?=dP zkZoMG66etji)-sLD*G|%boz5_DBq1i6L1vUAq!>0fyc)EE@S_gz&duujrOrScPj!4+ugOCY5LUN;?EX^q^s0yk$O z*f(2ZC27XI^$g<$iW>>5C}!YignWjAL%OE^Tp7zGXtmi);i#rroDiK;qZE{5PAASL zEbS6vIbJ#28-`(qBuu~wN3Su#UqFtboQ*WQ?@izn-R4yv!NZ*Z3IpV8j|9Y%!vI0h zr8FHfI7shs4O&Ln0XlpC%s=!KEAKI;5-%h*g~W8wWpwC%lGa`e z_2EIsq(-7uB23{Kbrj5XT2XlzdG*q*R;}Mu7Of2sxNrBPtDIX{2g##eP%A7TeG_1& zc`EGhl`(cS1u&l#6@OozLAXc5=qyL%+xLawEoXWf+R=WH!SKwG{BWxUbDBt2%~yfF zg+(Xo(QKiIbGAP>C%P_%t8Vo{a-mMB&9@Qd9W&+?Y;$NqbVPdGyF$9H=N8h*yruOh z=OS;X%zvPgCEvIt2o0l>UNKhDn$S?|3$M614*C^@N2-I!JjFyQW7#=Jm|%{l4&nYi zUGZL!I`XVN%JJA(5VY$_x{Z9TA_;z|T(ssMh;>z-A!Xj*o$bCHslF1T&Chn__i=rM zGgzKGbUzogft@%FCMo1mDFcUM+!2v&4n0l{Udk!H5YFr#s+Tvuz@&zheD4pLW}m#> z4G%ktJyE^uiV7C$AJ*+N#7UL}no#fyD3b=YWl(=+uNDprTsSEWQ^B@=b6uJdfDnXF zZot=5L)r7{YIy;-683eVkH&f*gZ}PI4@9g8M2i-QIFUS^XdP4^cLEjByBB{JQ9g_# z-PM=|l_V}|I+b5=P63Yf3wZ)ffbw3(K(194lmC-Wd31z*{Ly0I_Go&w?h~AA^3imz zERU;2r^?H_lKi{!g!dOSxwKL!A2A;%8d$RZ*(d`IA@42!qxL5RZ0^LZx~rLyG6B$1 zC11176ihGr%h6r&MO0hgCW3L^mBQY%;k=B02Y%MXUoJUY#2waXwg{VNNEyZ*JRH zv!WA0{Ct4ME@;RH&j)pk*@glFFyLXRGHPgZ(8l-T_Da4#@kEqDe$BjWUt3GUey~Tr z&Yc~Z5KxNf7oP?;d){Y*W_4$Fg0v|;W<3u_!@4vSvA|?dl=!$@6`hNhO91L$g5u1< zBWa$(q<-H~>qcjpQa3;gkw}^M(;yJx@A?UGZ~e#QL_LSyYPt+PUS3F$U?fT9ZeN`@4;Z5 z)-c=R}8KT5ElNNHL0kgaA;ufZ%`shgY>udp%7=Gs)Go_FIyr?7m zY1``UOsKY=mlIWNvgTv>EPmUz3 z8Ph;VFYxhI^UuVD_Gg#YQJ@m ziZ7_gwnNlBb~3hHZ{>;mV_se)WG=L^-yr<$TYOk>Au3e~=FLLimKoikcRvz+Y_O`Y zNgBpu%QcnH<=`ga!VmCsaQlYuv7Qg}Ts-ZqD6?U=NHC_DJ5%h+q8eiCcEZ?|q#Hy& zyS|2UTE4n-IwpSIN}+{IV}BC9d6aG$@^ns_OyvoJ##v}Wx`Tr{@#tjt>IUiFKEJn$ zxp09jO!F(x3AfvYu!TtPXYMk{R24dB2PPt2*X3_8=D5bp2Y+kLY9%&tF0I%WQgu!H z#9xkzXVz;6oml2)B91V$e%)%K%6IRUt|EgBjvp>IyLm>IFW#d!Rd9oLzq1$AyDw_L zT3U8XC#x?k$GXV?HtqZNp5Bwr%mtmHrgnLNM3YrVzpH2D6&kO0U0V5u;cm-s{zG@O z&C9yv-9k_!8=ybU0*{+&-t8=bG^2vy{SBw>uLhv=IfFxC>&i`KeL@3F`v9Ig4vJ& z60eod!3`0(uOct81(NqueWP;Q*>4Apy@vzAaA=IS1Ak<^U|*x(orgaNU#olWHMKtQ zf3Z{0Wlwk$NRyiAe+?q#0%cO4oMhqBUSZJv!cCOWgV!VNaBhc^s_0LATrVK3b%GW9 zV?)U4#n5Dh$s)WDBj4%s5)q+YF|q_5@rnS{ zC@079AWIo8(N~n&+qx+j{U{VMAL16WoNr%0D0*h)S{{?%LcDA+LhWr=^Y)4HI{xa< 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 literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xchma.oscillator.ex5 b/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xchma.oscillator.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..abeb89c824680295ad92b50047bcd75767ce529a GIT binary patch literal 49154 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

bjWqAw zgm`1I2^ao@9h+D-nPJAUhHi?$qdQLQk@T_z!Fr8{tK5dpc4MWDchvjzGrwr>3k_1& zK(4k4pOUCs64;c3D3z)53PAXYX0gAOyXQ0eUTE+qTx{{HRN|N$x^3b}^%^QlP_kDd zp`TqUE?_a#CkvPZDq@T`q8Je&mm_ zst$Qg+R1k-Y?lK*N9Uf^=%et5h=mt?2yADoOLq3y?__mK9{b+TDEnvGvrz~37+nox z;I2*JAIvu&v1N44s~NIv2O_*-byq>|YdDN;qD7N~kZaq5d22n9 z&o}rahsp-FoN4v!NpFoC-9hgs3OTY)&20^*LQR|_uZIOg#vz;g+@1LKD=XuX4V`}Q7 zgG$R*#NAZPhrJxPmeCR%b2C!i%VvWCl&HQJMKG_u~xM<%=vMfRo3u3tn#?k zuG88l4}lfk@^>LfxD1(E(C-*CT2!NbUl1x@F_F~t#7iQSs4)Q1ExAmQV};Y!p(^}g zywq8Dora7+bF9L+hqydv$o_p}eBdQ=!ElX6T8pHEnY>H7qLk#S^3iw2==vlC!3gQM zl%bxu@;Nt-&d59XQ+SKd=&~!qMDWE5^^kV4x<5l?eGC2yLd|0Q$VM8&*dN6;bbWn6K}s89TJd~hrM=~81&U!-%FHXKMRhtJ=S4b;Qnb9Nu4k1 zN$+=e{W_m@-^`dhutQt4ZpO8?uk8SOae6(xh-NEe#7$212Oy{EbdBCcI-6ai=!v=< zocq)hvmxq+4hoiOp%LHWc0d+*2)kBCnysv@jCgZBDlzK8_zyF*hOyaP&+o2KcPgqT z4c)EmzlUEYS27deFC8*JiZ-K@nY&Qw>1_*8l&i%vBT)5E$GgzwjGQV;QNEG;*?SgnjG>XZB!6G{oiQ%R4NNB-S2N~sC;{fGC{iuAv5vYSOJ7tnQWFJ9g=*|#K2vAeU45F|(%$;I*2yGO^My-ay`MI}Oe4-<_K1>btn5S^;r2H)%%JQS;TPc;5%`=Bb z_+js!Pvb>fMf&8RpEQeWZho6CHEy0CbE09_HAsUs4tT%788DivS*m&9tU`6?iSG%1 za9U4%xUf~Fcq?tqyzkv$E5LnqjQCmggs-kSvx_U zM79g7^H~~JNYJy7L80ong{euA@A5AC`!Z*vt6s$(nyDJuQU~i+k+shtdaP>q=LM^+ z;uRf}G#w^%>c`>k3!2)aCwa&Mq8g_oT8>RabLY&QV2UWAik?_~hEj4CTmhO>G`)mjYLiFk zYA3ZkkF=?CVT-K%d^gDU*L_F-D1CP+2bw5MyXO)Z=@u7*XLvL``as*ESjA_lckaB; zBtX_pq)Og8$?-YsrAixnf}B(lDHS+|oj|awJWUfU$*;0+fMw8fVLawe2Jbh=r3#&W zn?DO?sZu%GuHFsjMypSR6uUB8L0DLZoG1LkvIFBVpDbX*9NK)Y@A5kGLiP2J^opqO zSqzf>rSJL@T+@7BZb~(0& zqHZS$(0tK5^!@9y8cP<*pq96t@F;yt5eplE5s$zG{8hjeS`MR^2D96_;Y8cExj2Wx zcXI9HsCyT`Dz-smNp*PJMg_{ek_$krA(x6azK^-$YtI>S{pHt-y&CCDzyG3=U-)5} zG|g;RJWFo=p_5pus|Ezx#)^$eAw0wCqOPCIx;@eX&z|rm<9^Rf8wfYd#^bz#TbfGV zSzmU>2|r4V-)EA7ceAC(A2;+i8@>Fr9&y5)bWD4#Lk%t?BFR+4E_6u4zEvFyvdV=prSzLBlDbXqx{q#vJ2xk-_B=3K&{q=OPWwMw%v< z+EE#?)gYcm+_PK}mlwng-HZSQv&G(cUI{m}%0?h?m zoH8a%A<`OKg!(a+Do>2|M52=R)dY3PlTlX>6Vi(1hObfe5R=z#_r#r>Z89Q(sNTtu z3p19=_m!U>_UmSr^9Dw?kSxZ!6$H^6w5orBZg|w{o60{7utr+cuT4Cv!MkRGVE+g6 CMKERn literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..94b7af104509f8bbaecd21ab63dc4bc40e09d256 GIT binary patch literal 33778 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 YSWX)5sp$p9#hyX1Lr8IuPqEhj0y%b!#{d8T literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xchma.oscillator.helper.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xchma.oscillator.helper.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..e40f6e6bc1c63c20c476ee4bf5075a6457225e00 GIT binary patch literal 32648 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 RW=$q=;OPZVsc_cX{tt|I4yFJA literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xobd.oscillator.helper.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xobd.oscillator.helper.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..3a03aa3aad8148c593edf07cb823ce6295c158b6 GIT binary patch literal 6726 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 B$)ErL literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..a2ea18d8512b3a9d5b59f2a4c8a47140437122ba GIT binary patch literal 14368 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 gMC<6XR%7oob+Nak85beV3N9=Tzl_| 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

rvUgX>2#eEm%Mb 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 literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtest.provider.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtest.provider.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..1e5fed57d6237ccc227fef5d89dd1f15f1f9ef1d GIT binary patch literal 83324 zcmdSAV~{98(x)zuxD zRhgBQPq(ldGq63tJv<)>z;6NsIQp;hKlT4k4eN#l^8lX7&d`3qSa z|EHrMfGvO>fIEN#fH{CEfEj=j009640NwAw2tf5)R|L@ir5gXX3jqPQ?3VWMg+g0n2cRPZlVfkf^gBosxZM}q@BS6x6Mq{cV-!yFC*@bId`)&VuQB0 zRDxF!(bJcq66>zn#r*M8Bdn3rw@hXg<~#L4z>%PtfT#di!Ah0Q zU`{f?18RV5f~PTgLc7OER40X7q-H`Z_SokQbWph1Pr8ipuN}k~Axwl94Vy&Mi0FXf zc4$69lSFa_?Sccmt`Tx_#CyGYrHS0*lekO&Fg=;N}L-YfEQOr5tMP*qvdX6AAM|G!G4n zJsWhzOdYCZ>gsfyNX9Hjux@Oq(GFpJ8scW|PIMI-q+2+m-KBh(R^ogkae(~Fxxx`~ z)6%<2$$PUWoDkxyq#RH-i-6%+(qU&<%PP_`Vpzuz8T~5_Ao%f8gtBHz>d5nni6AgL{5GT5XX_ho4f zKHbhK2elLYzO0X$V&g7cXvn`8sv0QMx^^l1dMqK`VEchl-L#Smo#mK8W~dCu4;FSv zf(JZ#o$7J*vP`>vfL!0In}8WDR26fr&w)|@W}n+`&pEBI7?=X72PtP*HU9K_cH|6Ibl(KpfqCHrd3_AX6V2a*>sb;E*k$6{)%1E4zg^ZiBS<_A`Tv-%zAD zDHq^nHaX5m*>;mR_cM_$yujMI*G&n$yCcG0g~S&6vL(^DMYw-w7bTx62B!xKq8P~$ zBnF67uL^p0E2$whe+C$nQ{4Z?zznnwuHKutGy>O}20u8fo|zS;$aI5BG8+y;2ugr` z{Ov-9Ewc-T*Oy$bqqeZ5>*b!?Wf)#8Sfq}>u*cJ!bs}8aPO<6WF>j@wRf@zXgSOm2W_6IEt z$EksZ?bTV9f}1d!79YXgaRzJNWnT0J`AX(@>CYVr3LFQg?Q2>b2{YZ`G<2=#2T(DT z-r8;Ju||Iv%7)I(RIekWnzkF&&KUFvXkM~%Z?03zwYWp({31#Oczn)&{XT4iYcnmW zOCt)LNbp%D=AO(Tu0CfQdas)^q|+J1r0$Y2DCZI-o3DMkYz3orS5*=Fin$i6OSPHe zdcJ@kcfo~?dx~=BQBj6dV>Yg6Q7TDi85}kP1uDf;>!q06s)M)~^vkoOsS{_QBB;=0 z0FdVf>SENsY!IFb*!a`!WY;rxr*Ihv8`zynS171rb?2XjpB^JhwB9gr=9j<;WAPA> z=7|F5oMpnBMNf$Ic&Rtc)+qw3*L9kCme?`S>{tcqF*)+j0_gxWV8FRhlP-K-LZs!@ zfnnpl-Z?=;lcQQ^ZnS%_zJKY{rWyVE<5Qg@>~$^Y6?G4ldJ&^1jf2P{4jSGhY-DaSO4HPe0z}NF7+PV#ywVj?^>4>fv!WoI5$GBPr#+qKu8JD*4XkX-~_* z-ai4yzGMV@&c!U{w@FB)QEt}2dg%4Mc1cfO=#NE~{?rYmRc;9NDNs6C+1&O0yBRL0 z6x%5Mb_iOI8-x?+Jw!drj?}Evy4I=~W)U4jXy)6-Iwxt#e&fd1!YSCTWx2-BWGYan z(RIZpY}m+@2D~xWW(Ob2>jM*fzTL6TM23g6PT+M?{EuK z!d?^m!>7A$?{eq8{579rqBR7o@Fcezj2Qw03KZqu33|`xbxTTF6q2NaBuo7|GV5|+ zE5!fWv2azbH`G)YQ&1=l3a-M<$`&;VF(S!c5ghtWWJu7U+{YtiMA!5d6>9A#>cP{HsIZT0Vgj@`9n zHVhyn#lZIwatbpbD_f|a_7h8-J`5qaZX z!8wQIBhE793k*M?3@}!tm$<`0E80Uh0OO^c$QvrABnQj6+G{cG@WofEDb*65QkTO@ zv%>_)(GykuP;fUHC1b1g!REXKUo__LS2R)VUqPhT9NXsQ3jsBC}OK`35Nsqks zg_5dKX)^vZv$;L0x?WK7rAY-xm}*vP7=ov|lCTsuBzsZSz9KX6G4l %*7zifhbB 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 z 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 literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtm.indicator.helper.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.xtm.indicator.helper.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..23fbab8ccfa96e70122b0c740037db14c4a69c7a GIT binary patch literal 8864 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 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = + lcLength >= 4 && + lcLength > mcLength && + lcLength > scLength; + bool isMCInputsValid = + mcLength >= 4 && + mcLength > scLength && + mcLength < lcLength; + bool isSCInputsValid = + scLength >= 4 && + scLength < mcLength && + scLength < lcLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // SIGNAL ... + SignalDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// 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 // Current Candle Index ... +) +{ + // + // LC ... + LCCalculateBuffers(bar_index); + + // + // MC ... + MCCalculateBuffers(bar_index); + + // + // SC ... + SCCalculateBuffers(bar_index); + + // + // SIGNAL ... + SignalCalculateBuffers(bar_index); + + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC HH Buffer ... + string lcHHBufferLabel = ShortName + " LC HH (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcHHDrawType = lcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcHHBufferIndex, PLOT_LABEL, lcHHBufferLabel); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_COLOR, lcHHColor); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_TYPE, lcHHDrawType); + + // + // LC LL Buffer ... + string lcLLBufferLabel = ShortName + " LC LL (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcLLDrawType = lcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcLLBufferIndex, PLOT_LABEL, lcLLBufferLabel); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_COLOR, lcLLColor); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_TYPE, lcLLDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC HH Buffer ... + string mcHHBufferLabel = ShortName + " MC HH (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcHHDrawType = mcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcHHBufferIndex, PLOT_LABEL, mcHHBufferLabel); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_COLOR, mcHHColor); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_TYPE, mcHHDrawType); + + // + // MC LL Buffer ... + string mcLLBufferLabel = ShortName + " MC LL (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcLLDrawType = mcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcLLBufferIndex, PLOT_LABEL, mcLLBufferLabel); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_COLOR, mcLLColor); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_TYPE, mcLLDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC HH Buffer ... + string scHHBufferLabel = ShortName + " SC HH (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scHHDrawType = scDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scHHBufferIndex, PLOT_LABEL, scHHBufferLabel); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_COLOR, scHHColor); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_TYPE, scHHDrawType); + + // + // SC LL Buffer ... + string scLLBufferLabel = ShortName + " SC LL (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scLLDrawType = scDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scLLBufferIndex, PLOT_LABEL, scLLBufferLabel); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_COLOR, scLLColor); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_TYPE, scLLDrawType); +} + +// +// SIGNAL Buffers Definitions ... +void SignalDefineBuffers() +{ + // + // SIGNAL T Buffer ... + string signalTBufferLabel = ShortName + " Signal T"; + ArraySetAsSeries(signalTBuffer, true); + SetIndexBuffer(signalTBufferIndex, signalTBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalTBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(signalTBufferIndex, PLOT_LABEL, signalTBufferLabel); + + // + // SIGNAL B Buffer ... + string signalBBufferLabel = ShortName + " Signal B"; + ArraySetAsSeries(signalBBuffer, true); + SetIndexBuffer(signalBBufferIndex, signalBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(signalBBufferIndex, PLOT_LABEL, signalBBufferLabel); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Calculations ... +void LCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = lcLength; + ENUM_SERIESMODE hhMode = lcHHMode; + ENUM_SERIESMODE llMode = lcLLMode; + double threshold = PipsToPrice(lcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + lcHHBuffer[bar_index] = hhValue; + lcLLBuffer[bar_index] = llValue; +} + +// +// MC Calculations ... +void MCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = mcLength; + ENUM_SERIESMODE hhMode = mcHHMode; + ENUM_SERIESMODE llMode = mcLLMode; + double threshold = PipsToPrice(mcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + mcHHBuffer[bar_index] = hhValue; + mcLLBuffer[bar_index] = llValue; +} + +// +// SC Calculations ... +void SCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = scLength; + ENUM_SERIESMODE hhMode = scHHMode; + ENUM_SERIESMODE llMode = scLLMode; + double threshold = PipsToPrice(scThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + scHHBuffer[bar_index] = hhValue; + scLLBuffer[bar_index] = llValue; +} + +// +// SIGNAL Calculations ... +void SignalCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC Values ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + double lcDelta = lcHH - lcLL; + double lcAvg = lcDelta / 2; + + // + // MC Values ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + double mcDelta = mcHH - mcLL; + double mcAvg = mcDelta / 2; + + // + // SC Values ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + double scDelta = scHH - scLL; + double scAvg = scDelta / 2; + + // + // Min Value ... + double minValue = MathMin( + scLL, mcLL); + minValue = MathMin( + lcLL, minValue); + + // + // Max Value ... + double maxValue = MathMin( + scHH, mcHH); + maxValue = MathMin( + lcHH, maxValue); + + // + double operationalValue = 0; + switch(signalType) { + // + case X_XCHLH_DELTA_SIGNAL: + operationalValue = ((lcDelta + mcDelta + scDelta) / 3); + break; + + // + case X_XCHLH_AVG_SIGNAL: + default: + operationalValue = ((lcAvg + mcAvg + scAvg) / 3); + break; + } + + // + double signalTValue = minValue + operationalValue; + double signalBValue = maxValue - operationalValue; + + // + signalTBuffer[bar_index] = signalTValue; + signalBBuffer[bar_index] = signalBValue; +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + // + double lcHH1 = lcHHBuffer[bar_index + 1]; + double lcLL1 = lcLLBuffer[bar_index + 1]; + + // + // MC ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + // + double mcHH1 = mcHHBuffer[bar_index + 1]; + double mcLL1 = mcLLBuffer[bar_index + 1]; + + // + // SC ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + // + double scHH1 = scHHBuffer[bar_index + 1]; + double scLL1 = scLLBuffer[bar_index + 1]; + + // + bool isHotLLState = scLL == mcLL && mcLL == lcLL; + bool isHotLLState1 = scLL1 == mcLL1 && mcLL1 == lcLL1; + // + bool isHotHHState = scHH == mcHH && mcHH == lcHH; + bool isHotHHState1 = scHH1 == mcHH1 && mcHH1 == lcHH1; + + // + bool isHotLL = isHotLLState && !isHotLLState1; + bool isHotHH = isHotHHState && !isHotHHState1; + + // + double hotStateValue = X_XCHLH_NEUTURAL; + if (isHotHH) + { + hotStateValue = X_XCHLH_HOT_HH; + } + else if (isHotLL) + { + hotStateValue = X_XCHLH_HOT_LL; + } + + // + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotHHArea = hotStateValue == 1; + bool isHotLLArea = hotStateValue == -1; + if (isHotHHArea || isHotLLArea) + { + // + bool isHH = isHotHHArea; + + // + double price = isHH ? candle.high : candle.low; + ENUM_ARROW_ANCHOR anchor = isHH ? ANCHOR_BOTTOM : ANCHOR_TOP; + color clr = isHH ? hotHHArrowColor : hotLLArrowColor; + uchar arrowCode = isHH ? hotHHArrowCode : hotLLArrowCode; + string name = "HOT " + (isHH ? "HH" : "LL") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr, + STYLE_SOLID, + 1); + } + } +} +// +// END Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xchma.oscillator.mq5 b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 0000000..8f64a40 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xchma.oscillator.mq5 @@ -0,0 +1,1153 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel Moving Averages Oscillator +// ---------------------------------------------------------------- +// Name: XCHMA +// Description: trend detecting based on cycles ... +// +// +// 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 XCHMA Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHMA" + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotBullishArrowCode = 228; // Hot Bullish Arrow Code +input color hotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color +input uchar hotBearishArrowCode = 230; // Hot Bearish Arrow Code +input color hotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcFastLength = 20; // Fast Length +input int lcSlowLength = 50; // Slow Length +input ENUM_MA_METHOD lcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE lcAppliedTo = PRICE_CLOSE; // Applied To +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcFastColor = clrAqua; // Fast Color +input color lcSlowColor = clrFuchsia; // Slow Color +input group "LC Drawings"; +input bool lcDrawFast = true; // Draw Fast +input bool lcDrawSlow = true; // Draw Slow +input bool lcDrawCrosses = true; // Draw Cross Lines + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcFastLength = 10; // Fast Length +input int mcSlowLength = 30; // Slow Length +input ENUM_MA_METHOD mcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE mcAppliedTo = PRICE_CLOSE; // Applied To +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcFastColor = clrLime; // Fast Color +input color mcSlowColor = clrRed; // Slow Color +input group "MC Drawings"; +input bool mcDrawFast = true; // Draw Fast +input bool mcDrawSlow = true; // Draw Slow +input bool mcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scFastLength = 7; // Fast Length +input int scSlowLength = 14; // Slow Length +input ENUM_MA_METHOD scMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE scAppliedTo = PRICE_CLOSE; // Applied To +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_SOLID; // Draw Style +input color scFastColor = clrLightBlue; // Fast Color +input color scSlowColor = clrLightSalmon; // Slow Color +input group "SC Drawings"; +input bool scDrawFast = true; // Draw Fast +input bool scDrawSlow = true; // Draw Slow +input bool scDrawCrosses = false; // Draw Cross Lines +// +// END Inputs ... +// + +// +// 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"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcFastBufferIndex 0 +#define lcSlowBufferIndex 1 + +// +double lcFastBuffer[]; +double lcSlowBuffer[]; + +// +// MC ... +#define mcFastBufferIndex 2 +#define mcSlowBufferIndex 3 + +// +double mcFastBuffer[]; +double mcSlowBuffer[]; + +// +// SC ... +#define scFastBufferIndex 4 +#define scSlowBufferIndex 5 + +// +double scFastBuffer[]; +double scSlowBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// LC ... +int lcFastHandler = INVALID_HANDLE; +int lcSlowHandler = INVALID_HANDLE; + +// +// MC ... +int mcFastHandler = INVALID_HANDLE; +int mcSlowHandler = INVALID_HANDLE; + +// +// SC ... +int scFastHandler = INVALID_HANDLE; +int scSlowHandler = 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; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init All Required Handlers ... + if (!InitHandlers()) + { + 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 ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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(lcFastLength, lcSlowLength); + + // + // Get Retrieved Values from indicators ... + // + // LC ... + int lcFastCalculatedBars = BarsCalculated(lcFastHandler); + int lcSlowCalculatedBars = BarsCalculated(lcSlowHandler); + + // + // MC ... + int mcFastCalculatedBars = BarsCalculated(mcFastHandler); + int mcSlowCalculatedBars = BarsCalculated(mcSlowHandler); + + // + // SC ... + int scFastCalculatedBars = BarsCalculated(scFastHandler); + int scSlowCalculatedBars = BarsCalculated(scSlowHandler); + + // + // Check Calculated Bars ... + if ( + // + // LC ... + lcFastCalculatedBars < maxLength || + lcSlowCalculatedBars < maxLength || + // + // MC ... + mcFastCalculatedBars < maxLength || + mcSlowCalculatedBars < maxLength || + // + // SC ... + scFastCalculatedBars < maxLength || + scSlowCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Copy Buffers from indicators ... + // + // LC ... + int lcFastCopiedItems = CopyBuffer(lcFastHandler, 0, 0, limit + 1, lcFastBuffer); + int lcSlowCopiedItems = CopyBuffer(lcSlowHandler, 0, 0, limit + 1, lcSlowBuffer); + + // + // MC ... + int mcFastCopiedItems = CopyBuffer(mcFastHandler, 0, 0, limit + 1, mcFastBuffer); + int mcSlowCopiedItems = CopyBuffer(mcSlowHandler, 0, 0, limit + 1, mcSlowBuffer); + + // + // SC ... + int scFastCopiedItems = CopyBuffer(scFastHandler, 0, 0, limit + 1, scFastBuffer); + int scSlowCopiedItems = CopyBuffer(scSlowHandler, 0, 0, limit + 1, scSlowBuffer); + + // + // Check Copied Items Number ... + if ( + // + // LC ... + lcFastCopiedItems <= 0 || + lcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = lcFastLength >= 4 && lcSlowLength > lcFastLength; + bool isMCInputsValid = mcFastLength >= 4 && mcSlowLength > mcFastLength; + bool isSCInputsValid = scFastLength >= 4 && scSlowLength > scFastLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid && + lcFastLength > mcFastLength && + mcFastLength > scFastLength) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// Init Handlers ... +bool InitHandlers() +{ + // + bool result = false; + + // + // LC ... + result = LCInitHandlers(); + if (!result) + { + return result; + } + + // + // MC ... + result = MCInitHandlers(); + if (!result) + { + return result; + } + + // + // SC ... + result = SCInitHandlers(); + if (!result) + { + return result; + } + + // + 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 // Current Candle Index ... +) +{ + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC Fast Buffer ... + string lcFastBufferLabel = ShortName + " LC Fast (" + (string)lcFastLength + ")"; + ENUM_DRAW_TYPE lcFastDrawType = lcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcFastBuffer, true); + SetIndexBuffer(lcFastBufferIndex, lcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(lcFastBufferIndex, PLOT_LABEL, lcFastBufferLabel); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_COLOR, lcFastColor); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_BEGIN, lcFastLength); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_TYPE, lcFastDrawType); + + // + // LC Slow Buffer ... + string lcSlowBufferLabel = ShortName + " LC Slow (" + (string)lcSlowLength + ")"; + ENUM_DRAW_TYPE lcSlowDrawType = lcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcSlowBuffer, true); + SetIndexBuffer(lcSlowBufferIndex, lcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(lcSlowBufferIndex, PLOT_LABEL, lcSlowBufferLabel); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_COLOR, lcSlowColor); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_BEGIN, lcSlowLength); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_TYPE, lcSlowDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC Fast Buffer ... + string mcFastBufferLabel = ShortName + " MC Fast (" + (string)mcFastLength + ")"; + ENUM_DRAW_TYPE mcFastDrawType = mcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcFastBuffer, true); + SetIndexBuffer(mcFastBufferIndex, mcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(mcFastBufferIndex, PLOT_LABEL, mcFastBufferLabel); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_COLOR, mcFastColor); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_BEGIN, mcFastLength); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_TYPE, mcFastDrawType); + + // + // MC Slow Buffer ... + string mcSlowBufferLabel = ShortName + " MC Slow (" + (string)mcSlowLength + ")"; + ENUM_DRAW_TYPE mcSlowDrawType = mcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcSlowBuffer, true); + SetIndexBuffer(mcSlowBufferIndex, mcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(mcSlowBufferIndex, PLOT_LABEL, mcSlowBufferLabel); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_COLOR, mcSlowColor); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_BEGIN, mcSlowLength); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_TYPE, mcSlowDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC Fast Buffer ... + string scFastBufferLabel = ShortName + " SC Fast (" + (string)scFastLength + ")"; + ENUM_DRAW_TYPE scFastDrawType = scDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scFastBuffer, true); + SetIndexBuffer(scFastBufferIndex, scFastBuffer, INDICATOR_DATA); + PlotIndexSetString(scFastBufferIndex, PLOT_LABEL, scFastBufferLabel); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_COLOR, scFastColor); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_BEGIN, scFastLength); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_TYPE, scFastDrawType); + + // + // SC Slow Buffer ... + string scSlowBufferLabel = ShortName + " SC Slow (" + (string)scSlowLength + ")"; + ENUM_DRAW_TYPE scSlowDrawType = scDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scSlowBuffer, true); + SetIndexBuffer(scSlowBufferIndex, scSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(scSlowBufferIndex, PLOT_LABEL, scSlowBufferLabel); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_COLOR, scSlowColor); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_BEGIN, scSlowLength); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_TYPE, scSlowDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Init Handlers ... +bool LCInitHandlers() +{ + // + ResetLastError(); + + // + // LC Fast Handler ... + lcFastHandler = iMA( + _Symbol, + _Period, + lcFastLength, + 0, + lcMethod, + lcAppliedTo); + if (lcFastHandler == INVALID_HANDLE) + { + // + LogMessage("LC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // LC Slow Handler ... + lcSlowHandler = iMA( + _Symbol, + _Period, + lcSlowLength, + 0, + lcMethod, + lcAppliedTo); + if (lcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("LC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// MC Init Handlers ... +bool MCInitHandlers() +{ + // + ResetLastError(); + + // + // MC Fast Handler ... + mcFastHandler = iMA( + _Symbol, + _Period, + mcFastLength, + 0, + mcMethod, + mcAppliedTo); + if (mcFastHandler == INVALID_HANDLE) + { + // + LogMessage("MC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // MC Slow Handler ... + mcSlowHandler = iMA( + _Symbol, + _Period, + mcSlowLength, + 0, + mcMethod, + mcAppliedTo); + if (mcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("MC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// SC Init Handlers ... +bool SCInitHandlers() +{ + // + ResetLastError(); + + // + // SC Fast Handler ... + scFastHandler = iMA( + _Symbol, + _Period, + scFastLength, + 0, + scMethod, + scAppliedTo); + if (scFastHandler == INVALID_HANDLE) + { + // + LogMessage("SC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // SC Slow Handler ... + scSlowHandler = iMA( + _Symbol, + _Period, + scSlowLength, + 0, + scMethod, + scAppliedTo); + if (scSlowHandler == INVALID_HANDLE) + { + // + LogMessage("SC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// LC State ... +double GetLCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// MC State ... +double GetMCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// SC State ... +double GetSCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcFast = lcFastBuffer[bar_index]; + double lcSlow = lcSlowBuffer[bar_index]; + // + double lcFastPrev = lcFastBuffer[bar_index + 1]; + double lcSlowPrev = lcSlowBuffer[bar_index + 1]; + // + double lcState = GetLCState(bar_index); + + // + // MC ... + double mcFast = mcFastBuffer[bar_index]; + double mcSlow = mcSlowBuffer[bar_index]; + // + double mcFastPrev = mcFastBuffer[bar_index + 1]; + double mcSlowPrev = mcSlowBuffer[bar_index + 1]; + // + double mcState = GetMCState(bar_index); + + // + // SC ... + double scFast = scFastBuffer[bar_index]; + double scSlow = scSlowBuffer[bar_index]; + // + double scFastPrev = scFastBuffer[bar_index + 1]; + double scSlowPrev = scSlowBuffer[bar_index + 1]; + // + double scState = GetSCState(bar_index); + + // + // Detect HOT Bearish Area ... + bool isHotBearishArea = + lcFast < lcSlow && + mcFast < mcSlow && + scFast < scSlow; + // + bool isPrevHotBearishArea = + lcFastPrev < lcSlowPrev && + mcFastPrev < mcSlowPrev && + scFastPrev < scSlowPrev; + + // + // Detect HOT Bearish Area ... + bool isHotBullishArea = + lcFast > lcSlow && + mcFast > mcSlow && + scFast > scSlow; + // + bool isPrevHotBullishArea = + lcFastPrev > lcSlowPrev && + mcFastPrev > mcSlowPrev && + scFastPrev > scSlowPrev; + + // + // Generate HotState Value ... + double hotStateValue = + isHotBullishArea && !isPrevHotBullishArea + ? 1 + : isHotBearishArea && !isPrevHotBearishArea + ? -1 + : 0; + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotBullishArea = hotStateValue == 1; + bool isHotBearishArea = hotStateValue == -1; + if (isHotBullishArea || isHotBearishArea) + { + // + bool isBull = isHotBullishArea; + + // + double price = isBull ? candle.low : candle.high; + ENUM_ARROW_ANCHOR anchor = isBull ? ANCHOR_TOP : ANCHOR_BOTTOM; + color clr = isBull ? hotBullishArrowColor : hotBearishArrowColor; + uchar arrowCode = isBull ? hotBullishArrowCode : hotBearishArrowCode; + string name = "HOT " + (isBull ? "Bullish" : "Bearish") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); + } + } + + // + // Draw LC Crosses ... + if (lcDrawCrosses) + { + // + double lcStateValue = GetLCState(bar_index); + bool isLcFastCrossedOverSlow = lcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isLcFastCrossedUnderSlow = lcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isLcFastCrossedOverSlow || isLcFastCrossedUnderSlow) + { + // + bool isBull = isLcFastCrossedOverSlow; + + // + color clr = isBull ? lcFastColor : lcSlowColor; + string name = "LC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw MC Crosses ... + if (mcDrawCrosses) + { + // + double mcStateValue = GetMCState(bar_index); + bool isMcFastCrossedOverSlow = mcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isMcFastCrossedUnderSlow = mcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isMcFastCrossedOverSlow || isMcFastCrossedUnderSlow) + { + // + bool isBull = isMcFastCrossedOverSlow; + + // + color clr = isBull ? mcFastColor : mcSlowColor; + string name = "MC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw SC Crosses ... + if (scDrawCrosses) + { + // + double scStateValue = GetSCState(bar_index); + bool isScFastCrossedOverSlow = scStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isScFastCrossedUnderSlow = scStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isScFastCrossedOverSlow || isScFastCrossedUnderSlow) + { + // + bool isBull = isScFastCrossedOverSlow; + + // + color clr = isBull ? scFastColor : scSlowColor; + string name = "SC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } +} +// +// END Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xobd.oscillator.mq5 b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xobd.oscillator.mq5 new file mode 100644 index 0000000..c7907ce --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xobd.oscillator.mq5 @@ -0,0 +1,328 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Oscillator +// ------------------------------------------------------ +// Name: XOBD +// Description: detect Order Blocks based on Swings ... +// +// +// 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 XOBD Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XOBD" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input int length = 288; // Market Length + +// +// START Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5"; + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5"; + +// +// START Buffers ... +// + +// +#property indicator_separate_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +#define swingHighBufferIndex 0 +#define swingLowBufferIndex 1 +#define signalBufferIndex 2 + +// +double swingHighBuffer[]; +double swingLowBuffer[]; +double signalBuffer[]; + +// +#property indicator_label1 "XSwing High" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#property indicator_label2 "XSwing Low" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrFuchsia +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#property indicator_label3 "XSignal" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // 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, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + 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() +{ + // + // Swing High ... + string swingHighBufferLabel = ShortName + " Swing H (" + (string) length + ")"; + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(swingHighBufferIndex, PLOT_LABEL, swingHighBufferLabel); + + // + // Swing Low ... + string swingLowBufferLabel = ShortName + " Swing L (" + (string) length + ")"; + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(swingLowBufferIndex, PLOT_LABEL, swingLowBufferLabel); + + // + // Signal ... + string signalBufferLabel = ShortName + " Signal (" + (string) length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// 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) +{ + // + int inCycleSwingHighCount = 0; + int inCycleSwingLowCount = 0; + + // + // Loop Back Through Cycle ... + for (int i = bar_index; i < bar_index + length; i++) { + // + ENUM_X_SWING_TYPE iSwingType = GetCandleSwing(i); + if (iSwingType == X_NO_SWING) { + continue; + } + + // + if (iSwingType == X_SWING_HIGH) { + inCycleSwingHighCount++; + } else if (iSwingType == X_SWING_LOW) { + inCycleSwingLowCount++; + } + } + + // + swingHighBuffer[bar_index] = inCycleSwingHighCount; + swingLowBuffer[bar_index] = inCycleSwingLowCount; + + // + signalBuffer[bar_index] = inCycleSwingLowCount - inCycleSwingHighCount; +} + +// +// END Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xrsi.oscillator.mq5 b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 0000000..dda4f63 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xrsi.oscillator.mq5 @@ -0,0 +1,358 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Oscillator +// ------------------------------------------------------ +// Name: XRSI +// Description: detect market conditions based on RSI ... +// +// +// 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 XRSI Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XRSI" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 14; // Market Length +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +input group "Short Entry"; +input double shortEntryValue = 70; // Short Entry Level +input color shortEntryColor = clrRed; // Short Entry Level Color +input ENUM_LINE_STYLE shortEntryLineStyle = STYLE_SOLID; // Short Entry Style + +// +input group "Short Exit"; +input double shortExitValue = 40; // Short Exit Level +input color shortExitColor = clrFuchsia; // Short Exit Level Color +input ENUM_LINE_STYLE shortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +input group "Long Entry"; +input double longEntryValue = 30; // Long Entry Level +input color longEntryColor = clrGreen; // Long Entry Level Color +input ENUM_LINE_STYLE longEntryLineStyle = STYLE_SOLID; // Long Entry Style + +// +input group "Long Exit"; +input double longExitValue = 60; // Long Exit Level +input color longExitColor = clrAqua; // Long Exit Level Color +input ENUM_LINE_STYLE longExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// START Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5"; + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5"; + +// +// START Buffers ... +// + +// +#property indicator_separate_window +#property indicator_buffers 1 +#property indicator_plots 1 + +// +#define rsiBufferIndex 0 + +double rsiBuffer[]; + +#property indicator_label1 "XRSI" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int rsiHandler = 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; + + // + rsiHandler = iRSI( + _Symbol, + _Period, + length, + appliedTo); + if (rsiHandler == INVALID_HANDLE) + { + 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(rsiHandler); +} + +// +// 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, length); + + // + int rsiCalculatedBars = BarsCalculated(rsiHandler); + if (rsiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + int rsiCopiedItems = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + if (rsiCopiedItems <= 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 = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RSI ... + string rsiBufferLabel = ShortName + " (" + (string)length + ")"; + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rsiBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(rsiBufferIndex, PLOT_LABEL, rsiBufferLabel); + + // + // Set Indicator Levels here ... + // OB, ExitLong, ExitShort, OS ... + IndicatorSetInteger(INDICATOR_LEVELS, 4); + + // + // SHORTENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, shortEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, shortEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, shortEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 0, "Short Entry"); + + // + // LONGEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, longExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, longExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, shortExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 1, "Long Exit"); + + // + // SHORTEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, shortExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 2, shortExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 2, longEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 2, "Short Exit"); + + // + // LONGENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 3, longEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 3, longEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 3, longExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 3, "Long Entry"); + + // + // Set Maximum and Minimum for subwindow + IndicatorSetInteger(INDICATOR_DIGITS, 2); + IndicatorSetDouble(INDICATOR_MINIMUM, 0); + IndicatorSetDouble(INDICATOR_MAXIMUM, 100); +} + +// +// 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) +{ +} + +// +// END Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtd.oscillator.mq5 b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 0000000..675c149 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtd.oscillator.mq5 @@ -0,0 +1,465 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Trend Detector Oscillator +// -------------------------------------------------- +// Name: XTD +// Description: trend detecting in both sides ... +// +// +// 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 XTD Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTD" + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; +// +// END Constants ... +// + +// +// Include Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5"; + +// +// START Inputs ... +// +input int length = 14; // Market Length +input bool drawCrosses = true; // Draw Cross Arrows + +// +// Bullish ... +input uchar bullishArrowCode = 228; // Cross Over Arrow Code +input color bullishArrowColor = clrAqua; // Cross Over Arrow Color + +// +// Bearish ... +input uchar bearishArrowCode = 230; // Cross Under Arrow Code +input color bearishArrowColor = clrMagenta; // Cross Under Arrow Color +// +// END Inputs ... +// + +// +// 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"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +#define bullishBufferIndex 0 +#define bearishBufferIndex 1 +#define signalBufferIndex 2 + +// +double bullishBuffer[]; +double bearishBuffer[]; +double signalBuffer[]; + +// +#property indicator_label1 "XBullPower" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#property indicator_label2 "XBearPower" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#property indicator_label3 "XSignal" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +int xtdBullishCandleCount = 0; +int xtdBearishCandleCount = 0; +// +// 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; + + // + // 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 ... + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); +} + +// +// 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, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i, close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 5) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish Buffer ... + string bullishBufferLabel = ShortName + "BullPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bullishBuffer, true); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bullishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bullishBufferIndex, PLOT_LABEL, bullishBufferLabel); + + // + // Bearish Buffer ... + string bearishBufferLabel = ShortName + "BearPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bearishBuffer, true); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bearishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bearishBufferIndex, PLOT_LABEL, bearishBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + "Signal " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// 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, + const double &close[]) +{ + // + // Reset Global Counters ... + xtdBullishCandleCount = 0; + xtdBearishCandleCount = 0; + + // + // Loop through Closes ... + for (int i = bar_index; i <= bar_index + length; i++) + { + for (int j = i + 1; j <= bar_index + length; j++) + { + // + if (close[i] > close[j]) + { + xtdBullishCandleCount++; + } + + // + if (close[i] < close[j]) + { + xtdBearishCandleCount++; + } + } + } + + // + // Bullish Power Buffer ... + bullishBuffer[bar_index] = MathAbs(xtdBullishCandleCount); + + // + // Bearish Power Buffer ... + bearishBuffer[bar_index] = MathAbs(xtdBearishCandleCount); + + // + // Signal Buffer ... + signalBuffer[bar_index] = bullishBuffer[bar_index] - bearishBuffer[bar_index]; + + // + // Check and Draw Crosses if it's Specified ... + if (drawCrosses) + { + DrawCrosses(bar_index); + } +} + +// +// +double GetState( + int bar_index // Specified Bar Index +) +{ + // + // Check Cross Points ... + // bullishCrossedOverBearish = 2; + // bullishOverBearish = 1; + // bullishCrossedUnderBearish = -2; + // bullishUnderBearish = -1; + // OtherWise = 0; + bool isBullishCrossedOverBearish = IsCrossOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishCrossedUnderBearish = IsCrossUnder( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishOverBearish = IsOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishUnderBearish = IsUnder( + bullishBuffer, + bearishBuffer, + bar_index); + + // + double result = X_XTD_NEUTURAL; + if (isBullishCrossedOverBearish) + { + result = X_XTD_BULLISH_CROSSED_OVER_BEARISH; + } + else if (isBullishCrossedUnderBearish) + { + result = X_XTD_BULLISH_CROSSED_UNDER_BEARISH; + } + else if (isBullishOverBearish) + { + result = X_XTD_BULLISH_OVER_BEARISH; + } + else if (isBullishUnderBearish) + { + result = X_XTD_BULLISH_UNDER_BEARISH; + } + else + { + result = X_XTD_NEUTURAL; + } + + // + return result; +} + +// +// Draw Crosses ... +void DrawCrosses( + int bar_index // the bars which required to draw cross arrow on it ... +) +{ + // + double stateValue = GetState(bar_index); + + // + bool isOver = stateValue == 2; + double low = iLow(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + + // + double price = isOver ? low : high; + datetime time = iTime(_Symbol, _Period, bar_index); + ENUM_ARROW_ANCHOR anchor = isOver ? ANCHOR_TOP : ANCHOR_BOTTOM; + uchar arrowCode = isOver ? bullishArrowCode : bearishArrowCode; + color arrowColor = isOver ? bullishArrowColor : bearishArrowColor; + string crossName = "Trend " + (isOver ? "Up" : "Down") + "_" + (string)time + "_" + (string)price; + + // + DrawArrow( + 0, + crossName, + 0, + time, + price, + arrowCode, + anchor, + arrowColor); +} +// +// END Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtm.indicator.mq5 b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 0000000..fac9877 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Indicators/x-saherelm.xtm.indicator.mq5 @@ -0,0 +1,349 @@ +/////////////////////////////////////////////////////// +// +// 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 int maPeriod = 14; // Period +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Applied To +// +// 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() +{ + // + string maBufferLabel = "XTM " + "(" + (string)maPeriod + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // 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/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.alert.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 0000000..9ccf667 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.alert.lib.mq5 @@ -0,0 +1,197 @@ +/////////////////////////////////////////////////////// +// +// 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 = true; // Terminal Alerts +input bool mailAlerts = true; // Mail Alerts +input bool pushAlerts = true; // 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) +{ + // + 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); + } +} +void SendAlert( + XSignal &signal, // the Signal Object which requred to Alert + bool asExecuted = true // determines Alert Signal as Executed Signal or not +) +{ + // + // Prepare Message ... + string message = asExecuted ? ExecutedSignalToString(signal) : SignalToString(signal); + + // + // Do Alerting ... + SendAlert(message); +} +// +// END Provided Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.class.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.class.lib.mq5 new file mode 100644 index 0000000..4ede425 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.class.lib.mq5 @@ -0,0 +1,3991 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XClass +// Description: provides all classes for use ... +// +// +// 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 +#include +#include +#include +#include "x-saherelm.draw.lib.mq5" +#include "x-saherelm.models.lib.mq5" +#include "x-saherelm.common.lib.mq5" +#include + +// +// START Model Definitions ... +// +// +// END Model Definitions ... +// + +// +// START Overrides ... +// +class XSCTrade : public CTrade +{ +public: + // + // Specific Position Close ... + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment // Comment For Close + ) + { + // + bool result = false; + + // + // check stopped ... + if (IsStopped(__FUNCTION__)) + { + return result; + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return result; + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // Clean ... + ClearStructures(); + + // + // Check Position Type ... + // BUY / LONG ... + 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); + } + // + // SELL / Short ... + else + { + // + // Prepare Request for Close SELL Position ... + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // Setting Request Fields ... + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.position = ticket; + m_request.action = TRADE_ACTION_DEAL; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; // PositionGetString(POSITION_COMMENT); // "Comment anything"; + + // + // Log Info on Screen ... + PrintFormat("PositionClose #%I64d %s %.2f", ticket, EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)), m_request.volume); + + // + // Close Position ... + result = (OrderSend(m_request, m_result)); + + // + return result; + } + + // + // Specific Position Close ... + bool PositionClose( + const ulong ticket, // Position Ticket + const string comment = "" // Comment For Close + ) + { + // + bool result = false; + + // + // check stopped ... + if (IsStopped(__FUNCTION__)) + { + return result; + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return result; + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // Clean ... + ClearStructures(); + + // + // Check Position Type ... + // BUY / LONG ... + 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); + } + // + // SELL / Short ... + else + { + // + // Prepare Request for Close SELL Position ... + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // Setting Request Fields ... + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.position = ticket; + m_request.deviation = m_deviation; + m_request.action = TRADE_ACTION_DEAL; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + + // + // Specify Comment ... + m_request.comment = comment; // PositionGetString(POSITION_COMMENT); // "Comment anything"; + + // + // Log Info on Screen ... + PrintFormat("PositionClose #%I64d %s %.2f", ticket, EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)), m_request.volume); + + // + // Close Position ... + result = (OrderSend(m_request, m_result)); + + // + return result; + } +}; +// +// END Overrides ... +// + +// +// XSaherElm Account Info Class ... +class XCAccountInfo +{ + // + // Public properties ... +public: + // + // Constructro ... + void XCAccountInfo() + { + // + mAccountInfo = new CAccountInfo(); + + // + mInitialBalance = mAccountInfo.Balance(); + } + + // + // Deconstructor ... + void ~XCAccountInfo() + { + // + mInitialBalance = 0; + } + + // + // 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) ... + ENUM_ACCOUNT_TRADE_MODE GetTradeMode() + { + return mAccountInfo.TradeMode(); + } + + // + // Get Account Balance ... + double GetBalance() + { + return mAccountInfo.Balance(); + } + + // + // Get Initial Deposit Balance ... + double GetInitialBalance() + { + return mInitialBalance; + } + + // + // 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; + } + + // + // Protected properties ... +protected: + // + // Private properties ... +private: + // + // Initial Account Balance ... + double mInitialBalance; + + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// XSaherElm Trade Class ... +class XCTrade +{ + // + // all public features ... +public: + // + // Constructor ... + void XCTrade( + string tag, // Specify a Tag for Trader instance + string symbol, // Specify Trader Symbol + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + int maxAllowedTrades, // Specify Max Allowed Trades + int maxAllowedSupportTrades, // Specify Max Allowed Support Trades for each Trade + double minTradeProfitsInPips, // Minimum Profit of each Trade in Pips + double supportTradesPriceDistanceInPips, // Support Trades Price Distance in Pips + double minAllowedFreeMarginForOpenTrades, // Minimum Free Marging for Open Trades + double minBallanceForOpenTrades // Minimum Balance for Open Trades + ) + { + // + mTag = tag; + mSymbol = symbol; + mSlippage = slippage; + mMagicNumber = magicNumber; + mMaxAllowedTrades = maxAllowedTrades; + mMinTradeProfitsInPips = minTradeProfitsInPips; + mMaxAllowedSupportTrades = maxAllowedSupportTrades; + mMinBallanceForOpenTrades = minBallanceForOpenTrades; + mSupportTradesPriceDistanceInPips = supportTradesPriceDistanceInPips; + mMinAllowedFreeMarginForOpenTrades = minAllowedFreeMarginForOpenTrades; + + // + mTrader = new XSCTrade(); + + // + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + } + + // + // Deconstructor ... + void ~XCTrade() + { + } + + // + // Count Open Positions ... + int Count() + { + // + int result = 0; + + // + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + result++; + } + + // + return result; + } + + // + // Count Longs ... + int CountLongs() + { + int result = CountByType(X_SIGNAL_LONG); + return result; + } + + // + // Count Shorts ... + int CountShorts() + { + int result = CountByType(X_SIGNAL_SHORT); + return result; + } + + // + // Count By Type ... + int CountByType(ENUM_X_SIGNAL_TYPE type) + { + // + // Validate Args ... + ENUM_POSITION_TYPE mType = POSITION_TYPE_BUY; + if (type == X_SIGNAL_LONG) + { + mType = POSITION_TYPE_BUY; + } + else if (type == X_SIGNAL_SHORT) + { + mType = POSITION_TYPE_SELL; + } + + // + int result = CountByType(mType); + return result; + } + + // + // Count By Type and Kind ... + int CountByKind( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind // Specify Kind of Positions + ) + { + // + int result = 0; + + // + XSignal trades[]; + GetPositionsByKind( + type, + kind, + trades); + + // + result = ArraySize(trades); + + // + return result; + } + int CountByKind( + ENUM_X_SIGNAL_KIND kind // Specify Kind of Positions + ) + { + // + int result = 0; + + // + // Count Longs ... + result = CountByKind( + X_SIGNAL_UNKNOWN, + kind); + + // + return result; + } + + // + // Count Supported Positions belongs to Specified Parent Signal ... + int CountSupportedPositions( + XSignal &parent // Specified Parent Signal + ) + { + // + int result = 0; + + // + XSignal supports[]; + GetSupportedPositions(parent, supports); + result = ArraySize(supports); + + // + return result; + } + + // + // Retrieve Specified Position by it's Ticket ... + XSignal GetPosition( + ulong ticket // Specified Ticket + ) + { + // + XSignal result = {}; + + // + result = PositionToSignal(ticket); + + // + return result; + } + + // + // Retrieve all Positions ... + void GetAllPositions( + XSignal &result[] // Holds Result ... + ) + { + // + CleanBuffer(result); + + // + int totalPositions = PositionsTotal(); + for (int i = 0; i < totalPositions; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + // Position to Signal ... + XSignal signal = PositionToSignal(i); + Add( + signal, + result); + } + } + + // + // Retrieve all Long Positions ... + void GetLongPositions( + XSignal &result[] // Holds Result ... + ) + { + GetAllPositionsByType(POSITION_TYPE_BUY, result); + } + + // + // Retrieve all Short Positions ... + void GetShortPositions( + XSignal &result[] // Holds Result ... + ) + { + GetAllPositionsByType(POSITION_TYPE_SELL, result); + } + + // + // Get Positions by Specified Type ... + void GetPositionsByType( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + XSignal &result[] // Holds Result ... + ) + { + // + CleanBuffer(result); + + // + switch (type) + { + // + case X_SIGNAL_LONG: + GetLongPositions(result); + break; + + // + case X_SIGNAL_SHORT: + GetShortPositions(result); + break; + + // + case X_SIGNAL_UNKNOWN: + default: + GetAllPositions(result); + break; + } + } + + // + // Get Positions by Specified Type and Kind ... + void GetPositionsByKind( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result ... + ) + { + // + CleanBuffer(result); + + // + XSignal trades[]; + switch (type) + { + // + case X_SIGNAL_LONG: + GetLongPositions(trades); + break; + + // + case X_SIGNAL_SHORT: + GetShortPositions(trades); + break; + + // + case X_SIGNAL_UNKNOWN: + default: + GetAllPositions(trades); + break; + } + + // + int count = ArraySize(trades); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + XSignal trade = trades[i]; + if (trade.kind != kind) + { + continue; + } + + // + Add( + trade, + result); + } + } + + // + // Retrieve List Of Supported Positions belongs to Specified Parent Signal ... + void GetSupportedPositions( + XSignal &parent, // Specified Parent Signal + XSignal &result[] // Holds Result ... + ) + { + // + CleanBuffer(result); + + // + // Validate Signal ... + bool isValidSignal = IsValid(parent, mMagicNumber); + if (!isValidSignal) + { + return; + } + + // + // Validate Signal is Parent Signal ... + bool isParentSignal = parent.kind == X_KIND_TRADE; + if (!isParentSignal) + { + return; + } + + // + // Retrieve All Support Signals ... + XSignal supports[]; + GetPositionsByKind( + X_SIGNAL_UNKNOWN, + X_KIND_SUPPORT, + supports); + int supportsCount = ArraySize(supports); + if (supportsCount <= 0) + { + return; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XSignal support = supports[i]; + + // + bool isBelongsToParent = support.parent == parent.ticket; + if (isBelongsToParent) + { + // + Add( + support, + result); + } + } + } + + // + // Get All Trades Which Candle Passed after Open ... + void GetLongTimeTrades( + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period, // Calculate Candles based on time frame + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result + ) + { + // + CleanBuffer(result); + + // + // Normalize Period ... + if (period == EMPTY_VALUE) + { + period = _Period; + } + + // + XSignal positions[]; + GetPositionsByKind( + type, + kind, + positions); + int count = ArraySize(positions); + if (count <= 0) + { + return; + } + + // + // Current Time Frame Candle Index ... + int currentBarIndex = 0; + + // + // Loop through Positions ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = positions[i]; + + // + // Retrieve Trade Open Bar Index based on Current Period ... + int tradeOpenBarIndex = iBarShift( + mSymbol, + period, + trade.time); + + // + // Calculate Trade Life ... + int diff = MathAbs(currentBarIndex - tradeOpenBarIndex); + if (diff >= life) + { + // + Add( + trade, + result); + } + } + } + + // + // Get In DrawDown Trades ... + void GetInDrawDownTrades( + double maxDrawDown, // Maximum DrawDown of Trades + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result + ) + { + // + CleanBuffer(result); + + // + // Validate Args ... + if (maxDrawDown <= 0) + { + maxDrawDown = 0; + } + + // + XSignal trades[]; + + // + // Retrieve Signals ... + GetPositionsByKind( + type, + kind, + trades); + + // + // Check Trades Count ... + int count = ArraySize(trades); + if (count <= 0) + { + return; + } + + // + // Loop through all retrieved trades ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = trades[i]; + if (trade.profit > 0) + { + continue; + } + + // + bool isPassed = maxDrawDown == 0 ? true : (-1 * trade.profit) >= maxDrawDown; + if (isPassed) + { + // + Add( + trade, + result); + } + } + } + + // + // Get In Profit Trades ... + void GetInProfitTrades( + double minProfit, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result + ) + { + // + CleanBuffer(result); + + // + XSignal trades[]; + GetPositionsByKind( + type, + kind, + result); + + // + // Check Trades Count ... + int count = ArraySize(trades); + if (count <= 0) + { + return; + } + + // + // Loop through all retrieved trades ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = trades[i]; + if (trade.profit < 0) + { + continue; + } + + // + bool isPassed = minProfit <= 0 ? true : trade.profit >= minProfit; + if (isPassed) + { + // + Add( + trade, + result); + } + } + } + + // + // Filter Trades by Searching Comments ... + void FilterTrades( + string query, // Search String + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result + ) + { + // + // Free Buffer ... + CleanBuffer(result); + + // + XSignal source[]; + GetPositionsByKind( + type, + kind, + source); + int sourceCount = ArraySize(source); + + // + if (sourceCount <= 0) + { + return; + } + + // + // Do Filtering Signals ... + FilterSignals( + query, + source, + result); + } + + // + // Filter In DrawDown Trades by Searching Comments ... + void FilterInDrawDowntTrades( + string query, // Search String + double maxDrawDown, // Maximum DrawDown of Trades + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result + ) + { + // + // Free Buffer ... + CleanBuffer(result); + + // + XSignal source[]; + GetInDrawDownTrades( + maxDrawDown, + type, + kind, + source); + int sourceCount = ArraySize(source); + + // + if (sourceCount <= 0) + { + return; + } + + // + // Do Filtering Signals ... + FilterSignals( + query, + source, + result); + } + + // + // Filter In DrawDown Trades by Searching Comments ... + void FilterInProfitTrades( + string query, // Search String + double minProfit, // Minimum Profit of Trades + ENUM_X_SIGNAL_TYPE type, // Specify trades type to act + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &result[] // Holds Result + ) + { + // + // Free Buffer ... + CleanBuffer(result); + + // + XSignal source[]; + GetInProfitTrades( + minProfit, + type, + kind, + source); + int sourceCount = ArraySize(source); + + // + if (sourceCount <= 0) + { + return; + } + + // + // Do Filtering Signals ... + FilterSignals( + query, + source, + result); + } + + // + // Filter Trades by Searching Comments ... + void FilterTrades( + string query, // Search String + XSignal &source[], // Source Buffer to Filter + XSignal &result[] // Holds Result + ) + { + // + // Free Buffer ... + CleanBuffer(result); + + // + // Do Filtering Signals ... + FilterSignals( + query, + source, + result); + } + + // + // Force Open a Buy/Long Position ... + bool Buy( + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + const string comment = "" // comment + ) + { + // + bool result = false; + + // + result = mTrader.Buy( + volume, + mSymbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Force Open a Sell/Short Position ... + bool Sell( + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + const string comment = "" // comment + ) + { + // + bool result = false; + + // + result = mTrader.Sell( + volume, + mSymbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Validate Signal ... + bool ValidateSignal( + XSignal &signal // Specify Signal for Execution + ) + { + // + bool result = false; + + // + // Validate Signal Type ... + result = signal.type != X_SIGNAL_UNKNOWN; + if (!result) + { + return result; + } + + // + // Check Symbol ... + result = StringLen(signal.symbol) == 0 ? true : signal.symbol == mSymbol; + if (!result) + { + return result; + } + + // + // Check magic number ... + result = signal.magicNumber <= 0 ? true : signal.magicNumber == mMagicNumber; + if (!result) + { + return result; + } + + // + // Check Entry ... + result = signal.entry > 0; + if (!result) + { + return result; + } + + // + // Check SL ... + result = signal.sl == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.sl < signal.entry + : signal.sl > signal.entry; + if (!result) + { + return result; + } + + // + // Check TP ... + result = signal.tp == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.tp > signal.entry + : signal.tp < signal.entry; + if (!result) + { + return result; + } + + // + // Check Volume ... + result = signal.volume > 0; + if (!result) + { + return result; + } + + // + // Check Time ... + result = signal.time > 0; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Execute an Specific XSignal instance ... + bool ExecuteSignal( + XSignal &signal, // Specify Signal for Execution + int &error // Error code if Happens + ) + { + // + bool result = false; + + // + // Validate Signal ... + result = ValidateSignal(signal); + if (!result) + { + // + error = X_INVALID_SIGNAL_ERROR; + return result; + } + + // + signal.symbol = mSymbol; + + // + bool isTrade = signal.kind == X_KIND_TRADE; + + // + // Check Account Balance ... + result = IsAccountBalanceReadyForTrade(); + if (!result) + { + // + error = X_XTRADER_NOT_ENOUGH_BALANCE_ERROR; + return result; + } + + // + // Check Account Free Margin ... + result = IsFreeMarginReadyForTrade(); + if (!result) + { + // + error = X_XTRADER_NOT_ENOUGH_MARIGIN_ERROR; + return result; + } + + // + // Check Can Open Trades ... + result = CanOpenNewTrade( + signal.type, + signal.kind); + if (!result) + { + error = isTrade ? + // + X_XTRADER_MAX_ALLOWED_TRADE_KIND_REACHED_ERROR + : + // + X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR + // + ; + } + + // + ResetLastError(); + + // + // Execute Signal Trade ... + result = + // + signal.type == X_SIGNAL_LONG + // + ? + // + Buy( + signal.volume, + signal.entry, + signal.sl, + signal.tp, + signal.comment) + // + : + // + signal.type == X_SIGNAL_SHORT + // + ? + // + Sell( + signal.volume, + signal.entry, + signal.sl, + signal.tp, + signal.comment) + // + : + // + false + // + ; + + // + // if (!result) + // { + // // + // int errorCode = GetLastError(); + + // // + // // Not Enough Money, since Volume is High ... + // if (errorCode == 4756) + // { + // // + // signal.volume = NormalizeVolume(signal.volume / 3); + // result = ExecuteSignal( + // signal, + // error); + // } + // } + + // + if (result) + { + // + error = X_SUCCEED_EXECUTION; + + // + ulong positionTicket = 0; + if (mPositionInfo.SelectByIndex(PositionsTotal() - 1)) + { + positionTicket = mPositionInfo.Ticket(); + } + + // + signal.id = positionTicket; + signal.ticket = positionTicket; + + // + // Draw Signal On Chart ... + DrawSignalEvent(signal); + } + else + { + error = X_UNKNOWN_ERROR; + } + + // + return result; + } + + // + // Execute Support Signal ... + bool ExecuteSupportSignal( + XSignal &signal, // Specify Signal for Execution + int &error // Error code if Happens + ) + { + // + bool result = false; + error = X_UNKNOWN_ERROR; + + // + // Validate Signal ... + result = ValidateSignal(signal); + if (!result) + { + // + error = X_INVALID_SIGNAL_ERROR; + return result; + } + + // + // Determines Signal is Long or Short ... + bool isLong = signal.type == X_SIGNAL_LONG; + + // + // Check Signal Kind ... + result = signal.kind == X_KIND_SUPPORT; + if (!result) + { + // + error = X_INVALID_SIGNAL_ERROR; + return result; + } + + // + // Check Signal Kind Based Properties ... + result = signal.parent > 0; + if (!result) + { + // + error = X_INVALID_SIGNAL_ERROR; + return result; + } + + // + // Check Support Trade Parent Position Existance ... + XSignal parent = GetPosition(signal.parent); + result = IsValid(parent, mMagicNumber); + if (!result) + { + // + error = X_INVALID_SIGNAL_ERROR; + return result; + } + + // + // Check Max Number Of Support Trades which belongs to Parent ... + int supportsCount = CountSupportedPositions(parent); + result = supportsCount < mMaxAllowedSupportTrades; + if (!result) + { + // + error = X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR; + return result; + } + + // + // Check Support Trade Price Distance Passed ... + double supportTradesPriceDistance = PipsToPrice(mSupportTradesPriceDistanceInPips); + double supportPriceDistance = MathAbs(parent.entry - signal.entry); + result = supportPriceDistance >= supportTradesPriceDistance; + if (!result) + { + // + error = X_TRADER_SUPPORT_DISTANCE_NOT_HAPPENS_ERROR; + return result; + } + + // + // Check Account Balance ... + result = IsAccountBalanceReadyForTrade(); + if (!result) + { + // + error = X_XTRADER_NOT_ENOUGH_BALANCE_ERROR; + return result; + } + + // + ResetLastError(); + + // + // Execute Signal Trade ... + result = + // + signal.type == X_SIGNAL_LONG + // + ? + // + Buy( + signal.volume, + signal.entry, + signal.sl, + signal.tp, + signal.comment) + // + : + // + signal.type == X_SIGNAL_SHORT + // + ? + // + Sell( + signal.volume, + signal.entry, + signal.sl, + signal.tp, + signal.comment) + // + : + // + false + // + ; + + // + // if (!result) + // { + // // + // int errorCode = GetLastError(); + + // // + // // Not Enough Money, since Volume is High ... + // if (errorCode == 4756) + // { + // // + // signal.volume = NormalizeVolume(signal.volume / 3); + // result = ExecuteSupportSignal( + // signal, + // error); + // } + // } + + // + if (result) + { + // + error = X_SUCCEED_EXECUTION; + + // + ulong positionTicket = 0; + if (mPositionInfo.SelectByIndex(PositionsTotal() - 1)) + { + positionTicket = mPositionInfo.Ticket(); + } + + // + signal.id = positionTicket; + signal.ticket = positionTicket; + + // + // Draw Signal On Chart ... + DrawSignalEvent(signal); + } + else + { + error = X_UNKNOWN_ERROR; + } + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0 // take profit + ) + { + // + bool result = false; + + // + // Validate Args ... + if (tp <= 0 && sl <= 0) + { + result = false; + return result; + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp); + + // + 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, + comment); + if (result) + { + RemoveSignal(ticket); + } + + // + return result; + } + + // + // Close Partial By Ticket ... + bool ClosePartial(ulong ticket, double volume) + { + // + bool result = false; + + // + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume); + + // + return result; + } + + // + // Partial Close all Reached Signals ... + void RiskFreeSignals( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &riskFrees[] // Holds all Executed Signals + ) + { + // + CleanBuffer(riskFrees); + + // + XSignal trades[]; + GetPositionsByKind( + type, + kind, + trades); + int count = ArraySize(trades); + if (count <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = trades[i]; + + // + // Ignore Not Risk Free Signal ... + if ( + trade.riskFree <= 0 || + (trade.riskFree > 0 && trade.riskFreeRate <= 0)) + { + continue; + } + + // + bool isLong = trade.type == X_SIGNAL_LONG; + + // + // Check Exit Price reached Risk Free ... + double exitPrice = GetExit(trade.type); + double isPriceReachedRiskFree = isLong ? exitPrice >= trade.riskFree : exitPrice <= trade.riskFree; + if (!isPriceReachedRiskFree) + { + continue; + } + + // + double volume = trade.volume; + double riskFreeRate = trade.riskFreeRate; + double riskFreeVolume = riskFreeRate * volume; + riskFreeVolume = NormalizeVolume(riskFreeVolume); + + // + // Check Trade Doesnt Closed Partial Before ... + // Check Volume is Enough for Partial Closing ... + if ( + trade.sl > 0 || + riskFreeVolume == volume) + { + continue; + } + + // + bool isPartialClosed = ClosePartial(trade.ticket, riskFreeVolume); + if (isPartialClosed) + { + // + bool isLong = trade.type == X_SIGNAL_LONG; + double entry = GetEntry(trade.symbol, trade.type); + + // + double tpValue = trade.tp; + double slDistance = 0; // PipsToPrice(2); + double slValue = isLong ? trade.entry - slDistance : trade.entry + slDistance; + + // + ResetLastError(); + bool isModified = Modify(trade.ticket, slValue, tpValue); + if (isModified) + { + // + Add( + trade, + riskFrees); + + // + LogMessage("Order: " + (string)trade.ticket + " Modification Succeed ..."); + } + else + { + LogMessage("Order: " + (string)trade.ticket + " Modification Failed: " + (string)GetLastError() + ", Desc: " + GetErrorDescription(GetLastError())); + } + } + } + } + void RiskFreeSignals( + XSignal &riskFrees[] // Holds all Executed Signals + ) + { + // + CleanBuffer(riskFrees); + + // + XSignal trades[]; + RiskFreeSignals( + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + trades); + int tradesCount = ArraySize(trades); + if (tradesCount > 0) + { + // + // Loop ... + for (int i = 0; i < tradesCount; i++) + { + // + XSignal fTrade = trades[i]; + + // + Add( + fTrade, + riskFrees); + } + } + + // + XSignal supports[]; + RiskFreeSignals( + X_SIGNAL_UNKNOWN, + X_KIND_SUPPORT, + supports); + int supportsCount = ArraySize(supports); + if (supportsCount > 0) + { + // + // Loop ... + for (int i = 0; i < supportsCount; i++) + { + // + XSignal fTrade = supports[i]; + + // + Add( + fTrade, + riskFrees); + } + } + } + + // + // Close All Open Positions ... + void CloseAllPositions( + XSignal &closed[] // Holds Closed Positions + ) + { + // + CleanBuffer(closed); + + // + XSignal allPositions[]; + GetAllPositions(allPositions); + + // + // Count all Specified Positions ... + int total = ArraySize(allPositions); + if (total <= 0) + { + return; + } + + // + for (int i = 0; i < total; i++) + { + // + XSignal signal = allPositions[i]; + string comment = GetSignalForceClosedComment(signal); + bool isClosed = Close( + signal.ticket, + comment); + if (isClosed) + { + // + Add( + signal, + closed); + } + } + } + + // + // Close Positions By Type ... + void ClosePositionsByType( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + XSignal &closed[] // Holds Closed Positions + ) + { + // + CleanBuffer(closed); + + // + XSignal allPositions[]; + GetPositionsByType( + type, + allPositions); + + // + // Count all Specified Positions ... + int total = ArraySize(allPositions); + if (total <= 0) + { + return; + } + + // + for (int i = 0; i < total; i++) + { + // + XSignal signal = allPositions[i]; + string comment = GetSignalForceClosedComment(signal); + bool isClosed = Close( + signal.ticket, + comment); + if (isClosed) + { + // + Add( + signal, + closed); + } + } + } + + // + // Close Positions By Kind ... + void ClosePositionsByKind( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &closed[] // Holds Closed Positions + ) + { + // + CleanBuffer(closed); + + // + XSignal allPositions[]; + GetPositionsByKind( + type, + kind, + allPositions); + + // + // Count all Specified Positions ... + int total = ArraySize(allPositions); + if (total <= 0) + { + return; + } + + // + for (int i = 0; i < total; i++) + { + // + XSignal signal = allPositions[i]; + string comment = GetSignalForceClosedComment(signal); + bool isClosed = Close( + signal.ticket, + comment); + if (isClosed) + { + // + Add( + signal, + closed); + } + } + } + + // + // Close All Trades Which Candle Passed after Open ... + void CloseLongTimeTrades( + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period, // Calculate Candles based on time frame + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + // Normalize Period ... + if (period == EMPTY_VALUE) + { + period = _Period; + } + + // + XSignal positions[]; + GetLongTimeTrades( + life, + period, + type, + kind, + positions); + int count = ArraySize(positions); + if (count <= 0) + { + return; + } + + // + // Loop through Positions ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = positions[i]; + string comment = GetSignalForceClosedComment(trade); + bool isClosed = Close( + trade.ticket, + comment); + if (isClosed) + { + // + Add( + trade, + closed); + } + } + } + void CloseLongTimeTrades( + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period, // Calculate Candles based on time frame + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + XSignal trades[]; + CloseLongTimeTrades( + life, + period, + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + trades); + int tradesCount = ArraySize(trades); + if (tradesCount > 0) + { + // + // Loop ... + for (int i = 0; i < tradesCount; i++) + { + // + XSignal fTrade = trades[i]; + + // + Add( + fTrade, + closed); + } + } + + // + XSignal supports[]; + CloseLongTimeTrades( + life, + period, + X_SIGNAL_UNKNOWN, + X_KIND_SUPPORT, + supports); + int supportsCount = ArraySize(supports); + if (supportsCount > 0) + { + // + // Loop ... + for (int i = 0; i < supportsCount; i++) + { + // + XSignal fTrade = supports[i]; + + // + Add( + fTrade, + closed); + } + } + } + + // + // Close In DrawDown Trades ... + void CloseInDrawDownTrades( + double maxDrawDown, // Maximum DrawDown of Trades + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + // Validate Args ... + if (maxDrawDown <= 0) + { + return; + } + + // + XSignal trades[]; + GetInDrawDownTrades( + maxDrawDown, + type, + kind, + trades); + + // + // Check Trades Count ... + int count = ArraySize(trades); + if (count <= 0) + { + return; + } + + // + // Loop through all retrieved trades ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = trades[i]; + string comment = GetSignalInDistanceClosedComment(trade); + bool isClosed = Close( + trade.ticket, + comment); + if (isClosed) + { + Add( + trade, + closed); + } + } + } + void CloseInDrawDownTrades( + double maxDrawDown, // Maximum DrawDown of Trades + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + XSignal trades[]; + CloseInDrawDownTrades( + maxDrawDown, + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + trades); + int tradesCount = ArraySize(trades); + if (tradesCount > 0) + { + // + // Loop ... + for (int i = 0; i < tradesCount; i++) + { + // + XSignal fTrade = trades[i]; + + // + Add( + fTrade, + closed); + } + } + + // + XSignal supports[]; + CloseInDrawDownTrades( + maxDrawDown, + X_SIGNAL_UNKNOWN, + X_KIND_SUPPORT, + supports); + int supportsCount = ArraySize(supports); + if (supportsCount > 0) + { + // + // Loop ... + for (int i = 0; i < supportsCount; i++) + { + // + XSignal fTrade = supports[i]; + + // + Add( + fTrade, + closed); + } + } + } + + // + // Close All In Profit Trades ... + void CloseInProfitTrades( + double minProfit, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type, // Specify trades type to act + ENUM_X_SIGNAL_KIND kind, // Specify Kind of Positions + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + XSignal trades[]; + GetInProfitTrades( + minProfit, + type, + kind, + trades); + + // + // Check Trades Count ... + int count = ArraySize(trades); + if (count <= 0) + { + return; + } + + // + // Loop through all retrieved trades ... + for (int i = 0; i < count; i++) + { + // + XSignal trade = trades[i]; + string comment = GetSignalInDistanceClosedComment(trade); + bool isClosed = Close( + trade.ticket, + comment); + if (isClosed) + { + Add( + trade, + closed); + } + } + } + void CloseInProfitTrades( + double minProfit, // Minimum Profit To Close Trades + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + XSignal trades[]; + CloseInProfitTrades( + minProfit, + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + trades); + int tradesCount = ArraySize(trades); + if (tradesCount > 0) + { + // + // Loop ... + for (int i = 0; i < tradesCount; i++) + { + // + XSignal fTrade = trades[i]; + + // + Add( + fTrade, + closed); + } + } + + // + XSignal supports[]; + CloseInProfitTrades( + minProfit, + X_SIGNAL_UNKNOWN, + X_KIND_SUPPORT, + supports); + int supportsCount = ArraySize(supports); + if (supportsCount > 0) + { + // + // Loop ... + for (int i = 0; i < supportsCount; i++) + { + // + XSignal fTrade = supports[i]; + + // + Add( + fTrade, + closed); + } + } + } + + // + // Pyramid Open Trades ... + void PyramidTrades( + XSignal &closed[] // Holds Closed Trades + ) + { + // + CleanBuffer(closed); + + // + // Check Open Positions In DrawDown Values ... + + // + // Trades ... + XSignal inDDTrades[]; + GetInDrawDownTrades( + 0, + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + inDDTrades); + int inDDTradesCount = ArraySize(inDDTrades); + + // + // Supports ... + XSignal inDDSupports[]; + GetInDrawDownTrades( + 0, + X_SIGNAL_UNKNOWN, + X_KIND_SUPPORT, + inDDSupports); + int inDDSupportsCount = ArraySize(inDDSupports); + + // + // Prevent Going Forward ... + if (inDDTradesCount == 0 && inDDSupportsCount == 0) + { + return; + } + + // + // Number Of In DD Trades ... + int count = inDDTradesCount + inDDSupportsCount; + if (count <= 1) + { + return; + } + + // + // Select Longest inDD ... + XSignal longestDD = {}; + + // + // Trades ... + if (inDDTradesCount > 0) + { + // + for (int i = 0; i < inDDTradesCount; i++) + { + // + XSignal iSignal = inDDTrades[i]; + + // + longestDD = longestDD.profit == 0 || longestDD.profit > iSignal.profit ? iSignal : longestDD; + } + } + + // + // Supports ... + if (inDDSupportsCount > 0) + { + // + for (int i = 0; i < inDDSupportsCount; i++) + { + // + XSignal iSignal = inDDSupports[i]; + + // + longestDD = longestDD.profit == 0 || longestDD.profit > iSignal.profit ? iSignal : longestDD; + } + } + + // + // Check Longest In DD ... + LogMessage("Longest (" + (string)count + ") inDD: " + (string)longestDD.ticket + ", Profit: " + (string)longestDD.profit); + + // + // Close Longest In DD ... + Close(longestDD.ticket, "Longets In Drawdown Position"); + + // + Add( + longestDD, + closed); + } + + // + // START Signal Related ... + // + + // + // Prepare a Signall ... + XSignal GenerateSignal( + ENUM_X_SIGNAL_TYPE type, // Signal Type + double tp = 0, // Take Profit + double sl = 0, // Stop Loss + double volume = 0, // Volume + double riskFree = 0, // Risk Free Price + double riskFreeRate = 0, // Risk Free Rate + ENUM_X_SIGNAL_KIND kind = X_KIND_TRADE, // Signal Kind + ulong parent = 0 // Support Kind Signal Parent + ) + { + // + XSignal result = {}; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + // Check Signal Type ... + bool isLong = type == X_SIGNAL_LONG; + + // + // Retrieve entry Price ... + double entry = GetEntry(mSymbol, type); + double spread = GetSpread(mSymbol); + + // + double tpPrice = 0; + double slPrice = 0; + double riskFreePrice = 0; + + // + // Normalize TP Value ... + if (tp <= 0) + { + // + double minReward = PipsToPrice(mMinTradeProfitsInPips); + tp = minReward; + } + + // + if (riskFree > 0 && riskFreeRate > 0) + { + // + riskFreePrice = type == X_SIGNAL_LONG ? entry + riskFree : entry - riskFree; + riskFreePrice = NormalizePrice(riskFreePrice, mSymbol); + } + + // + if (tp > 0) + { + // + tp += spread; + + // + tpPrice = isLong ? entry + tp : entry - tp; + tpPrice = NormalizePrice(tpPrice, mSymbol); + } + + // + if (sl > 0) + { + // + sl += spread; + + // + slPrice = isLong ? entry - sl : entry + sl; + slPrice = NormalizePrice(slPrice, mSymbol); + } + + // + result.type = type; + result.kind = kind; + result.tp = tpPrice; + result.sl = slPrice; + result.entry = entry; + result.parent = parent; + result.symbol = mSymbol; + result.riskFree = riskFreePrice; + result.magicNumber = mMagicNumber; + result.riskFreeRate = riskFreeRate; + result.time = iTime(mSymbol, _Period, 0); + result.volume = NormalizeVolume(volume, mSymbol); + + // + // Since we Use signal instance to Generate Comment, this must be at the end ... + result.comment = GetSignalComment(result); + + // + return result; + } + XSignal GenerateTradeSignal( + ENUM_X_SIGNAL_TYPE type, // Signal Type + double tp, // Take Profit + double sl, // Stop Loss + double volume, // Volume + double riskFree = 0, // Risk Free Price + double riskFreeRate = 0 // Risk Free Rate + ) + { + // + XSignal result = GenerateSignal( + type, + tp, + sl, + volume, + riskFree, + riskFreeRate, + X_KIND_TRADE, + 0 + // + ); + + // + return result; + } + XSignal GenerateSupportSignal( + ENUM_X_SIGNAL_TYPE type, // Signal Type + double tp, // Take Profit + double sl, // Stop Loss + double volume, // Volume + double riskFree, // Risk Free Price + double riskFreeRate, // Risk Free Rate + ulong parent // Support Kind Signal Parent + ) + { + // + XSignal result = GenerateSignal( + type, + tp, + sl, + volume, + riskFree, + riskFreeRate, + X_KIND_SUPPORT, + parent + // + ); + + // + return result; + } + + // + // Calculate SignalAge ... + int GetSignalAge( + datetime time // Signal Execution Time + ) + { + // + int result = 0; + + // + // Validate Arg ... + if (time <= 0) + { + return result; + } + + // + int sIndex = iBarShift( + mSymbol, + _Period, + time); + + // + datetime cTime = iTime( + mSymbol, + _Period, + 0); + int cIndex = iBarShift( + mSymbol, + _Period, + cTime); + + // + result = MathAbs(cIndex - sIndex); + + // + return result; + } + int GetSignalAge( + datetime time, // Signal Execution Time + ENUM_TIMEFRAMES period // Specify Time Frame + ) + { + // + int result = 0; + + // + // Validate Arg ... + if (time <= 0) + { + return result; + } + + // + int sIndex = iBarShift( + mSymbol, + period, + time); + + // + datetime cTime = iTime( + mSymbol, + period, + 0); + int cIndex = iBarShift( + mSymbol, + _Period, + cTime); + + // + result = MathAbs(cIndex - sIndex); + + // + return result; + } + int GetSignalAge( + XSignal &signal // Specify Signal + ) + { + // + int result = 0; + + // + // Validate Arg ... + if ( + signal.time <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalAge(signal.time); + + // + return result; + } + int GetSignalAge( + XSignal &signal, // Specify Signal + ENUM_TIMEFRAMES period // Specify Time Frame + ) + { + // + int result = 0; + + // + // Validate Arg ... + if ( + signal.time <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalAge( + signal.time, + period); + + // + return result; + } + + // + // Generate a Signal Object name for Draw Events On Chart ... + string GetSignalObjectName( + ulong ticket // Specify Ticket + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + // TICKET ... + // it is very importants since they hold position info ... + result += "T(" + (string)ticket + ")"; + + // + return result; + } + string GetSignalObjectName( + XSignal &signal // Specify Signal + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (!IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalObjectName(signal.ticket); + + // + return result; + } + + // + // Convert a Signal to String Representation ... + string ToString( + XSignal &signal // Specify Signal + ) + { + // + string result = ""; + + // + if (!IsValid(signal, mMagicNumber) || signal.ticket <= 0) + { + return result; + } + + // + // TICKET ... + // it is very importants since they hold position info ... + result += "T(" + (string)signal.ticket + ")"; + + // + // TYPE ... + string typeStr = GetSignalType(signal.type); + result += "_TY(" + typeStr + ")"; + + // + // KIND ... + string kindStr = GetSignalKind(signal.kind); + result += "_K(" + kindStr + ")"; + + // + // PARENT ... + result += "_PR(" + (string)signal.parent + ")"; + + // + // ENTRY ... + result += "_E(" + (string)signal.entry + ")"; + + // + // RISKFREE ... + result += "_RF(" + (string)signal.riskFree + ")"; + + // + // RISKFREERATE ... + result += "_RR(" + (string)signal.riskFreeRate + ")"; + + // + // VOLUME ... + result += "_V(" + (string)signal.volume + ")"; + + // + // TYPE ... + // KIND ... + // ENTRY ... + // TICKET ... + // PARENT ... + // VOLUME ... + // RISKFREE ... + // VIRTUALTP ... + // VIRTUALSL ... + // RISKFREERATE ... + // an String Representation of a Signal Carry above fields ... + + // + // ID ... + // TP ... + // SL ... + // TIME ... + // SYMBOL ... + // PROFIT ... + // COMMENT ... + // MAGICNUMBER ... + // these above items can read using PositionInfo instance ... + // so they are not necessary ... + + // + return result; + } + + // + // Convert an string to signal ... + XSignal FromString( + string represent // String Represenation of a Signal + ) + { + // + XSignal result = {}; + + // + // Validate Arg ... + if (StringLen(represent) == 0) + { + return result; + } + + // + // TICKET ... + string ticketStr = ExtractString( + represent, + "T(", + ")"); + if (StringLen(ticketStr) > 0) + { + result.ticket = (ulong)ticketStr; + } + + // + // TYPE ... + string typeStr = ExtractString( + represent, + "_TY(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_X_SIGNAL_TYPE type = GetSignalType(typeStr); + result.type = type; + } + + // + // KIND ... + string kindStr = ExtractString( + represent, + "_K(", + ")"); + if (StringLen(kindStr) > 0) + { + // + ENUM_X_SIGNAL_KIND kind = GetSignalKind(kindStr); + result.kind = kind; + } + + // + // PARENT ... + string parentStr = ExtractString( + represent, + "_PR(", + ")"); + if (StringLen(parentStr) > 0) + { + result.parent = (ulong)parentStr; + } + + // + // ENTRY ... + string entryStr = ExtractString( + represent, + "_E(", + ")"); + if (StringLen(entryStr) > 0) + { + result.entry = (double)entryStr; + } + + // + // RISKFREE ... + string riskFreeStr = ExtractString( + represent, + "_RF(", + ")"); + if (StringLen(riskFreeStr) > 0) + { + result.riskFree = (double)riskFreeStr; + } + + // + // RISKFREERATE ... + string riskFreeRateStr = ExtractString( + represent, + "_RR(", + ")"); + if (StringLen(riskFreeRateStr) > 0) + { + result.riskFreeRate = (double)riskFreeRateStr; + } + + // + // VOLUME ... + string volumeStr = ExtractString( + represent, + "_V(", + ")"); + if (StringLen(volumeStr) > 0) + { + result.volume = (double)volumeStr; + } + + // + return result; + } + void FromString( + XSignal &result, // Holds Result + string represent // String Represenation of a Signal + ) + { + // + // Validate Arg ... + if (StringLen(represent) == 0) + { + return; + } + + // + // TICKET ... + string ticketStr = ExtractString( + represent, + "T(", + ")"); + if (StringLen(ticketStr) > 0) + { + result.ticket = (ulong)ticketStr; + } + + // + // TYPE ... + string typeStr = ExtractString( + represent, + "_TY(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_X_SIGNAL_TYPE type = GetSignalType(typeStr); + result.type = type; + } + + // + // KIND ... + string kindStr = ExtractString( + represent, + "_K(", + ")"); + if (StringLen(kindStr) > 0) + { + // + ENUM_X_SIGNAL_KIND kind = GetSignalKind(kindStr); + result.kind = kind; + } + + // + // PARENT ... + string parentStr = ExtractString( + represent, + "_PR(", + ")"); + if (StringLen(parentStr) > 0) + { + result.parent = (ulong)parentStr; + } + + // + // ENTRY ... + string entryStr = ExtractString( + represent, + "_E(", + ")"); + if (StringLen(entryStr) > 0) + { + result.entry = (double)entryStr; + } + + // + // RISKFREE ... + string riskFreeStr = ExtractString( + represent, + "_RF(", + ")"); + if (StringLen(riskFreeStr) > 0) + { + result.riskFree = (double)riskFreeStr; + } + + // + // RISKFREERATE ... + string riskFreeRateStr = ExtractString( + represent, + "_RR(", + ")"); + if (StringLen(riskFreeRateStr) > 0) + { + result.riskFreeRate = (double)riskFreeRateStr; + } + + // + // VOLUME ... + string volumeStr = ExtractString( + represent, + "_V(", + ")"); + if (StringLen(volumeStr) > 0) + { + result.volume = (double)volumeStr; + } + } + + // + // END Signal Related ... + // + + // + // all protected features ... +protected: + // + // all private features ... +private: + // + // Specified Unique Tag ... + string mTag; + + // + // which Symbol ... + string mSymbol; + + // + // using deviation, it must be in Point ... + int mSlippage; + + // + // using magic number ... + ulong mMagicNumber; + + // + // Specify Max Allowed Trades + int mMaxAllowedTrades; + + // + // Specify Max Allowed Support Trades for each Trade + int mMaxAllowedSupportTrades; + + // + // Minimum Profit of each Trade in Pips + double mMinTradeProfitsInPips; + + // + // Support Trades Price Distance in Pips + double mSupportTradesPriceDistanceInPips; + + // + // Minimum Free Marging for Open Trades + double mMinAllowedFreeMarginForOpenTrades; + + // + // Minimum Balance for Open Trades + double mMinBallanceForOpenTrades; + + // + // using CTrade instance ... + XSCTrade mTrader; + + // + // An Instance Of XCAccount Info for Handling Account Related Actions ... + XCAccountInfo mAccountInfo; + + // + // using PositionInfo instance ... + CPositionInfo mPositionInfo; + + // + // For Manage Deals ... + CDealInfo mDealInfo; + + // + // using OrderInfo instance ... + COrderInfo mPendingInfo; + + // + // using HistoryOrderInfo instance ... + CHistoryOrderInfo mHistoryInfo; + + // + // Count Specific Type Of Positions ... + int CountByType(ENUM_POSITION_TYPE type) + { + // + int result = 0; + + // + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + if (mPositionInfo.PositionType() != type) + { + continue; + } + + // + result++; + } + + // + return result; + } + + // + // Convert Position to Signal by Index ... + XSignal PositionToSignal(int index) + { + // + XSignal result = {}; + + // + if (!mPositionInfo.SelectByIndex(index)) + { + return result; + } + + // + ulong ticket = mPositionInfo.Ticket(); + string signalContent = RetrieveSignalContent(ticket); + if (StringLen(signalContent) > 0) + { + // + // Fill Additional Contents ... + FromString( + result, + signalContent); + } + + // + // Ticket ... + result.ticket = mPositionInfo.Ticket(); + + // + // ID ... + result.id = mPositionInfo.Identifier(); + + // + // Symbol ... + result.symbol = mPositionInfo.Symbol(); + + // + // Type ... + ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)mPositionInfo.PositionType(); + ENUM_X_SIGNAL_TYPE type = pType == POSITION_TYPE_BUY ? X_SIGNAL_LONG : X_SIGNAL_SHORT; + result.type = type; + + // + // MagicNumber ... + result.magicNumber = mPositionInfo.Magic(); + + // + // Entry/Open Price ... + result.entry = mPositionInfo.PriceOpen(); + + // + // Take Profit ... + result.tp = mPositionInfo.TakeProfit(); + + // + // Stop Loss ... + result.sl = mPositionInfo.StopLoss(); + + // + // Profit ... + result.profit = mPositionInfo.Profit(); + + // + // Time ... + result.time = mPositionInfo.Time(); + + // + // Volume ... + result.volume = mPositionInfo.Volume(); + + // + // Comment ... + result.comment = mPositionInfo.Comment(); + + // + return result; + } + + // + // Position To Signal by Ticket ... + XSignal PositionToSignal(ulong ticket) + { + // + XSignal result = {}; + + // + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + string signalContent = RetrieveSignalContent(ticket); + if (StringLen(signalContent) > 0) + { + // + // Fill Additional Contents ... + FromString( + result, + signalContent); + } + + // + // Ticket ... + result.ticket = mPositionInfo.Ticket(); + + // + // ID ... + result.id = mPositionInfo.Identifier(); + + // + // Symbol ... + result.symbol = mPositionInfo.Symbol(); + + // + // Type ... + ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)mPositionInfo.PositionType(); + ENUM_X_SIGNAL_TYPE type = pType == POSITION_TYPE_BUY ? X_SIGNAL_LONG : X_SIGNAL_SHORT; + result.type = type; + + // + // MagicNumber ... + result.magicNumber = mPositionInfo.Magic(); + + // + // Entry/Open Price ... + result.entry = mPositionInfo.PriceOpen(); + + // + // Take Profit ... + result.tp = mPositionInfo.TakeProfit(); + + // + // Stop Loss ... + result.sl = mPositionInfo.StopLoss(); + + // + // Profit ... + result.profit = mPositionInfo.Profit(); + + // + // Time ... + result.time = mPositionInfo.Time(); + + // + // Volume ... + result.volume = mPositionInfo.Volume(); + + // + // Comment ... + result.comment = mPositionInfo.Comment(); + + // + return result; + } + + // + // Convert Position to Signal by Index ... + XSignal OrderToSignal(int index) + { + // + XSignal result = {}; + + // + if (!mHistoryInfo.SelectByIndex(index)) + { + return result; + } + + // + // ID ... + result.id = mHistoryInfo.PositionId(); + + // + // Symbol ... + result.symbol = mHistoryInfo.Symbol(); + + // + // Type ... + ENUM_ORDER_TYPE pType = (ENUM_ORDER_TYPE)mHistoryInfo.OrderType(); + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN; + switch (pType) + { + // + case ORDER_TYPE_BUY: + case ORDER_TYPE_BUY_LIMIT: + case ORDER_TYPE_BUY_STOP: + case ORDER_TYPE_BUY_STOP_LIMIT: + type = X_SIGNAL_LONG; + break; + + // + case ORDER_TYPE_SELL: + case ORDER_TYPE_SELL_LIMIT: + case ORDER_TYPE_SELL_STOP: + case ORDER_TYPE_SELL_STOP_LIMIT: + type = X_SIGNAL_SHORT; + break; + + // + // Default ... + default: + type = X_SIGNAL_UNKNOWN; + break; + } + result.type = type; + + // + // MagicNumber ... + result.magicNumber = mHistoryInfo.Magic(); + + // + // Ticket ... + result.ticket = mHistoryInfo.Ticket(); + + // + // Entry/Open Price ... + result.entry = mHistoryInfo.PriceOpen(); + + // + // Take Profit ... + result.tp = mHistoryInfo.TakeProfit(); + + // + // Stop Loss ... + result.sl = mHistoryInfo.StopLoss(); + + // + // Profit ... + // TODO Calculate it ... + // result.profit = mHistoryInfo.Profit(); + + // // + // // Time ... + // result.time = mHistoryInfo.Time(); + + // // + // // Volume ... + // result.volume = mHistoryInfo.Volume(); + + // + // Comment ... + result.comment = mHistoryInfo.Comment(); + + // + return result; + } + + // + // Draw a Signal on Screen ... + void DrawSignalEvent( + XSignal &signal, // Specify Draw which Signal on Screen + color longColor = clrAqua, // Long Signal Object Color + color shortColor = clrFuchsia, // Short Signal Object Color + int chartId = -1, // Specify Chart ID + int subWindow = -1 // Specify SubWindow ID + ) + { + // + // Validate Args ... + if ( + signal.ticket <= 0 || + !IsValid(signal, mMagicNumber) || + signal.type == X_SIGNAL_UNKNOWN) + { + return; + } + + // + // Normalize Chart and SubWindow ID ... + if (chartId == -1) + { + chartId = 0; + } + if (subWindow == -1) + { + subWindow = 0; + } + + // + bool isLong = signal.type == X_SIGNAL_LONG; + + // + // Simply Draw an Arrow on Chart for Representing Signal Info ... + string name = GetSignalObjectName(signal); + string content = ToString(signal); + if (StringLen(content) == 0) + { + return; + } + + // + color signalColor = isLong ? longColor : shortColor; + + // + // Create an Event On Chart ... + bool isCreated = EventCreate( + chartId, + name, + subWindow, + content, + signal.time, + signalColor); + if (isCreated) + { + // + DrawSignalShape( + signal, + longColor, + shortColor); + } + } + + // + // Filter Trades Buffer ... + void FilterSignals( + string query, // Search String + XSignal &source[], // Source Buffer to Filter + XSignal &result[] // Holds Result + ) + { + // + // Free Buffer ... + CleanBuffer(result); + + // + int sourceCount = ArraySize(source); + + // + // Check Conditions and Validate Args ... + if ( + sourceCount == 0 || + StringLen(query) == 0) + { + return; + } + + // + // Loop Through Source ... + for (int i = 0; i < sourceCount; i++) + { + // + // Retrieve Indexed Item ... + XSignal trade = source[i]; + + // + // Check Query Exists or not ... + int pos = StringFind( + trade.comment, + query); + + // + // Continue if nothing found ... + if (pos <= -1) + { + continue; + } + + // + // Resize the result array ... + ArrayResize( + result, + ArraySize(result) + 1); + result[ArraySize(result) - 1] = trade; + } + } + + // + // Get all Positions based on Position Type ... + void GetAllPositionsByType(ENUM_POSITION_TYPE type, XSignal &result[]) + { + // + int existsTotal = CountByType(type); + + // + CleanBuffer(result); + ArrayResize(result, existsTotal); + + // + int filledIndex = 0; + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + if (mPositionInfo.PositionType() != type) + { + continue; + } + + // + result[filledIndex] = PositionToSignal(i); + filledIndex++; + } + } + + // + // Retrieve Signal Specified Object Text ... + string RetrieveSignalContent( + ulong ticket, // Specify Position Ticket + int chartId = -1, // Specify Chart ID + int subWindow = -1 // Specify SubWindow ID + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + string signalObjectName = GetSignalObjectName(ticket); + if (StringLen(signalObjectName) == 0) + { + return result; + } + + // + // Normalize Chart and SubWindow ID ... + if (chartId == -1) + { + chartId = 0; + } + if (subWindow == -1) + { + subWindow = 0; + } + + // + // Search For Signal Object Name ... + int objectIndex = ObjectFind( + chartId, + signalObjectName); + if (objectIndex < 0) + { + return result; + } + + // + // Loop Through Objects ... + int count = ObjectsTotal( + chartId, + subWindow); + for (int i = count - 1; i >= 0; i--) + { + // + // Retrieve Object Name ... + string objectName = ObjectName(chartId, i, subWindow); + + // + // Find Signal Ticket Position in Object Name ... + int stPos = StringFind( + objectName, + signalObjectName); + if (stPos < 0) + { + continue; + } + + // + // Retrieve Object Type and Check it Event ... + int oType = (int)ObjectGetInteger(chartId, objectName, OBJPROP_TYPE); + if (oType != OBJ_EVENT) { + continue; + } + + // + // Retrieve Object Text as String Representation OF Signal ... + result = ObjectGetString(chartId, objectName, OBJPROP_TEXT); + break; + } + + // + return result; + } + string RetrieveSignalContent( + XSignal &signal, // Specify Signal + int chartId = -1, // Specify Chart ID + int subWindow = -1 // Specify SubWindow ID + ) + { + // + string result = ""; + + // + result = RetrieveSignalContent( + signal.ticket, + chartId, + subWindow); + + // + return result; + } + + // + // Remove Signal Object from Chart ... + bool RemoveSignal( + ulong ticket, // Specify Position Ticket + int chartId = -1 // Specify Chart ID + ) + { + // + bool result = false; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + // Normalize Chart Id ... + if (chartId <= 0) + { + chartId = 0; + } + + // + // Generate Signal Object Name ... + string signalObjectName = GetSignalObjectName(ticket); + + // + // Remove Object from Chart ... + result = ObjectDelete(chartId, signalObjectName); + + // + return result; + } + bool RemoveSignal( + XSignal &signal, // Specify Signal + int chartId = -1 // Specify Chart ID + ) + { + // + bool result = false; + + // + result = RemoveSignal( + signal.ticket, + chartId); + + // + return result; + } + + // + // Generate Comments for Specific Signal ... + string GetSignalComment( + ENUM_X_SIGNAL_KIND kind, // Specify Kind + ENUM_X_SIGNAL_TYPE type, // Specify Kind Signal Type + ulong parentTicket, // Parent Signal Ticket + double volume, // Signal Volume + double riskFree, // Risk Free Price + double riskFreeRate // Risk Free Volume Multiplier + ) + { + // + string result = ""; + + // + string kindStr = GetSignalKind(kind); + string typeStr = GetSignalType(type); + if ( + volume <= 0 || + StringLen(kindStr) == 0 || + StringLen(typeStr) == 0 || + (parentTicket <= 0 && kind == X_KIND_SUPPORT)) + { + return result; + } + + // + // Normalize Data ... + // + if (riskFreeRate < 0) + { + riskFreeRate = 0; + } + else if (riskFreeRate > 1) + { + riskFreeRate = 0.75; + } + + // + volume = NormalizeVolume(volume, mSymbol); + riskFree = NormalizePrice(riskFree, mSymbol); + + // + if (riskFree > 0 && riskFreeRate == 0) + { + riskFreeRate = 0.75; + } + else if (riskFree <= 0 && riskFreeRate > 0) + { + riskFreeRate = 0; + } + + // + string kindTitle = kind == X_KIND_TRADE ? kindStr : kindStr + "_For_" + (string)parentTicket; + result = mTag + "_" + typeStr + "_" + kindTitle; + + // + return result; + } + string GetSignalComment( + XSignal &signal // Specify Signal + ) + { + // + string result = GetSignalComment( + signal.kind, + signal.type, + signal.parent, + signal.volume, + signal.riskFree, + signal.riskFreeRate + // + ); + + // + return result; + } + + // + // Generate TP Comment For Closing Signal ... + string GetSignalClosedOnTPComment( + XSignal &signal // Model Signal to Use + ) + { + // + string result = ""; + + // + if (signal.ticket <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + double exitPrice = GetExit(signal.type); + string prefix = GetSignalObjectName(signal); + + // + // "_E(" + (string)signal.entry + ")" ... + result = prefix + "_TP(" + (string)exitPrice + ")"; + + // + return result; + } + + // + // Generate SL Comment For Closing Signal ... + string GetSignalClosedOnSLComment( + XSignal &signal // Model Signal to Use + ) + { + // + string result = ""; + + // + if (signal.ticket <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + double exitPrice = GetExit(signal.type); + string prefix = GetSignalObjectName(signal); + + // + // "_E(" + (string)signal.entry + ")" ... + result = prefix + "_SL(" + (string)exitPrice + ")"; + + // + return result; + } + + // + // Generate Comment For Force Closing Signal ... + string GetSignalForceClosedComment( + XSignal &signal // Model Signal to Use + ) + { + // + string result = ""; + + // + if (signal.ticket <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + double exitPrice = GetExit(signal.type); + string prefix = GetSignalObjectName(signal); + + // + // "_E(" + (string)signal.entry + ")" ... + result = "F_" + prefix + "_P(" + (string)exitPrice + ")"; + + // + return result; + } + + // + // Generate Comment For In DrawDown and In Profit Closing Signal ... + string GetSignalInDistanceClosedComment( + XSignal &signal // Model Signal to Use + ) + { + // + string result = ""; + + // + if (signal.ticket <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + double exitPrice = GetExit(signal.type); + string prefix = GetSignalObjectName(signal); + string distanceStr = signal.profit > 0 ? "InP" : "InDD"; + + // + // "_E(" + (string)signal.entry + ") ... + // "_P(" + (string)exitPrice + ")" ... + result = distanceStr + "_" + prefix + "_D(" + (string)signal.profit + ")"; + + // + return result; + } + + // + // Generate Comment For Long Time Closing Signal ... + string GetSignalLongTimeClosedComment( + XSignal &signal // Model Signal to Use + ) + { + // + string result = ""; + + // + if (signal.ticket <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + double exitPrice = GetExit(signal.type); + string prefix = GetSignalObjectName(signal); + + // + int signalAge = GetSignalAge(signal); + + // + // "_E(" + (string)signal.entry + ")" ... + // "_P(" + (string)exitPrice + ")" ... + result = "LT_" + prefix + "_A(" + (string)signalAge + ")" + "_D(" + (string)signal.profit + ")"; + + // + return result; + } + + // + // Check Number Of Trades is Valid ... + bool CanOpenNewTrade( + ENUM_X_SIGNAL_TYPE type, // Specify Type of Positions + ENUM_X_SIGNAL_KIND kind // Specify Kind of Positions + ) + { + // + bool result = false; + + // + int tradesCount = CountByKind( + type, + kind); + + // + result = tradesCount <= 0; + if (!result) + { + return result; + } + + // + bool isTradeKind = kind == X_KIND_TRADE; + + // + // Check based on Trade Kind ... + result = + // + isTradeKind + // + ? + // + tradesCount < mMaxAllowedTrades + // + : + // + tradesCount < mMaxAllowedSupportTrades + // + ; + + // + return result; + } + + // + // Check Account Has Minimum Balance For Trade ... + bool IsAccountBalanceReadyForTrade() + { + // + bool result = false; + + // + result = mAccountInfo.GetBalance() >= mMinBallanceForOpenTrades; + + // + return result; + } + + // + // Check Free Margin Has Enough For Trade ... + bool IsFreeMarginReadyForTrade() + { + // + bool result = false; + + // + double freeMargin = mAccountInfo.GetFreeMargin(); + + // + result = freeMargin >= mMinAllowedFreeMarginForOpenTrades; + + // + return result; + } +}; +// +// END Global Definitions: Variables, Properties and etc ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.common.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..e94b782 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,3584 @@ +/////////////////////////////////////////////////////// +// +// 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; +} + +// +// 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_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetAsk() : GetBid(); + result = NormalizePrice(result); + + // + return result; +} +double GetEntry( + string symbol, // Specified Symbol + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetAsk(symbol) : GetBid(symbol); + result = NormalizePrice(result, symbol); + + // + return result; +} + +// +// Get Signal Exit ... +double GetExit( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetBid() : GetAsk(); + result = NormalizePrice(result); + + // + return result; +} +double GetExit( + string symbol, // Specified Symbol + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetBid(symbol) : GetAsk(symbol); + result = NormalizePrice(result, symbol); + + // + 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; +} + +// +// 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; +} + +// +// 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 HasStrongBody(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 = HasStrongBody(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 = HasStrongBody(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 = HasStrongBody(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; +} + +// +// 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; +} + +// +// 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; +} +// +// END Provided Functions ... +// + +// +// Find Farest Time Frame ... +ENUM_TIMEFRAMES GetFarestTimeFrame() +{ + // + ENUM_TIMEFRAMES result = PERIOD_MN1; + + // + switch (_Period) + { + // + // M1-M30 ... + 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_D1; + break; + + // + // H1-H12 ... + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + case PERIOD_H12: + result = PERIOD_W1; + break; + + // + // D!, W1 ... + case PERIOD_D1: + case PERIOD_W1: + result = PERIOD_MN1; + break; + + // + // Otherwise ... + default: + result = PERIOD_MN1; + } + + // + return result; +} + +// +// Find Medium Time Frame ... +ENUM_TIMEFRAMES GetMediumTimeFrame() +{ + // + ENUM_TIMEFRAMES result = PERIOD_D1; + + // + switch (_Period) + { + // + // M1-M30 ... + 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; + + // + // H1-H12 ... + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + case PERIOD_H12: + result = PERIOD_D1; + break; + + // + // D!, W1 ... + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + // Otherwise ... + default: + result = PERIOD_MN1; + } + + // + return result; +} + +// +// Find Smallest Time Frame ... +ENUM_TIMEFRAMES GetSmallestTimeFrame() +{ + // + ENUM_TIMEFRAMES result = PERIOD_M5; + + // + switch (_Period) + { + // + // M1-M5 ... + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + case PERIOD_M5: + result = _Period; + break; + + // + // M6-M30 ... + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_M5; + break; + + // + // H1-H12 ... + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + case PERIOD_H12: + result = PERIOD_H1; + break; + + // + // D! ... + case PERIOD_D1: + result = PERIOD_H2; + break; + + // + // Otherwise ... + default: + result = PERIOD_H4; + } + + // + 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; +} + +// +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; +} + +// +// Validate Struct ... +bool IsValid(XSignal &model, ulong magicNumber) +{ + // + bool result = false; + + // + // Validate Signal Type ... + result = model.type != X_SIGNAL_UNKNOWN; + if (!result) + { + return result; + } + + // + // Check Symbol ... + result = StringLen(model.symbol) == 0 ? true : model.symbol == _Symbol; + if (!result) + { + return result; + } + + // + // Check magic number ... + result = model.magicNumber <= 0 ? true : model.magicNumber == magicNumber; + if (!result) + { + return result; + } + + // + // Check Entry ... + result = model.entry > 0; + if (!result) + { + return result; + } + + // + // Check SL ... + result = model.sl == 0 ? true : model.type == X_SIGNAL_LONG ? model.sl < model.entry + : model.sl > model.entry; + if (!result) + { + return result; + } + + // + // Check TP ... + result = model.tp == 0 ? true : model.type == X_SIGNAL_LONG ? model.tp > model.entry + : model.tp < model.entry; + if (!result) + { + return result; + } + + // + // Check Volume ... + result = model.volume > 0; + if (!result) + { + return result; + } + + // + // Check Time ... + result = model.time > 0; + if (!result) + { + return result; + } + + // + return result; +} +bool IsValid(XTPSL &model) +{ + // + bool result = false; + + // + result = model.entry > 0 && model.type != X_SIGNAL_UNKNOWN; + + // + return result; +} + +// +void CleanBuffer(int &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(double &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XSignal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +void Add( + int item, // item want to add + int &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( + XSignal &item, // item want to add + XSignal &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// Check a Signal is Long or not ... +bool IsLong(ENUM_X_SIGNAL_TYPE type) +{ + return type == X_SIGNAL_LONG; +} +bool IsLong(XSignal &signal) +{ + // + bool result = IsLong(signal.type); + + // + return result; +} + +// +// Check a Signal is Short or not ... +bool IsShort(ENUM_X_SIGNAL_TYPE type) +{ + return type == X_SIGNAL_SHORT; +} +bool IsShort(XSignal &signal) +{ + // + bool result = IsShort(signal.type); + + // + return result; +} + +// +// Retrieve a Signal Type String Value ... +string GetSignalType(ENUM_X_SIGNAL_TYPE type) +{ + // + string result = ""; + + // + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + result = type == X_SIGNAL_LONG ? "Long" : "Short"; + + // + return result; +} +string GetSignalType(XSignal &signal) +{ + // + string result = ""; + + // + result = GetSignalType(signal.type); + + // + return result; +} +ENUM_X_SIGNAL_TYPE GetSignalType(string typeStr) +{ + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + if (typeStr == GetSignalType(X_SIGNAL_LONG)) + { + result = X_SIGNAL_LONG; + } + else if (typeStr == GetSignalType(X_SIGNAL_SHORT)) + { + result = X_SIGNAL_SHORT; + } + + // + return result; +} + +// +// Retrieve a Signal Kind String Value ... +string GetSignalKind(ENUM_X_SIGNAL_KIND kind) +{ + // + string result = ""; + + // + if (kind != X_KIND_TRADE && kind != X_KIND_SUPPORT) + { + return result; + } + + // + result = kind == X_KIND_TRADE ? "Trade" : "Support"; + + // + return result; +} +string GetSignalKind(XSignal &signal) +{ + // + string result = ""; + + // + result = GetSignalKind(signal.kind); + + // + return result; +} +ENUM_X_SIGNAL_KIND GetSignalKind(string kindStr) +{ + // + ENUM_X_SIGNAL_KIND result = X_KIND_TRADE; + + // + if (kindStr == GetSignalKind(X_KIND_TRADE)) + { + result = X_KIND_TRADE; + } + else if (kindStr == GetSignalKind(X_KIND_SUPPORT)) + { + result = X_KIND_SUPPORT; + } + + // + return result; +} + +// +// Retrieve Signal Execution String ... +string GetSignalExecutionError(int error) +{ + // + string result = ""; + + // + switch (error) + { + // + case X_INVALID_SIGNAL_ERROR: + result = "Invalid Signal ..."; + break; + + // + case X_XTRADER_NOT_ENOUGH_BALANCE_ERROR: + result = "Not Enough Balance for Trade ..."; + break; + + // + case X_XTRADER_NOT_ENOUGH_MARIGIN_ERROR: + result = "Not Enough Marigin For Trade ..."; + break; + + // + case X_XTRADER_MAX_ALLOWED_TRADE_KIND_REACHED_ERROR: + result = "Max Allowed Trade Reached ..."; + break; + + // + case X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR: + result = "Max Allowed Support Trade Reached ..."; + break; + + // + case X_UNKNOWN_ERROR: + default: + result = "Unknown Issue ..."; + break; + } + + // + return result; +} + +// +// 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 normalization +) +{ + // + double result = volume; + + // + // Normalize Volume ... + result = NormalizeDouble(result, 2); + + // + 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; +} +double NormalizeVolume( + double volume, // desired volume to normalize + string symbol // Specified Symbol for Normalization +) +{ + // + double result = volume; + + // + // Normalize Volume ... + result = NormalizeDouble(result, 2); + + // + 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 +) +{ + // + double result = 0; + + // + result = NormalizeDouble(price, _Digits); + + // + return result; +} +double NormalizePrice( + double price, // desired Price for normalization + string symbol // Specified Symbol for Normalization +) +{ + // + double result = 0; + + // + int digits = GetDigits(symbol); + result = NormalizeDouble(price, digits); + + // + return result; +} + +// +// START Error Descriptions ... +// + +// +// 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; +} diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.draw.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..e904cd6 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2220 @@ +/////////////////////////////////////////////////////// +// +// 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" + +// +// 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(); +} + +// +void DrawSignalShape( + XSignal &signal, // Specify Signal to Draw + color longColor = clrAqua, // Long Signals Color + color shortColor = clrFuchsia, // Short Signal Color + color entryColor = clrGold // Signal Entry Price Color +) { + // + // Draw Signal Info : + // - Draw Entry Price Line; + // - Draw SL; + // - Draw TP; + // - Risk Free; + + // + bool isLong = signal.type == X_SIGNAL_LONG; + + // + color tpColor = longColor; + color slColor = shortColor; + + // + string name = "T(" + (string) signal.ticket + ")" + "_" + "TY(" + EnumToString(signal.type) + ")" + "_" + "KI(" + EnumToString(signal.kind) + ")"; + string tpName = "TP_" + name; + string slName = "SL_" + name; + string riskFreeName = "RF_" + name; + string entryName = "Entry_" + name; + + // + int signalBarIndex = iBarShift( + signal.symbol, + _Period, + signal.time + ); + + // + datetime time1 = iTime( + signal.symbol, + _Period, + signalBarIndex + 1 + ); + datetime time2 = iTime( + signal.symbol, + _Period, + signalBarIndex - 1 + ); + + // + // Entry ... + bool isTrendLineDrawn = DrawTrendLine( + 0, + entryName, + 0, + time1, + signal.entry, + time2, + signal.entry, + entryColor + ); + + // + // TP ... + bool isTPDrawn = false; + if (signal.tp > 0) { + // + isTPDrawn = DrawTrendLine( + 0, + tpName, + 0, + time1, + signal.tp, + time2, + signal.tp, + tpColor, + STYLE_SOLID, + 1, + false, + true + ); + } + + // + // RISKFREE ... + bool isRFDrawn = false; + if (signal.riskFree > 0) { + // + isRFDrawn = DrawTrendLine( + 0, + riskFreeName, + 0, + time1, + signal.riskFree, + time2, + signal.riskFree, + tpColor, + STYLE_DOT, + 1, + false, + true + ); + } + + // + // SL ... + bool isSLDrawn = false; + if (signal.sl > 0) { + // + isSLDrawn = DrawTrendLine( + 0, + slName, + 0, + time1, + signal.sl, + time2, + signal.sl, + slColor, + STYLE_SOLID, + 1, + false, + true + ); + } +} + +// +// 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(); +} +// +// 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 sub_window = 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, sub_window, 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 back_clr = 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, back_clr); + + // + // 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 ... +// + +// +// END Regular Draws ... +// + +// +// START Chart Style Drawers ... +// +// +// Apply Styles On Chart ... +void ApplyChartStyle( + int chartId = -1, // chart's ID + ENUM_CHART_MODE mode = CHART_CANDLES, // chart's mode + bool showBidLine = true, // show bid line + bool showAskLine = true, // show ask line + bool showGrid = false, // show grids on chart + bool showVolumes = false, // show volumes + bool showTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool autoScroll = true, // chart autoscroll + bool quickNavigation = true, // chart quick navigation state + color foreGroundColor = clrWhite, // chart's foreground color + color backGroundColor = clrBlack, // chart's background color + color upColor = clrGreen, // Up Color + color downColor = clrRed, // Down Color + color bullishColor = clrGreen, // Bullish color + color bearishColor = clrRed, // Bearish color + color gridColor = clrGray, // grid color + color bidLineColor = clrGray, // bid line color + color askLineColor = clrRed, // ask line color + color lineColor = clrLime, // line mode and doji candlestick color + color stopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color volumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (chartId == -1) + { + chartId = 0; + } + + // + ChartSetInteger(chartId, CHART_MODE, mode); + ChartSetInteger(chartId, CHART_SHOW_BID_LINE, showBidLine); + ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, showAskLine); + ChartSetInteger(chartId, CHART_SHOW_GRID, showGrid); + ChartSetInteger(chartId, CHART_SHOW_VOLUMES, showVolumes); + ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, showTradeLevels); + ChartSetInteger(chartId, CHART_AUTOSCROLL, autoScroll); + ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, quickNavigation); + ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, foreGroundColor); + ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, backGroundColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_UP, upColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, downColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, bullishColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, bearishColor); + ChartSetInteger(chartId, CHART_COLOR_GRID, gridColor); + ChartSetInteger(chartId, CHART_COLOR_BID, bidLineColor); + ChartSetInteger(chartId, CHART_COLOR_ASK, askLineColor); + ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, stopColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, lineColor); + ChartSetInteger(chartId, CHART_COLOR_VOLUME, volumesColor); +} +// +// END Chart Style Drawers ... +// \ No newline at end of file diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.http.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 0000000..97f7ac0 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.http.lib.mq5 @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Http Library +// ------------------------------------------ +// Name: XHttp +// Description: provide http communication +// 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 Model Definition ... +// +enum X_HTTP_METHOD +{ + X_HTTP_GET, + X_HTTP_POST +}; +// +// END Model Definition ... +// + +// +// START Inputs ... +// +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Initial Library if required ... +bool OnInInitHttpLibrary() +{ + return false; +} + +// +// DeInitial Library if required ... +void OnDeinitHttpLibrary() +{ +} + +// +// 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; +} + +// +// 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; + } + + // + result = WebRequest( + strMethod, + url, + headers, + timeout, + payload, + response, + responseHeaders + ); + + // + 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; +} +// +// END Provided Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.log.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 0000000..e74039e --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.log.lib.mq5 @@ -0,0 +1,161 @@ +/////////////////////////////////////////////////////// +// +// 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); +} + +// +// 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); +} + +// +// Convert a Signal to String Message ... +string SignalToString(XSignal &signal) +{ + // + string result = ""; + + // + result += (signal.type == X_SIGNAL_LONG ? "Buy" : "Sell") + " Signal provided on (" + signal.symbol + " _ " + EnumToString(_Period) + ") by this comment: " + signal.comment; + + // + return result; +} + +// +// Convert an Executed Signal to String Message ... +string ExecutedSignalToString(XSignal &signal) +{ + // + string result = ""; + + // + result += (signal.type == X_SIGNAL_LONG ? "Buy" : "Sell") + " Signal Executed provided on (" + signal.symbol + " _ " + EnumToString(_Period) + ") by this comment: " + signal.comment; + + // + return result; +} + +// +// Logging Signal ... +void LogSignal(XSignal &signal) +{ + // + string message = SignalToString(signal); + + // + LogMessage(message); +} + +// +// Log Signal Execution ... +void LogExecutedSignal(XSignal &signal) +{ + // + string message = ExecutedSignalToString(signal); + + // + LogMessage(message); +} +// +// END Provided Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.models.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 0000000..52e4050 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.models.lib.mq5 @@ -0,0 +1,187 @@ +/////////////////////////////////////////////////////// +// +// 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 ... +// + +// +// START Model Definitions ... +// +// +// OHCL Candel Model ... +enum ENUM_X_PRICE +{ + X_PRICE_HIGH, + X_PRICE_OPEN, + X_PRICE_CLOSE, + X_PRICE_LOW +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + double high; + double open; + double close; + double low; +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +// XTrader Execution Signal Result ... +enum ENUM_EXECUTION_SIGNAL_RESULT +{ + // + X_INVALID_SIGNAL_ERROR, + X_XTRADER_NOT_ENOUGH_BALANCE_ERROR, + X_XTRADER_NOT_ENOUGH_MARIGIN_ERROR, + X_XTRADER_MAX_ALLOWED_TRADE_KIND_REACHED_ERROR, + X_XTRADER_MAX_ALLOWED_SUPPORT_KIND_REACHED_ERROR, + // + X_TRADER_SUPPORT_DISTANCE_NOT_HAPPENS_ERROR, + // + X_UNKNOWN_ERROR, + X_SUCCEED_EXECUTION +}; + +// +// Signal Types ... +enum ENUM_X_SIGNAL_TYPE +{ + X_SIGNAL_LONG, + X_SIGNAL_SHORT, + X_SIGNAL_UNKNOWN, +}; + +// +// Represent a Signal issued for Trade or Support a Trade ... +enum ENUM_X_SIGNAL_KIND +{ + X_KIND_TRADE, + X_KIND_SUPPORT +}; + +// +// Signal Structure ... +struct XSignal +{ + // + // Identifier ... + ulong id; + + // + // Which Symbol used for Signal ... + string symbol; + + // + // Which Type of operations ... + ENUM_X_SIGNAL_TYPE type; + + // + // Signal Kind ... + ENUM_X_SIGNAL_KIND kind; + + // + // Parent Ticket ... + ulong parent; + + // + // Magic Number ... + ulong magicNumber; + + // + // Ticket ... + ulong ticket; + + // + // Entry/Open Price ... + double entry; + + // + // TP ... + double tp; + + // + // SL ... + double sl; + + // + // Make Risk Free Trade on this Value if provided ... + double riskFree; + + // + // a Multiplier for determines how much trade volume exit on risk free time ... + double riskFreeRate; + + // + // Trade Profit ... + double profit; + + // + // Time of Operation ... + datetime time; + + // + // Volume ... + double volume; + + // + // Comment ... + string comment; +}; + +// +// TP/SL Struct ... +struct XTPSL +{ + ENUM_X_SIGNAL_TYPE type; + double tp; + double sl; + double entry; + double r2r; +}; +// +// END Provided Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.nn.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.nn.lib.mq5 new file mode 100644 index 0000000..8fa40f5 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.nn.lib.mq5 @@ -0,0 +1,258 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 NN Class Library +// ---------------------------------------- +// Name: XNNClass +// Description: provides all classes for implementing +// Neural Network ... +// +// +// 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 Global Definitions: Variables, Properties and etc ... +// +class XCNNBase +{ + // + // Public Definitions ... +public: + // + // Constructor ... + void XCNNBase( + int nodes = 10, // Number of Input Nodes + double starterWeight = 0.5, // start weight for each input + double coEfficient = 0.1, // COEfficient Multiplier + double upperRange = 1, // Upper Normal Range Value + double lowerRange = -1, // Lower Normal Range Value + double learningRates = 0.1 // Back Propagation Learning Rate + ) { + // + mNodes = nodes; + mUpperRange = upperRange; + mLowerRange = lowerRange; + mCoEfficient = coEfficient; + mLearningRates = learningRates; + mStarterWeight = starterWeight; + + // + ReConstructWeights(); + } + + // + // Deconstructor ... + void ~XCNNBase() {} + + // + // Protected Definitions ... + void NormalizeInputs(double &inputs[], double &result[]) + { + // + ArrayFree(result); + ArrayResize(result, 1); + + // + // Validate inputs ... + if (ArraySize(inputs) != mNodes) + { + return; + } + + // + // Prepare Result ... + ArrayResize(result, mNodes); + + // + // Calculating min and max range value ... + double minRangeValue = inputs[ArrayMinimum(inputs)]; + double maxRangeValue = inputs[ArrayMaximum(inputs)]; + + // + // Loop through Inputs nd Normalize them ... + for (int i = 0; i < mNodes; i++) + { + // + double normalValue = (((inputs[i] - minRangeValue) * (mUpperRange - mLowerRange)) / (maxRangeValue - minRangeValue)) + mLowerRange; + result[i] = normalValue; + } + } + + // + // Hyperbolic Tangent Activation Function ... + double TanHActivationFunction(double weightedInputs) + { + // + double result = (exp(weightedInputs) - exp(-weightedInputs)) / (exp(weightedInputs) + exp(-weightedInputs)); + return result; + } + + // + // Calculate Weighted Inputs ... + double CalculateWeightedInputs( + double &inputs[], + bool applyCOEfficient = true) + { + // + double result = 0; + + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) + { + // + result = -1; + return result; + } + + // + for (int i = 0; i < mNodes; i++) + { + result += inputs[i] * mWeights[i]; + } + + // + // Multiply if required ... + if (applyCOEfficient) + { + result *= mCoEfficient; + } + + // + return result; + } + + // + // Calculate Hidden Layers ... + virtual double CalculateHiddenLayer(double &inputs[]) + { + // + // this is Default Activation Function which used ... + // you can override this by writing your own ... + double totalWeightedInputs = CalculateWeightedInputs(inputs); + double result = TanHActivationFunction(totalWeightedInputs); + + // + return result; + } + + // + // Calculate Output Layers ... + double CalculateOutputLayer(double &inputs[]) + { + // + double result = -1; + + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) { + return result; + } + + // + double normalizedInputs[]; + NormalizeInputs(inputs, normalizedInputs); + if (ArraySize(normalizedInputs) != mNodes) { + return result; + } + + // + double hiddenLayerResult = CalculateHiddenLayer(normalizedInputs); + + // + result = 1 * hiddenLayerResult; + + // + return result; + } + + // + // Basck Propaggation Learning ... + void BackPropagation( + double &inputs[], + double &outputs, + double targetOutput + ) { + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) { + return; + } + + // + double normalizedInputs[]; + NormalizeInputs(inputs, normalizedInputs); + if (ArraySize(normalizedInputs) != mNodes) { + return; + } + + // + double error = targetOutput - outputs; + double derivative = 1 - MathPow(outputs, 2); + + // + for (int i = 0; i < mNodes; i++) { + // + double gradient = error * derivative * inputs[i]; + mWeights[i] = mLearningRates * gradient; + } + } + +protected: + // + // Private Definitions ... +private: + // + // Number of Input Nodes ... + int mNodes; + + // + // Specify Upper range of Normal Values ... + double mUpperRange; + + // + // Specify Lower range of Normal Values ... + double mLowerRange; + + // + // Starter Weight for each input node ... + double mStarterWeight; + + // + // double Input Node Weights ... + double mWeights[]; + + // + // CoEfficient is a multiplyer for weighted inputs ... + double mCoEfficient; + + // + // Back Propagation Learning Rates ... + double mLearningRates; + + // + // ReConstruct Weights ... + void ReConstructWeights() { + // + ArrayFree(mWeights); + ArrayResize(mWeights, mNodes); + + // + for (int i = 0; i< mNodes; i++) { + mWeights[i] = mStarterWeight; + } + } +} +// +// END Global Definitions: Variables, Properties and etc ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..75f8068 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchlh.oscillator.helper.lib.mq5 @@ -0,0 +1,925 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHLH Oscillator 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 + +// +// Includes ... +#include "..\Libraries\x-saherelm.log.lib.mq5" +#include "..\Libraries\x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XCHLH Hot States ... +enum ENUM_X_XCHLH_HOT_STATES +{ + X_XCHLH_HOT_HH = 1, + X_XCHLH_NEUTURAL = 0, + X_XCHLH_HOT_LL = -1, +}; + +// +// XCHLH Signal Calculation Types ... +enum ENUM_X_XCHLH_SIGNAL_TYPES +{ + X_XCHLH_AVG_SIGNAL, + X_XCHLH_DELTA_SIGNAL, +}; + +// +// XCHLH Buffer Lines ... +enum ENUM_X_XCHLH_BUFFER_LINES +{ + X_XCHLH_LC_HH_LINE = 0, + X_XCHLH_LC_LL_LINE = 1, + X_XCHLH_MC_HH_LINE = 2, + X_XCHLH_MC_LL_LINE = 3, + X_XCHLH_SC_HH_LINE = 4, + X_XCHLH_SC_LL_LINE = 5, + X_XCHLH_SIGNAL_T_LINE = 6, + X_XCHLH_SIGNAL_B_LINE = 7, + X_XCHLH_HOT_STATE_LINE = 8, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// +input group "XCHLH Oscillator"; + +// +// Signal Calculations ... +input group "XCHLH Signal Calculations"; +input ENUM_X_XCHLH_SIGNAL_TYPES xCHLHSignalType = X_XCHLH_AVG_SIGNAL; // Signal Method + +// +// Common ... +input group "XCHLH Hot Areas"; +input bool xCHLHDrawHotAreas = false; // Draw Hot Areas Symbol +input uchar xCHLHHotHHArrowCode = 234; // Hot HH Arrow Code +input color xCHLHHotHHArrowColor = clrAqua; // Hot HH Arrow Color +input uchar xCHLHHotLLArrowCode = 233; // Hot LL Arrow Code +input color xCHLHHotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// +// LC Inputs ... +input group "XCHLH Long Cycle"; +input group "XCHLH LC Market"; +input int xCHLHLcLength = 288; // Length +input double xCHLHLcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE xCHLHLcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE xCHLHLcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "XCHLH LC Style"; +input int xCHLHLcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE xCHLHLcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE xCHLHLcDrawStyle = STYLE_DOT; // Draw Style +input color xCHLHLcHHColor = clrAqua; // Highest High Color +input color xCHLHLcLLColor = clrFuchsia; // Lowest Low Color +input group "XCHLH LC Drawings"; +input bool xCHLHLcDrawHH = true; // Draw Highest High +input bool xCHLHLcDrawLL = true; // Draw Lowest Low + +// +// MC Inputs ... +input group "XCHLH Medium Cycle"; +input group "XCHLH MC Market"; +input int xCHLHMcLength = 72; // Length +input double xCHLHMcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE xCHLHMcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE xCHLHMcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "XCHLH MC Style"; +input int xCHLHMcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE xCHLHMcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE xCHLHMcDrawStyle = STYLE_DOT; // Draw Style +input color xCHLHMcHHColor = clrLime; // Highest High Color +input color xCHLHMcLLColor = clrRed; // Lowest Low Color +input group "XCHLH MC Drawings"; +input bool xCHLHMcDrawHH = true; // Draw Highest High +input bool xCHLHMcDrawLL = true; // Draw Lowest Low + +// +// SC Inputs ... +input group "XCHLH Short Cycle"; +input group "XCHLH SC Market"; +input int xCHLHScLength = 7; // Length +input double xCHLHScThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE xCHLHScHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE xCHLHScLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "XCHLH SC Style"; +input int xCHLHScDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE xCHLHScDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE xCHLHScDrawStyle = STYLE_DOT; // Draw Style +input color xCHLHScHHColor = clrLightBlue; // Highest High Color +input color xCHLHScLLColor = clrLightSalmon; // Lowest Low Color +input group "XCHLH SC Drawings"; +input bool xCHLHScDrawHH = true; // Draw Highest High +input bool xCHLHScDrawLL = true; // Draw Lowest Low + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xCHLHHandler = INVALID_HANDLE; +double xCHLHLcHHBuffer[]; +double xCHLHLcLLBuffer[]; +double xCHLHMcHHBuffer[]; +double xCHLHMcLLBuffer[]; +double xCHLHScHHBuffer[]; +double xCHLHScLLBuffer[]; +double xCHLHSignalTBuffer[]; +double xCHLHSignalBBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Init Oscillators ... +bool XCHLHInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XCHLH Handler ... + ArraySetAsSeries(xCHLHLcHHBuffer, true); + ArraySetAsSeries(xCHLHLcLLBuffer, true); + ArraySetAsSeries(xCHLHMcHHBuffer, true); + ArraySetAsSeries(xCHLHMcLLBuffer, true); + ArraySetAsSeries(xCHLHScHHBuffer, true); + ArraySetAsSeries(xCHLHScLLBuffer, true); + ArraySetAsSeries(xCHLHSignalTBuffer, true); + ArraySetAsSeries(xCHLHSignalBBuffer, true); + xCHLHHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xchlh.oscillator", + // + // Inputs ... + // + // Signal Calculations ... + "", + xCHLHSignalType, + // + // Commons ... + "", + xCHLHDrawHotAreas, + xCHLHHotHHArrowCode, + xCHLHHotHHArrowColor, + xCHLHHotLLArrowCode, + xCHLHHotLLArrowColor, + // + // LC ... + "", + "", + xCHLHLcLength, + xCHLHLcThresholdInPips, + xCHLHLcHHMode, + xCHLHLcLLMode, + "", + xCHLHLcDrawWidth, + xCHLHLcDrawType, + xCHLHLcDrawStyle, + xCHLHLcHHColor, + xCHLHLcLLColor, + "", + xCHLHLcDrawHH, + xCHLHLcDrawLL, + // + // MC ... + "", + "", + xCHLHMcLength, + xCHLHMcThresholdInPips, + xCHLHMcHHMode, + xCHLHMcLLMode, + "", + xCHLHMcDrawWidth, + xCHLHMcDrawType, + xCHLHMcDrawStyle, + xCHLHMcHHColor, + xCHLHMcLLColor, + "", + xCHLHMcDrawHH, + xCHLHMcDrawLL, + // + // SC ... + "", + "", + xCHLHScLength, + xCHLHScThresholdInPips, + xCHLHScHHMode, + xCHLHScLLMode, + "", + xCHLHScDrawWidth, + xCHLHScDrawType, + xCHLHScDrawStyle, + xCHLHScHHColor, + xCHLHScLLColor, + "", + xCHLHScDrawHH, + xCHLHScDrawLL); + if (xCHLHHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XCHLH Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XCHLHReleaseHandlers() +{ + IndicatorRelease(xCHLHHandler); +} + +// +// Handle Reading Buffers ... +void XCHLHReadBuffers( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XCHLH LC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_LC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHLcHHBuffer); + + // + // XCHLH LC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_LC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHLcLLBuffer); + + // + // XCHLH MC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_MC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHMcHHBuffer); + + // + // XCHLH MC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_MC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHMcLLBuffer); + + // + // XCHLH SC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHScHHBuffer); + + // + // XCHLH SC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHScLLBuffer); + + // + // XCHLH Signal T Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SIGNAL_T_LINE, + 0, + xCHLHItemsPerTick, + xCHLHSignalTBuffer); + + // + // XCHLH Signal B Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SIGNAL_B_LINE, + 0, + xCHLHItemsPerTick, + xCHLHSignalBBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START Signal Related Conditions ... +// + +// +// XCHLH Long Conditions ... +bool XCHLHHasLongConditions( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isSignalBCrossedOverLCLL = XCHLHIsSignalBCrossedOverLCLL(1); + + // + result = + // + isSignalBCrossedOverLCLL + // + ; + + // + return result; +} + +// +// XCHLH Close Long Conditions ... +bool XCHLHHasLongCloseConditions( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) { + // + bool result = false; + + // + bool isSignalBCrossedOverSignalT = XCHLHIsSignalBCrossedOverSignalT(1); + + // + result = + // + isSignalBCrossedOverSignalT + // + ; + + // + return result; +} + +// +// XCHLH Short Conditions ... +bool XCHLHHasShortConditions( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isSignalBCrossedUnderSignalT = XCHLHIsSignalBCrossedUnderSignalT(1); + + // + result = + // + isSignalBCrossedUnderSignalT + // + ; + + // + return result; +} + +// +// XCHLH Close Short Conditions ... +bool XCHLHHasShortCloseConditions( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isSignalBCrossedUnderLCLL = XCHLHIsSignalBCrossedUnderLCLL(1); + + // + result = + // + isSignalBCrossedUnderLCLL + // + ; + + // + return result; +} + +// +// END Signal Related Conditions ... +// + +// +// START XCHLH Custom Functions ... +// + +// +// Check Signal B Crossed Over LC LL ... +bool XCHLHIsSignalBCrossedOverLCLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsCrossOver( + xCHLHSignalBBuffer, + xCHLHLcLLBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Over LC LL ... +bool XCHLHIsSignalBOverLCLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsOver( + xCHLHSignalBBuffer, + xCHLHLcLLBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Crossed Under LC LL ... +bool XCHLHIsSignalBCrossedUnderLCLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsCrossUnder( + xCHLHSignalBBuffer, + xCHLHLcLLBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Under LC LL ... +bool XCHLHIsSignalBUnderLCLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsUnder( + xCHLHSignalBBuffer, + xCHLHLcLLBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Crossed Over Signal T ... +bool XCHLHIsSignalBCrossedOverSignalT( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsCrossOver( + xCHLHSignalBBuffer, + xCHLHSignalTBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Over Signal T ... +bool XCHLHIsSignalBOverSignalT( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsOver( + xCHLHSignalBBuffer, + xCHLHSignalTBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Crossed Under Signal T ... +bool XCHLHIsSignalBCrossedUnderSignalT( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsCrossUnder( + xCHLHSignalBBuffer, + xCHLHSignalTBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal B Under Signal T ... +bool XCHLHIsSignalBUnderSignalT( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 2)) + { + return result; + } + + // + result = IsUnder( + xCHLHSignalBBuffer, + xCHLHSignalTBuffer, + bar_index); + + // + return result; +} + +// +// Check LC and MC has Same HH ... +bool XCHLHIsLCMCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double mcValue = xCHLHMcHHBuffer[bar_index]; + + // + result = lcValue == mcValue; + + // + return result; +} + +// +// Check LC and MC has Same LL ... +bool XCHLHIsLCMCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double mcValue = xCHLHMcLLBuffer[bar_index]; + + // + result = lcValue == mcValue; + + // + return result; +} + +// +// Check LC and SC has Same HH ... +bool XCHLHIsLCSCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = lcValue == scValue; + + // + return result; +} + +// +// Check LC and SC has Same LL ... +bool XCHLHIsLCSCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = lcValue == scValue; + + // + return result; +} + +// +// Check MC and SC has Same HH ... +bool XCHLHIsMCSCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double mcValue = xCHLHMcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = mcValue == scValue; + + // + return result; +} + +// +// Check MC and SC has Same LL ... +bool XCHLHIsMCSCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double mcValue = xCHLHMcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = mcValue == scValue; + + // + return result; +} + +// +// Check Is Same Highest Highs ... +bool XCHLHIsSameHHs( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double mcValue = xCHLHMcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = + // + lcValue == mcValue && + mcValue == scValue + // + ; + + // + return result; +} + +// +// Check Is Same Lowest Lows ... +bool XCHLHIsSameLLs( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double mcValue = xCHLHMcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = + // + lcValue == mcValue && + mcValue == scValue + // + ; + + // + return result; +} + +// +// Check and Validate Buffer Sizes ... +bool XCHLHIsValidBufferSizes( + int size // Specified Min Size +) +{ + // + bool result = false; + + // + result = + // + ArraySize(xCHLHLcHHBuffer) > size && + ArraySize(xCHLHLcLLBuffer) > size && + // + ArraySize(xCHLHMcHHBuffer) > size && + ArraySize(xCHLHMcLLBuffer) > size && + // + ArraySize(xCHLHScHHBuffer) > size && + ArraySize(xCHLHScLLBuffer) > size; + + // + return result; +} + +// +// END XCHLH Custom Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchma.oscillator.helper.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..b028bb9 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xchma.oscillator.helper.lib.mq5 @@ -0,0 +1,1535 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHMA Oscillator 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 + +// +// Includes ... +#include "..\Libraries\x-saherelm.log.lib.mq5" +#include "..\Libraries\x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XCHMA Cycles ... +enum ENUM_XCHMA_CYCLES +{ + X_XCHMA_CYCLE_LONG, + X_XCHMA_CYCLE_MEDIUM, + X_XCHMA_CYCLE_SHORT, +}; + +// +// XCHMA Oscillator Hot State Presentation ... +enum ENUM_XCHMA_HOT_STATES +{ + X_XCHMA_HOT_BULLISH = 1, + X_XCHMA_HOT_NEUTURAL = 0, + X_XCHMA_HOT_BEARISH = -1, +}; + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; + +// +// XCHMA Oscillator Buffer Lines ... +enum ENUM_X_XCHMA_BUFFER_LINES +{ + X_XCHMA_LC_FAST_LINE = 0, + X_XCHMA_LC_SLOW_LINE = 1, + X_XCHMA_LC_STATE_LINE = 6, + X_XCHMA_MC_FAST_LINE = 2, + X_XCHMA_MC_SLOW_LINE = 3, + X_XCHMA_MC_STATE_LINE = 7, + X_XCHMA_SC_FAST_LINE = 4, + X_XCHMA_SC_SLOW_LINE = 5, + X_XCHMA_SC_STATE_LINE = 8, + X_XCHMA_HOT_STATE_LINE = 9, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +input group "XCHMA Oscillator"; + +// +// Commons ... +input group "XCHMA Hot Areas"; +input bool xCHMADrawHotAreas = false; // Draw Hot Areas Symbol; +input uchar xCHMAHotBullishArrowCode = 228; // Hot Bullish Arrow Code; +input color xCHMAHotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color; +input uchar xCHMAHotBearishArrowCode = 230; // Hot Bearish Arrow Code; +input color xCHMAHotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color; + +// +// LC Inputs ... +input group "XCHMA Long Cycle"; +input group "XCHMA LC Market"; +input int xCHMALcFastLength = 288; // Fast Length +input int xCHMALcSlowLength = 576; // Slow Length +input ENUM_MA_METHOD xCHMALcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE xCHMALcAppliedTo = PRICE_CLOSE; // Applied To +input group "XCHMA LC Style"; +input int xCHMALcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE xCHMALcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE xCHMALcDrawStyle = STYLE_DOT; // Draw Style +input color xCHMALcFastColor = clrAqua; // Fast Color +input color xCHMALcSlowColor = clrFuchsia; // Slow Color +input group "XCHMA LC Drawings"; +input bool xCHMALcDrawFast = true; // Draw Fast +input bool xCHMALcDrawSlow = true; // Draw Slow +input bool xCHMALcDrawCrosses = false; // Draw Cross Lines + +// +// MC Inputs ... +input group "XCHMA Medium Cycle"; +input group "XCHMA MC Market"; +input int xCHMAMcFastLength = 72; // Fast Length +input int xCHMAMcSlowLength = 144; // Slow Length +input ENUM_MA_METHOD xCHMAMcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE xCHMAMcAppliedTo = PRICE_CLOSE; // Applied To +input group "XCHMA MC Style"; +input int xCHMAMcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE xCHMAMcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE xCHMAMcDrawStyle = STYLE_DOT; // Draw Style +input color xCHMAMcFastColor = clrLime; // Fast Color +input color xCHMAMcSlowColor = clrRed; // Slow Color +input group "XCHMA MC Drawings"; +input bool xCHMAMcDrawFast = true; // Draw Fast +input bool xCHMAMcDrawSlow = true; // Draw Slow +input bool xCHMAMcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +input group "XCHMA Short Cycle"; +input group "XCHMA SC Market"; +input int xCHMAScFastLength = 7; // Fast Length +input int xCHMAScSlowLength = 14; // Slow Length +input ENUM_MA_METHOD xCHMAScMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE xCHMAScAppliedTo = PRICE_CLOSE; // Applied To +input group "XCHMA SC Style"; +input int xCHMAScDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE xCHMAScDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE xCHMAScDrawStyle = STYLE_SOLID; // Draw Style +input color xCHMAScFastColor = clrLightBlue; // Fast Color +input color xCHMAScSlowColor = clrLightSalmon; // Slow Color +input group "XCHMA SC Drawings"; +input bool xCHMAScDrawFast = true; // Draw Fast +input bool xCHMAScDrawSlow = true; // Draw Slow +input bool xCHMAScDrawCrosses = false; // Draw Cross Lines + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xCHMAHandler = INVALID_HANDLE; +double xCHMALcFastBuffer[]; +double xCHMALcSlowBuffer[]; +double xCHMAMcFastBuffer[]; +double xCHMAMcSlowBuffer[]; +double xCHMAScFastBuffer[]; +double xCHMAScSlowBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Init Oscillators ... +bool XCHMAInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XCHMA Handler ... + ArraySetAsSeries(xCHMALcFastBuffer, true); + ArraySetAsSeries(xCHMALcSlowBuffer, true); + ArraySetAsSeries(xCHMAMcFastBuffer, true); + ArraySetAsSeries(xCHMAMcSlowBuffer, true); + ArraySetAsSeries(xCHMAScFastBuffer, true); + ArraySetAsSeries(xCHMAScSlowBuffer, true); + xCHMAHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xchma.oscillator", + // + // Inputs ... + "", + xCHMADrawHotAreas, + xCHMAHotBullishArrowCode, + xCHMAHotBullishArrowColor, + xCHMAHotBearishArrowCode, + xCHMAHotBearishArrowColor, + // + // Long Cycle ... + "", + "", + xCHMALcFastLength, + xCHMALcSlowLength, + xCHMALcMethod, + xCHMALcAppliedTo, + "", + xCHMALcDrawWidth, + xCHMALcDrawType, + xCHMALcDrawStyle, + xCHMALcFastColor, + xCHMALcSlowColor, + "", + xCHMALcDrawFast, + xCHMALcDrawSlow, + xCHMALcDrawCrosses, + // + // Medium Cycle ... + "", + "", + xCHMAMcFastLength, + xCHMAMcSlowLength, + xCHMAMcMethod, + xCHMAMcAppliedTo, + "", + xCHMAMcDrawWidth, + xCHMAMcDrawType, + xCHMAMcDrawStyle, + xCHMAMcFastColor, + xCHMAMcSlowColor, + "", + xCHMAMcDrawFast, + xCHMAMcDrawSlow, + xCHMAMcDrawCrosses, + // + // Short Cycle ... + "", + "", + xCHMAScFastLength, + xCHMAScSlowLength, + xCHMAScMethod, + xCHMAScAppliedTo, + "", + xCHMAScDrawWidth, + xCHMAScDrawType, + xCHMAScDrawStyle, + xCHMAScFastColor, + xCHMAScSlowColor, + "", + xCHMAScDrawFast, + xCHMAScDrawSlow, + xCHMAScDrawCrosses); + if (xCHMAHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XCHMA Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XCHMAReleaseHandlers() +{ + IndicatorRelease(xCHMAHandler); +} + +// +// Handle Reading Buffers ... +void XCHMAReadBuffers( + int xCHMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XCHMA Long Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_LC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMALcFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_LC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMALcSlowBuffer); + + // + // XCHMA Medium Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_MC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMAMcFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_MC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMAMcSlowBuffer); + + // + // XCHMA Short Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_SC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMAScFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_SC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMAScSlowBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START Signal Related Conditions ... +// + +// +// XCHMA Long Conditions ... +bool XCHMAHasLongConditions( + int xCHMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isSCVale = XCHMAIsSCVale(); + bool isSCFastOverSlow = XCHMAIsSCFastOverSlow(1); + bool isScFastCrossedOver = XCHMAIsSCFastCrossedOverSlow(1); + + // + bool isMcVale = XCHMAIsMCVale(); + bool isMCFastOverSlow = XCHMAIsMCFastOverSlow(1); + bool isMcFastCrossedOver = XCHMAIsMCFastCrossedOverSlow(1); + + // + bool isLcVale = XCHMAIsLCVale(); + bool isLCFastOverSlow = XCHMAIsLCFastOverSlow(1); + bool isLcFastCrossedOver = XCHMAIsLCFastCrossedOverSlow(1); + + // + bool scHasSignal = + // isSCVale && + isScFastCrossedOver && + ( + // + isMCFastOverSlow || + isMcFastCrossedOver + // + ) && + ( + // + isLCFastOverSlow || + isLcFastCrossedOver + // + ); + + // + bool mcHasSignal = + // isMcVale && + isMcFastCrossedOver && + ( + // + isSCFastOverSlow || + isScFastCrossedOver + // + ) && + ( + // + isLCFastOverSlow || + isLcFastCrossedOver + // + ); + ; + + // + bool lcHasSignal = + // isLcVale && + isLcFastCrossedOver && + ( + // + isSCFastOverSlow || + isScFastCrossedOver + // + ) && + ( + // + isMCFastOverSlow || + isMcFastCrossedOver + // + ); + + // + // Signal ... + bool hasSignal = + // + scHasSignal + // + || + // + mcHasSignal + // + || + // + lcHasSignal + // + ; + + // + result = + // + hasSignal + // + ; + + // + return result; +} + +// +// XCHMA Short Conditions ... +bool XCHMAHasShortConditions( + int xCHMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool scHasSignal = false; // XCHMAIsSCPeak(); + bool mcHasSignal = false; // XCHMAIsMCPeak(); + bool lcHasSignal = false; // XCHMAIsLCPeak(); + + // + // Signal ... + bool hasSignal = + // + scHasSignal + // + || + // + mcHasSignal + // + || + // + lcHasSignal + // + ; + + // + // Very Strong Signal ... + bool hasVeryStrongSignal = + // + scHasSignal + // + && + // + mcHasSignal + // + && + // + lcHasSignal + // + ; + + // + // Strong Signal ... + bool hasStrongSignal = + // + !hasVeryStrongSignal + // + && + // + ( + // + // SC and MC Provide Signal ... + ( + // + scHasSignal + // + && + // + mcHasSignal + // + ) + // + || + // + // MC and LC Provide Signal ... + ( + // + mcHasSignal + // + && + // + lcHasSignal + // + ) + // + || + // + // SC and LC Provide Signal ... + ( + // + scHasSignal + // + && + // + lcHasSignal + // + ) + // + ) + // + ; + + // + // Has Regular Signal ... + bool hasRegularSignal = + hasSignal && !hasStrongSignal && !hasVeryStrongSignal; + + // + result = + // + lcHasSignal + // + || + // + mcHasSignal + // + || + // + scHasSignal + // + ; + + // + return result; +} + +// +// END Signal Related Conditions ... +// + +// +// START XCHMA Custom Functions ... +// + +// +// Retrieve Max Cycles Value ... +double XCHMAGetMax( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if (!XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // SC Fast ... + result = MathMax( + result, + xCHMAScFastBuffer[bar_index]); + + // + // SC Slow ... + result = MathMax( + result, + xCHMAScSlowBuffer[bar_index]); + + // + // MC Fast ... + result = MathMax( + result, + xCHMAMcFastBuffer[bar_index]); + + // + // MC Slow ... + result = MathMax( + result, + xCHMAMcSlowBuffer[bar_index]); + + // + // LC Fast ... + result = MathMax( + result, + xCHMALcFastBuffer[bar_index]); + + // + // LC Slow ... + result = MathMax( + result, + xCHMALcSlowBuffer[bar_index]); + + // + return result; +} + +// +// Retrieve Max Cycles Value ... +double XCHMAGetMin( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if (!XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = xCHMAScFastBuffer[bar_index]; + + // + // SC Fast ... + result = MathMin( + result, + xCHMAScFastBuffer[bar_index]); + + // + // SC Slow ... + result = MathMin( + result, + xCHMAScSlowBuffer[bar_index]); + + // + // MC Fast ... + result = MathMin( + result, + xCHMAMcFastBuffer[bar_index]); + + // + // MC Slow ... + result = MathMin( + result, + xCHMAMcSlowBuffer[bar_index]); + + // + // LC Fast ... + result = MathMin( + result, + xCHMALcFastBuffer[bar_index]); + + // + // LC Slow ... + result = MathMin( + result, + xCHMALcSlowBuffer[bar_index]); + + // + return result; +} + +// +// Long Cycle ... +// + +// +// Check LC is Peak ... +bool XCHMAIsLCPeak() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 30, + 9, + xCHMALcFastBuffer); + + // + bool isDecreasing = IsDecreasing( + 9, + 1, + xCHMALcFastBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check LC is Vale ... +bool XCHMAIsLCVale() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 9, + 1, + xCHMALcFastBuffer); + + // + bool isDecreasing = IsDecreasing( + 30, + 9, + xCHMALcFastBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check LC Fast Crossed Over Slow ... +bool XCHMAIsLCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Over Slow ... +bool XCHMAIsLCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Crossed Under Slow ... +bool XCHMAIsLCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Under Slow ... +bool XCHMAIsLCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Medium Cycle ... +// + +// +// Check MC is Peak ... +bool XCHMAIsMCPeak() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 20, + 6, + xCHMAMcFastBuffer); + + // + bool isDecreasing = IsDecreasing( + 6, + 1, + xCHMAMcFastBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check MC is Vale ... +bool XCHMAIsMCVale() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 6, + 1, + xCHMAMcFastBuffer); + + // + bool isDecreasing = IsDecreasing( + 20, + 6, + xCHMAMcFastBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check MC Fast Crossed Over Slow ... +bool XCHMAIsMCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Over Slow ... +bool XCHMAIsMCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Crossed Under Slow ... +bool XCHMAIsMCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Under Slow ... +bool XCHMAIsMCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Short Cycle ... +// + +// +// Check SC is Peak ... +bool XCHMAIsSCPeak() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 10, + 3, + xCHMAScFastBuffer); + + // + bool isDecreasing = IsDecreasing( + 3, + 1, + xCHMAScFastBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check SC is Vale ... +bool XCHMAIsSCVale() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 3, + 1, + xCHMAScFastBuffer); + + // + bool isDecreasing = IsDecreasing( + 10, + 3, + xCHMAScFastBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check SC Fast Crossed Over Slow ... +bool XCHMAIsSCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Over Slow ... +bool XCHMAIsSCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Crossed Under Slow ... +bool XCHMAIsSCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Under Slow ... +bool XCHMAIsSCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Utility Functions ... +// + +// +// Check all Buffers has valid Size ... +bool XCHMAIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xCHMALcFastBuffer) < size || + ArraySize(xCHMALcSlowBuffer) < size || + // + ArraySize(xCHMAMcFastBuffer) < size || + ArraySize(xCHMAMcSlowBuffer) < size || + // + ArraySize(xCHMAScFastBuffer) < size || + ArraySize(xCHMAScSlowBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Get Cycle Fast Length ... +int XCHMAGetCycleFastLength( + ENUM_XCHMA_CYCLES cycle // Specified Cycle +) +{ + // + int result = 0; + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + result = xCHMALcFastLength; + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + result = xCHMAMcFastLength; + break; + + // + case X_XCHMA_CYCLE_SHORT: + result = xCHMAScFastLength; + break; + } + + // + return result; +} + +// +// Get Cycle Slow Length ... +int XCHMAGetCycleSlowLength( + ENUM_XCHMA_CYCLES cycle // Specified Cycle +) +{ + // + int result = 0; + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + result = xCHMALcSlowLength; + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + result = xCHMAMcSlowLength; + break; + + // + case X_XCHMA_CYCLE_SHORT: + result = xCHMAScSlowLength; + break; + } + + // + return result; +} + +// +// Retrieve Cycle Fast Buffer ... +void XCHMAGetCycleFastBuffer( + ENUM_XCHMA_CYCLES cycle, // Specified Cycle + double &result[] // Specified Result buffer to Hold Values ... +) +{ + // + CleanBuffer(result); + ArraySetAsSeries(result, true); + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + // + ArrayCopy( + result, + xCHMALcFastBuffer); + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + // + ArrayCopy( + result, + xCHMAMcFastBuffer); + break; + + // + case X_XCHMA_CYCLE_SHORT: + // + ArrayCopy( + result, + xCHMAScFastBuffer); + break; + } +} + +// +// Retrieve Cycle Fast Buffer ... +void XCHMAGetCycleSlowBuffer( + ENUM_XCHMA_CYCLES cycle, // Specified Cycle + double &result[] // Specified Result buffer to Hold Values ... +) +{ + // + CleanBuffer(result); + ArraySetAsSeries(result, true); + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + // + ArrayCopy( + result, + xCHMALcSlowBuffer); + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + // + ArrayCopy( + result, + xCHMAMcSlowBuffer); + break; + + // + case X_XCHMA_CYCLE_SHORT: + // + ArrayCopy( + result, + xCHMAScSlowBuffer); + break; + } +} + +// +// Check a Cycle is vale ... +bool XCHMAIsCycleVale( + ENUM_XCHMA_CYCLES cycle // Specified Cycle +) +{ + // + bool result = false; + + // + // Retrieve Length ... + int length = XCHMAGetCycleFastLength(cycle); + int halfLength = length / 2; + int thirdLength = length / 3; + int qLength = length / 4; + qLength = qLength < 3 ? 3 : qLength > 7 ? 7 + : qLength; + + // + double buffer[]; + XCHMAGetCycleFastBuffer( + cycle, + buffer); + + // + bool isIncreasing = IsIncreasing( + qLength, + 1, + buffer); + + // + bool isDecreasing = IsDecreasing( + thirdLength, + qLength, + buffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check a Cycle is peak ... +bool XCHMAIsCyclePeak( + ENUM_XCHMA_CYCLES cycle // Specified Cycle +) +{ + // + bool result = false; + + // + // Retrieve Length ... + int length = XCHMAGetCycleFastLength(cycle); + int halfLength = length / 2; + int thirdLength = length / 3; + int qLength = length / 4; + qLength = qLength < 3 ? 3 : qLength > 7 ? 7 + : qLength; + + // + double buffer[]; + XCHMAGetCycleFastBuffer( + cycle, + buffer); + + // + bool isIncreasing = IsIncreasing( + thirdLength, + qLength, + buffer); + + // + bool isDecreasing = IsDecreasing( + qLength, + 1, + buffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} +// +// END XCHMA Custom Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xobd.oscillator.helper.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xobd.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..75543de --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xobd.oscillator.helper.lib.mq5 @@ -0,0 +1,417 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XOBD Oscillator 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 + +// +// Includes ... +#include "..\Libraries\x-saherelm.log.lib.mq5" +#include "..\Libraries\x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XOBD Oscillator Buffer Lines ... +enum ENUM_X_XOBD_BUFFER_LINES +{ + X_XOBD_SWING_HIGH_LINE = 0, + X_XOBD_SWING_LOW_LINE = 1, + X_XOBD_SIGNAL_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +input group "XOBD Oscillator"; +input int xOBDLength = 72; // Market Length + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xOBDHandler = INVALID_HANDLE; +double xOBDSwingHighBuffer[]; +double xOBDSwingLowBuffer[]; +double xOBDSignalBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Init Oscillators ... +bool XOBDInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XOBD Handler ... + ArraySetAsSeries(xOBDSwingHighBuffer, true); + ArraySetAsSeries(xOBDSwingLowBuffer, true); + ArraySetAsSeries(xOBDSignalBuffer, true); + xOBDHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xobd.oscillator", + // + // Inputs ... + xOBDLength + // + ); + if (xOBDHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XOBD Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XOBDReleaseHandlers() +{ + IndicatorRelease(xOBDHandler); +} + +// +// Handle Reading Buffers ... +void XOBDReadBuffers( + int xOBDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // XOBD Swing High ... + CopyBuffer( + xOBDHandler, + X_XOBD_SWING_HIGH_LINE, + 0, + xOBDItemsPerTick, + xOBDSwingHighBuffer); + + // + // XOBD Swing Low ... + CopyBuffer( + xOBDHandler, + X_XOBD_SWING_LOW_LINE, + 0, + xOBDItemsPerTick, + xOBDSwingLowBuffer); + + // + // XOBD Signal ... + CopyBuffer( + xOBDHandler, + X_XOBD_SIGNAL_LINE, + 0, + xOBDItemsPerTick, + xOBDSignalBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START Signal Related Conditions ... +// + +// +// XOBD Long Conditions ... +bool XOBDHasLongConditions( + int xOBDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isVale = XOBDIsVale(); + bool isInPeak = IsInPeak( + xOBDItemsPerTick, + xOBDSignalBuffer); + + // + result = + // + isVale + // + && + // + !isInPeak + // + ; + + // + return result; +} + +// +// XOBD Short Conditions ... +bool XOBDHasShortConditions( + int xOBDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + return result; +} + +// +// END Signal Related Conditions ... +// + +// +// START XOBD Custom Functions ... +// + +// +// Check all Buffers has valid Size ... +bool XOBDIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xOBDSignalBuffer) < size || + ArraySize(xOBDSwingLowBuffer) < size || + ArraySize(xOBDSwingHighBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Check SC is Peak ... +bool XOBDIsPeak() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 10, + 3, + xOBDSignalBuffer); + + // + bool isDecreasing = IsDecreasing( + 3, + 1, + xOBDSignalBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check SC is Vale ... +bool XOBDIsVale() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 5, + 1, + xOBDSignalBuffer); + + // + bool isDecreasing = IsDecreasing( + 20, + 5, + xOBDSignalBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check Signal Crossed Over Swing High ... +bool XOBDIsSignalCrossedOverSwingHigh( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = IsCrossOver( + xOBDSignalBuffer, + xOBDSwingHighBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal Over Swing High ... +bool XOBDIsSignalOverSwingHigh( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = IsOver( + xOBDSignalBuffer, + xOBDSwingHighBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal Crossed Under Swing High ... +bool XOBDIsSignalCrossedUnderSwingHigh( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = IsCrossUnder( + xOBDSignalBuffer, + xOBDSwingHighBuffer, + bar_index); + + // + return result; +} + +// +// Check Signal Under Swing High ... +bool XOBDIsSignalUnderSwingHigh( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = IsUnder( + xOBDSignalBuffer, + xOBDSwingHighBuffer, + bar_index); + + // + return result; +} + +// +// END XOBD Custom Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..c1eb3f2 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xrsi.oscillator.helper.lib.mq5 @@ -0,0 +1,424 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XRSI Oscillator 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 + +// +// Includes ... +#include "..\Libraries\x-saherelm.log.lib.mq5" +#include "..\Libraries\x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XRSI Oscillator Buffer Lines ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +input group "XRSI Oscillator"; + +// +input group "XRSI Market"; +input int xRSILength = 14; // Market Length +input ENUM_APPLIED_PRICE xRSIAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "XRSI Short Entry"; +input double xRSIShortEntryValue = 70; // Short Entry Level +input color xRSIShortEntryColor = clrRed; // Short Entry Level Color +input ENUM_LINE_STYLE xRSIShortEntryLineStyle = STYLE_SOLID; // Short Entry Style + +// +input group "XRSI Short Exit"; +input double xRSIShortExitValue = 40; // Short Exit Level +input color xRSIShortExitColor = clrFuchsia; // Short Exit Level Color +input ENUM_LINE_STYLE xRSIShortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +input group "XRSI Long Entry"; +input double xRSILongEntryValue = 30; // Long Entry Level +input color xRSILongEntryColor = clrGreen; // Long Entry Level Color +input ENUM_LINE_STYLE xRSILongEntryLineStyle = STYLE_SOLID; // Long Entry Style + +// +input group "XRSI Long Exit"; +input double xRSILongExitValue = 60; // Long Exit Level +input color xRSILongExitColor = clrAqua; // Long Exit Level Color +input ENUM_LINE_STYLE xRSILongExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xRSIHandler = INVALID_HANDLE; +double xRSIBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Init Oscillators ... +bool XRSIInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XRSI Handler ... + ArraySetAsSeries(xRSIBuffer, true); + xRSIHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xrsi.oscillator", + // + // Inputs ... + // + // Market ... + "", + xRSILength, + xRSIAppliedTo, + // + // Short Entry ... + "", + xRSIShortEntryValue, + xRSIShortEntryColor, + xRSIShortEntryLineStyle, + // + // Short Exit ... + "", + xRSIShortExitValue, + xRSIShortExitColor, + xRSIShortExitLineStyle, + // + // Long Entry ... + "", + xRSILongEntryValue, + xRSILongEntryColor, + xRSILongEntryLineStyle, + // + // Long Exit ... + "", + xRSILongExitValue, + xRSILongExitColor, + xRSILongExitLineStyle + // + ); + if (xRSIHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XRSI Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XRSIReleaseHandlers() +{ + IndicatorRelease(xRSIHandler); +} + +// +// Handle Reading Buffers ... +void XRSIReadBuffers( + int xRSIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XRSI Signal ... + CopyBuffer( + xRSIHandler, + 0, + 0, + xRSIItemsPerTick, + xRSIBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START Signal Related Conditions ... +// + +// +// XRSI Long Conditions ... +bool XRSIHasLongConditions( + int xRSIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + return result; +} + +// +// XRSI Short Conditions ... +bool XRSIHasShortConditions( + int xRSIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + return result; +} + +// +// END Signal Related Conditions ... +// + +// +// START XRSI Custom Functions ... +// + +// +// Check SC is Peak ... +bool XRSIIsPeak() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 11, + 3, + xRSIBuffer); + + // + bool isDecreasing = IsDecreasing( + 3, + 1, + xRSIBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check SC is Vale ... +bool XRSIIsVale() +{ + // + bool result = false; + + // + bool isIncreasing = IsIncreasing( + 3, + 1, + xRSIBuffer); + + // + bool isDecreasing = IsDecreasing( + 11, + 3, + xRSIBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// RSI Value GO Up from Long Entry ... +bool XRSIIsCrossedOverLongEntry( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] > xRSILongEntryValue && + xRSIBuffer[bar_index + 2] <= xRSILongEntryValue; + + // + return result; +} + +// +// RSI Value GO Up from Long Exit ... +bool XRSIIsCrossedOverLongExit( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] > xRSILongExitValue && + xRSIBuffer[bar_index + 2] <= xRSILongExitValue; + + // + return result; +} + +// +// RSI Value Go Down Short Entry ... +bool XRSIIsCrossedUnderShortEntry( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] < xRSIShortEntryValue && + xRSIBuffer[bar_index + 2] >= xRSIShortEntryValue; + + // + return result; +} + +// +// RSI Value Go Down Short Exit ... +bool XRSIIsCrossedUnderShortExit( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] < xRSIShortExitValue && + xRSIBuffer[bar_index + 2] >= xRSIShortExitValue; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XRSIIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xRSIBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XRSI Custom Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtd.oscillator.helper.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..ba6d60b --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtd.oscillator.helper.lib.mq5 @@ -0,0 +1,917 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTD Oscillator 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 + +// +// Includes ... +#include "..\Libraries\x-saherelm.log.lib.mq5" +#include "..\Libraries\x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; + +// +// XTD Oscillator Buffer Lines ... +enum ENUM_X_XTD_BUFFER_LINES +{ + X_XTD_BULLISH_POWER_LINE = 0, + X_XTD_BEARISH_POWER_LINE = 1, + X_XTD_SIGNAL_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +input group "XTD Oscillator"; +input int xTDLength = 14; // Market Length +input bool xTDDrawCrosses = false; // Draw Cross Arrows +input uchar xTDBullishArrowCode = 228; // Cross Over Arrow Code +input color xTDBullishArrowColor = clrAqua; // Cross Over Arrow Color +input uchar xTDBearishArrowCode = 230; // Cross Under Arrow Code +input color xTDBearishArrowColor = clrMagenta; // Cross Under Arrow Color + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTDHandler = INVALID_HANDLE; +double xTDBullishBuffer[]; +double xTDBearishBuffer[]; +double xTDSignalBuffer[]; +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Init Oscillators ... +bool XTDInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTD Handler ... + ArraySetAsSeries(xTDBullishBuffer, true); + ArraySetAsSeries(xTDBearishBuffer, true); + ArraySetAsSeries(xTDSignalBuffer, true); + xTDHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xtd.oscillator", + // + // Inputs ... + xTDLength, + xTDDrawCrosses, + xTDBullishArrowCode, + xTDBullishArrowColor, + xTDBearishArrowCode, + xTDBearishArrowColor); + if (xTDHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTD Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XTDReleaseHandlers() +{ + IndicatorRelease(xTDHandler); +} + +// +// Handle Reading Buffers ... +void XTDReadBuffers( + int xTDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XTD Bullish Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_BULLISH_POWER_LINE, + 0, + xTDItemsPerTick, + xTDBullishBuffer); + + // + // XTD Bullish Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_BEARISH_POWER_LINE, + 0, + xTDItemsPerTick, + xTDBearishBuffer); + + // + // XTD Signal Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_SIGNAL_LINE, + 0, + xTDItemsPerTick, + xTDSignalBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START Signal Related Conditions ... +// + +// +// XTD Long Conditions ... +bool XTDHasLongConditions( + int xTDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isVale = XTDIsSignalVale(); + + // + bool isInPeak = IsInPeak( + 15, + xTDSignalBuffer); + + // + bool isSharpChanged = IsSharpChanged( + 15, + 1, + xTDSignalBuffer); + + // + double entry = GetEntry(X_SIGNAL_LONG); + double maxPrice = GetHighestHigh( + 7, + 0); + double minPrice = GetLowestLow( + 7, + 0); + double priceDelta = maxPrice - minPrice; + double priceStep = priceDelta / 7; + + // + bool isPricePassed = + entry < maxPrice && + maxPrice - entry < (priceDelta / 4) * 3; + + // + result = + // + isVale + // + && + // + !isInPeak + // + && + // + !isSharpChanged + // + && + // + isPricePassed + // + ; + + // + return result; +} + +// +// XTD Short Conditions ... +bool XTDHasShortConditions( + int xTDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isPeak = XTDIsSignalPeak(); + + // + bool isInVale = IsInVale( + 15, + xTDSignalBuffer); + + // + bool isSharpChanged = IsSharpChanged( + 15, + 1, + xTDSignalBuffer); + + // + double entry = GetEntry(X_SIGNAL_SHORT); + double maxPrice = GetHighestHigh( + 7, + 0); + double minPrice = GetLowestLow( + 7, + 0); + double priceDelta = maxPrice - minPrice; + double priceStep = priceDelta / 7; + + // + bool isPricePassed = + entry > minPrice && + minPrice + entry > (priceDelta / 4); + + // + result = + // + isPeak + // + && + // + !isInVale + // + && + // + !isSharpChanged + // + && + // + isPricePassed + // + ; + + // + return result; +} + +// +// END Signal Related Conditions ... +// + +// +// START XTD Custom Functions ... +// + +// +// Check Signal Vale ... +bool XTDIsSignalVale() +{ + // + bool result = false; + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + 3, + 1, + xTDSignalBuffer); + + // + // Must Increasing ... + bool isDecreasing = IsDecreasing( + 15, + 3, + xTDSignalBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsSignalPeak() +{ + // + bool result = false; + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + 15, + 3, + xTDSignalBuffer); + + // + // Must Increasing ... + bool isDecreasing = IsDecreasing( + 3, + 1, + xTDSignalBuffer); + + // + // Generating Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Check Signal Peak ... + +// +// Check Bullish Crossed Over Bearish ... +bool XTDIsBullCrossedOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Over Bearish ... +bool XTDIsBullOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Crossed Under Bearish ... +bool XTDIsBullCrossedUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Under Bearish ... +bool XTDIsBullUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Crossed Over Bearish ... +bool XTDIsSignalCrossedOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Over Bearish ... +bool XTDIsSignalOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Crossed Under Bearish ... +bool XTDIsSignalCrossedUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Under Bearish ... +bool XTDIsSignalUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTDIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + ArraySize(xTDBullishBuffer) < size || + ArraySize(xTDBullishBuffer) < size || + ArraySize(xTDSignalBuffer) < size) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Count Signal Crossed Over Bear ... +int XTDCountSignalCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedOverBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Signal Crossed Under Bear ... +int XTDCountSignalCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedUnderBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Bull Crossed Over Bear ... +int XTDCountBullCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedOverBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Bull Crossed Under Bear ... +int XTDCountBullCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedUnderBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Find Last Signal Crossed Over Bear ... +int XTDFindLastSignalCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedOverBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Signal Crossed Onder Bear ... +int XTDFindLastSignalCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedUnderBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Bull Crossed Over Bear ... +int XTDFindLastBullCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedOverBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Bull Crossed Under Bear ... +int XTDFindLastBullCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedUnderBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// END XTD Custom Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.indicators.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.indicators.lib.mq5 new file mode 100644 index 0000000..7e3ec99 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.indicators.lib.mq5 @@ -0,0 +1,2316 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTEST Signal Provider Indicators Library +// ---------------------------------------------------------------- +// +// 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 Provider Inputs ... +#include "x-saherelm.xtest.provider.inputs.lib.mq5"; + +// +// START Define Enums ... +// + +// +// Represent Signals Methods ... +enum ENUM_X_SIGNAL_METHODS +{ + X_SIGNAL_METHOD_1, + X_SIGNAL_METHOD_2, + X_SIGNAL_METHOD_3, +}; + +// +// Represent Market Conditions ... +struct X_TEST_MARKET_CONDITIONS +{ + // + // XTM ... + bool isXTMPeak; + bool isXTMVale; + + // + // XTD ... + bool isXTDSignalPeak; + bool isXTDSignalVale; + bool isXTDSignalOverBear; + bool isXTDSignalUnderBear; + bool isXTDSignalCrossedOverBear; + bool isXTDSignalCrossedUnderBear; + + // + // XRSI ... + bool isXRSIPeak; + bool isXRSIVale; + bool isXRSICrossedOverLongExit; + bool isXRSICrossedOverLongEntry; + bool isXRSICrossedUnderShortExit; + bool isXRSICrossedUnderShortEntry; + + // + // XOBD ... + bool isXOBDPeak; + bool isXOBDVale; + bool isXOBDSignalOverSwingHigh; + bool isXOBDSignalUnderSwingHigh; + bool isXOBDSignalCrossedOverSwingHigh; + bool isXOBDSignalCrossedUnderSwingHigh; + + // + // XCHLH ... + // + bool isXCHLHSignalBOverSignalT; + bool isXCHLHSignalBUnderSignalT; + bool isXCHLHSignalBCrossedOverSignalT; + bool isXCHLHSignalBCrossedUnderSignalT; + // + bool isXCHLHSignalBOverLCLL; + bool isXCHLHSignalBUnderLCLL; + bool isXCHLHSignalBCrossedOverLCLL; + bool isXCHLHSignalBCrossedUnderLCLL; + // + bool isXCHLHSCMCHHSame; + bool isXCHLHSCMCLLSame; + // + bool isXCHLHSCLCHHSame; + bool isXCHLHSCLCLLSame; + // + bool isXCHLHMCLCHHSame; + bool isXCHLHMCLCLLSame; + + // + // XCHMA ... + // + bool isXCHMASCPeak; + bool isXCHMASCVale; + bool isXCHMASCFastOverSlow; + bool isXCHMASCFastUnderSlow; + bool isXCHMASCFastCrossedOverSlow; + bool isXCHMASCFastCrossedUnderSlow; + // + bool isXCHMAMCPeak; + bool isXCHMAMCVale; + bool isXCHMAMCFastOverSlow; + bool isXCHMAMCFastUnderSlow; + bool isXCHMAMCFastCrossedOverSlow; + bool isXCHMAMCFastCrossedUnderSlow; + // + bool isXCHMALCPeak; + bool isXCHMALCVale; + bool isXCHMALCFastOverSlow; + bool isXCHMALCFastUnderSlow; + bool isXCHMALCFastCrossedOverSlow; + bool isXCHMALCFastCrossedUnderSlow; +}; + +// +// END Define Enums ... +// + +// +// Imports all Indicators Helper here ... +input group "XTEST Provider Indicators"; +// +#include "x-saherelm.xtm.indicator.helper.lib.mq5"; +#include "x-saherelm.xtd.oscillator.helper.lib.mq5"; +#include "x-saherelm.xrsi.oscillator.helper.lib.mq5"; +#include "x-saherelm.xobd.oscillator.helper.lib.mq5"; +#include "x-saherelm.xchlh.oscillator.helper.lib.mq5"; +#include "x-saherelm.xchma.oscillator.helper.lib.mq5"; + +// +int xTESTMaxLengthOfInputs = 0; +int xTESTCalculatedBars = 0; + +// +// Here we Define some Global Market Variables to Analyse MArket Conditions +// using them at each time ... +X_TEST_MARKET_CONDITIONS conditions = {}; + +// +// Init Indicators ... +bool XTESTInitIndicators() +{ + // + bool result = false; + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xTESTMaxLengthOfInputs = MathMax( + xTMMaPeriod, + xTESTNumberOfItemsPerTick); + + // + // XTD ... + xTESTMaxLengthOfInputs = MathMax( + xTDLength, + xTESTMaxLengthOfInputs); + + // + // XRSI ... + xTESTMaxLengthOfInputs = MathMax( + xRSILength, + xTESTMaxLengthOfInputs); + + // + // XOBD ... + xTESTMaxLengthOfInputs = MathMax( + xOBDLength, + xTESTMaxLengthOfInputs); + + // + // XCHLH ... + xTESTMaxLengthOfInputs = MathMax( + xCHLHLcLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHLHMcLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHLHScLength, + xTESTMaxLengthOfInputs); + + // + // XCHMA ... + xTESTMaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xTESTMaxLengthOfInputs); + xTESTMaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xTESTMaxLengthOfInputs); + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTM Init ... + result = XTMInitHandlers(); + if (!result) + { + return result; + } + + // + // XTD Init ... + result = XTDInitHandlers(); + if (!result) + { + return result; + } + + // + // XRSI Init ... + result = XRSIInitHandlers(); + if (!result) + { + return result; + } + + // + // XOBD Init ... + result = XOBDInitHandlers(); + if (!result) + { + return result; + } + + // + // XCLH Init ... + result = XCHLHInitHandlers(); + if (!result) + { + return result; + } + + // + // XCHMA Init ... + result = XCHMAInitHandlers(); + if (!result) + { + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XTESTReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XTDReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XTESTHandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xTESTCalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xTESTNumberOfItemsPerTick); + XTDReadBuffers(xTESTNumberOfItemsPerTick); + XRSIReadBuffers(xTESTNumberOfItemsPerTick); + XOBDReadBuffers(xTESTNumberOfItemsPerTick); + XCHMAReadBuffers(xTESTNumberOfItemsPerTick); + XCHLHReadBuffers(xTESTNumberOfItemsPerTick); + + // + XTESTReadConditions(); +} + +// +// +// START Combination Functions ... +// +// + +// +// Can Open Long Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Long Signals ... +bool XTESTCanOpenLongTrade( + double &providedSignals // Recieve Which Number of Providers has Conditions here, used for Volume Increasing +) +{ + // + bool result = false; + + // + bool hasSignal = XTESTHasLongSignal(providedSignals); + + // + result = + // + hasSignal + // + ; + + // + // TODO: Remove this On Production ... + if (result) + { + // + string message = XTESTGetConditionsString("\n"); + + // + XTESTClearConditions(); + + // + if (StringFind(message, "true") >= 0) + { + LogMessage(message); + } + } + + // + return result; +} + +// +// Can Close Long Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Long Signals ... +bool XTESTCanCloseLongTrade() +{ + // + bool result = false; + + // + // TODO: Check Market Conditions for Close Long Trades ... + // result = isXCHMASCFastCrossedUnderMax; + + // + return result; +} + +// +// Can Open Short Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Short Signals ... +bool XTESTCanOpenShortTrade( + double &providedSignals // Recieve Which Number of Providers has Conditions here, used for Volume Increasing +) +{ + // + bool result = false; + + // + bool hasSignal = XTESTHasShortSignal(providedSignals); + + // + result = + // + hasSignal + // + ; + + // + // TODO: Remove this On Production ... + if (result) + { + // + string message = XTESTGetConditionsString("\n"); + + // + XTESTClearConditions(); + + // + if (StringFind(message, "true") >= 0) + { + LogMessage(message); + } + } + + // + return result; +} + +// +// Can Close Short Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Short Signals ... +bool XTESTCanCloseShortTrade() +{ + // + bool result = false; + + // + // TODO: Check Market Conditions for Close Short Trades ... + // result = XTESTHasShortCloseConditions(xTESTNumberOfItemsPerTick); + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// TODO: Works i Had To Do: +// +// - [] Test All Strategies in All Available Brokers; +// - [] Find a Good Age for Closing Long Time Trades; +// - [] Find a Good Value for Closing Max DrawDown Equity Trades; +// - [] For All Strategies, Find Desired Long/Short Exit Points; +// - [] Find a Combination Point for Close All Trades; +// - [x] Try to Increase Trade Volume on Giving Multiple Signals at Same Time; +// - [] Prepare Signal and Event Alerts and Test Them for Production Environment; +// - [] Add SUpport for Daily and Hourly Alerts and also Make Report of Account State in Start Of Each Day; +// - [] Test All Methods for Find other Assets to Trade On them; +// - [] Do R&D about Multi Asset Trading in MT5; +// - [] Test Other Indicators/Oscillators or Exists Examples to Check and Found Market Conditions; +// + +// +// Read All Globally Required Conditions ... +void XTESTReadConditions() +{ + // + XTESTClearConditions(); + + // + // XTM ... + conditions.isXTMPeak = XTMIsPeak(); + conditions.isXTMVale = XTMIsVale(); + + // + // XTD ... + conditions.isXTDSignalPeak = XTDIsSignalPeak(); + conditions.isXTDSignalVale = XTDIsSignalVale(); + conditions.isXTDSignalOverBear = XTDIsSignalOverBear(1); + conditions.isXTDSignalUnderBear = XTDIsSignalUnderBear(1); + conditions.isXTDSignalCrossedOverBear = XTDIsSignalCrossedOverBear(1); + conditions.isXTDSignalCrossedUnderBear = XTDIsSignalCrossedUnderBear(1); + + // + // XRSI ... + conditions.isXRSIPeak = XRSIIsPeak(); + conditions.isXRSIVale = XRSIIsVale(); + conditions.isXRSICrossedOverLongExit = XRSIIsCrossedOverLongExit(1); + conditions.isXRSICrossedOverLongEntry = XRSIIsCrossedOverLongEntry(1); + conditions.isXRSICrossedUnderShortExit = XRSIIsCrossedUnderShortExit(1); + conditions.isXRSICrossedUnderShortEntry = XRSIIsCrossedUnderShortEntry(1); + + // + // XOBD ... + conditions.isXOBDPeak = XOBDIsPeak(); + conditions.isXOBDVale = XOBDIsVale(); + conditions.isXOBDSignalOverSwingHigh = XOBDIsSignalOverSwingHigh(1); + conditions.isXOBDSignalUnderSwingHigh = XOBDIsSignalUnderSwingHigh(1); + conditions.isXOBDSignalCrossedOverSwingHigh = XOBDIsSignalCrossedOverSwingHigh(1); + conditions.isXOBDSignalCrossedUnderSwingHigh = XOBDIsSignalCrossedUnderSwingHigh(1); + + // + // XCHLH ... + // + conditions.isXCHLHSignalBOverSignalT = XCHLHIsSignalBOverSignalT(1); + conditions.isXCHLHSignalBUnderSignalT = XCHLHIsSignalBUnderSignalT(1); + conditions.isXCHLHSignalBCrossedOverSignalT = XCHLHIsSignalBCrossedOverSignalT(1); + conditions.isXCHLHSignalBCrossedUnderSignalT = XCHLHIsSignalBCrossedUnderSignalT(1); + // + conditions.isXCHLHSignalBOverLCLL = XCHLHIsSignalBOverLCLL(1); + conditions.isXCHLHSignalBUnderLCLL = XCHLHIsSignalBUnderLCLL(1); + conditions.isXCHLHSignalBCrossedOverLCLL = XCHLHIsSignalBCrossedOverLCLL(1); + conditions.isXCHLHSignalBCrossedUnderLCLL = XCHLHIsSignalBCrossedUnderLCLL(1); + // + conditions.isXCHLHSCMCHHSame = XCHLHIsMCSCHasSameHH(1); + conditions.isXCHLHSCMCLLSame = XCHLHIsMCSCHasSameLL(1); + // + conditions.isXCHLHSCLCHHSame = XCHLHIsLCSCHasSameHH(1); + conditions.isXCHLHSCLCLLSame = XCHLHIsLCSCHasSameLL(1); + // + conditions.isXCHLHMCLCHHSame = XCHLHIsLCMCHasSameHH(1); + conditions.isXCHLHMCLCLLSame = XCHLHIsLCMCHasSameLL(1); + + // + // XCHMA ... + // + conditions.isXCHMASCPeak = XCHMAIsSCPeak(); + conditions.isXCHMASCVale = XCHMAIsSCVale(); + conditions.isXCHMASCFastOverSlow = XCHMAIsSCFastOverSlow(1); + conditions.isXCHMASCFastUnderSlow = XCHMAIsSCFastUnderSlow(1); + conditions.isXCHMASCFastCrossedOverSlow = XCHMAIsSCFastCrossedOverSlow(1); + conditions.isXCHMASCFastCrossedUnderSlow = XCHMAIsSCFastCrossedUnderSlow(1); + // + conditions.isXCHMAMCPeak = XCHMAIsMCPeak(); + conditions.isXCHMAMCVale = XCHMAIsMCVale(); + conditions.isXCHMAMCFastOverSlow = XCHMAIsMCFastOverSlow(1); + conditions.isXCHMAMCFastUnderSlow = XCHMAIsMCFastUnderSlow(1); + conditions.isXCHMAMCFastCrossedOverSlow = XCHMAIsMCFastCrossedOverSlow(1); + conditions.isXCHMAMCFastCrossedUnderSlow = XCHMAIsMCFastCrossedUnderSlow(1); + // + conditions.isXCHMALCPeak = XCHMAIsLCPeak(); + conditions.isXCHMALCVale = XCHMAIsLCVale(); + conditions.isXCHMALCFastOverSlow = XCHMAIsLCFastOverSlow(1); + conditions.isXCHMALCFastUnderSlow = XCHMAIsLCFastUnderSlow(1); + conditions.isXCHMALCFastCrossedOverSlow = XCHMAIsLCFastCrossedOverSlow(1); + conditions.isXCHMALCFastCrossedUnderSlow = XCHMAIsLCFastCrossedUnderSlow(1); +} + +// +// Cleanup Conditions ... +void XTESTClearConditions() +{ + // + X_TEST_MARKET_CONDITIONS mConditions = {}; + + // + conditions = mConditions; +} + +// +// Converts Market Conditions to Specific String Representation ... +string XTESTGetConditionsString( + string separator = ",", // Specify Separator + bool ignoreFalses = true // Ignore False Conditions +) +{ + // + string result = ""; + + // + // XTM ... + result += + "| XTM |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTMPeak)) + { + result += "isXTMPeak: " + (string)conditions.isXTMPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTMVale)) + { + result += "isXTMVale: " + (string)conditions.isXTMVale + separator; + } + + // + // Separator ... + result += separator; + + // + // XTD ... + result += + "| XTD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTDSignalPeak)) + { + result += "isXTDSignalPeak: " + (string)conditions.isXTDSignalPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTDSignalVale)) + { + result += "isXTDSignalVale: " + (string)conditions.isXTDSignalVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTDSignalOverBear)) + { + result += "isXTDSignalOverBear: " + (string)conditions.isXTDSignalOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTDSignalUnderBear)) + { + result += "isXTDSignalUnderBear: " + (string)conditions.isXTDSignalUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTDSignalCrossedOverBear)) + { + result += "isXTDSignalCrossedOverBear: " + (string)conditions.isXTDSignalCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXTDSignalCrossedUnderBear)) + { + result += "isXTDSignalCrossedUnderBear: " + (string)conditions.isXTDSignalCrossedUnderBear + separator; + } + + // + // Separator ... + result += separator; + + // + // XRSI ... + result += + "| XRSI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXRSIPeak)) + { + result += "isXRSIPeak: " + (string)conditions.isXRSIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXRSIVale)) + { + result += "isXRSIVale: " + (string)conditions.isXRSIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXRSICrossedOverLongExit)) + { + result += "isXRSICrossedOverLongExit: " + (string)conditions.isXRSICrossedOverLongExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXRSICrossedOverLongEntry)) + { + result += "isXRSICrossedOverLongEntry: " + (string)conditions.isXRSICrossedOverLongEntry + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXRSICrossedUnderShortExit)) + { + result += "isXRSICrossedUnderShortExit: " + (string)conditions.isXRSICrossedUnderShortExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXRSICrossedUnderShortEntry)) + { + result += "isXRSICrossedUnderShortEntry: " + (string)conditions.isXRSICrossedUnderShortEntry + separator; + } + + // + // Separator ... + result += separator; + + // + // XOBD ... + result += + "| XOBD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXOBDPeak)) + { + result += "isXOBDPeak: " + (string)conditions.isXOBDPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXOBDVale)) + { + result += "isXOBDVale: " + (string)conditions.isXOBDVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXOBDSignalOverSwingHigh)) + { + result += "isXOBDSignalOverSwingHigh: " + (string)conditions.isXOBDSignalOverSwingHigh + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXOBDSignalUnderSwingHigh)) + { + result += "isXOBDSignalUnderSwingHigh: " + (string)conditions.isXOBDSignalUnderSwingHigh + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXOBDSignalCrossedOverSwingHigh)) + { + result += "isXOBDSignalCrossedOverSwingHigh: " + (string)conditions.isXOBDSignalCrossedOverSwingHigh + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXOBDSignalCrossedUnderSwingHigh)) + { + result += "isXOBDSignalCrossedUnderSwingHigh: " + (string)conditions.isXOBDSignalCrossedUnderSwingHigh + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHLH ... + result += + "| XCHLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBOverSignalT)) + { + result += "isXCHLHSignalBOverSignalT: " + (string)conditions.isXCHLHSignalBOverSignalT + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBUnderSignalT)) + { + result += "isXCHLHSignalBUnderSignalT: " + (string)conditions.isXCHLHSignalBUnderSignalT + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBCrossedOverSignalT)) + { + result += "isXCHLHSignalBCrossedOverSignalT: " + (string)conditions.isXCHLHSignalBCrossedOverSignalT + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBCrossedUnderSignalT)) + { + result += "isXCHLHSignalBCrossedUnderSignalT: " + (string)conditions.isXCHLHSignalBCrossedUnderSignalT + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBOverLCLL)) + { + result += "isXCHLHSignalBOverLCLL: " + (string)conditions.isXCHLHSignalBOverLCLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBUnderLCLL)) + { + result += "isXCHLHSignalBUnderLCLL: " + (string)conditions.isXCHLHSignalBUnderLCLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBCrossedOverLCLL)) + { + result += "isXCHLHSignalBCrossedOverLCLL: " + (string)conditions.isXCHLHSignalBCrossedOverLCLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSignalBCrossedUnderLCLL)) + { + result += "isXCHLHSignalBCrossedUnderLCLL: " + (string)conditions.isXCHLHSignalBCrossedUnderLCLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSCMCHHSame)) + { + result += "isXCHLHSCMCHHSame: " + (string)conditions.isXCHLHSCMCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSCMCLLSame)) + { + result += "isXCHLHSCMCLLSame: " + (string)conditions.isXCHLHSCMCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSCLCHHSame)) + { + result += "isXCHLHSCLCHHSame: " + (string)conditions.isXCHLHSCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHSCLCLLSame)) + { + result += "isXCHLHSCLCLLSame: " + (string)conditions.isXCHLHSCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHMCLCHHSame)) + { + result += "isXCHLHMCLCHHSame: " + (string)conditions.isXCHLHMCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHLHMCLCLLSame)) + { + result += "isXCHLHMCLCLLSame: " + (string)conditions.isXCHLHMCLCLLSame + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHMA ... + result += + "| XCHMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMASCPeak)) + { + result += "isXCHMASCPeak: " + (string)conditions.isXCHMASCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMASCVale)) + { + result += "isXCHMASCVale: " + (string)conditions.isXCHMASCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMASCFastOverSlow)) + { + result += "isXCHMASCFastOverSlow: " + (string)conditions.isXCHMASCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMASCFastUnderSlow)) + { + result += "isXCHMASCFastUnderSlow: " + (string)conditions.isXCHMASCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMASCFastCrossedOverSlow)) + { + result += "isXCHMASCFastCrossedOverSlow: " + (string)conditions.isXCHMASCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMASCFastCrossedUnderSlow)) + { + result += "isXCHMASCFastCrossedUnderSlow: " + (string)conditions.isXCHMASCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMAMCPeak)) + { + result += "isXCHMAMCPeak: " + (string)conditions.isXCHMAMCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMAMCVale)) + { + result += "isXCHMAMCVale: " + (string)conditions.isXCHMAMCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMAMCFastOverSlow)) + { + result += "isXCHMAMCFastOverSlow: " + (string)conditions.isXCHMAMCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMAMCFastUnderSlow)) + { + result += "isXCHMAMCFastUnderSlow: " + (string)conditions.isXCHMAMCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMAMCFastCrossedOverSlow)) + { + result += "isXCHMAMCFastCrossedOverSlow: " + (string)conditions.isXCHMAMCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMAMCFastCrossedUnderSlow)) + { + result += "isXCHMAMCFastCrossedUnderSlow: " + (string)conditions.isXCHMAMCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMALCPeak)) + { + result += "isXCHMALCPeak: " + (string)conditions.isXCHMALCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMALCVale)) + { + result += "isXCHMALCVale: " + (string)conditions.isXCHMALCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMALCFastOverSlow)) + { + result += "isXCHMALCFastOverSlow: " + (string)conditions.isXCHMALCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMALCFastUnderSlow)) + { + result += "isXCHMALCFastUnderSlow: " + (string)conditions.isXCHMALCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMALCFastCrossedOverSlow)) + { + result += "isXCHMALCFastCrossedOverSlow: " + (string)conditions.isXCHMALCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && conditions.isXCHMALCFastCrossedUnderSlow)) + { + result += "isXCHMALCFastCrossedUnderSlow: " + (string)conditions.isXCHMALCFastCrossedUnderSlow + separator; + } + + // + // Separator ... + result += separator; + + // + return result; +} + +// +// Check Market Conditions by Combination of Power of All tools for LONGs ... +bool XTESTHasLongSignal( + double &providedSignals // Recieve Which Number of Providers has Conditions here, used for Volume Increasing +) +{ + // + bool result = false; + ENUM_X_SIGNAL_METHODS methods[]; + + // + // START Custom Mechanism ... + // + + // + // Required Data ... + double entry = GetEntry(X_SIGNAL_LONG); + double nearHH = GetHighestHigh(3, 1); + double nearLL = GetLowestLow(3, 1); + XOHCL candle1 = GetCandle(1); + + // + bool isSharpChanged = IsSharpChanged( + 5, + 1, + xTMMaBuffer); + + // + bool isCandleSharpChanged = IsSharpChanged( + 5, + 1, + PRICE_CLOSE); + + // + // XRSI ... + bool isXRSIOverLongExit = + xRSIBuffer[1] > xRSILongExitValue; + + // + // XTD ... + // bool isXTDSignalIncreasing = + // xTDSignalBuffer[1] > xTDSignalBuffer[2] && + // xTDSignalBuffer[1] > xTDSignalBuffer[3]; + + // + // XCHLH ... + bool isDecreasingMCHH = IsDecreasing( + 12, + 1, + xCHLHMcHHBuffer); + + // + // XCHMA ... + // + double xCHMAMin1 = XCHMAGetMin(1); + double xCHMAMin2 = XCHMAGetMin(2); + + // + double xCHMAMax1 = XCHMAGetMax(1); + double xCHMAMax2 = XCHMAGetMax(2); + + // + // Calculate Non SC Max ... + double xCHMANonSCMax1 = MathMax(xCHMAMcFastBuffer[1], xCHMAMcSlowBuffer[1]); + xCHMANonSCMax1 = MathMax(xCHMANonSCMax1, xCHMALcFastBuffer[1]); + xCHMANonSCMax1 = MathMax(xCHMANonSCMax1, xCHMALcSlowBuffer[1]); + + // + // Calculate Non SC Min ... + double xCHMANonSCMin1 = MathMin(xCHMAMcFastBuffer[1], xCHMAMcSlowBuffer[1]); + xCHMANonSCMin1 = MathMin(xCHMANonSCMin1, xCHMALcFastBuffer[1]); + xCHMANonSCMin1 = MathMin(xCHMANonSCMin1, xCHMALcSlowBuffer[1]); + + // + double xCHMASCMin1 = MathMin(xCHMAScFastBuffer[1], xCHMAScSlowBuffer[1]); + double xCHMASCMin2 = MathMin(xCHMAScFastBuffer[2], xCHMAScSlowBuffer[2]); + + // + double xCHMASCMax1 = MathMax(xCHMAScFastBuffer[1], xCHMAScSlowBuffer[1]); + double xCHMASCMax2 = MathMax(xCHMAScFastBuffer[2], xCHMAScSlowBuffer[2]); + + // + double xCHMAMCTrend1 = MathAbs(xCHMAMcFastBuffer[1] - xCHMAMcSlowBuffer[1]); + double xCHMAMCTrend5 = MathAbs(xCHMAMcFastBuffer[5] - xCHMAMcSlowBuffer[5]); + double xCHMAMCTrend10 = MathAbs(xCHMAMcFastBuffer[10] - xCHMAMcSlowBuffer[10]); + + // + double xCHMALCTrend1 = MathAbs(xCHMALcFastBuffer[1] - xCHMALcSlowBuffer[1]); + double xCHMALCTrend5 = MathAbs(xCHMALcFastBuffer[5] - xCHMALcSlowBuffer[5]); + double xCHMALCTrend10 = MathAbs(xCHMALcFastBuffer[10] - xCHMALcSlowBuffer[10]); + + // + bool isXCHMASCCrossedOverMin = + // + xCHMASCMin2 <= xCHMAMin2 && + xCHMASCMin1 > xCHMAMin1 + // + ; + + // + bool isXCHMASCFastCrossedOverMax = + xCHMASCMax2 < xCHMAMax2 && + xCHMASCMax1 >= xCHMAMax1; + + // + bool isXCHMASCFastCrossedUnderMin = + xCHMASCMin2 > xCHMAMin2 && + xCHMASCMin1 <= xCHMAMin1; + + // + bool isXCHMASCFastCrossedUnderMax = + xCHMASCMax2 >= xCHMAMax2 && + xCHMASCMax1 < xCHMAMax1; + + // + // Condition 1 ... + // this Method waits for XCHMA Short Cycle's Fast to Going down + // of all Cycles Minimum Value, then Check when its Crossed Over + // min value and then start to Open Long Trades based On Conditions, + // and Recieved Verifications from other Indicator/Oscillator(s) ... + bool customMethodCond1 = + // + isXCHMASCCrossedOverMin + // + && + // + entry < nearHH + // + && + // + candle1.high != nearHH + // + && + // + !isCandleSharpChanged + // + && + // + !( + // + ( + // + conditions.isXCHMASCFastUnderSlow || + conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + && + // + ( + // + conditions.isXCHMAMCFastUnderSlow || + conditions.isXCHMAMCFastCrossedUnderSlow + // + ) + // + && + // + ( + // + conditions.isXCHMALCFastUnderSlow || + conditions.isXCHMALCFastCrossedUnderSlow + // + ) + // + ) + // + && + // + ( + // + conditions.isXCHMAMCFastOverSlow + // + ? + // + xCHMAMCTrend1 >= xCHMAMCTrend5 && + xCHMAMCTrend5 >= xCHMAMCTrend10 + // + : + // + xCHMAMCTrend1 < xCHMAMCTrend5 && + xCHMAMCTrend5 < xCHMAMCTrend10 + // + ) + // + && + // + !( + // + ( + // + conditions.isXCHMAMCFastUnderSlow || + conditions.isXCHMAMCFastCrossedUnderSlow + // + ) + // + && + // + ( + // + conditions.isXCHMALCFastUnderSlow || + conditions.isXCHMALCFastCrossedUnderSlow + // + ) + // + ) + // + && + // + ( + // + conditions.isXCHMAMCFastUnderSlow && + xTDSignalBuffer[1] < xTDSignalBuffer[2] + // + ? + // + xCHMAMcFastBuffer[1] > xCHMANonSCMin1 + // + && + // + !( + // + xCHLHSignalTBuffer[1] > xCHLHScHHBuffer[1] && + xCHLHSignalBBuffer[1] < xCHLHLcLLBuffer[1] + // + ) + // + : + // + true + // + ) + // + && + // + !( + // + conditions.isXCHMASCVale && + conditions.isXCHMASCFastUnderSlow + // + && + // + ( + // + ( + // + conditions.isXCHLHMCLCHHSame + // + && + // + ( + // + conditions.isXCHLHMCLCLLSame || + conditions.isXCHLHSCMCLLSame + // + ) + // + ) + // + ) + // + ) + // + && + // + !( + // + ( + // + xRSIBuffer[1] > xRSILongExitValue || + conditions.isXRSICrossedOverLongExit + // + ) + // + && + // + conditions.isXCHLHSCMCHHSame && + conditions.isXCHLHSCMCLLSame && + // + conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + ( + // + conditions.isXCHLHSignalBOverLCLL || + conditions.isXCHLHSignalBCrossedOverLCLL + // + ) + // + && + conditions.isXCHLHMCLCLLSame && + // + conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + conditions.isXTDSignalOverBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBUnderSignalT && + conditions.isXCHLHSignalBOverLCLL && + conditions.isXCHLHMCLCLLSame && + // + conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + conditions.isXTDSignalOverBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBUnderSignalT && + conditions.isXCHLHSignalBUnderLCLL && + conditions.isXCHLHMCLCLLSame && + // + conditions.isXCHMASCFastOverSlow && + conditions.isXCHMAMCFastUnderSlow && + conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + conditions.isXTDSignalOverBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBOverSignalT && + conditions.isXCHLHSignalBOverLCLL && + conditions.isXCHLHMCLCHHSame && + // + conditions.isXCHMASCFastOverSlow && + conditions.isXCHMAMCFastOverSlow && + conditions.isXCHMALCFastUnderSlow + // + ) + // + ; + + // + // Filling Methods ... + if (customMethodCond1) + { + // + ArrayResize( + methods, + ArraySize(methods) + 1); + + // + methods[ArraySize(methods) - 1] = X_SIGNAL_METHOD_1; + } + + // + // Condition 2 ... + // this Method waits for XCHMA Medium Cycles Fast Line Crossed Over Slow, + // then start to Open Long Trades based On Conditions, and Recieved Verifications from + // other Indicator/Oscillator(s) ... + bool customMethodCond2 = + // + // MCFast Based ... + ( + // + conditions.isXCHMAMCFastCrossedOverSlow && + // + ( + // + conditions.isXCHMASCFastOverSlow + // + && + // + conditions.isXCHMALCFastOverSlow + // + ) + // + ) + // + && + // + !( + // + ( + // + conditions.isXOBDSignalUnderSwingHigh || + conditions.isXOBDSignalCrossedUnderSwingHigh + // + ) + // + && + // + conditions.isXCHLHSignalBOverSignalT && + conditions.isXCHLHSignalBOverLCLL && + conditions.isXCHLHSCMCHHSame + // + ) + // + && + // + !( + // + conditions.isXTDSignalCrossedOverBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBUnderSignalT && + conditions.isXCHLHSignalBOverLCLL && + conditions.isXCHLHMCLCLLSame + // + ) + // + && + // + !( + // + xCHLHScHHBuffer[1] > xCHLHSignalTBuffer[1] && + xCHLHScLLBuffer[1] > xCHLHSignalTBuffer[1] && + xCHLHSignalBBuffer[1] < xCHLHSignalTBuffer[1] && + xCHLHSignalBBuffer[1] < xCHLHMcLLBuffer[1] + // + ) + // + && + // + !( + // + conditions.isXTDSignalOverBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBCrossedOverSignalT && + conditions.isXCHLHSignalBOverLCLL && + conditions.isXCHLHSCMCHHSame && + conditions.isXCHLHMCLCLLSame + // + ) + // + && + // + !( + // + conditions.isXTDSignalUnderBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBUnderSignalT && + conditions.isXCHLHSignalBOverLCLL && + conditions.isXCHLHMCLCHHSame && + conditions.isXCHLHMCLCLLSame + // + ) + // + && + // + !( + // + conditions.isXTDSignalOverBear && + // + conditions.isXRSICrossedOverLongExit && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBOverSignalT && + conditions.isXCHLHSignalBOverLCLL + // + ) + // + && + // + !( + // + conditions.isXTDSignalCrossedUnderBear && + // + conditions.isXOBDSignalUnderSwingHigh && + // + conditions.isXCHLHSignalBOverSignalT && + conditions.isXCHLHSignalBOverLCLL + // + ) + // + // + && + // + entry < nearHH + // + && + // + nearHH != candle1.high + // + && + // + !isXRSIOverLongExit + // + ; + + // + // Filling Methods ... + if (customMethodCond2) + { + // + ArrayResize( + methods, + ArraySize(methods) + 1); + + // + methods[ArraySize(methods) - 1] = X_SIGNAL_METHOD_2; + } + + // + // Condition 3 ... + // this Method waits for XCHMA Short Cycle's Fast to Crossed Over all Cycles max value + // and then start to Open Long Trades based On Conditions, + // and Recieved Verifications from other Indicator/Oscillator(s) ... + bool customMethodCond3 = + // + isXCHMASCFastCrossedOverMax + // + && + // + conditions.isXCHMALCFastOverSlow + // + && + // + !( + // + xCHLHScLLBuffer[1] > xCHLHMcLLBuffer[1] && + xCHLHMcLLBuffer[1] > xCHLHSignalBBuffer[1] && + xCHLHSignalBBuffer[1] > xCHLHSignalTBuffer[1] && + xCHLHSignalTBuffer[1] > xCHLHLcLLBuffer[1] + // + ) + // + && + // + !( + conditions.isXCHLHSignalBUnderSignalT && + conditions.isXCHLHSignalBOverLCLL && + ( + // + conditions.isXCHLHSCMCHHSame || + conditions.isXCHLHMCLCLLSame + // + ) + // + ) + // + && + // + !( + // + conditions.isXCHLHSignalBOverSignalT && + conditions.isXCHLHSignalBOverLCLL && + // + ( + // + conditions.isXCHLHSCMCHHSame || + conditions.isXCHLHMCLCLLSame || + conditions.isXCHLHMCLCHHSame || + conditions.isXCHLHSCMCLLSame + // + ) + // + ) + // + && + // + !isSharpChanged + // + && + // + !isCandleSharpChanged + // + && + // + entry < nearHH + // + && + // + candle1.close > xTMMaBuffer[1]; + // + ; + + // + // Filling Methods ... + if (customMethodCond3) + { + // + ArrayResize( + methods, + ArraySize(methods) + 1); + + // + methods[ArraySize(methods) - 1] = X_SIGNAL_METHOD_3; + } + + // + // Combine Custom Methods together ... + bool isCustomMethodHasSignal = + // + customMethodCond1 + // + || + // + customMethodCond2 + // + || + // + customMethodCond3 + // + ; + + // + // END Custom Mechanism ... + // + + // + result = + // + // isXTMHasSignal + // isXTDHasSignal + // isXCHMAHasSignal + // + // isXTMMethodHasSignal + // + // || + // + // isXTDMethodHasSignal + // + // || + // // + // isXOBDMethodHasSignal + // // + // || + // // + // isXCHMAMethodHasSignal + // // + // || + // // + // isXCHLHMethodHasSignal + // // + // || + // // + // isXRSIMethodHasSignal + // + // || + isCustomMethodHasSignal + // + ; + + // + if (result) + { + // + // Set Number of Occured Conditions for Increasing Volume ... + providedSignals = ArraySize(methods); + } + + // + return result; +} + +// +// Check Market Conditions by Combination of Power of All tools for SHORTs ... +bool XTESTHasShortSignal( + double &providedSignals // Recieve Which Number of Providers has Conditions here, used for Volume Increasing +) +{ + // + bool result = false; + ENUM_X_SIGNAL_METHODS methods[]; + + // + // START Custom Mechanism ... + // + + // + // Required Data ... + double entry = GetEntry(X_SIGNAL_SHORT); + double nearHH = GetHighestHigh(3, 1); + double nearLL = GetLowestLow(3, 1); + XOHCL candle1 = GetCandle(1); + + // + bool isSharpChanged = IsSharpChanged( + 5, + 1, + xTMMaBuffer); + + // + bool isCandleSharpChanged = IsSharpChanged( + 5, + 1, + PRICE_CLOSE); + + // + // XRSI ... + bool isXRSIOverLongExit = + xRSIBuffer[1] > xRSILongExitValue; + + // + // XCHLH ... + bool isIncreasingMCHH = IsIncreasing( + 12, + 1, + xCHLHMcHHBuffer); + + // + double xCHLHLCRange1 = xCHLHLcHHBuffer[1] - xCHLHLcLLBuffer[1]; + double xCHLHMCRange1 = xCHLHMcHHBuffer[1] - xCHLHMcLLBuffer[1]; + double xCHLHSCRange1 = xCHLHScHHBuffer[1] - xCHLHScLLBuffer[1]; + + // + double xCHLHNonLCMax1 = MathMax(xCHLHScHHBuffer[1], xCHLHMcHHBuffer[1]); + double xCHLHNonLCMin1 = MathMin(xCHLHScLLBuffer[1], xCHLHMcLLBuffer[1]); + double xCHLHNonLCRange1 = xCHLHNonLCMax1 - xCHLHNonLCMin1; + + // // + // bool isIncreasingMCLL = IsIncreasing( + // 12, + // 1, + // xCHLHMcLLBuffer); + + // // + // bool isDecreasingSCHH = IsDecreasing( + // 12, + // 1, + // xCHLHScHHBuffer); + + // // + // bool isDecreasingSCLL = IsDecreasing( + // 12, + // 1, + // xCHLHScLLBuffer); + + // + // XCHMA ... + // + double xCHMAMin1 = XCHMAGetMin(1); + double xCHMAMin2 = XCHMAGetMin(2); + + // + double xCHMAMax1 = XCHMAGetMax(1); + double xCHMAMax2 = XCHMAGetMax(2); + + // + // Calculate Non SC Max ... + double xCHMANonSCMax1 = MathMax(xCHMAMcFastBuffer[1], xCHMAMcSlowBuffer[1]); + xCHMANonSCMax1 = MathMax(xCHMANonSCMax1, xCHMALcFastBuffer[1]); + xCHMANonSCMax1 = MathMax(xCHMANonSCMax1, xCHMALcSlowBuffer[1]); + + // + // Calculate Non SC Min ... + double xCHMANonSCMin1 = MathMin(xCHMAMcFastBuffer[1], xCHMAMcSlowBuffer[1]); + xCHMANonSCMin1 = MathMin(xCHMANonSCMin1, xCHMALcFastBuffer[1]); + xCHMANonSCMin1 = MathMin(xCHMANonSCMin1, xCHMALcSlowBuffer[1]); + + // + // Calculate Non LC Max ... + double xCHMANonLCMax1 = MathMax(xCHMAScFastBuffer[1], xCHMAScSlowBuffer[1]); + xCHMANonLCMax1 = MathMax(xCHMANonLCMax1, xCHMAMcFastBuffer[1]); + xCHMANonLCMax1 = MathMax(xCHMANonLCMax1, xCHMAMcSlowBuffer[1]); + + // + // Calculate Non LC Min ... + double xCHMANonLCMin1 = MathMin(xCHMAScFastBuffer[1], xCHMAScSlowBuffer[1]); + xCHMANonLCMin1 = MathMin(xCHMANonLCMin1, xCHMAMcFastBuffer[1]); + xCHMANonLCMin1 = MathMin(xCHMANonLCMin1, xCHMAMcSlowBuffer[1]); + + // + // Check LC On Top Of Others ... + double xCHMALCMin1 = MathMin(xCHMALcFastBuffer[1], xCHMALcSlowBuffer[1]); + + // + double xCHMASCMin1 = MathMin(xCHMAScFastBuffer[1], xCHMAScSlowBuffer[1]); + double xCHMASCMin2 = MathMin(xCHMAScFastBuffer[2], xCHMAScSlowBuffer[2]); + + // + double xCHMASCMax1 = MathMax(xCHMAScFastBuffer[1], xCHMAScSlowBuffer[1]); + double xCHMASCMax2 = MathMax(xCHMAScFastBuffer[2], xCHMAScSlowBuffer[2]); + + // + double xCHMAMCTrend1 = MathAbs(xCHMAMcFastBuffer[1] - xCHMAMcSlowBuffer[1]); + double xCHMAMCTrend5 = MathAbs(xCHMAMcFastBuffer[5] - xCHMAMcSlowBuffer[5]); + double xCHMAMCTrend10 = MathAbs(xCHMAMcFastBuffer[10] - xCHMAMcSlowBuffer[10]); + + // + double xCHMALCTrend1 = MathAbs(xCHMALcFastBuffer[1] - xCHMALcSlowBuffer[1]); + double xCHMALCTrend5 = MathAbs(xCHMALcFastBuffer[5] - xCHMALcSlowBuffer[5]); + double xCHMALCTrend10 = MathAbs(xCHMALcFastBuffer[10] - xCHMALcSlowBuffer[10]); + + // + bool isXCHMASCCrossedOverMin = + // + xCHMASCMin2 <= xCHMAMin2 && + xCHMASCMin1 > xCHMAMin1 + // + ; + + // + bool isXCHMASCFastCrossedOverMax = + xCHMASCMax2 < xCHMAMax2 && + xCHMASCMax1 >= xCHMAMax1; + + // + bool isXCHMASCFastCrossedUnderMin = + xCHMASCMin2 > xCHMAMin2 && + xCHMASCMin1 <= xCHMAMin1; + + // + bool isXCHMASCFastCrossedUnderMax = + xCHMASCMax2 >= xCHMAMax2 && + xCHMASCMax1 < xCHMAMax1; + + // + // Condition 1 ... + // this Method waits for XCHMA Short Cycle's Fast to Going up + // of all Cycles Maximum Value, then Check when its Crossed Under + // max value and then start to Open Short Trades based On Conditions, + // and Recieved Verifications from other Indicator/Oscillator(s) ... + bool customMethodCond1 = + // + isXCHMASCFastCrossedUnderMax + // + && + // + entry > nearLL + // + && + // + !isSharpChanged + // + && + // + !isCandleSharpChanged + // + && + // + candle1.low != nearLL + // + && + // + !conditions.isXCHLHMCLCLLSame + // + && + // + ( + // + xCHLHNonLCRange1 > (xCHLHLCRange1 / 2) + // + ? + // + true + // + : + // + xCHLHMcHHBuffer[1] > (xCHLHLcHHBuffer[1] - (xCHLHLCRange1 / 2)) && + MathAbs(xCHLHMcLLBuffer[1] - xCHLHLcLLBuffer[1]) > (MathAbs(xCHLHMcHHBuffer[1] - xCHLHLcHHBuffer[1]) / 2) + // + ) + // + && + // + !( + // + xCHLHMcLLBuffer[1] > (xCHLHLcHHBuffer[1] - (xCHLHLCRange1 / 2)) && + xCHLHSignalTBuffer[1] < xCHLHSignalBBuffer[1] && + MathAbs(xCHLHScLLBuffer[1] - xCHLHMcLLBuffer[1]) > MathAbs(xCHLHScHHBuffer[1] - xCHLHMcHHBuffer[1]) + // + ) + // + && + // + !( + // + xTDSignalBuffer[1] > xTDSignalBuffer[2] && + xTDSignalBuffer[2] > xTDSignalBuffer[3] && + xTDSignalBuffer[1] > xTDSignalBuffer[3] + // + ) + // + && + // + !( + // + ( + // + conditions.isXCHMASCFastOverSlow || + conditions.isXCHMASCFastCrossedOverSlow + // + ) + // + && + // + ( + // + conditions.isXCHMAMCFastOverSlow || + conditions.isXCHMAMCFastCrossedOverSlow + // + ) + // + && + // + ( + // + conditions.isXCHMALCFastOverSlow || + conditions.isXCHMALCFastCrossedOverSlow + // + ) + // + ) + // + && + // + !( + // + ( + // + conditions.isXCHMAMCFastOverSlow || + conditions.isXCHMAMCFastCrossedOverSlow + // + ) + // + && + // + ( + // + conditions.isXCHMALCFastOverSlow || + conditions.isXCHMALCFastCrossedOverSlow + // + ) + // + ) + // + && + // + ( + // + conditions.isXCHMAMCFastOverSlow + // + ? + // + xCHMAMCTrend1 < xCHMAMCTrend5 + // + && + // + ( + // + xCHMAMCTrend1 < xCHMAMCTrend10 || + xCHMAMCTrend5 < xCHMAMCTrend10 + // + ) + // + : + // + true + // + ) + // + && + // + ( + // + conditions.isXCHMALCFastOverSlow + // + ? + // + xCHMALCTrend1 <= xCHMALCTrend5 + // + && + // + ( + // + xCHMALCTrend1 <= xCHMALCTrend10 || + xCHMALCTrend5 <= xCHMALCTrend10 + // + ) + // + : + // + true + // + ) + // + && + // + !( + // + conditions.isXCHMASCVale || + conditions.isXCHMAMCVale || + conditions.isXCHMASCPeak || + conditions.isXCHMAMCPeak + // + ) + // + && + // + ( + conditions.isXCHMASCFastOverSlow || + conditions.isXCHMAMCFastOverSlow + // + ? + // + xOBDSwingHighBuffer[1] < xOBDSwingLowBuffer[1] + // + : + // + true) + // + ; + + // + // Filling Methods ... + if (customMethodCond1) + { + // + ArrayResize( + methods, + ArraySize(methods) + 1); + + // + methods[ArraySize(methods) - 1] = X_SIGNAL_METHOD_1; + } + + // + // Condition 2 ... + // this Method waits for XCHMA Medium Cycle Fast Line Crossed Under Slow, + // then start to Open Short Trades based On Conditions, and Recieved Verifications from + // other Indicator/Oscillator(s) ... + bool customMethodCond2 = + // + conditions.isXCHMAMCFastCrossedUnderSlow + // + && + // + entry > nearLL + // + && + // + candle1.low != nearLL + // + && + // + xCHMALCMin1 < xCHMANonLCMax1 + // + && + // + conditions.isXTDSignalUnderBear + // + && + // + ( + // + conditions.isXCHLHMCLCHHSame + // + ? + // + xOBDSwingHighBuffer[1] < xOBDSwingLowBuffer[1] + // + : + // + true + // + ) + // + && + // + !( + conditions.isXCHLHSCMCLLSame || + conditions.isXCHLHSCLCLLSame + // + ) + // + && + // + !( + // + xCHLHMcHHBuffer[1] < xCHLHLcHHBuffer[1] && + // + xCHLHScHHBuffer[1] < xCHLHMcHHBuffer[1] && + xCHLHScLLBuffer[1] > xCHLHMcLLBuffer[1] && + // + xCHLHMcLLBuffer[1] > xCHLHSignalBBuffer[1] && + xCHLHMcLLBuffer[1] > xCHLHSignalTBuffer[1] && + // + xCHLHSignalBBuffer[1] > xCHLHLcLLBuffer[1] && + xCHLHSignalTBuffer[1] > xCHLHLcLLBuffer[1] && + // + MathAbs(xCHLHScLLBuffer[1] - xCHLHMcLLBuffer[1]) < MathAbs(xCHLHScHHBuffer[1] - xCHLHMcHHBuffer[1]) + // + ) + // + ; + + // + // Filling Methods ... + if (customMethodCond2) + { + // + ArrayResize( + methods, + ArraySize(methods) + 1); + + // + methods[ArraySize(methods) - 1] = X_SIGNAL_METHOD_2; + } + + // + // Condition 3 ... + // this Method waits for XCHMA Short Cycle's Fast to Crossed Under all Cycles min value + // and then start to Open Short Trades based On Conditions, + // and Recieved Verifications from other Indicator/Oscillator(s) ... + bool customMethodCond3 = + // + isXCHMASCFastCrossedUnderMin + // + && + // + xCHMAScSlowBuffer[1] < xCHMANonSCMin1 + // + && + // + ( + // + conditions.isXCHMASCFastCrossedUnderSlow || + conditions.isXCHMASCFastUnderSlow + // + ) + // + && + // + ( + // + ( + // + conditions.isXCHMAMCFastCrossedUnderSlow || + conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + ( + // + conditions.isXCHMALCFastCrossedUnderSlow || + conditions.isXCHMALCFastUnderSlow + // + ) + // + ) + // + && + // + ( + // + ( + // + conditions.isXTDSignalCrossedUnderBear || + conditions.isXTDSignalUnderBear + // + ) + // + && + // + xTDBullishBuffer[1] < xTDBearishBuffer[1] + // + ) + // + && + // + !( + // + xCHLHMCRange1 < (xCHLHLCRange1 / 2) + // + && + // + xCHLHMcHHBuffer[1] < (xCHLHLcHHBuffer[1] - (xCHLHLCRange1 / 2)) + // + ) + // + && + // + !( + // + conditions.isXCHMAMCFastUnderSlow + // + && + // + ( + // + xCHMAMcFastBuffer[1] > xCHMAMcFastBuffer[5] && + xCHMAMcFastBuffer[1] > xCHMAMcFastBuffer[10] + // + ) + // + && + // + ( + // + xCHMAMCTrend1 < xCHMAMCTrend5 && + xCHMAMCTrend1 < xCHMAMCTrend10 + // + ) + // + ) + // + ; + + // + // Filling Methods ... + if (customMethodCond3) + { + // + ArrayResize( + methods, + ArraySize(methods) + 1); + + // + methods[ArraySize(methods) - 1] = X_SIGNAL_METHOD_3; + } + + // + // Combine Custom Methods together ... + bool isCustomMethodHasSignal = + // + customMethodCond1 + // + || + // + customMethodCond2 + // + || + // + customMethodCond3 + // + ; + + // + // END Custom Mechanism ... + // + + // + // Fill Result ... + result = + // + isCustomMethodHasSignal + // + ; + + // + if (result) + { + // + // Set Number of Occured Conditions for Increasing Volume ... + providedSignals = ArraySize(methods); + } + + // + return result; +} + +// +// +// END Combination Signaling ... +// +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.inputs.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.inputs.lib.mq5 new file mode 100644 index 0000000..3aba747 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.inputs.lib.mq5 @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTEST Signal Provider Library Inputs +// ----------------------------------------------------------- +// +// 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 + +// +input group "XTEST Provider"; + +// +input group "XTEST Common"; +input bool xTESTEnableProvider = true; // Enable Provider +input bool xTESTEnableAlerts = false; // Enable Events Alert +input int xTESTNumberOfItemsPerTick = 110; // Number Of items Readed In Each Tick + +// +input group "XTEST Trader"; +input int xTESTMagicNumber = 16940567; // Trader MagicNumber +input int xTESTSlippage = 10; // Trader Slippage + +// +input group "XTEST Trade Management"; +input bool xTESTAllowLongTrades = true; // Allow Long Trades +input bool xTESTAllowShortTrades = true; // Allow Short Trades + +// +input group "XTEST Risk Management"; +// +// Trade Count ... +input int xTESTMaxAllowedTrades = 5; // Max Allowed Trades at Same Time +input int xTESTMaxAllowedSupportTrades = 3; // Max Allowed Support Trades for Single Position +// +// Trades Age ... +// 1 Day = 288 +// 14 Day = 4320 +input int xTESTMaxInDrawDownTradeAge = 0; // Max In DrawDown Trades Age +// +// Trade Volume ... +input double xTESTStaticVolume = 0.3; // Static Volume +input double xTESTVolumeMultiplier = 2; // Volume Multiplier +input double xTESTMaxSupportedVolumePerTradeInLots = 2.4; // Max Supported Volume Per Trade in Lot +// +// Trade Profits ... +input double xTESTMinRewardPerTradeInPips = 8; // Min Reward Per Trade In Pips +input double xTESTRiskFreeTradesInPips = 3; // Make Trades Risk Free in Pips +input int xTESTMinRewardPerSupportTradesInPips = 2; // Min Reward for Support Trade +input int xTESTSupportTradesPriceDistanceInPips = 5; // Distance Price to Open Support Trade In Pips +// +// 1000000 Pips = 100$ in EURUSD ... +input double xTESTMaxAllowedDrawDownPerTradesInPips = 0; // Max Allowed Drawdown Per Trade In Pips +input double xTESTRiskFreeRate = 0.5; // Volume Multiplier for Risk Free +// +// Account ... +input double xTESTFreeMarginFactorForOpenTrades = 0.8; // Minimum Free Marging for Open Trades +input double xTESTBalanceFactorForOpenTrades = 0.5; // Minimum Balance for Open Trades + +// +// Validate Inputs before Initialization ... +bool XTESTValidateInputs() +{ + // + bool result = false; + + // + // TODO: Fix this ... + result = true; + + // + return result; +} \ No newline at end of file diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.lib.mq5 new file mode 100644 index 0000000..e2ba2a0 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtest.provider.lib.mq5 @@ -0,0 +1,1073 @@ +//////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTEST Signal Provider Library +// -------------------------------------------------------- +// Name: XTESTSignalProvider +// Description: XTEST based 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 + +#define XTESTProviderName "XTEST" + +// +// START Inputs ... +// + +#include "x-saherelm.xtest.provider.inputs.lib.mq5"; + +// +// END Inputs ... +// + +// +// Include Common Library ... +#include "x-saherelm.common.lib.mq5" + +// +// Include Logger Library ... +#include "x-saherelm.log.lib.mq5" + +// +// Include Alert Library ... +#include "x-saherelm.alert.lib.mq5" + +// +// Include Draw Library ... +#include "x-saherelm.draw.lib.mq5" + +// +// Include Class Libraries ... +#include "x-saherelm.class.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +XCTrade *xTESTTrader; +XCAccountInfo xTESTAccountInfo; + +// +#include "x-saherelm.xtest.provider.indicators.lib.mq5" + +// +double xTESTDeposit = 0; +double xTESTBalance = 0; +double xTESTFreeMargin = 0; +double xTESTRiskFreeTrades = 0; +double xTESTMinRewardPerTrade = 0; +double xTESTBalanceForOpenTrades = 0; +double xTESTFreeMarginForOpenTrades = 0; +double xTESTMinRewardPerSupportTrades = 0; +double xTESTSupportTradesPriceDistance = 0; +double xTESTMaxAllowedDrawDownPerTrades = 0; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// Initial Library if required ... +bool XTESTInitSignalProviderLibrary() +{ + // + bool result = false; + + // + // Validate Inputs ... + result = XTESTValidateInputs(); + if (!result) + { + return result; + } + + // + // Init Indicators ... + result = XTESTInitIndicators(); + if (!result) + { + return result; + } + + // + // Calculate Account Deposit ... + xTESTDeposit = xTESTAccountInfo.GetInitialBalance(); + + // + // Calculate RiskFree Price Distance ... + if (xTESTRiskFreeTradesInPips > 0 && xTESTRiskFreeRate > 0) + { + xTESTRiskFreeTrades = PipsToPrice(xTESTRiskFreeTradesInPips); + } + + // + // Calculate xTESTMinRewardPerTrade ... + if (xTESTMinRewardPerTradeInPips > 0) + { + xTESTMinRewardPerTrade = PipsToPrice(xTESTMinRewardPerTradeInPips); + } + + // + // Calculate Min Balance for Trades ... + if (xTESTBalanceFactorForOpenTrades > 0) + { + xTESTBalanceForOpenTrades = xTESTBalanceFactorForOpenTrades * xTESTDeposit; + } + + // + // Claculate Min Free Marging for Trades ... + if (xTESTFreeMarginFactorForOpenTrades > 0) + { + xTESTFreeMarginForOpenTrades = xTESTFreeMarginFactorForOpenTrades * xTESTDeposit; + } + + // + // Calculate xTESTSupportTradesPriceDistance ... + if (xTESTMaxAllowedSupportTrades > 0 && xTESTSupportTradesPriceDistanceInPips > 0 && xTESTMinRewardPerSupportTradesInPips > 0) + { + xTESTMinRewardPerSupportTrades = PipsToPrice(xTESTMinRewardPerSupportTradesInPips); + xTESTSupportTradesPriceDistance = PipsToPrice(xTESTSupportTradesPriceDistanceInPips); + } + + // + // Calculate xTESTMaxAllowedDrawDownPerTrade ... + if (xTESTMaxAllowedDrawDownPerTradesInPips > 0) + { + // + xTESTMaxAllowedDrawDownPerTrades = PipsToPrice(xTESTMaxAllowedDrawDownPerTradesInPips); + + // + LogMessage("Max Allowed DrawDown per Trade: " + (string)xTESTMaxAllowedDrawDownPerTrades); + } + + // + // Make XCTrader instance ... + xTESTTrader = new XCTrade( + XTESTProviderName, + _Symbol, + xTESTSlippage, + xTESTMagicNumber, + xTESTMaxAllowedTrades, + xTESTMaxAllowedSupportTrades, + xTESTMinRewardPerTradeInPips, + xTESTSupportTradesPriceDistanceInPips, + xTESTFreeMarginForOpenTrades, + xTESTBalanceForOpenTrades); + + // + result = true; + + // + // Logging State ... + XTESTIssueInitializationSucceedAlert(); + + // + return result; +} + +// +// DeInitial Library if required ... +void XTESTDeinitSignalProviderLibrary( + const int reason) +{ + // + // Release Handlers ... + XTESTReleaseIndicators(); + + // + // Logging State ... + XTESTIssueDeinitializationSucceedAlert(); +} + +// +// this is a Globally Function which do all of +// checkings and positions handling ... +void XTESTSignalProviderHandleTick() +{ + // + // Update account Balance ... + xTESTBalance = xTESTAccountInfo.GetBalance(); + xTESTFreeMargin = xTESTAccountInfo.GetFreeMargin(); + + // + // Check Provider is Enable or Not ... + if (!xTESTEnableProvider) + { + return; + } + + // + // Reading Indicator Buffers ... + XTESTHandleReadingBuffers(); + if (xTESTCalculatedBars < xTESTMaxLengthOfInputs) + { + return; + } + + // + // Handle Open Trades ... + XTESTHandleOpenTrades(); + + // + // Handle Close Trades ... + XTESTHandleCloseTrades(); + + // + // Handle Support Trades ... + XTESTHandleSupportTrades(); +} + +// +// Handle Open Trades ... +void XTESTHandleOpenTrades() +{ + // + // Check Can Trade ... + bool canTrade = xTESTAllowLongTrades || xTESTAllowShortTrades; + if (!canTrade) + { + return; + } + + // + // Check Max Open Trades ... + int openPositions = xTESTTrader.Count(); + int openTradeKinds = xTESTTrader.CountByKind( + X_SIGNAL_UNKNOWN, + X_KIND_TRADE); + bool canOpenPositions = openTradeKinds < xTESTMaxAllowedTrades; + if (!canOpenPositions) + { + return; + } + + // + // Check Signals Exists ... + double longsForceVolume = 0; + double shortsForceVolume = 0; + bool hasLongSignal = XTESTCanOpenLongTrade(longsForceVolume); + bool hasShortSignal = XTESTCanOpenShortTrade(shortsForceVolume); + if (!hasLongSignal && !hasShortSignal) + { + return; + } + + // + // Open Long Trades ... + if ( + // + hasLongSignal && + xTESTAllowLongTrades) + { + // + bool isOpened = XTESTOpenLongPosition(longsForceVolume); + } + + // + // Open Short Trades ... + if ( + // + hasShortSignal && + xTESTAllowShortTrades) + { + // + bool isOpened = XTESTOpenShortPosition(shortsForceVolume); + } +} + +// +// Handle Close Trades ... +void XTESTHandleCloseTrades() +{ + // + // All Close Mechanism Handles Here ... + // - Force Close; + // - Partial Close; + // - Risk Free Close; + // - Virtual TP/SL Close; + + // + // Force Close Long Trades ... + bool canCloseLongTrades = XTESTCanCloseLongTrade(); + if (xTESTAllowLongTrades && canCloseLongTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; + + // + XSignal closed[]; + xTESTTrader.ClosePositionsByType( + type, + closed); + + // + bool isClosed = ArraySize(closed) > 0; + if (isClosed) + { + XTESTIssueForceCloseTradesAlert(type); + } + } + + // + // Force Close Short Trades ... + bool canCloseShortTrades = XTESTCanCloseShortTrade(); + if (xTESTAllowShortTrades && canCloseShortTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; + + // + XSignal closed[]; + xTESTTrader.ClosePositionsByType( + type, + closed); + + // + bool isClosed = ArraySize(closed) > 0; + if (isClosed) + { + XTESTIssueForceCloseTradesAlert(type); + } + } + + // + // Close Risk Free Trades ... + bool canRiskFree = xTESTRiskFreeTradesInPips > 0 && xTESTRiskFreeTrades > 0 && xTESTRiskFreeRate > 0; + if (canRiskFree) + { + XSignal riskFrees[]; + xTESTTrader.RiskFreeSignals(riskFrees); + bool isRiskFree = ArraySize(riskFrees) > 0; + if (isRiskFree) + { + XTESTIssueRiskFreeTradesAlert(); + } + } + + // + XTESTHandleCloseMaxDrawDownTrades(); + + // + XTESTHandleCloseTooOldTrades(); +} + +// +// Handle Supported Trades ... +void XTESTHandleSupportTrades() +{ + // + bool canDoTrade = + xTESTMaxAllowedSupportTrades > 0 && + xTESTMinRewardPerSupportTradesInPips > 0 && + xTESTSupportTradesPriceDistanceInPips > 0; + if (!canDoTrade) + { + return; + } + + // + XSignal supports[]; + bool hasSupportTrade = XTESTOpenSupportTrade(supports); + if (hasSupportTrade) + { + } +} + +// +// Open Long Position ... +bool XTESTOpenLongPosition(double additionalVolumeMultiplier = 0) +{ + // + bool result = false; + + // + // Calculate Required Data for Position ... + double sl = 0; + double tp = xTESTMinRewardPerTrade; + double riskFree = xTESTRiskFreeTrades; + double riskFreeRate = xTESTRiskFreeRate; + double volume = XTESTCalculateVolume(additionalVolumeMultiplier); + + // + XSignal signal = {}; + signal = xTESTTrader.GenerateTradeSignal( + X_SIGNAL_LONG, + tp, + sl, + volume, + riskFree, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xTESTMagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int error = -1; + result = xTESTTrader.ExecuteSignal(signal, error); + if (result) + { + XTESTIssueSignalExecutionAlert(signal); + } + + // + return result; +} + +// +// Open Short Position ... +bool XTESTOpenShortPosition(double additionalVolumeMultiplier = 0) +{ + // + bool result = false; + + // + // Calculate Required Data for Position ... + double sl = 0; + double tp = xTESTMinRewardPerTrade; + double riskFree = xTESTRiskFreeTrades; + double riskFreeRate = xTESTRiskFreeRate; + double volume = XTESTCalculateVolume(additionalVolumeMultiplier); + + // + XSignal signal = {}; + signal = xTESTTrader.GenerateTradeSignal( + X_SIGNAL_SHORT, + tp, + sl, + volume, + riskFree, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xTESTMagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int error = -1; + result = xTESTTrader.ExecuteSignal(signal, error); + if (result) + { + XTESTIssueSignalExecutionAlert(signal); + } + + // + return result; +} + +// +// Open a Support Signal ... +bool XTESTOpenSupportTrade( + XSignal &supports[] // Holds Result ... +) +{ + // + bool result = false; + + // + // Check Can Trade ... + result = xTESTAllowLongTrades || xTESTAllowShortTrades; + if (!result) + { + return result; + } + + // + // Check Support Trades is Enable or not ... + bool isSupportTradesEnabled = + // + xTESTMaxAllowedSupportTrades > 0 && + xTESTMinRewardPerSupportTrades > 0 && + xTESTSupportTradesPriceDistance > 0 + // + ; + if (!isSupportTradesEnabled) + { + return result; + } + + // + // Recieve InDD Open Trades ... + XSignal inDDTrades[]; + xTESTTrader.GetInDrawDownTrades( + xTESTSupportTradesPriceDistance, + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + inDDTrades); + int inDDTradesCount = ArraySize(inDDTrades); + result = inDDTradesCount > 0; + if (!result) + { + return result; + } + + // + // Check Signals Exists ... + double longsForceVolume = 0; + double shortsForceVolume = 0; + bool hasLongSignal = XTESTCanOpenLongTrade(longsForceVolume); + bool hasShortSignal = XTESTCanOpenShortTrade(shortsForceVolume); + result = hasLongSignal || hasShortSignal; + if (!result) + { + return result; + } + + // + // Loop Through In DrawDown Trades ... + XSignal supportedSignals[]; + for (int i = 0; i < inDDTradesCount; i++) + { + // + // Retrieve Parent Signal ... + XSignal parent = inDDTrades[i]; + + // + // Check if Long Signal Happens ... + if (hasLongSignal && parent.type == X_SIGNAL_LONG) + { + // + // Generate Support Signal ... + XSignal sSignal = GenerateSupportSignal( + longsForceVolume, + X_SIGNAL_LONG, + parent); + + // + // Validate it ... + bool isValidSupport = IsValid(sSignal, xTESTMagicNumber); + if (!isValidSupport) + { + continue; + ; + } + + // + // Try To Execute Support Signal ... + int error = 0; + bool isExecuted = xTESTTrader.ExecuteSupportSignal( + sSignal, + error); + if (isExecuted) + { + // + if (!result) + { + result = true; + } + + // + Add( + sSignal, + supports); + + // + XTESTIssueSignalExecutionAlert(sSignal); + } + + // + continue; + } + + // + // Check if Short Signal Happens ... + if (hasShortSignal && parent.type == X_SIGNAL_SHORT) + { + // + // Generate Support Signal ... + XSignal sSignal = GenerateSupportSignal( + shortsForceVolume, + X_SIGNAL_SHORT, + parent); + + // + // Validate it ... + bool isValidSupport = IsValid(sSignal, xTESTMagicNumber); + if (!isValidSupport) + { + continue; + ; + } + + // + // Try To Execute Support Signal ... + int error = 0; + bool isExecuted = xTESTTrader.ExecuteSupportSignal( + sSignal, + error); + if (isExecuted) + { + // + if (!result) + { + result = true; + } + + // + Add( + sSignal, + supports); + + // + XTESTIssueSignalExecutionAlert(sSignal); + } + + // + continue; + } + } + + // + return result; +} + +// +// Close All InDrawDown Trades ... +void XTESTHandleCloseMaxDrawDownTrades() +{ + // + if (xTESTMaxAllowedDrawDownPerTrades > 0) + { + // + XSignal closed[]; + xTESTTrader.CloseInDrawDownTrades( + xTESTMaxAllowedDrawDownPerTrades, + closed); + + // + int count = ArraySize(closed); + if (count > 0) + { + XTESTIssueLongInDrawdownTradeClosed(); + } + } +} + +// +// Close All Too Old Trades ... +void XTESTHandleCloseTooOldTrades() +{ + // + // in DrawDown Trades ... + if (xTESTMaxInDrawDownTradeAge > 0) + { + // + XSignal oldTrades[]; + xTESTTrader.CloseLongTimeTrades( + xTESTMaxInDrawDownTradeAge, + _Period, + oldTrades); + + // + bool hasOldClosedTrades = ArraySize(oldTrades) > 0; + if (hasOldClosedTrades) + { + // + LogMessage("Old Trade Closed ..."); + } + } +} + +// +// END Provided Functions ... +// + +// +// START Private Functions ... +// + +// +// Calculating Volume for Tradings ... +double XTESTCalculateVolume( + double forceMultiplier = 0 // some times we get more than one signal at the same time, here we increase volume using this ... +) +{ + // + // Assign default Value ... + double result = xTESTStaticVolume; + + // + // we can count open trades and in draw down trades + // then do check volume based on it for gridding ... + XSignal openInProfitTrades[]; + xTESTTrader.GetInProfitTrades( + 0, + X_SIGNAL_UNKNOWN, + X_KIND_TRADE, + openInProfitTrades); + int openTrades = ArraySize(openInProfitTrades); + + // + // Calculate Normalized Multiplier ... + double mVolumeMultiplier = xTESTVolumeMultiplier <= 0 ? 1 : xTESTVolumeMultiplier; + double multiplier = mVolumeMultiplier; + multiplier = multiplier * openTrades; + if (multiplier < 1) + { + multiplier = 1; + } + + // + double growRate = xTESTBalance / xTESTDeposit; + if (growRate >= 1 && multiplier == 1) + { + // + double growDiff = growRate - 1; + if (growDiff < 1) + { + growRate = 1 + (growDiff * mVolumeMultiplier); + } + + // + multiplier = multiplier * growRate; + } + + // + result = multiplier * xTESTStaticVolume; + + // + // Apply Force Multiplier ... + if (forceMultiplier > 1) { + result *= forceMultiplier; + } + + // + // Check Max Allowed Lottage ... + double maxAllowedVolume = xTESTMaxSupportedVolumePerTradeInLots; + if (growRate >= 4 * mVolumeMultiplier) { + maxAllowedVolume *= mVolumeMultiplier; + } + + // + if ( + maxAllowedVolume > 0 && + result > maxAllowedVolume) + { + result = maxAllowedVolume; + } + + // + // Normalize Volume ... + result = NormalizeVolume(result); + + // + return result; +} + +// +// Calculate Signal TP and SL ... +XTPSL XTESTCalculateTPSL( + ENUM_X_SIGNAL_TYPE type // Position Type +) +{ + // + XTPSL result = {}; + + // + // Validate Args ... + if ( + type != X_SIGNAL_LONG && + type != X_SIGNAL_SHORT) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + + // + double ask = GetAsk(); + double bid = GetBid(); + double spread = GetSpread(); + double entry = isLong ? ask : bid; + + // + // TODO: Find Risk .. + double risk = 0; + + // + // Calculate Reward ... + double reward = PipsToPrice(xTESTMinRewardPerTradeInPips) + spread; + + // + // Calculate TP and SL ... + double tp = isLong ? entry + reward : entry - reward; + double sl = 0; + + // + result.type = type; + result.tp = tp; + result.sl = sl; + result.entry = entry; + // + // TODO: Calculate R2R ... + result.r2r = 0; + + // + return result; +} + +// +// Generate Support Signal for Specific Trade ... +XSignal GenerateSupportSignal( + double forceVolumeMultiplier, // how many time increase volume based on signal providers + ENUM_X_SIGNAL_TYPE type, // which type of support signal issued + XSignal &parent // generate support signal for which Trade Kind Position + ) +{ + // + XSignal result = {}; + + // + // Validate Type ... + bool isTypeValid = type == X_SIGNAL_LONG || type == X_SIGNAL_SHORT; + if (!isTypeValid) + { + return result; + } + + // + // Validate Parent Signal ... + bool isValidSignal = IsValid(parent, xTESTMagicNumber); + if (!isValidSignal) + { + return result; + } + + // + // Validate Parent is Kind ... + bool isKindValid = parent.kind == X_KIND_TRADE; + if (!isKindValid) + { + return result; + } + + // + // Check Parent Ticket ... + bool isValidTicket = parent.ticket > 0; + if (!isValidTicket) + { + return result; + } + + // + // Validate DrawDown ... + bool isInDD = parent.profit < 0; + if (!isInDD) + { + return result; + } + + // + // Calculate What we Want ... + // + bool isLong = type == X_SIGNAL_LONG; + + // + // Entry Price ... + // double entry = GetEntry(parent.symbol, type); + + // + // Required for Calculating RiskFree Level of Support Signals ... + double riskFreeRate = 0; + double riskFreePrice = 0; + bool canRiskFree = xTESTRiskFreeRate > 0; + + // + // TP ... + double tp = MathAbs(parent.tp - parent.entry) / 2; + // PriceToPips(MathAbs(parent.tp - parent.entry) / 2); + if (tp <= xTESTMinRewardPerSupportTrades) + { + tp = xTESTMinRewardPerSupportTrades; + } + else if ( + canRiskFree && + tp > xTESTMinRewardPerSupportTrades) + { + // + // Fill Risk Free Info ... + riskFreeRate = xTESTRiskFreeRate; + riskFreePrice = + isLong ? xTESTMinRewardPerSupportTrades : xTESTMinRewardPerSupportTrades; + } + + // + // SL ... + double sl = isLong ? 0 : 0; + + // + // VOLUME ... + int pOpenSupportCount = xTESTTrader.CountSupportedPositions(parent); + double volume = parent.volume * forceVolumeMultiplier; + + // + // Check and Normalize Volume based on MaxAllowed Volume ... + if (xTESTMaxSupportedVolumePerTradeInLots > 0 && volume > xTESTMaxSupportedVolumePerTradeInLots) { + volume = xTESTMaxSupportedVolumePerTradeInLots; + } + + // + // Normalize Volume ... + volume = NormalizeVolume(volume); + + // + // Generating Support Signal for Parent ... + result = xTESTTrader.GenerateSupportSignal( + type, + tp, + sl, + volume, + riskFreePrice, + riskFreeRate, + parent.ticket); + + // + return result; +} + +void XTESTIssueInitializationSucceedAlert() +{ + // + string message = "Initializion of (" + XTESTProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueDeinitializationSucceedAlert() +{ + // + string message = "De Initializion of (" + XTESTProviderName + " Provider" + ") Succeeded ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueForceCloseTradesAlert(ENUM_X_SIGNAL_TYPE type) +{ + // + string typeStr = GetSignalType(type); + if (StringLen(typeStr) == 0) + { + return; + } + + // + string message = "Force Close " + typeStr + " Trades ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueMaxAllowedTradesReachedAlert() +{ + // + string message = "reached Max Allowed Same Time Trades ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueMaxAllowedFreeMarginReachedAlert() +{ + // + string message = "reached FreeMarigin For Open Trades ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueMinAllowedBalanceReachedAlert() +{ + // + string message = "doesn't have Minimum Balance For Open Trades ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueSignalExecutionAlert( + XSignal &signal // Executed Signal +) +{ + // + XTESTIssueAlert(signal); +} + +void XTESTIssueSignalExecutionError(int error) +{ + // + string message = GetSignalExecutionError(error); + if (StringLen(message) == 0) + { + return; + } + + // + XTESTIssueAlert(message); +} + +void XTESTIssueRiskFreeTradesAlert() +{ + // + string message = "Make Some Trades Risk Free ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueLongInProfitTradeClosed() +{ + // + string message = "Closed Long Time in Profit Trades ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueLongInDrawdownTradeClosed() +{ + // + string message = "Closed Long Time in Profit Trades ..."; + XTESTIssueAlert(message); +} + +void XTESTIssueAlert(string message) +{ + // + if (xTESTEnableAlerts) + { + SendAlert(message); + } + else + { + LogMessage(message); + } +} +void XTESTIssueAlert(XSignal &signal) +{ + // + string signalStr = xTESTTrader.ToString(signal); + XTESTIssueAlert(signalStr); + + // // + // if (xTESTEnableAlerts) + // { + // SendAlert(signal); + // } + // else + // { + // LogSignal(signal); + // } +} + +// +// END Private Functions ... +// diff --git a/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtm.indicator.helper.lib.mq5 b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 0000000..02c0a04 --- /dev/null +++ b/EURUSD-5M-V0.1/MQ5/Libraries/x-saherelm.xtm.indicator.helper.lib.mq5 @@ -0,0 +1,319 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTM 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 + +// +// Includes ... +#include "..\Libraries\x-saherelm.log.lib.mq5" +#include "..\Libraries\x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 1, + X_XTM_BEARISH = -1, + X_XTM_NEUTURAL = 0, +}; + +// +// XTM Indicator Buffer Lines ... +enum ENUM_X_XTM_BUFFER_LINES +{ + X_XTM_MA_LINE = 0, + X_XTM_MC_COLOR_LINE = 1, + X_XTM_STATE_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +input group "XTM Indicator"; +input int xTMMaPeriod = 14; // Period +input int xTMMaShift = 0; // Shift +input ENUM_MA_METHOD xTMMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE xTMMaAppliedTo = PRICE_WEIGHTED; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTMHandler = INVALID_HANDLE; +double xTMMaBuffer[]; +double xTMStateBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Init Indicators ... +bool XTMInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTM Handler ... + ArraySetAsSeries(xTMMaBuffer, true); + ArraySetAsSeries(xTMStateBuffer, true); + xTMHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xtm.indicator", + // + // Inputs ... + xTMMaPeriod, + xTMMaShift, + xTMMaMethod, + xTMMaAppliedTo); + if (xTMHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTM Indicator: " + (string)GetLastError()); + return result; + } + + // + // xTMOHandler ... + // ArraySetAsSeries(xTMOBuffer, true); + // xTMOHandler = iCustom( + // _Symbol, + // _Period, + // "x-saherelm.xma.indicator", + // // + // // Inputs ... + // xTMMaPeriod, + // xTMMaShift, + // MODE_SMA, + // PRICE_OPEN); + // if (xTMOHandler == INVALID_HANDLE) + // { + // // + // LogMessage("failed to Initialize XMA Indicator: " + (string)GetLastError()); + // return result; + // } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XTMReleaseHandlers() +{ + IndicatorRelease(xTMHandler); + // IndicatorRelease(xTMOHandler); +} + +// +// Handle Reading Buffers ... +void XTMReadBuffers( + int xTMItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // Ma Buffer ... + CopyBuffer( + xTMHandler, + X_XTM_MA_LINE, + 0, + xTMItemsPerTick, + xTMMaBuffer); + + // + // State Buffer ... + CopyBuffer( + xTMHandler, + X_XTM_STATE_LINE, + 0, + xTMItemsPerTick, + xTMStateBuffer); + + // + // XTMO Buffer ... + // CopyBuffer( + // xTMOHandler, + // 0, + // 0, + // xTMItemsPerTick, + // xTMOBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START Signal Related Conditions ... +// + +// +// XTM Long Conditions ... +bool XTMHasLongConditions( + int xTMItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isVale = XTMIsVale(); + + // + result = + // + isVale + // + ; + + // + return result; +} + +// +// XTM Short Conditions ... +bool XTMHasShortConditions( + int xTMItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + bool result = false; + + // + bool isPeak = XTMIsPeak(); + + // + result = + // + isPeak + // + ; + + // + return result; +} + +// +// END Signal Related Conditions ... +// + +// +// START XTM Custom Functions ... +// + +// +// Find Peak based On this Indicator ... +bool XTMIsPeak() +{ + // + bool result = false; + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + 20, + 5, + xTMMaBuffer); + + // + // Must Increasing ... + bool isDecreasing = IsDecreasing( + 5, + 1, + xTMMaBuffer); + + // + // Calculate Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// Find Vale based On this Indicator ... +bool XTMIsVale() +{ + // + bool result = false; + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + 5, + 1, + xTMMaBuffer); + + // + // Must Increasing ... + bool isDecreasing = IsDecreasing( + 20, + 5, + xTMMaBuffer); + + // + // Calculate Result ... + result = + // + isIncreasing + // + && + // + isDecreasing + // + ; + + // + return result; +} + +// +// END XTM Custom Functions ... +// diff --git a/EURUSD-5M-V0.1/Version.txt b/EURUSD-5M-V0.1/Version.txt new file mode 100644 index 0000000..15c2a42 --- /dev/null +++ b/EURUSD-5M-V0.1/Version.txt @@ -0,0 +1 @@ +packed at: Sunday, December 3, 2023 7:12:48 PM \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..40eff0f --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# xSaherElmEAPacks + +this is a submodule repo of **xTradeBotWorkspace** which contains all published packs of SaherElm IT Center EAs. + +## Maintainer + +Hadi Khazaee asl + +[https://www.saherelm.ir](https://www.saherelm.ir) + +[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com) \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/Ex4/Experts/x-saherelm.ea.ex4 b/XAUUSD-15M-V1.0/Ex4/Experts/x-saherelm.ea.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..e277c985573de099881549d3fc5236df07246c52 GIT binary patch literal 122876 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

>?tGROrLv!MVg0>1a2(2+I(xC=5*TMaI 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

ar`_E`wULgu{sL>t5{b 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 literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/Ex4/Indicators/x-saherelm.xtpow.ex4 b/XAUUSD-15M-V1.0/Ex4/Indicators/x-saherelm.xtpow.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..6e81928a2d799ddf83dc1eb5a0b432e4ce65b64a GIT binary patch literal 12694 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

$P=NX)>YYboER686u0X;C8m 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 Div*MF literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.dialog.ex4 b/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.dialog.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..b92c87635b2b8e3da13af40f13aaf5b3d16f3094 GIT binary patch literal 21464 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 literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.draw.lib.ex4 b/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.draw.lib.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..99f8ece5d9578976dfbd6c7860500ddfe7cd657f GIT binary patch literal 7218 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 literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.indicator.lib.ex4 b/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.indicator.lib.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..56a524ea077289099117aa3fb0a6f000f10a6254 GIT binary patch literal 8046 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 V!y42r>8b}~RK9JM1X}7={~zp|gINFo literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.models.lib.ex4 b/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.models.lib.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..aac8c2fc8a41a7f45ba016bb4d1de8fd54d12474 GIT binary patch literal 4890 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 F{0}TrG;aU^ literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.signal.lib.ex4 b/XAUUSD-15M-V1.0/Ex4/Libraries/x-saherelm.signal.lib.ex4 new file mode 100644 index 0000000000000000000000000000000000000000..ac56a7dfa8bb52ae6ae105b1eacdd4fd6a4b3b7d GIT binary patch literal 19232 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 EFDD%*tYGRXSepPt@^gUdjIa}>h9Cm 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 literal 0 HcmV?d00001 diff --git a/XAUUSD-15M-V1.0/MQ4/Experts/x-saherelm.ea.mq4 b/XAUUSD-15M-V1.0/MQ4/Experts/x-saherelm.ea.mq4 new file mode 100644 index 0000000..7af93af --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Experts/x-saherelm.ea.mq4 @@ -0,0 +1,1116 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XST Strategy Expert Advisor +// --------------------------------------------- +// saherelm implementation of strategy expert advisor ... +// in this EA, we try to combine multiple tools, to ashive best +// results ... +// +// ShortName: XST +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +989121694056 +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XST Strategy Expert Advisor" +#property strict + +// +// START Inputs ... +// +// +// Signal Prefixe ... +input string signalPrefix = "XST_EA"; // Signal Prefix + +// +// Signal Draw Specifications ... +input string bullishSignalLabel = "X_BUY"; // Bullish Signal Label +input color bullishSignalColor = clrAqua; // Bullish Signal Color + +// +input string bearishSignalLabel = "X_SELL"; // Bearish Signal Label +input color bearishSignalColor = clrFuchsia; // Bearish Signal Color + +// +input color signalEntryColor = clrAquamarine; // Signal Entry Ptice Color +input color signalSLColor = clrRed; // Signal SL Color +input color signalTPColor = clrGreen; // Signal TP Color + +// +input int candleGapBetweenSignals = 7; // How many Candle waits to new Signal from last one + +// +// Trade ... +input bool allowTrade = true; // Allow Trade Based on given Signals +input bool allowLongTrades = true; // Allow Long Trades +input bool allowShortTrades = true; // Allow Short Trades + +// +// Balance and Finanical Specifications ... +input double lotsPerTradePercent = 0.00001; // Lots Per Trade Percent +input int maxOpenTrades = 4; // Maximum Open Trade +input double maxDrawdownPercentPerPTrade = 0.1; // Maximum DrawDown Per Trade +input double minBalancePercent = 0.5; // Minimum Balance for Trading +input double maxEquityPercent = 0.1; // Maximum Trade Equity + +// +// START Global Definitions: Variables, Properties and etc ... +// +int lastSignalledBar = 0; + +// +// Includes our shared library ... +#include "../Libraries/x-saherelm.lib.mq4" + +// +// TODO: Complete this ... +// Include Dialog Handler ... +// #include "../Libraries/x-saherelm.dialog.mq4" + +// +// Includes our shared library ... +#include "../Libraries/x-saherelm.signal.lib.mq4" + +// +// Add Logging Inputs ... +// +input string xAlertingLabel = "- Alerts -"; // --> Alerts <-- + +// +// Alerts ... + +// +// Alert Bot Events ... +input bool logEvents = true; // Log Events +input bool alertEvents = true; // Alert Events + +// +// Alert Types ... +input bool terminalAlert = false; // Terminal Alert +input bool pushAlert = false; // Push Notification Alerts + +// +// Positions ... +input bool alertPositions = true; // Alert Positions +input bool longPositionAlerts = true; // Alert Long Positions +input bool shortPositionAlerts = true; // Alert Short Positions + +// +input bool enableNewDayAlert = true; // New Day Alert +input bool enableNewHourAlert = true; // New Hour Alert + +// +int maxMarketLength = 0; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// Start Event Handlers ... +// +// +// Initialization ... +int OnInit() { + // + // Validate Inputs ... + bool inputsNotValiid = + // + // EA ... + maxOpenTrades <= 0 + || maxEquityPercent < 0 + || minBalancePercent < 0 + || lotsPerTradePercent < 0 + || maxDrawdownPercentPerPTrade < 0 + ; + + // + if (inputsNotValiid) { + return INIT_PARAMETERS_INCORRECT; + } + + // + totalSignals = 0; + totalLongSignals = 0; + totalShortSignals = 0; + + // + initialBalance = 0; + + // + // START Define Array Series ... + // + // + // END Define Array Series ... + // + + // + // here we specify logging enabled or not ... + enableLogging = true; + + // + // this is a Tag which attached to our Logger ... + logTag = "XST"; + + // + ClearSignalConditions(); + + // + maxMarketLength = MathMax(0, GetDailyCandleCount()); + + // + // TODO: Complete this ... + // try to Create App Window ... + // CreateDialog(logTag); + + // + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) { + // + // TODO: Complete this ... + // Destroy Dialog ... + // DestroyDialog(reason); +} + +// +// Handling Chart Events ... +void OnChartEvent( + const int id, // event ID + const long& lparam, // event parameter of the long type + const double& dparam, // event parameter of the double type + const string& sparam // event parameter of the string type +) { + // + // TODO: Complete this ... + // DialogChartEvent( + // id, + // lparam, + // dparam, + // sparam + // ); +} + +// +// Ticker Event Handler ... +void OnTick() { + // + isNewDay = IsNewDay(); + if ( + isNewDay + && enableNewDayAlert + ) { + // + SendAlert( + StringConcatenate( + "New Day ..." + ) + ); + } + + // + isNewHour = IsNewHour(); + if ( + isNewHour + && enableNewHourAlert + ) { + // + SendAlert( + StringConcatenate( + "New Hour ..." + ) + ); + } + + // + // Process Signals to Open Positions ... + ProcessSignals(); + + // + // Checking State for Signal Handling ... + CheckState(); + + // + // Process Open Positions for Trailing Stop Loss or Close ... + ProcessOpenPositions(); +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Check State for Signal Handling ... +void CheckState() { + // + // Here we Must to Check Market State for enable or disable + // Signal Handlers and also make dection to close all long/short + // trades ... +} + +// +// Calculate Signals and Process Based on Exists Signals ... +void ProcessSignals() { + // + XSignalRequest request = {}; + request.type = X_SIGNAL_NONE; + request.hasSignal = false; + + // + // Prevent Multiple Calculating on Same Bars ... + isNewBar = IsNewBar(); + if (isNewBar) { + countedBars++; + } + + // + if (countedBars < maxMarketLength) { + return; + } + + // + bool allowDoTrade = true; + + // + // Check Balance ... + if (initialBalance > 0) { + // + // Retrieve Account Balance ... + double balance = AccountInfoDouble(ACCOUNT_BALANCE); + double minimumBalanceForTrade = + balance > initialBalance + ? + minBalancePercent * balance + : + minBalancePercent * initialBalance; + + // + // Retrieve Account Equity ... + double equity = AccountInfoDouble(ACCOUNT_EQUITY); + double maxAllowedEquity = balance - (balance * maxEquityPercent); + + // + // Retrieve Free Marigin ... + double freeMargin = AccountFreeMargin(); + double maximumMariginRisk = balance - (balance * maxEquityPercent); + + // + if ( + // + // Do not Open Positions if equity not passed ... + equity < maxAllowedEquity || + // + // Do not Open Positions if free margin not passed ... + freeMargin <= maximumMariginRisk || + // + // Do not open positions if balance less than minimum ... + balance <= minimumBalanceForTrade + ) { + // + static bool tradingPauseAlerted; + + // + allowDoTrade = false; + + // + if (!tradingPauseAlerted) { + // + string message = StringConcatenate( + "Trading Pause => ", + "Balance: ", balance, + ", Equity: ", equity, + ", FreeMargin: ", freeMargin + ); + + // + LogMessage(message); + SendAlert(message); + + // + tradingPauseAlerted = true; + } + } + } + + // + // Retrieve Signal Exists ... + request = GenerateSignal(0); + + // + // Prevent doing anything else, if there is no signals ... + if ( + !allowDoTrade || + !request.hasSignal || + request.type == X_SIGNAL_NONE + ) { + return; + } + + // + bool hasLongSignal = request.type == X_SIGNAL_LONG; + + // + // Check last Signalled Bar with Counted Bars ... + // Prevent Multiple Signalling on Same Bar ... + bool isInLastSignalledBars = false; + for (int i=0; i < candleGapBetweenSignals; i++) { + // + isInLastSignalledBars = + isInLastSignalledBars + || lastSignalledBar == countedBars - i + ; + } + if (isInLastSignalledBars) { + // + // Clear Signal Conditions ... + if (hasLongSignal) { + ClearLongSignalConditions(); + } else { + ClearShortSignalConditions(); + } + + // + return; + } + + // + // increase last signalled bar ... + lastSignalledBar = countedBars; + + // + // Calculate Can Trade or not ... + allowDoTrade = allowTrade + && ( + hasLongSignal ? + allowLongTrades : + allowShortTrades + ); + + // + // Chack Maximum Open Positions ... + int openTrades = CountOpenTrades(); + if (maxOpenTrades > 0) { + // + if (openTrades >= maxOpenTrades) { + // + allowDoTrade = false; + + // + if (!allowDoTrade) { + // + string message = StringConcatenate( + "Trading Pause => ", + "Max Open Trades (", + maxOpenTrades, + ") reached ..." + ); + + // + LogMessage(message); + SendAlert(message); + } + } + } + + // + // Check Trading is Enable or not ... + // nothing to do if trading is disabled ... + if (!allowDoTrade) { + // + // Clear Signal Conditions ... + if (hasLongSignal) { + ClearLongSignalConditions(); + } else { + ClearShortSignalConditions(); + } + + // + string message = StringConcatenate( + "Trading Not Allowed ..." + ); + + // + LogMessage(message); + SendAlert(message); + return; + } + + // + // Retrieve Signal Lots Per Trade ... + double lPTradePercent = GetSignalLottage( + request.signal, + lotsPerTradePercent + ); + + // + bool isPositionOpened = TradeSignal( + request.signal, + lPTradePercent, + // + bullishSignalLabel, + bullishSignalColor, + bearishSignalLabel, + bearishSignalColor + ); + + // + totalSignals++; + if (hasLongSignal) { + // + totalLongSignals++; + ClearLongSignalConditions(); + } else { + // + totalShortSignals++; + ClearShortSignalConditions(); + } + + // + if (isPositionOpened) { + // + bool canAlert = + alertPositions + && ( + hasLongSignal ? + longPositionAlerts + : + shortPositionAlerts + ); + + // + if (canAlert) { + // + // Alert Message ... + string message = StringConcatenate( + "Trade on Signal ID: ", request.signal.id, + ", ProvidedBy: ", GetSignalProviderIdentifier(request.signal.provider), + ", Entry: ", request.signal.entry, + ", TP: ", request.signal.tp + ); + + // + // Terminal Alert ... + if (terminalAlert) { + Alert(message); + } + + // + // Push Alert ... + if (pushAlert) { + SendNotification(message); + } + } + } +} + +// +// Process All Open Positions ... +void ProcessOpenPositions() { + // + // XSignalling ... + if (enableXSignalling) { + // + // Close All XXX Provided Signals on it's Specific Condition ... + if (xCloseLongTrades) { + // + CloseAllProviderLongTrades(X_XXX_PROVIDER); + + // + xCloseLongTrades = false; + } + + // + if (xCloseShortTrades) { + // + CloseAllProviderShortTrades(X_XTPW_PROVIDER); + + // + xCloseShortTrades = false; + } + + // + // Close Maximum DrawDown Passed Trades ... + + // + // Longs ... + bool hasClosedLongInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + xLongMaxDrawdownPerTradePercent, + X_SIGNAL_LONG, + X_XXX_PROVIDER + ); + + // + // Shorts ... + bool hasClosedShortInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + xShortMaxDrawdownPerTradePercent, + X_SIGNAL_SHORT, + X_XXX_PROVIDER + ); + + // + // Close All Long Time Trades based on Provider provided Length ... + bool hasClosedLongTimeTrade = CloseAllLongTimeTrades( + xMaximumCandlesPerTrade, + X_XXX_PROVIDER + ); + + // + if ( + hasClosedLongTimeTrade + || hasClosedLongInDrawDownLongTrade + || hasClosedShortInDrawDownLongTrade + ) { + xFailedSignals++; + } + } + + // + // XR Signalling ... + if (enableXRSignalling) { + // + if (xRCloseLongTrades) { + // + CloseAllProviderLongTrades(X_XR_PROVIDER); + + // + xRCloseLongTrades = false; + } + + // + if (xRCloseShortTrades) { + // + CloseAllProviderShortTrades(X_XR_PROVIDER); + + // + xRCloseShortTrades = false; + } + + // + // Close Maximum DrawDown Passed Trades ... + + // + // Longs ... + bool hasClosedLongInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + xRLongMaxDrawdownPerTradePercent, + X_SIGNAL_LONG, + X_XR_PROVIDER + ); + + // + // Shorts ... + bool hasClosedShortInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + xRShortMaxDrawdownPerTradePercent, + X_SIGNAL_SHORT, + X_XR_PROVIDER + ); + + // + // Close All Long Time Trades based on Provider provided Length ... + bool hasClosedLongTimeTrade = CloseAllLongTimeTrades( + xRMaximumCandlesPerTrade, + X_XR_PROVIDER + ); + + // + if ( + hasClosedLongTimeTrade + || hasClosedLongInDrawDownLongTrade + || hasClosedShortInDrawDownLongTrade + ) { + xRFailedSignals++; + } + } + + // + // XTPW Signalling ... + if (enableXTPWSignalling) { + // + if (xTPWCloseLongTrades) { + // + CloseAllProviderLongTrades(X_XTPW_PROVIDER); + + // + xTPWCloseLongTrades = false; + } + + // + if (xTPWCloseShortTrades) { + // + CloseAllProviderShortTrades(X_XTPW_PROVIDER); + + // + xTPWCloseShortTrades = false; + } + + // + // Close Maximum DrawDown Passed Trades ... + + // + // Longs ... + bool hasClosedLongInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + xTPWLongMaxDrawdownPerTradePercent, + X_SIGNAL_LONG, + X_XTPW_PROVIDER + ); + + // + // Shorts ... + bool hasClosedShortInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + xTPWShortMaxDrawdownPerTradePercent, + X_SIGNAL_SHORT, + X_XTPW_PROVIDER + ); + + // + // Close All Long Time Trades based on Provider provided Length ... + bool hasClosedLongTimeTrade = CloseAllLongTimeTrades( + xTPWMaximumCandlesPerTrade, + X_XTPW_PROVIDER + ); + + // + if ( + hasClosedLongTimeTrade + || hasClosedLongInDrawDownLongTrade + || hasClosedShortInDrawDownLongTrade + ) { + xTPWFailedSignals++; + } + } + + // + // Close Maximum DrawDown Passed Trades ... + // this is the Maximum Controller ... + // + double maxOfXPercent = enableXSignalling ? + MathMax( + xLongMaxDrawdownPerTradePercent, + xShortMaxDrawdownPerTradePercent + ) : 0 + ; + + // + double maxOfXRPercent = enableXRSignalling ? + MathMax( + xRLongMaxDrawdownPerTradePercent, + xRShortMaxDrawdownPerTradePercent + ) : 0 + ; + + // + double maxOfXTPWPercent = enableXTPWSignalling ? + MathMax( + xTPWLongMaxDrawdownPerTradePercent, + xTPWShortMaxDrawdownPerTradePercent + ) : 0 + ; + + // + double maxDrawDownPercent = MathMax( + maxOfXPercent, + maxOfXRPercent + ); + maxDrawDownPercent = MathMax( + maxDrawDownPercent, + maxOfXTPWPercent + ); + maxDrawDownPercent = MathMax( + maxDrawDownPercent, + maxDrawdownPercentPerPTrade + ); + + // + // we Calculate Max DrawDown Percent Per Trade ... + // then try to Close based on them ... + bool hasClosedInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades( + maxDrawDownPercent + ); +} + +// +// Send Special Type of Alerts ... +void SendAlert(string message) { + // + if ( + !logEvents + && !alertEvents + ) { + return; + } + + // + // Log Handling ... + if (logEvents) { + LogMessage(message); + } + + // + // Alert Handling ... + if (alertEvents) { + // + // Terminal Alert ... + if (terminalAlert) { + Alert(message); + } + + // + // Push Alert ... + if (pushAlert) { + SendNotification(message); + } + } +} +// +// END Functions ... +// + +// +// +// Calculate Signal ... +// in this function we calculate a signal exists in +// specific bar or not ... +XSignalRequest GenerateSignal( + const int bar_index // Bar Index ... +) { + // + // create temp result ... + XSignalRequest result = {}; + result.hasSignal = false; + result.type = X_SIGNAL_NONE; + result.provider = X_UNKNOWN_PROVIDER; + + // + bool hasSignal = false; + bool hasLongSignal = false; + bool hasShortSignal = false; + + // + XSignal signal = {}; + + // + // Define Template Signal Requests for Managing Multiple Signals ... + // + // X ... + XSignalRequest xLongSignalRequest = {}; + XSignalRequest xShortSignalRequest = {}; + // + // XR ... + XSignalRequest xrLongSignalRequest = {}; + XSignalRequest xrShortSignalRequest = {}; + // + // XTPW ... + XSignalRequest xTPWLongSignalRequest = {}; + XSignalRequest xTPWShortSignalRequest = {}; + + // + // START XR Signal Handler ... + // + // + if (enableXRSignalling) { + // + CheckXRSignalHandler( + bar_index + ); + + // + // Long Trades ... + if (allowTrade && allowLongTrades) { + // + if (xRWaitForLongSignals) { + // + CheckXRLongSignalConditions( + bar_index + ); + + // + xrLongSignalRequest = GenerateXRSignal( + X_SIGNAL_LONG, + signalPrefix, + bar_index + ); + + // + if (xrLongSignalRequest.hasSignal) { + // + // Here we can Check and Filter Signals Based On State ... + bool isReady = IsReadyForXRSignals( + xrLongSignalRequest.signal + ); + + // + if (isReady && xRWaitForLongSignals) { + // + hasLongSignal = true; + signal = xrLongSignalRequest.signal; + } else { + ClearXRLongSignalConditions(); + } + } + } else { + ClearXRLongSignalConditions(); + } + } + + // + // Short Trades ... + if (allowTrade && allowShortTrades) { + // + if (xRWaitForShortSignals) { + // + CheckXRShortSignalConditions( + bar_index + ); + + // + xrShortSignalRequest = GenerateXRSignal( + X_SIGNAL_SHORT, + signalPrefix, + bar_index + ); + + // + if (xrShortSignalRequest.hasSignal) { + // + // Here we can Check and Filter Signals Based On State ... + bool isReady = IsReadyForXRSignals( + xrShortSignalRequest.signal + ); + + // + if (isReady && xRWaitForShortSignals) { + // + hasShortSignal = true; + signal = xrShortSignalRequest.signal; + } else { + ClearXRShortSignalConditions(); + } + } + } else { + ClearXRShortSignalConditions(); + } + } + } + // + // END XR Signal Handler ... + // + + // + // START XTPW Signal Handler ... + // + if (enableXTPWSignalling) { + // + CheckXTPWSignalHandler( + bar_index + ); + + // + // Long Trades ... + if (allowTrade && allowLongTrades) { + // + if (xTPWWaitForLongSignals) { + // + CheckXTPWLongSignalConditions( + bar_index + ); + + // + xTPWLongSignalRequest = GenerateXTPWSignal( + X_SIGNAL_LONG, + signalPrefix, + bar_index + ); + + // + if (xTPWLongSignalRequest.hasSignal) { + // + // Here we can Check and Filter Signals Based On State ... + bool isReady = IsReadyForXTPWSignals( + xTPWLongSignalRequest.signal + ); + + // + if (isReady && xTPWWaitForLongSignals) { + // + hasLongSignal = true; + signal = xTPWLongSignalRequest.signal; + } else { + ClearXTPWLongSignalConditions(); + } + } + } else { + ClearXTPWLongSignalConditions(); + } + } + + // + // Short Trades ... + if (allowTrade && allowShortTrades) { + // + if (xTPWWaitForShortSignals) { + // + CheckXTPWShortSignalConditions( + bar_index + ); + + // + xTPWShortSignalRequest = GenerateXTPWSignal( + X_SIGNAL_SHORT, + signalPrefix, + bar_index + ); + + // + if (xTPWShortSignalRequest.hasSignal) { + // + // Here we can Check and Filter Signals Based On State ... + bool isReady = IsReadyForXTPWSignals( + xTPWShortSignalRequest.signal + ); + + // + if (isReady && xTPWWaitForShortSignals) { + // + hasShortSignal = true; + signal = xTPWShortSignalRequest.signal; + } else { + ClearXTPWShortSignalConditions(); + } + } + } else { + ClearXTPWShortSignalConditions(); + } + } + } + // + // END XTPW Signal Handler ... + // + + // + // START X Signal Handler ... + // + // + if (enableXSignalling) { + // + CheckXSignalHandler( + bar_index + ); + + // + // Long Trades ... + if (allowTrade && allowLongTrades) { + // + if (xWaitForLongSignals) { + // + CheckXLongSignalConditions( + bar_index + ); + + // + xLongSignalRequest = GenerateXSignal( + X_SIGNAL_LONG, + signalPrefix, + bar_index + ); + + // + if (xLongSignalRequest.hasSignal) { + // + // Here we can Check and Filter Signals Based On State ... + bool isReady = IsReadyForXSignals( + xLongSignalRequest.signal + ); + + // + if (isReady && xWaitForLongSignals) { + // + hasLongSignal = true; + signal = xLongSignalRequest.signal; + } else { + ClearXLongSignalConditions(); + } + } + } else { + ClearXLongSignalConditions(); + } + } + + // + // Short Trades ... + if (allowTrade && allowShortTrades) { + // + if (xWaitForShortSignals) { + // + CheckXShortSignalConditions( + bar_index + ); + + // + xShortSignalRequest = GenerateXSignal( + X_SIGNAL_SHORT, + signalPrefix, + bar_index + ); + + // + if (xShortSignalRequest.hasSignal) { + // + // Here we can Check and Filter Signals Based On State ... + bool isReady = IsReadyForXSignals( + xShortSignalRequest.signal + ); + + // + if (isReady && xWaitForShortSignals) { + // + hasShortSignal = true; + signal = xShortSignalRequest.signal; + } else { + ClearXShortSignalConditions(); + } + } + } else { + ClearXShortSignalConditions(); + } + } + } + // + // END XR Signal Handler ... + // + + // + hasSignal = hasLongSignal || hasShortSignal; + + // + if (!hasSignal) { + // + signal.type = X_SIGNAL_NONE; + result.type = X_SIGNAL_NONE; + } + + // + // Normalize TP, SL and Entry Price ... + signal.tp = NormalizeDouble(signal.tp, _Digits); + signal.sl = NormalizeDouble(signal.sl, _Digits); + signal.entry = NormalizeDouble(signal.entry, _Digits); + + // + result.signal = signal; + result.type = signal.type; + result.hasSignal = hasSignal; + result.provider = signal.provider; + + // + // Return Result ... + return result; +} diff --git a/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.ma.mq4 b/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.ma.mq4 new file mode 100644 index 0000000..e3a5737 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.ma.mq4 @@ -0,0 +1,173 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MA Indicator +// --------------------------------------------- +// saherelm implementation of above indicator ... +// this indicator uses two ma line: +// - fast ma; +// - slow ma; +// +// 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 MA Indicator" +#property strict + +// +// START Inputs ... +// +// +// Fast MA ... +input int maLength = 20; // MA Length +input int maShift = 0; // MA Shift +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method +input ENUM_APPLIED_PRICE maAppliedPrice = PRICE_CLOSE; // MA Applied Price + +// +// START Global Definitions: Variables, Properties and etc ... +// +#property indicator_chart_window + +// +#property indicator_buffers 1 + +// +#property indicator_plots 1 + +// +// Start Define Indicator Buffer Styles ... +// +// +// Fast Ma Buffer ... +#property indicator_label1 "Ma" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_DOT +#property indicator_width1 2 + +// +// End Define Indicator Buffer Styles ... +// + +// +// Buffers ... +#define maBufferIndex 0 + +double maBuffer[]; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// Start Event Handlers ... +// +// +// Initialization ... +int OnInit() { + // + // Initialize what we want ... + if (maLength <= 0) { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Start Set Index Buffers ... + // + // + // Ma ... + SetIndexBuffer(maBufferIndex, maBuffer); + SetIndexDrawBegin(maBufferIndex, maLength + 1); + // + // End Set Index Buffers ... + // + + // + return INIT_SUCCEEDED; +} + +// +// Calculating what we want ... +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[] +) { + // + // 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, maLength); + + // + // input variable, we return 0 means nothing passed ... + if (rates_total < maxLength) { + return 0; + } + + // + // found which candles calculated before ... + limit = (prev_calculated == 0) ? rates_total - maxLength - 1 : rates_total - prev_calculated + 1; + + // + // this is the main loop of calculations, for each bar index ... + for (int i = limit - 1; i >= 0; i--) { + // + // Start Calculation here ... + // i is bar_index ... + + // + // Calculate Ma ... + CalculateMa(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Calculating Ma ... +void CalculateMa( + const int &bar_index +) { + // + // Calculating Fast Ma ... + double ma = iMA( + _Symbol, + _Period, + maLength, + maShift, + maMethod, + maAppliedPrice, + bar_index + ); + + // + maBuffer[bar_index] = ma; +} +// +// END Functions ... +// \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xrange.mq4 b/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xrange.mq4 new file mode 100644 index 0000000..1359f57 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xrange.mq4 @@ -0,0 +1,294 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XRange Indicator +// --------------------------------------------- +// saherelm implementation of above 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 XRange Indicator" +#property strict + +// +// START Inputs ... +// +input int marketLength = 14; +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 + +// +#property indicator_plots 3 + +// +// Start Define Indicator Buffer Styles ... +// +// +// Highest High Buffer ... +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrGreen +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// Lowest Low Buffer ... +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Middle Buffer ... +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrYellow +#property indicator_style3 STYLE_DASH +#property indicator_width3 1 +// +// End Define Indicator Buffer Styles ... +// + +// +// Buffers ... +// +#define highestHighBufferIndex 0 +#define lowestLowBufferIndex 1 +#define middleBufferIndex 2 + +// +double highestHighBuffer[]; +double lowestLowBuffer[]; +double middleBuffer[]; + +// +datetime startTime; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// Start Event Handlers ... +// +// +// Initialization ... +int OnInit() { + // + // Initialize what we want ... + if ( + marketLength <= 0 + ) { + return INIT_PARAMETERS_INCORRECT; + } + + // + string hhLbl = StringConcatenate( + "XR HH(", marketLength, ")" + ); + SetIndexBuffer(highestHighBufferIndex, highestHighBuffer); + SetIndexLabel(highestHighBufferIndex, hhLbl); + + // + string llLbl = StringConcatenate( + "XR LL(", marketLength, ")" + ); + SetIndexBuffer(lowestLowBufferIndex, lowestLowBuffer); + SetIndexLabel(lowestLowBufferIndex, llLbl); + + // + string midLbl = StringConcatenate( + "XR Mid(", marketLength, ")" + ); + SetIndexBuffer(middleBufferIndex, middleBuffer); + SetIndexLabel(middleBufferIndex, midLbl); + + // + return INIT_SUCCEEDED; +} + +// +// Calculating what we want ... +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[] +) { + // + // 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, marketLength); + + // + // input variable, we return 0 means nothing passed ... + if (rates_total < maxLength) { + return 0; + } + + // + // found which candles calculated before ... + limit = (prev_calculated == 0) ? rates_total - maxLength - 1 : rates_total - prev_calculated + 1; + + // + // this is the main loop of calculations, for each bar index ... + for (int i = limit - 1; i >= 0; i--) { + // + // Start Calculation here ... + // i is bar_index ... + + // + // Calculations ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Calculations ... +void CalculateBuffers( + const int &bar_index +) { + // + // Retrieve Bar Time ... + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + if (startTime == 0) { + // + startTime = barTime; + SetIndicatorBuffersNone(bar_index); + return; + } + + // + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime + ); + + // + int startDistance = startBarIndex - bar_index; + if (startDistance < marketLength) { + // + SetIndicatorBuffersNone(bar_index); + return; + } + + // + // Highest High ... + int hhIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + marketLength, + bar_index + ); + double hh = iHigh( + _Symbol, + _Period, + hhIdx + ); + highestHighBuffer[bar_index] = hh; + + // + // Lowest Low ... + int llIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + marketLength, + bar_index + ); + double ll = iLow( + _Symbol, + _Period, + llIdx + ); + lowestLowBuffer[bar_index] = ll; + + // + // Middle Buffer ... + double mid = (hh + ll) / 2; + middleBuffer[bar_index] = mid; + + // + // Reset Start Time ... + startTime = 0; +} + +// +void SetIndicatorBuffersNone( + const int bar_index +) { + // + int lastBarIndex = bar_index + 1; + + // + double lastHighestHigh; + double lastLowestLow; + + // + // Highest High ... + if (ArraySize(highestHighBuffer) > lastBarIndex) { + lastHighestHigh = highestHighBuffer[lastBarIndex]; + } else { + lastHighestHigh = 0; + } + + // + // Lowest Low ... + if (ArraySize(lowestLowBuffer) > lastBarIndex) { + lastLowestLow = lowestLowBuffer[lastBarIndex]; + } else { + lastLowestLow = 0; + } + + // + highestHighBuffer[bar_index] = lastHighestHigh; + lowestLowBuffer[bar_index] = lastLowestLow; + + // + double mid = (lastHighestHigh + lastLowestLow) / 2; + middleBuffer[bar_index] = mid; +} +// +// END Functions ... +// \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xtpow.mq4 b/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xtpow.mq4 new file mode 100644 index 0000000..46ff59e --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Indicators/x-saherelm.xtpow.mq4 @@ -0,0 +1,275 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center Trend Power Indicator +// --------------------------------------------- +// saherelm implementation of above indicator ... +// this indicator uses two ma line: +// - fast ma; +// - slow ma; +// +// 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 MA Indicator" +#property strict + +// +// START Inputs ... +// +input int marketLength = 7; // Market Length +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +#property indicator_separate_window + +// +#property indicator_plots 3 +#property indicator_buffers 3 +#property indicator_minimum 0 +#property indicator_maximum 100 + +// +#property indicator_levelcolor clrGray +#property indicator_levelstyle STYLE_DOT + +// +// Start Define Indicator Buffer Styles ... +// +#property indicator_type1 DRAW_HISTOGRAM +#property indicator_color1 clrLime +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +#property indicator_type2 DRAW_HISTOGRAM +#property indicator_color2 clrRed +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrYellow +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// End Define Indicator Buffer Styles ... +// + +// +// Buffers ... +#define powerUpBufferIndex 0 +#define powerDownBufferIndex 1 +#define signalBufferIndex 2 + +double powerUpBuffer[]; +double powerDownBuffer[]; +double signalBuffer[]; + +// +#include "../Libraries/x-saherelm.lib.mq4" +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// Start Event Handlers ... +// +// +// Initialization ... +int OnInit() { + // + // Initialize what we want ... + if (marketLength <= 0) { + return INIT_PARAMETERS_INCORRECT; + } + + // + SetLevelValue(0, 0.0); + IndicatorSetString(INDICATOR_LEVELTEXT,0,""); + + // + SetLevelValue(1, 20.0); + IndicatorSetString(INDICATOR_LEVELTEXT,1,""); + + // + SetLevelValue(2, 50); + IndicatorSetString(INDICATOR_LEVELTEXT,2,""); + + // + SetLevelValue(3, 100); + IndicatorSetString(INDICATOR_LEVELTEXT,3,""); + + // + string pUpLbl = StringConcatenate( + "P Up (", marketLength, ")" + ); + SetIndexLabel(powerUpBufferIndex, pUpLbl); + SetIndexBuffer(powerUpBufferIndex, powerUpBuffer); + SetIndexDrawBegin(powerUpBufferIndex, marketLength + 1); + + // + string pDownLbl = StringConcatenate( + "P Down (", marketLength, ")" + ); + SetIndexLabel(powerDownBufferIndex, pDownLbl); + SetIndexBuffer(powerDownBufferIndex, powerDownBuffer); + SetIndexDrawBegin(powerDownBufferIndex, marketLength + 1); + + // + string pSignalLbl = StringConcatenate( + "P Signal (", marketLength, ")" + ); + SetIndexLabel(signalBufferIndex, pSignalLbl); + SetIndexBuffer(signalBufferIndex, signalBuffer); + SetIndexDrawBegin(signalBufferIndex, marketLength + 1); + + // + // here we specify logging enabled or not ... + enableLogging = true; + + // + // this is a Tag which attached to our Logger ... + logTag = "X_TPW_OSC"; + + // + return INIT_SUCCEEDED; +} + +// +// Calculating what we want ... +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[] +) { + // + // 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, marketLength); + + // + // input variable, we return 0 means nothing passed ... + if (rates_total < maxLength) { + return 0; + } + + // + // found which candles calculated before ... + limit = (prev_calculated == 0) ? rates_total - maxLength - 1 : rates_total - prev_calculated + 1; + + // + // this is the main loop of calculations, for each bar index ... + for (int i = limit - 1; i >= 0; i--) { + // + // Start Calculation here ... + // i is bar_index ... + + // + // Calculate Buffers ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Calculating Ma ... +void CalculateBuffers( + const int &bar_index +) { + // + double powerUp = 0; + double powerDown = 0; + + // + int dailyCount = GetDailyCandleCount(); + double dailyHH = GetMarketHighestHigh( + bar_index, + dailyCount + ); + double dailyLL = GetMarketLowestLow( + bar_index, + dailyCount + ); + double dailyDiff = dailyHH - dailyLL; + double rate = dailyDiff / 100; + + // + for (int i = bar_index; i < bar_index + marketLength; i++) { + // + XOHCL c = GetCandleModel(i); + + // + double cRange = + MathAbs(c.open - c.close) + // MathAbs(c.high - c.low) + ; + bool isBullish = c.open < c.close; + + // + if (isBullish) { + powerUp += cRange; + } else { + powerDown += cRange; + } + } + + // + powerUp = powerUp / rate; + powerDown = powerDown / rate; + + // + int doubleMarketLength = (marketLength * 2); + double ema = GetMA( + bar_index, + doubleMarketLength, + 0, + MODE_EMA, + PRICE_WEIGHTED + ); + + // + double emaRate = GetMarketHighestHigh(bar_index, doubleMarketLength) - GetMarketLowestLow(bar_index, doubleMarketLength) / 100; + + // + double signal = (ema / 100) * rate; + double signalAddition = MathMin(powerUp, powerDown); + + // + powerUpBuffer[bar_index] = powerUp; + powerDownBuffer[bar_index] = powerDown; + signalBuffer[bar_index] = signal + signalAddition; +} +// +// END Functions ... +// \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.dialog.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.dialog.mq4 new file mode 100644 index 0000000..c00318e --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.dialog.mq4 @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Dialog Library +// --------------------------------------------- +// saherelm useful tools and definitions +// for handling dialogs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes Logger library ... +// #include "../Libraries/x-saherelm.lib.mq4" +#include "../Libraries/x-saherelm.log.lib.mq4" + +// +#include + +// +CAppDialog AppWindow; + +// +// Prefix for Created Dialogs ... +string windowPrefix = "XWinD"; + +// +// Generate a random number for dialogs ... +int GenerateWindowNumber() { + // + int result = MathRand() + 1; + + // + return result; +} + +// +// Generate a Window Prefix ID ... +string GenerateWindowID() { + // + string result = windowPrefix; + + // + // Generate INT ID ... + int idNum = GenerateWindowNumber(); + + // + result += "_" + StringConcatenate(idNum); + + // + return result; +} + +// +bool CreateDialog( + const string title = "" +) { + // + // string windowID = GenerateWindowID(); + + // + // Try to Create Window ... + bool result = AppWindow.Create( + 0, + title, + 0, + 20, + 20, + 360, + 324 + ); + + // + if (result) { + AppWindow.Run(); + } + + // + return result; +} + +// +void DestroyDialog(const int reason) { + AppWindow.Destroy(reason); +} + +// +// Apply Chart Event on Created Window ... +void DialogChartEvent( + const int id, // event ID + const long& lparam, // event parameter of the long type + const double& dparam, // event parameter of the double type + const string& sparam // event parameter of the string type +) { + // + AppWindow.ChartEvent( + id, + lparam, + dparam, + sparam + ); +} \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.draw.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.draw.lib.mq4 new file mode 100644 index 0000000..776cde4 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.draw.lib.mq4 @@ -0,0 +1,2010 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Draw Global Library +// --------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes our shared library ... +#include "../Libraries/x-saherelm.log.lib.mq4" + +// +// Draw Highest High ... +bool DrawHighestHigh( + const int bar_index, + const int marketLen, + const string tag, + const int drawUntilBarIndex = 0, + const long chartID = 0, + const int subWindow = 0, + const color clr = clrAqua, + const ENUM_LINE_STYLE style = STYLE_DOT, + const int width = 1, + const bool back = false, + const bool selection = false, + const bool hidden = false, + const long zOrder = 0 +) { + // + bool result = false; + + // + // Calculate Highest High ... + int hhIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + marketLen, + bar_index + ); + + // + datetime hhTime = iTime( + _Symbol, + _Period, + hhIdx + ); + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + datetime drawUntilTime = + drawUntilBarIndex != bar_index ? + iTime( + _Symbol, + _Period, + drawUntilBarIndex + ) : + barTime + ; + + // + double hh = iHigh( + _Symbol, + _Period, + hhIdx + ); + + // + int rnd = rand(); + + // + // Define Label ... + string lbl = StringConcatenate( + tag, + "_HH(", marketLen ,")_", + hh, + "_", rnd + ); + + // + result = ObjectDelete( + chartID, + lbl + ); + + // + // Draw a Trend Line ... + result = DrawTrendLine( + chartID, + lbl, + subWindow, + hhTime, + hh, + drawUntilTime, + hh, + clr, + style, + width, + back, + selection, + hidden, + zOrder + ); + + // + return result; +} + +// +// Draw Lowest Low ... +bool DrawLowestLow( + const int bar_index, + const int marketLen, + const string tag, + const int drawUntilBarIndex = 0, + const long chartID = 0, + const int subWindow = 0, + const color clr = clrFuchsia, + const ENUM_LINE_STYLE style = STYLE_DOT, + const int width = 1, + const bool back = false, + const bool selection = false, + const bool hidden = false, + const long zOrder = 0 +) { + // + bool result = false; + + // + // Calculate Highest High ... + int llIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + marketLen, + bar_index + ); + + // + datetime llTime = iTime( + _Symbol, + _Period, + llIdx + ); + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + datetime drawUntilTime = + drawUntilBarIndex != bar_index ? + iTime( + _Symbol, + _Period, + drawUntilBarIndex + ) : + barTime + ; + + // + double ll = iLow( + _Symbol, + _Period, + llIdx + ); + + // + int rnd = rand(); + + // + // Define Label ... + string lbl = StringConcatenate( + tag, + "_LL(", marketLen ,")_", + ll, + "_", rnd + ); + + // + result = ObjectDelete( + chartID, + lbl + ); + + // + // Draw a Trend Line ... + result = DrawTrendLine( + chartID, + lbl, + subWindow, + llTime, + ll, + drawUntilTime, + ll, + clr, + style, + width, + back, + selection, + hidden, + zOrder + ); + + // + return result; +} + +// +// Draw Market Middle ... +bool DrawMarketMiddle( + const int bar_index, + const int marketLen, + const string tag, + const int drawUntilBarIndex = 0, + const long chartID = 0, + const int subWindow = 0, + const color clr = clrYellow, + const ENUM_LINE_STYLE style = STYLE_DOT, + const int width = 1, + const bool back = false, + const bool selection = false, + const bool hidden = false, + const long zOrder = 0 +) { + // + bool result = false; + + // + // Calculate Highest High ... + int llIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + marketLen, + bar_index + ); + + // + datetime llTime = iTime( + _Symbol, + _Period, + llIdx + ); + + // + double ll = iLow( + _Symbol, + _Period, + llIdx + ); + + // + // Calculate Highest High ... + int hhIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + marketLen, + bar_index + ); + + // + datetime hhTime = iTime( + _Symbol, + _Period, + hhIdx + ); + + // + double hh = iHigh( + _Symbol, + _Period, + hhIdx + ); + + // + double middle = ll + ((hh - ll) / 2); + datetime middleTime = hhIdx < llIdx + ? hhTime + : llTime + ; + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + datetime drawUntilTime = + drawUntilBarIndex != bar_index ? + iTime( + _Symbol, + _Period, + drawUntilBarIndex + ) : + barTime + ; + + // + int rnd = rand(); + + // + // Define Label ... + string lbl = StringConcatenate( + tag, + "_MID(", marketLen ,")_", + middle, + "_", rnd + ); + + // + result = ObjectDelete( + chartID, + lbl + ); + + // + // Draw a Trend Line ... + result = DrawTrendLine( + chartID, + lbl, + subWindow, + middleTime, + middle, + drawUntilTime, + middle, + clr, + style, + width, + back, + selection, + hidden, + zOrder + ); + + // + return result; +} + +// +// 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 = OBJ_ARROW_UP, // 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(); + + // + // create an arrow ... + if(!ObjectCreate(chartID, name, OBJ_ARROW, subWindow, time, price)) { + // + string message = StringConcatenate(__FUNCTION__, + ": failed to create an arrow! Error code = ", + GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // set the arrow code ... + ObjectSetInteger(chartID, name, OBJPROP_ARROWCODE, arrowCode); + + // + // set anchor type ... + ObjectSetInteger(chartID, name, OBJPROP_ANCHOR, anchor); + + // + // set the arrow color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set the border line style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set the arrow's size ... + 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 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,name, OBJPROP_SELECTABLE, true); + 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); +} + +// +// 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 = StringConcatenate( + __FUNCTION__, + ": failed to move the anchor point! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to delete an arrow! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to change the arrow code! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to change anchor type! Error code = ",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(); + + // + // create a horizontal line ... + if(!ObjectCreate(chartID, name, OBJ_HLINE, subWindow, 0, price)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create a horizontal line! Error code = ",GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // set line color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set line width ... + 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 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, 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); +} + +// +// 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 = StringConcatenate( + __FUNCTION__, + ": failed to move the horizontal line! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to delete a horizontal line! Error code = ",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 sub_window = 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(); + + // + // create a vertical line ... + if (!ObjectCreate(chartID, name, OBJ_VLINE, sub_window, time, 0)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create a vertical line! Error code = ", GetLastError() + ); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set line width ... + 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 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, name, OBJPROP_SELECTABLE, true); + 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; +} + +// +// 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 = StringConcatenate( + __FUNCTION__, + ": failed to move the vertical line! Error code = ", 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 = StringConcatenate( + __FUNCTION__, + ": failed to delete the vertical line! Error code = ", 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 back_clr = C'236,233,216', // 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(); + + // + //--- create a rectangle label + if(!ObjectCreate(chartID, name, OBJ_RECTANGLE_LABEL, subWindow, 0, 0)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create a rectangle label! Error code = ",GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // set label coordinates ... + ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + // set label size ... + ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + // set background color ... + ObjectSetInteger(chartID, name, OBJPROP_BGCOLOR, back_clr); + + // + // set border type ... + ObjectSetInteger(chartID, name, OBJPROP_BORDER_TYPE, border); + + // + // set the chart's corner, relative to which point coordinates are defined ... + ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + // set flat border color (in Flat mode) ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set flat border line style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set flat border width ... + ObjectSetInteger(chartID, name, OBJPROP_WIDTH, lineWidth); + + // + // display in the foreground (false) or background (true) ... + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // enable (true) or disable (false) the mode of moving the label 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); +} + +// +// 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 = StringConcatenate( + __FUNCTION__, + ": failed to move X coordinate of the label! Error code = ",GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + if(!ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to move Y coordinate of the label! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to delete a rectangle label! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to change the label's width! Error code = ",GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + if(!ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to change the label's height! Error code = ",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 = StringConcatenate( + __FUNCTION__, + ": failed to change the border type! Error code = ",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(); + + // + // create a trend line by the given coordinates ... + if(!ObjectCreate(chartID, name, OBJ_TREND, subWindow, time1, price1, time2, price2)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create a trend line! Error code = ", GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // set line color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set line width ... + 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 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, name, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // enable (true) or disable (false) the mode of continuation of the line's display to the right ... + ObjectSetInteger(chartID, name, OBJPROP_RAY_RIGHT, rayRight); + + // + // 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); +} + +// +// 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 = StringConcatenate( + __FUNCTION__, + ": failed to move the anchor point! Error code = ", 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 = StringConcatenate( + __FUNCTION__, + ": failed to delete a trend line! Error code = ", 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(); + + // + //--- create Text object + if(!ObjectCreate(chartID, name, OBJ_TEXT, subWindow, time, price)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create \"Text\" object! Error code = ", GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // 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 the slope angle of the text ... + ObjectSetDouble(chartID, name, OBJPROP_ANGLE, angle); + + // + // set anchor type ... + ObjectSetInteger(chartID, name, OBJPROP_ANCHOR, anchor); + + // + // set color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // display in the foreground (false) or background (true) ... + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // enable (true) or disable (false) the mode of moving the object by mouse ... + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, true); + 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); +} + +// +// 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 = StringConcatenate( + __FUNCTION__, + ": failed to move the anchor point! Error code = ", 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 = StringConcatenate( + __FUNCTION__, + ": failed to change the text! Error code = ", 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 = StringConcatenate( + __FUNCTION__, + ": failed to delete \"Text\" object! Error code = ", 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(); + + // + // Create Fibonacci Retracement by the given coordinates ... + if (!ObjectCreate(chartID, name, OBJ_FIBO, subWindow, time1, price1, time2, price2)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create \"Fibonacci Retracement\"! Error code = " , GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // set color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set line width ... + 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 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, name, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // enable (true) or disable (false) the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, name, OBJPROP_RAY_RIGHT, rayRight); + + // + // 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); +} + +// +// 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(); + + // + // Create Fibonacci Retracement by the given coordinates ... + if (!ObjectCreate(chartID, name, OBJ_FIBO, subWindow, time1, price1, time2, price2)) { + // + string message = StringConcatenate( + __FUNCTION__, + ": failed to create \"Fibonacci Retracement\"! Error code = " , GetLastError() + ); + + // + LogMessage(message); + + // + return(false); + } + + // + // set color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // set line width ... + 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 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, name, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // enable (true) or disable (false) the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, name, OBJPROP_RAY_RIGHT, rayRight); + + // + // 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); + + // + // Change Levels Of Fibonacci ... + bool result = FibonacciLevelsSet( + levels, + values, + colors, + styles, + widths, + descriptions, + chartID, + name + ); + + // + // 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 = StringConcatenate( + __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 = StringConcatenate( + __FUNCTION__, + ": failed to move the anchor point! Error code = ", 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 = StringConcatenate( + __FUNCTION__, + ": failed to delete \"Fibonacci Retracement\"! Error code = ", 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 General Functions ... +// +// +// Remove all Drawn Objects ... +void RemoveDraws(const string &tag) { + // + for(int iObj=ObjectsTotal()-1; iObj >= 0; iObj--) { + // + string on = ObjectName(iObj); + if (StringFind(on, tag) == 0) { + ObjectDelete(on); + } + } +} +// +// End General Functions ... +// \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.indicator.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.indicator.lib.mq4 new file mode 100644 index 0000000..0e4b162 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.indicator.lib.mq4 @@ -0,0 +1,450 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Indicator Global Library +// --------------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes library ... +#include "../Libraries/x-saherelm.lib.mq4" + +// +// Includes Models library ... +#include "../Libraries/x-saherelm.models.lib.mq4" + +// +// START Global Requirement Functions ... +// +// +// Reading specified Buffer From ADX Indicator ... +double ReadXMABuffer( + const int bar_index, + const int buffer_index, + // + const int marketLen, + // + const double stp, + const double mxm, + // + const int shortCycleMult, + const int mediumCycleMult, + const int longCycleMult +) { + // + string xmaIndicatorName = "x-saherelm.x.xma"; + + // + double result = iCustom( + _Symbol, + _Period, + xmaIndicatorName, + // + // Inputs ... + marketLen, + stp, + mxm, + shortCycleMult, + mediumCycleMult, + longCycleMult, + MODE_SMA, + // + buffer_index, + bar_index + ); + + // + return result; +} + +// +// Reading specified Buffer from XHL Indicator ... +double ReadXHLBuffer( + const int bar_index, + const int buffer_index, + // + const int marketLen, + // + const int shortCycleMult, + const int mediumCycleMult, + const int longCycleMult +) { + // + string xhlIndicatorName = "x-saherelm.x.hl"; + + // + double result = iCustom( + _Symbol, + _Period, + xhlIndicatorName, + // + // Inputs ... + marketLen, + shortCycleMult, + mediumCycleMult, + longCycleMult, + MODE_SMA, + // + buffer_index, + bar_index + ); + + // + return result; +} + +// +// Reading ADX Values ... +double ReadADX( + const int bar_index, + const int marketLen, + const int mult +) { + // + double result; + + // + int period = marketLen * mult; + + // + result = iADX( + _Symbol, + _Period, + period, + PRICE_CLOSE, + MODE_MAIN, + bar_index + ); + + // + return result; +} + +// +// Reading Pivot States ... +XPvtState GetPVTState( + const int bar_index, + const int marketLen +) { + // + XPvtState result = {}; + + // + double hh = GetMarketHighestHigh( + bar_index, + marketLen + ); + + // + double ho = GetMarketHighestOpen( + bar_index, + marketLen + ); + + // + double hc = GetMarketHighestClose( + bar_index, + marketLen + ); + + // + double hl = GetMarketHighestLow( + bar_index, + marketLen + ); + + // + double ll = GetMarketLowestLow( + bar_index, + marketLen + ); + + // + double lo = GetMarketLowestOpen( + bar_index, + marketLen + ); + + // + double lc = GetMarketLowestClose( + bar_index, + marketLen + ); + + // + double lh = GetMarketLowestHigh( + bar_index, + marketLen + ); + + // + // Filling Result ... + // + result.hh = hh; + result.ho = ho; + result.hc = hc; + result.hl = hl; + + // + result.ll = ll; + result.lo = lo; + result.lc = lc; + result.lh = lh; + + // + return result; +} + +// +// Calculate XRange from Market ... +static XRState lastXRState; +XRState GetXRange( + const int bar_index, + const int rangeMarketLength +) { + // + XRState result = {}; + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + int marketBarIndex = bar_index + rangeMarketLength; + + // + // Highest High ... + // + int hhIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + marketBarIndex, + bar_index + ); + + // + double hh = iHigh( + _Symbol, + _Period, + hhIdx + ); + + // + // Lowest Low ... + // + int llIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + marketBarIndex, + bar_index + ); + + // + double ll = iLow( + _Symbol, + _Period, + llIdx + ); + + // + if (lastXRState.start == 0) { + // + lastXRState.start = barTime; + lastXRState.length = rangeMarketLength; + + // + lastXRState.hh = hh; + lastXRState.ll = ll; + + // + // Middle ... + double mid = (hh + ll) / 2; + lastXRState.mid = mid; + } else { + // + int startBarIndex = iBarShift( + _Symbol, + _Period, + lastXRState.start + ); + + // + if (startBarIndex - bar_index >= rangeMarketLength) { + // + lastXRState.start = barTime; + lastXRState.length = rangeMarketLength; + + // + lastXRState.hh = hh; + lastXRState.ll = ll; + + // + // Middle ... + double mid = (hh + ll) / 2; + lastXRState.mid = mid; + } + } + + // + result = lastXRState; + + // + return result; +} + +// +// Reading XTPowState from Indicatoe ... +XTPOWState GetXTPowState( + const int bar_index, + const int marketLen +) { + // + XTPOWState result = {}; + + // + // + double powerUp = 0; + double powerDown = 0; + double signal = 0; + + // + string indicatorName = "x-saherelm.xtpow"; + + // + int pUpIndex = 0; + int pDownIndex = 1; + int signalIndex = 2; + + // + powerUp = iCustom( + _Symbol, + _Period, + indicatorName, + // + marketLen, + // + pUpIndex, + bar_index + ); + + // + powerDown = iCustom( + _Symbol, + _Period, + indicatorName, + // + marketLen, + // + pDownIndex, + bar_index + ); + + // + signal = iCustom( + _Symbol, + _Period, + indicatorName, + // + marketLen, + // + signalIndex, + bar_index + ); + + // + result.signal = signal; + result.powerUp = powerUp; + result.powerDown = powerDown; + + // + return result; +} + +// +// Reading XRState From Indicator ... +XRState ReadXRange( + const int bar_index, + const int marketLen +) { + // + XRState result = {}; + + // + // Define Buffer Indexes ... + int hhBufferIndex = 0; + int llBufferIndex = 1; + int midBufferIndex = 2; + + // + string indicatorName = "x-saherelm.xrange"; + + // + // Read Values From XRange Indicator ... + + // + double hh = iCustom( + _Symbol, + _Period, + indicatorName, + // + // Inputs ... + marketLen, + // + hhBufferIndex, // Buffer Index ... + bar_index + ); + + // + double ll = iCustom( + _Symbol, + _Period, + indicatorName, + // + // Inputs ... + marketLen, + // + llBufferIndex, // Buffer Index ... + bar_index + ); + + // + double mid = iCustom( + _Symbol, + _Period, + indicatorName, + // + // Inputs ... + marketLen, + // + midBufferIndex, // Buffer Index ... + bar_index + ); + + // + // Filling Result ... + result.hh = hh; + result.ll = ll; + result.mid = mid; + + // + return result; +} +// +// END Indicator Reading Data ... +// diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.lib.mq4 new file mode 100644 index 0000000..9cbc3d6 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.lib.mq4 @@ -0,0 +1,1695 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Global Library +// --------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes Logger library ... +#include "../Libraries/x-saherelm.log.lib.mq4" + +// +// Includes Drawing library ... +#include "../Libraries/x-saherelm.draw.lib.mq4" + +// +static datetime lastBarTime; + +// +struct XOHCL { + double high; + double open; + double close; + double low; +}; + +// +struct XRange { + // + datetime time; + + // + double highestHigh; + double lowestLow; + + // + int levels; + int marketLength; + + // + double rate; +}; + +// +struct XPrice { + // + double askPrice; + double bidPrice; + double priceGap; + + // + double longEntry; + double longExit; + + // + double shortEntry; + double shortExit; +}; + +// +// START Functions ... +// + +// +// Determines current working is New Bar or not ... +bool IsNewBar() { + // + // Reading Last Bar Date ... + datetime curbar = (datetime)SeriesInfoInteger( + _Symbol, + _Period, + SERIES_LASTBAR_DATE + ); + + // + if(lastBarTime != curbar) { + // + lastBarTime = curbar; + return true; + } + + // + return false; +} + +// +// Determines we are in new Day or not ... +bool IsNewDay() { + // + bool result = false; + + // + // Reading Last Bar Date ... + datetime curbar = (datetime)SeriesInfoInteger( + _Symbol, + _Period, + SERIES_LASTBAR_DATE + ); + + // + if (lastBarTime == 0) { + lastBarTime = curbar; + } + + // + if (curbar == lastBarTime) { + return result; + } + + // + // Retrieve Day and Month and Year for Last Bar Time ... + int lastBarDay = TimeDay(lastBarTime); + int lastBarMonth = TimeMonth(lastBarTime); + int lastBarYear = TimeYear(lastBarTime); + + // + // Retrieve Day and Month and Year for Current Bar Time ... + int curBarDay = TimeDay(curbar); + int curBarMonth = TimeMonth(curbar); + int curBarYear = TimeYear(curbar); + + // + result = curBarDay > lastBarDay + || curBarMonth > lastBarMonth + || curBarYear > lastBarYear; + + // + return result; +} + +// +// Determines we are in new Hour or not ... +bool IsNewHour() { + // + // Save Last Hour value ... + static int lastHour = 0; + + // + bool isInNewDay = IsNewDay(); + if (isInNewDay) { + // + // Reset Last Hour if it's in New Day ... + lastHour = 0; + } + + // + // Retrieve Current Hour value ... + int currentHour = Hour(); + + // + // Check values ... + bool result = currentHour > lastHour; + if (result) { + // + // Update Last Hour value ... + lastHour = currentHour; + } + + // + // returns result ... + return result; +} + +// +// Retrieve Number of Candles in a Day ... +int GetDailyCandleCount() { + // + int seconds = PeriodSeconds(_Period); + + // + int daySeconds = 24 * 60 * 60; + + // + int result = daySeconds / seconds; + + // + return result; +} + +// +// XRange Detector ... +XRange GetMarketRange( + const int bar_index, + const int marketLen, + const int levels +) { + // + XRange result = {}; + + // + result.levels = levels; + result.marketLength = marketLen; + + // + datetime time = iTime( + _Symbol, + _Period, + bar_index + ); + result.time = time; + + // + double highestHigh = GetMarketHighestHigh( + bar_index, + marketLen + ); + result.highestHigh = highestHigh; + + // + double lowestLow = GetMarketLowestLow( + bar_index, + marketLen + ); + result.lowestLow = lowestLow; + + // + double diff = highestHigh - lowestLow; + double rate = diff / levels; + + // + result.rate = rate; + + // + return result; +} + +// +// Retrieve RMA on Specific Candle ... +double GetRMA( + int bar_index, + int length +) { + // + double shortSMA = iMA(_Symbol, _Period, length, 0, MODE_SMA, PRICE_CLOSE, bar_index); + double mediumSMA = iMA(_Symbol, _Period, length * 2, 0, MODE_SMA, PRICE_CLOSE, bar_index); + double longSMA = iMA(_Symbol, _Period, length * 3, 0, MODE_SMA, PRICE_CLOSE, bar_index); + + // + double result = longSMA - mediumSMA + shortSMA; + + // + return result; +} + +// +// Retrieve Moving Average ... +double GetMA( + const int bar_index, + const int maLength, + const int maShift, + const ENUM_MA_METHOD maMethod, + const ENUM_APPLIED_PRICE appliedPrice +) { + // + double result = iMA( + _Symbol, + _Period, + maLength, + maShift, + maMethod, + appliedPrice, + bar_index + ); + + // + 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; +} + +// +// Retrieve True Range ... +double GetTR( + const int bar_index +) { + // + double result = 0; + + // + double high = iHigh( + _Symbol, + _Period, + bar_index + ); + + // + double low = iLow( + _Symbol, + _Period, + bar_index + ); + + // + double prevClose = iClose( + _Symbol, + _Period, + bar_index + 1 + ); + + // + double highLowDif = high - low; + double hpCDif = MathAbs(high - prevClose); + double lpCDiff = MathAbs(low - prevClose); + + // + result = MathMax(highLowDif, hpCDif); + result = MathMax(result, lpCDiff); + + // + return result; +} + +// +// Calculate True Range Simple Moving Average ... +double GetMarketTRSMA( + const int bar_index, + const int marketLen +) { + // + double result = 0; + + // + // Create Barket Length Trs ... + double trs[]; + ArrayResize( + trs, + marketLen + ); + int index = 0; + double trSum = 0; + for (int i = bar_index; i < bar_index + marketLen; i++) { + // + double tr = GetTR(i); + trs[index] = tr; + + // + trSum += tr; + + // + index++; + } + + // + result = trSum / marketLen; + + // + return result; +} + +// +// Retrieve Commodity Channel ... +double GetMarketCCI( + const int bar_index, + const int marketLen, + const ENUM_APPLIED_PRICE appliedPrice = PRICE_CLOSE +) { + // + double result = 0; + + // + result = iCCI( + _Symbol, + _Period, + marketLen, + appliedPrice, + bar_index + ); + + // + return result; +} + +// +// this function check crossing up two Buffers ... +bool IsCrossedOver( + double &arr1[], + double &arr2[], + int index1, + int index2 = -1 +) { + // + // Normalize Index 2 Value ... + if (index2 < 0) { + index2 = index1 + 1; + } + + // + bool result = (arr1[index1] > arr2[index1]) && !(arr1[index2] > arr2[index2]); + + // + return result; +} + +// +// this function check crossing down two Buffers ... +bool IsCrossedUnder( + double &arr1[], + double &arr2[], + int index1, + int index2 = -1 +) { + // + // Normalize Index 2 Value ... + if (index2 < 0) { + index2 = index1 + 1; + } + + // + bool result = (arr1[index1] < arr2[index1]) && !(arr1[index2] < arr2[index2]); + + // + return result; +} + +// +// Convert points to Actual Point ... +double PointsToDouble(int points) { + // + double result = points * _Point; + return result; +} + +// +// Converts Pips to Points ... +int PipsToPoints(int pips) { + // + int result = pips * ((_Digits == 3 || _Digits == 5) ? 10 : 1); + return result; +} + +// +// Converts Pips to Double ... +double PipsToDouble(int pips) { + // + double result = PointsToDouble(PipsToPoints(pips)); + return result; +} + +// +// Converts Double Value to Pips ... +int PriceToPips(double value) { + // + if (value <= 0) { + return 0; + } + + // + double pipValue = _Point * MathPow(10, _Digits); + int result = (int)(value / pipValue); + + // + return result; +} + +// +// Converts Pips to Double ... +double PipsToPrice(int pips) { + // + if (pips <= 0) { + return 0; + } + + // + double pipValue = _Point * MathPow(10, _Digits); + double result = pipValue * pips; + + // + return result; +} + +// +// Generate ATR StopLoss Value ... +double CalculateATRSL( + int period, + double multiplier +) { + // + if (period <= 0 || multiplier <= 0) { + return 0; + } + + // + double atrValue = iATR( + _Symbol, + _Period, + period, + 0 + ); + + // + double result = atrValue * multiplier; + + // + return result; +} + +// +// Detect Candle Type ... +// Bullish => means close > open ... +bool IsBullishCandle( + const int bar_index +) { + // + // Temp Result ... + bool result = false; + + // + if (bar_index < 0) { + return result; + } + + // + double open = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double close = iClose( + _Symbol, + _Period, + bar_index + ); + + // + result = IsBullishCandle( + open, + close + ); + + // + return result; +} + +bool IsBullishCandle( + const double open, + const double close +) { + // + // Temp Result ... + bool result = false; + + // + result = open < close; + + // + return result; +} + +// +// Detect Candle Type ... +// Bearish => means close < open ... +bool IsBearishCandle( + const int bar_index +) { + // + // Temp Result ... + bool result = false; + + // + if (bar_index < 0) { + return result; + } + + // + double open = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double close = iClose( + _Symbol, + _Period, + bar_index + ); + + // + result = IsBearishCandle( + open, + close + ); + + // + return result; +} + +bool IsBearishCandle( + const double open, + const double close +) { + // + // Temp Result ... + bool result = false; + + // + result = open > close; + + // + return result; +} + +// +// Retrieve a Candle Info ... +XOHCL GetCandleModel( + const int bar_index +) { + // + XOHCL result = {}; + + // + double high = iHigh( + _Symbol, + _Period, + bar_index + ); + result.high = high; + + // + double open = iOpen( + _Symbol, + _Period, + bar_index + ); + result.open = open; + + // + double close = iClose( + _Symbol, + _Period, + bar_index + ); + result.close = close; + + // + double low = iLow( + _Symbol, + _Period, + bar_index + ); + result.low = low; + + // + return result; +} + +// +// Retrieve Market Current Prices for Signals ... +XPrice GetPrice() { + // + XPrice result = {}; + + // + RefreshRates(); + + // + double askPrice = SymbolInfoDouble( + _Symbol, + SYMBOL_ASK + ); + + // + double bidPrice = SymbolInfoDouble( + _Symbol, + SYMBOL_BID + ); + + // + double priceGap = MathAbs(bidPrice - askPrice); + + // + result.askPrice = askPrice; + result.bidPrice = bidPrice; + result.priceGap = priceGap; + + // + result.longEntry = askPrice; + result.longExit = bidPrice; + + // + result.shortEntry = bidPrice; + result.shortExit = askPrice; + + // + return result; +} + +// +// Detect Market Has Sharp Bullish or not ... +bool IsSharpBullishDetected( + const int bar_index, // Bar Index ... + const int marketLen, // Market Length ... + // + const double shpDetectMultipliers // Sharp Detect Multiplier +) { + // + bool result = false; + + // + double open = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double close = iClose( + _Symbol, + _Period, + bar_index + ); + + // + double high = iHigh( + _Symbol, + _Period, + bar_index + ); + + // + double low = iLow( + _Symbol, + _Period, + bar_index + ); + + // + double minValue = 0; + double maxValue = 0; + int positionedLength = bar_index + marketLen; + + // + for (int i = bar_index; i < positionedLength; i++) { + // + double cHigh = iHigh( + _Symbol, + _Period, + i + ); + + // + double cLow = iLow( + _Symbol, + _Period, + i + ); + + // + minValue += MathMin(cLow, cHigh); + maxValue += MathMax(cLow, cHigh); + } + + // + double minAvg = minValue / positionedLength; + double maxAvg = maxValue / positionedLength; + + // + double shpValue = shpDetectMultipliers * _Point; + + // + result = (low - minAvg) > shpValue; + + // + int index = bar_index; + while ( + index < positionedLength + || !result + ) { + // + low = iLow( + _Symbol, + _Period, + index + ); + + // + result = result + || (low - minAvg) > shpValue; + + // + index++; + }; + + // + return result; +} + +// +// Detect Market Has Sharp Bullish or not ... +bool IsSharpBearishDetected( + const int bar_index, // Bar Index ... + const int marketLen, // Market Length ... + // + const double shpDetectMultipliers // Sharp Detect Multiplier +) { + // + bool result = false; + + // + double open = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double close = iClose( + _Symbol, + _Period, + bar_index + ); + + // + double high = iHigh( + _Symbol, + _Period, + bar_index + ); + + // + double low = iLow( + _Symbol, + _Period, + bar_index + ); + + // + double minValue = 0; + double maxValue = 0; + int positionedLength = bar_index + marketLen; + + // + for (int i = bar_index; i < positionedLength; i++) { + // + double cHigh = iHigh( + _Symbol, + _Period, + i + ); + + // + double cLow = iLow( + _Symbol, + _Period, + i + ); + + // + minValue += MathMin(cLow, cHigh); + maxValue += MathMax(cLow, cHigh); + } + + // + double minAvg = minValue / positionedLength; + double maxAvg = maxValue / positionedLength; + + // + double shpValue = shpDetectMultipliers * _Point; + + // + result = (high - maxAvg) > shpValue; + + // + int index = bar_index; + while ( + index < positionedLength + || !result + ) { + // + high = iHigh( + _Symbol, + _Period, + index + ); + + // + result = result + || (high - maxAvg) > shpValue; + + // + index++; + }; + + // + return result; +} + +// +// Retrieve Highest High Value based on Given Market ... +double GetMarketHighestHigh( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iHighest( + _Symbol, + _Period, + MODE_HIGH, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iHigh( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Highest Low Value based on Given Market ... +double GetMarketHighestLow( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iHighest( + _Symbol, + _Period, + MODE_LOW, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iLow( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Highest Open Value based on Given Market ... +double GetMarketHighestOpen( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iHighest( + _Symbol, + _Period, + MODE_OPEN, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iOpen( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Highest Close Value based on Given Market ... +double GetMarketHighestClose( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iHighest( + _Symbol, + _Period, + MODE_CLOSE, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iClose( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Lowest Low Value based on Given Market ... +double GetMarketLowestLow( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iLowest( + _Symbol, + _Period, + MODE_LOW, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iLow( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Lowest High Value based on Given Market ... +double GetMarketLowestHigh( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iLowest( + _Symbol, + _Period, + MODE_HIGH, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iHigh( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Lowest Open Value based on Given Market ... +double GetMarketLowestOpen( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iLowest( + _Symbol, + _Period, + MODE_OPEN, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iOpen( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Retrieve Lowest Close Value based on Given Market ... +double GetMarketLowestClose( + // + const int bar_index, // Bar Index ... + const int marketLen // Market Length ... +) { + // + // Empty Result ... + double result = 0.0; + + // + // Retrieve Desired Bar Index ... + int foundedBarIndex = iLowest( + _Symbol, + _Period, + MODE_CLOSE, + marketLen, + bar_index + ); + + // + // Retrieve Price ... + result = iClose( + _Symbol, + _Period, + foundedBarIndex + ); + + // + return result; +} + +// +// Find last Candle which it's Low Price is +// less than given price ... +double GetLowLessCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iLow( + _Symbol, + _Period, + index + ); + + // + while (result >= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetLowLessCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iLow( + _Symbol, + _Period, + result + ); + + // + while (cP >= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's Low Price is +// great than given price ... +double GetLowGreatCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iLow( + _Symbol, + _Period, + index + ); + + // + while (result >= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetLowGreatCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iLow( + _Symbol, + _Period, + result + ); + + // + while (cP >= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's High Price is +// less than given price ... +double GetHighLessCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iHigh( + _Symbol, + _Period, + index + ); + + // + while (result >= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetHighLessCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iHigh( + _Symbol, + _Period, + result + ); + + // + while (cP >= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's High Price is +// great than given price ... +double GetHighGreatCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iHigh( + _Symbol, + _Period, + index + ); + + // + while (result <= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetHighGreatCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iHigh( + _Symbol, + _Period, + result + ); + + // + while (cP <= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's Open Price is +// less than given price ... +double GetOpenLessCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iOpen( + _Symbol, + _Period, + index + ); + + // + while (result >= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetOpenLessCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iOpen( + _Symbol, + _Period, + result + ); + + // + while (cP >= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's Open Price is +// less than given price ... +double GetOpenGreatCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iOpen( + _Symbol, + _Period, + index + ); + + // + while (result <= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetOpenGreatCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iOpen( + _Symbol, + _Period, + result + ); + + // + while (cP <= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's Close Price is +// less than given price ... +double GetCloseLessCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iClose( + _Symbol, + _Period, + index + ); + + // + while (result >= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetCloseLessCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iClose( + _Symbol, + _Period, + result + ); + + // + while (cP >= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Find last Candle which it's Close Price is +// great than given price ... +double GetCloseGreatCandlePrice( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int index = bar_index + 1; + double result = iClose( + _Symbol, + _Period, + index + ); + + // + while (result <= price) { + // + index++; + + // + result = iLow( + _Symbol, + _Period, + index + ); + } + + // + return result; +} +int GetCloseGreatCandleIndex( + // + const int bar_index, // Bar Index ... + const double price // Position Open Price ... +) { + // + int result = bar_index + 1; + double cP = iClose( + _Symbol, + _Period, + result + ); + + // + while (cP <= price) { + // + result++; + + // + cP = iLow( + _Symbol, + _Period, + result + ); + } + + // + return result; +} + +// +// Get Slope of a Line by it's two Point ... +double GetSlope( + double x1, + double y1, + double x2, + double y2 +) { + // + double result = (y2 - y1)/MathAbs(x2 - x1); + return result; +} +// +// END Functions ... +// \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.log.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.log.lib.mq4 new file mode 100644 index 0000000..066b3f7 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.log.lib.mq4 @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Draw Global Library +// --------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Log Tag ... +static string logTag = ""; + +// +// Enable or Disable Logging ... +static bool enableLogging = false; + +// +// Start Log Messages ... +// + +// +// Logging a Message, specified for this EA ... +// using provided LogTag ... +void LogMessage(string message) { + // + if (!enableLogging) { + return; + } + + // + Print(logTag, " > ", message); +} + +// +// this used for logging series ... +void LogSeries( + double &series[], // which series to Log ... + int length = 0, // number of items to Log, 0 means all ... + int skip = 0 // number of items which skip before logging ... +) { + // + string msg = ""; + + // + int seriesSize = ArraySize(series); + if ( + skip < 0 + || length < 0 + || seriesSize == 0 + || skip > seriesSize + || skip + length > seriesSize + ) { + return; + } + + // + length = length == 0 ? + seriesSize : + length; + int start = skip > 1 ? + skip - 1 : + skip == 1 ? + 1 : + 0; + + // + // Loop through series items ... + for (int i = start; i < start + length; i++) { + // + msg += StringConcatenate( + "i[", i, "]: ", series[i], ", " + ); + } + + // + LogMessage(msg); +} +// +// End Log Messages ... +// + diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.models.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.models.lib.mq4 new file mode 100644 index 0000000..6899040 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.models.lib.mq4 @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Models Global Library +// --------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START STATIC Variables ... +// +// +static int totalSignals = 0; +static int totalLongSignals = 0; +static int totalShortSignals = 0; + +// +static double initialBalance = 0; + +// +static int countedBars = 0; +static bool isNewBar = false; +static bool isNewDay = false; +static bool isNewHour = false; +// +// END STATIC Variables ... +// + +// +// Start Models ... +// +// +// Signal Providers ... +enum ENUM_X_SIGNAL_PROVIDER { + X_UNKNOWN_PROVIDER, + X_XXX_PROVIDER, + X_XR_PROVIDER, + X_XTPW_PROVIDER +}; + +// +// these are different signal types ... +enum ENUM_X_SIGNAL_TYPE { + X_SIGNAL_NONE, + X_SIGNAL_LONG, + X_SIGNAL_SHORT, +}; + +// +// Model Market Highs and Lows ... +struct XPvtState { + // + double hh; + double ho; + double hc; + double hl; + + // + double ll; + double lo; + double lc; + double lh; +}; + +// +// we Model each signals as this type ... +struct XSignal { + // + // Signal Symbol ... + string symbol; + + // + // Signal Type ... + ENUM_X_SIGNAL_TYPE type; + + // + // Signal ID ... + int id; + + // + // Signal Ticket Number, when Opening Trade ... + int ticket; + + // + // Signal Provider ... + ENUM_X_SIGNAL_PROVIDER provider; + + // + // Target Point ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Signal Entry Price ... + double entry; + + // + // Signalling Time ... + datetime time; + + // + // Signal Comments ... + string comment; + + // + // Signal TAG ... + string tag; +}; + +// +// this is Signal Request Response model ... +struct XSignalRequest { + bool hasSignal; + XSignal signal; + ENUM_X_SIGNAL_TYPE type; + ENUM_X_SIGNAL_PROVIDER provider; +}; + +// +struct XRState { + // + datetime start; + int length; + + // + double hh; + double ll; + double mid; +}; + +// +struct XTPOWState { + // + double powerUp; + double powerDown; + + // + double signal; +}; +// +// End Models ... +// diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.signal.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.signal.lib.mq4 new file mode 100644 index 0000000..097ce74 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.signal.lib.mq4 @@ -0,0 +1,1756 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 Signal Draw Global Library +// --------------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes library ... +#include "../Libraries/x-saherelm.lib.mq4" + +// +// Includes Indicator library ... +#include "../Libraries/x-saherelm.indicator.lib.mq4" + +// +// Includes Models library ... +#include "../Libraries/x-saherelm.models.lib.mq4" + +// +// Includes Drawing library ... +#include "../Libraries/x-saherelm.draw.lib.mq4" + +// +#include "../Libraries/x-saherelm.x.signal.lib.mq4" +#include "../Libraries/x-saherelm.xr.signal.lib.mq4" +#include "../Libraries/x-saherelm.xtpw.signal.lib.mq4" + +// +// START Global Requirement Functions ... +// +// +// END Global Requirement Functions ... +// + +// +// START Signal Related Functions ... +// +// +// Retrieve Signal Bar Index ... +int GetSignalBarIndex(XSignal &signal) { + // + // Temp Result ... + int result = -1; + + // + // Retriev Signal Bar Index ... + result = iBarShift( + _Symbol, + _Period, + signal.time + ); + + // + return result; +} + +// +string GetSignalProviderIdentifier( + ENUM_X_SIGNAL_PROVIDER provider +) { + // + string result = ""; + + // + switch (provider) { + // + case X_XXX_PROVIDER: + result = "XXX"; + break; + + // + case X_XR_PROVIDER: + result = "XR"; + break; + + // + case X_XTPW_PROVIDER: + result = "XTPW"; + break; + + // + default: + result = ""; + break; + } + + // + return result; +} + +// +ENUM_X_SIGNAL_PROVIDER GetSignalProvider(string identifier) { + // + ENUM_X_SIGNAL_PROVIDER result = X_UNKNOWN_PROVIDER; + + // + if ( + StringFind( + identifier, + GetSignalProviderIdentifier(X_XXX_PROVIDER) + ) > -1 + ) { + result = X_XXX_PROVIDER; + } else if ( + StringFind( + identifier, + GetSignalProviderIdentifier(X_XR_PROVIDER) + ) > -1 + ) { + result = X_XR_PROVIDER; + } else if ( + StringFind( + identifier, + GetSignalProviderIdentifier(X_XTPW_PROVIDER) + ) > -1 + ) { + result = X_XTPW_PROVIDER; + } + + // + return result; +} + +// +// Retrieve Signal Lots Per Trade ... +double GetSignalLottage( + const XSignal &signal, + const double defLotsPerTrade +) { + // + double result = defLotsPerTrade; + + // + bool isLong = signal.type == X_SIGNAL_LONG; + + // + switch (signal.provider) { + // + case X_XR_PROVIDER: + // + result = isLong ? + xRLongLotsPerTradePercent : + xRShortLotsPerTradePercent + ; + break; + + // + case X_XXX_PROVIDER: + // + result = isLong ? + xLongLotsPerTradePercent : + xShortLotsPerTradePercent + ; + break; + + // + case X_XTPW_PROVIDER: + // + result = isLong ? + xTPWLongLotsPerTradePercent : + xTPWShortLotsPerTradePercent + ; + break; + } + + // + return result; +} + +// +// Draw Specific Range On Chart ... +void DrawRange( + const XRange &range, + const long chartID = 0, + const int subWindowID = 0, + const string tag = "", + const color clr = clrYellow +) { + // + // Loop through Levels Count ... + for (int i = 0; i <= range.levels; i++) { + // + datetime time1 = iTime( + _Symbol, + _Period, + 1 + ); + + // + datetime time2 = iTime( + _Symbol, + _Period, + 0 + ); + + // + double price = range.lowestLow + (i * range.rate); + + // + string lbl = StringConcatenate( + tag, + "_XRL_", + price + ); + + // + DrawTrendLine( + chartID, + lbl, + subWindowID, + time1, + price, + time2, + price, + clr, + STYLE_DOT + ); + } +} + +// +// Draw Signal Shapes on Chart ... +bool DrawSignal( + const XSignal &signal, + long chartID = 0, + int subWindowID = 0, + const double positionThresholdFactor = 10, + string longSignalLabel = "X-Long", + color longSignalColor = clrAqua, + string shortSignalLabel = "X-Short", + color shortSignalColor = clrFuchsia +) { + // + // Generate isLongSignal Var ... + bool isLongSignal = signal.type == X_SIGNAL_LONG; + + // + // Signal Bar Index ... + int bar_index = iBarShift( + _Symbol, + _Period, + signal.time + ); + + // + // START Draw Signal Arrow ... + // + // + // Arrow Shape Name ... + string arrowName = StringConcatenate(signal.tag, "_Arrow_", signal.id); + + // + // Arrow Price ... + double arrowPrice = 0; + if (isLongSignal) { + // + arrowPrice = iLow( + _Symbol, + _Period, + bar_index + 1 + ); + + // + arrowPrice = arrowPrice - (positionThresholdFactor * _Point); + } else { + // + arrowPrice = iHigh( + _Symbol, + _Period, + bar_index + 1 + ); + + // + arrowPrice = arrowPrice + (positionThresholdFactor * _Point); + } + + // + // Arrow Code ... + uchar arrowCode = isLongSignal ? SYMBOL_ARROWUP : SYMBOL_ARROWDOWN; + + // + // Arrow Anchor Point ... + ENUM_ARROW_ANCHOR arrowAnchorPoint = isLongSignal ? ANCHOR_BOTTOM : ANCHOR_TOP; + + // + // Arrow Color ... + color arrowColor = isLongSignal ? longSignalColor : shortSignalColor; + + // + // Draw Signal Arrow Shape ... + bool result = DrawArrow( + chartID, + arrowName, + subWindowID, + signal.time, + arrowPrice, + arrowCode, + arrowAnchorPoint, + arrowColor + ); + // + // END Draw Signal Arrow ... + // + + // + // START Draw Signal SL/TP ... + // + string slLineName = StringConcatenate(signal.tag, "_SL_", signal.id); + string tpLineName = StringConcatenate(signal.tag, "_TP_", signal.id); + string entryLineName = StringConcatenate(signal.tag, "_ENTRY_", signal.id); + + // + color slColor = shortSignalColor; // isLongSignal ? shortSignalColor : longSignalColor; + color tpColor = longSignalColor; // isLongSignal ? shortSignalColor : longSignalColor; + color entryColor = clrGreen; + + // + datetime time1 = iTime( + _Symbol, + _Period, + bar_index + 1 + ); + + // + // Draw Enrty Price ... + result = DrawTrendLine( + chartID, + entryLineName, + subWindowID, + time1, + signal.entry, + signal.time, + signal.entry, + entryColor, + STYLE_SOLID, + 2 + ); + + // + // Draw Signal SL ... + if (signal.sl > 0) { + // + result = DrawTrendLine( + chartID, + slLineName, + subWindowID, + time1, + signal.sl, + signal.time, + signal.sl, + slColor, + STYLE_SOLID, + 2 + ); + } + + // + // Draw Signal TP ... + if (signal.tp > 0) { + // + result = DrawTrendLine( + chartID, + tpLineName, + subWindowID, + time1, + signal.tp, + signal.time, + signal.tp, + tpColor, + STYLE_SOLID, + 2 + ); + } + // + // END Draw Signal SL/TP ... + // + + // + // Start Draw Signal Label ... + // + // + string labelName = StringConcatenate(signal.tag, "_Label_", signal.id); + + // + double labelPrice = isLongSignal ? arrowPrice - (positionThresholdFactor * _Point) : arrowPrice + (positionThresholdFactor * _Point); + + // + string labelText = isLongSignal ? longSignalLabel : shortSignalLabel; + labelText = StringConcatenate( + labelText, + "_", + GetSignalProviderIdentifier(signal.provider) + ); + + // + result = DrawText( + chartID, + labelName, + subWindowID, + signal.time, + labelPrice, + labelText, + "Arial", + 8, + arrowColor, + 0, + ANCHOR_CENTER + ); + // + // End Draw Signal Label ... + // + + // + return result; +} + +// +// Trade on Specific Signal ... +bool TradeSignal( + XSignal &signal, + // + double volumePercent, + // + // Long ... + const string longSignalLabel, + const color longSignalColor, + // + // Short ... + const string shortSignalLabel, + const color shortSignalColor +) { + // + // Temp Result ... + bool result = false; + + // + if (initialBalance == 0) { + initialBalance = AccountInfoDouble(ACCOUNT_BALANCE); + } + + // + double balance = AccountInfoDouble(ACCOUNT_BALANCE); + int openPositions = CountOpenTrades(); + double volume = (volumePercent * initialBalance); + + // + if ( + signal.type != X_SIGNAL_LONG && + signal.type != X_SIGNAL_SHORT + ) { + return result; + } + + // + bool hasLongSignal = signal.type == X_SIGNAL_LONG; + + // + // Check TP and Entry Price ... + if ( + ( + hasLongSignal + && signal.entry > signal.tp + ) || + ( + !hasLongSignal + && signal.entry < signal.tp + ) + ) { + return result; + } + + // + // Order Operation ... + int operation = hasLongSignal ? + OP_BUY : + OP_SELL; + + // + // Detect Trade Color ... + color clr = hasLongSignal ? + longSignalColor : + shortSignalColor; + + // + // Generate Signal Comment ... + string label = hasLongSignal ? + longSignalLabel : + shortSignalLabel; + + // + // Generate Signal Comment ... + string comment = StringConcatenate( + signal.tag, + "_", signal.id, + "_", GetSignalProviderIdentifier(signal.provider), + "_", label + ); + + // + // Placing Order ... + int orderTicket = OrderSend( + _Symbol, + operation, + volume, + signal.entry, + 3, + signal.sl, + signal.tp, + comment, + signal.id, + 0, + clr + ); + + // + // Draw Signal Shape if Order Opened Successfully ... + if (orderTicket >= 0) { + // + signal.ticket = orderTicket; + + // + // Here i must to Draw Signal Shapes ... + bool isDrawn = DrawSignal( + signal, + 0, + 0, + 50, + longSignalLabel, // Long Signal Label ... + longSignalColor, + shortSignalLabel, // Short Signal Label ... + shortSignalColor + ); + + // + LogMessage( + StringConcatenate( + "Order [", orderTicket ,"]: Provided by: ", GetSignalProviderIdentifier(signal.provider) + ) + ); + + // + // TODO: here we have to check if there are another + // open positions which their entry price is bigger + // than current signal entry price, for long trades and + // their tp is high than current tp, ... + // close in profit trades or modify orders tp to current ... + // // + // if (CountOpenTrades() > 0) { + // // + // // Here we have to + // ModifyOpenTradesBasedOnCurrentTrade(signal); + // } + + // + result = true; + } + + // + return result; +} +// +// END Signal Related Functions ... +// + +// +// START Orders Functions ... +// +// +// Convert To XSignal Model ... +XSignal OrderToSignal() { + // + // Temp Result ... + XSignal result = {}; + result.type = X_SIGNAL_NONE; + + // + // Here we can get some usefull info based on selected order ... + double swap = OrderSwap(); + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + double stopLoss = OrderStopLoss(); + double openPrice = OrderOpenPrice(); + datetime openTime = OrderOpenTime(); + int magicNumber = OrderMagicNumber(); + double takeProfit = OrderTakeProfit(); + string comment = OrderComment(); + + // + ENUM_X_SIGNAL_PROVIDER provider = GetSignalProvider(comment); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // Conver Position to Signal ... + result.sl = stopLoss; + result.tp = takeProfit; + result.time = openTime; + result.symbol = _Symbol; + result.id = magicNumber; + result.comment = comment; + result.entry = openPrice; + result.provider = provider; + result.type = isLongOrder ? X_SIGNAL_LONG : X_SIGNAL_SHORT; + + // + return result; +} + +// +// START Count Orders ... +// +// +// Count Open Positions ... +int CountOpenTrades() { + // + int result = 0; + + // + // Loop through Orders ... + for (int i = 0; i < OrdersTotal(); i++) { + // + // Select indexed Order ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order ... + if (OrderSymbol() == _Symbol) { + result++; + } + } + } + + // + // Return Result ... + return result; +} + +// +// Count Open Long Positions ... +int CountOpenLongTrades() { + // + int result = 0; + + // + // Loop through Orders ... + for (int i = 0; i < OrdersTotal(); i++) { + // + // Select indexed Order ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order ... + if ( + OrderSymbol() == _Symbol + && OrderType() == OP_BUY + ) { + result++; + } + } + } + + // + // Return Result ... + return result; +} + +// +// Count Open Short Positions ... +int CountOpenShortTrades() { + // + int result = 0; + + // + // Loop through Orders ... + for (int i = 0; i < OrdersTotal(); i++) { + // + // Select indexed Order ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order ... + if ( + OrderSymbol() == _Symbol + && OrderType() == OP_SELL + ) { + result++; + } + } + } + + // + // Return Result ... + return result; +} +// +// END Count Orders ... +// + +// +// START Close Orders ... +// +// +// Close All Open Trades ... +bool CloseAllTrades() { + // + // Loop through all Positions ... + bool result = false; + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of All Trade Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + + // + return result; +} + +// +bool CloseAllProviderTrades( + ENUM_X_SIGNAL_PROVIDER provider +) { + // + bool result = false; + + // + // Loop through Signals ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + XSignal signal = OrderToSignal(); + + // + if (signal.provider == provider) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of All Provider Long Trades Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +bool CloseAllProviderLongTrades( + ENUM_X_SIGNAL_PROVIDER provider +) { + // + bool result = false; + + // + // Loop through Signals ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + XSignal signal = OrderToSignal(); + + // + if ( + signal.provider == provider + && signal.type == X_SIGNAL_LONG + ) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of All Provider Long Trades Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +bool CloseAllProviderShortTrades( + ENUM_X_SIGNAL_PROVIDER provider +) { + // + bool result = false; + + // + // Loop through Signals ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + XSignal signal = OrderToSignal(); + + // + if ( + signal.provider == provider + && signal.type == X_SIGNAL_SHORT + ) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of All Provider Long Trades Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close All Open Long Trades ... +bool CloseAllLongTrades() { + // + // Loop through all Positions ... + bool result = false; + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + if (isLongOrder) { + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of All Long Trade Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close All Open Short Trades ... +bool CloseAllShortTrades() { + // + // Loop through all Positions ... + bool result = false; + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + if (!isLongOrder) { + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of All Short Trade Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close All In Profit Trades ... +bool CloseAllInProfitTrades() { + // + // Loop through all Positions ... + bool result = false; + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + if ( + profit > 0 + && profit > 50 * _Point + ) { + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of InProfit Trade Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close All In DrawDown Trades ... +bool CloseAllInDrawDownTrades() { + // + // Loop through all Positions ... + bool result = false; + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + if (profit < 0) { + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of InDrawDown Trade Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close Biggest In DrawDown Trades ... +bool CloseBiggestDrawDownTrade() { + // + // Loop through all Positions ... + bool result = false; + double drawDown = 0; + + // + // Find Biggest In DrawDown ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + if ( + profit < 0 + && MathAbs(profit) > drawDown + ) { + drawDown = profit; + } + } + } + } + + // + // Close Biggest In DrawDown ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + if ( + profit < 0 + && MathAbs(profit) >= drawDown + ) { + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of Max InDrawDown Trade Closing issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close All Long Time Trades ... +bool CloseAllLongTimeTrades( + const int passedCandles, + const ENUM_X_SIGNAL_PROVIDER provider = X_UNKNOWN_PROVIDER +) { + // + bool result = false; + + // + if (passedCandles <= 0) { + return result; + } + + // + int currentBarIndex = iBarShift( + _Symbol, + _Period, + TimeCurrent() + ); + + // + int openTrades = CountOpenTrades(); + + // + // Loop through all Positions ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + datetime openTime = OrderOpenTime(); + int openBarIndex = iBarShift( + _Symbol, + _Period, + openTime + ); + string comment = OrderComment(); + + // + ENUM_X_SIGNAL_PROVIDER orderProvider = GetSignalProvider(comment); + bool isProviderVerified = + provider == X_UNKNOWN_PROVIDER ? + true : + orderProvider != X_UNKNOWN_PROVIDER + && orderProvider == provider + ; + + // + if ( + profit < 0 + && isProviderVerified + && openBarIndex - currentBarIndex >= passedCandles + // || ( + // profit > 0.5 + // && openBarIndex - currentBarIndex >= passedCandles - (passedCandles / 3) + // ) + ) { + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of Long Time issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + // else if ( + // openTrades > 0 + // && openBarIndex - currentBarIndex >= passedCandles - (passedCandles / 2) + // ) { + // result = CloseAllInProfitTrades() + // && CloseBiggestDrawDownTrade(); + // } + } + } + } + + // + return result; +} + +// +// Close all trades which passed Maximum Drawdown ... +bool CloseAllMaximumDrawDownPassedTrades( + const double maxDrDownPercentPerPTrade, + const ENUM_X_SIGNAL_TYPE type = X_SIGNAL_NONE, + const ENUM_X_SIGNAL_PROVIDER provider = X_UNKNOWN_PROVIDER +) { + // + if ( + initialBalance <= 0 + || maxDrDownPercentPerPTrade <= 0 + ) { + return false; + } + + // + // Retrieve Account Balance ... + double balance = AccountInfoDouble(ACCOUNT_BALANCE); + double maxAllowedDrawDown = -1 * (initialBalance * maxDrDownPercentPerPTrade); + + // + // Loop through all Positions ... + bool result = false; + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + string comment = OrderComment(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + bool isTypeVerified = + type == X_SIGNAL_NONE ? + true : + ( isLongOrder + && type == X_SIGNAL_LONG + ) || ( + !isLongOrder + && type == X_SIGNAL_SHORT + ) + ; + + // + ENUM_X_SIGNAL_PROVIDER orderProvider = GetSignalProvider(comment); + bool isProviderVerified = + provider == X_UNKNOWN_PROVIDER ? + true : + orderProvider != X_UNKNOWN_PROVIDER + && orderProvider == provider + ; + + // + if ( + profit < 0 + && isTypeVerified + && isProviderVerified + && MathAbs(profit) >= MathAbs(maxAllowedDrawDown) + ) { + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of Maximum DarwDown issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } + } + } + } + + // + return result; +} + +// +// Close All Trades Which Opens before Specified Length ... +bool CloseAllTradesWhichOpenInPastMarketLength( + const int marketLen +) { + // + bool result = false; + + // + if (marketLen <= 0) { + return result; + } + + // + int currentBarIndex = iBarShift( + _Symbol, + _Period, + TimeCurrent() + ); + + // + int openTrades = CountOpenTrades(); + + // + // Loop through all Positions ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + datetime openTime = OrderOpenTime(); + int openBarIndex = iBarShift( + _Symbol, + _Period, + openTime + ); + + // + if (openBarIndex <= currentBarIndex + marketLen) { + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // Since because of equity ... + // we have to ckose allpositions ... + bool isOrderClosed = OrderClose( + ticket, + lots, + closePrice, + clrYellow + ); + + // + if (isOrderClosed) { + // + LogMessage( + StringConcatenate( + "Order [", ticket, "] Closed because of Market Reverse issue ..." + ) + ); + } + + // + result = + result + || isOrderClosed; + } else if (openTrades > 0) { + // + // Close all InProfit Trdes and Biggest InDrawDown Trades ... + // result = CloseAllInProfitTrades(); + // && CloseBiggestDrawDownTrade(); + } + } + } + } + + // + return result; +} +// +// END Close Orders ... +// + +// +// START Modify Orders ... +// +// +void ModifyAllPriceLesserOpenTrades( + const XSignal &signal +) { + // + // Loop through all Open Trades ... + for (int i = OrdersTotal(); i >= 0; i--) { + // + // Check Order Selected or not ... + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { + // + // Check Order Symbol is same as Current Symbol ... + if (OrderSymbol() == _Symbol) { + // + double lots = OrderLots(); + int ticket = OrderTicket(); + double profit = OrderProfit(); + double stopLoss = OrderStopLoss(); + double openPrice = OrderOpenPrice(); + datetime openTime = OrderOpenTime(); + double takeProfit = OrderTakeProfit(); + + // + // find order type ... + bool isLongOrder = OrderType() == OP_BUY; + + // + // find close price ... + double closePrice = isLongOrder ? + SymbolInfoDouble(_Symbol, SYMBOL_BID) : + SymbolInfoDouble(_Symbol, SYMBOL_ASK); + + // + // When new Signal Comming with price less than + // currently open trade and tp less than currently + // open trade, this means a market change happens ... + // here we can Close InProfit Trades or Modify Trades TP ... + if ( + ( + openPrice < signal.entry + || MathAbs(openPrice - signal.entry) < 300 * _Point + ) + && takeProfit > signal.tp + ) { + bool result = OrderModify( + ticket, + openPrice, + signal.sl, + signal.tp, + clrYellow + ); + } + } + } + } +} + +// +void ModifyOpenTradesBasedOnCurrentTrade( + const XSignal &signal +) { + // + ModifyAllPriceLesserOpenTrades(signal); +} +// +// END Modify Orders ... +// +// +// END Orders Functions ... +// + +// +// START Signal Conditions ... +// +// +// Clear Signal Conditions ... +void ClearSignalConditions() { + // + ClearLongSignalConditions(); + ClearShortSignalConditions(); +} + +// +// Clear all Conditions Waiter for Long Signals ... +void ClearLongSignalConditions() { + // + ClearXLongSignalConditions(); + ClearXRLongSignalConditions(); + ClearXTPWLongSignalConditions(); +} + +// +// Clear all Conditions Waiter for Short Signals ... +void ClearShortSignalConditions() { + // + ClearXShortSignalConditions(); + ClearXRShortSignalConditions(); + ClearXTPWShortSignalConditions(); +} +// +// END Signal Conditions ... +// diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.x.signal.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.x.signal.lib.mq4 new file mode 100644 index 0000000..834ddb1 --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.x.signal.lib.mq4 @@ -0,0 +1,1063 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 X Signal Global Library +// --------------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes library ... +#include "../Libraries/x-saherelm.lib.mq4" + +// +// Includes Indicator library ... +#include "../Libraries/x-saherelm.indicator.lib.mq4" + +// +// Includes Models library ... +#include "../Libraries/x-saherelm.models.lib.mq4" + +// +// START Inputs ... +// +// +input string xStarter = "- X Signal Provider -"; // ---> X Signal Provider <--- + +// +input bool enableXSignalling = true; // X Signalling Enable + +// +input bool enableXLong = true; // X Signalling Enable Long +input bool enableXShort = true; // X Signalling Enable Short + +// +input double xShortR2R = 3; // X Short Risk To Reward Ratio +input double xShortLotsPerTradePercent = 0.0002; // X Lots Percent per Short Trades +input double xShortMaxDrawdownPerTradePercent = 0.4; // X Max Allowed DrawDown Percent per Short Trade + +// +input double xLongR2R = 3; // X Long Risk To Reward Ratio +input double xLongLotsPerTradePercent = 0.0002; // X Lots Percent per Short Trades +input double xLongMaxDrawdownPerTradePercent = 0.4; // X Max Allowed DrawDown Percent per Long Trade + +// +input double xSharpDetectorFactor = 700; // X Sharp Detection Factor + +// +input int xMaximumCandlesPerTrade = 206; // X Maximum Candles which a Trade can open + +// +input int xOscillatorLength = 7; // X Oscillator Length + +// +input double xPSarStep = 0.02; // X Parabolic Sar Step +input double xPSarMaximum = 0.2; // X Parabolic Sar Maximum + +// +input int xRangeMarketLength = 5; // X Range Detector Length + +// +input int xSwingLength = 7; // X Signal Swing Length +// +// END Inputs ... +// + +// +// START Global Requirement Functions ... +// +// +// X Based Signal Conditions ... +struct XSignalConditions { + datetime startTime; + datetime signalTime; + datetime entryTime; +}; + +// +struct XMarketState { + double psar; + double fast; + double slow; + double open; + double verifier; + double oscillator; + double oscillatorVerifier; +}; + +// +static XSignalConditions xLongConds; +static bool xCloseLongTrades = false; +static bool xWaitForLongSignals = true; + +// +static XSignalConditions xShortConds; +static bool xCloseShortTrades = false; +static bool xWaitForShortSignals = true; + +// +// Count Number of Closed Maximum DrawDown Trades ... +static int xFailedSignals = 0; + +// +datetime lastVerifierTouched; +// +// END Global Requirement Functions ... +// + +// +// START Functions ... +// +// +// Check and Fill Long and Short Signal Handlers ... +void CheckXSignalHandler( + const int bar_index +) { + // + // Check Market For Enable/Disable Signal Handlers ... + // Checking Market for Long Signals ... + // + if ( + !enableXSignalling + || !(enableXLong || enableXShort) + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + XOHCL candle = GetCandleModel(bar_index); + XOHCL pCandle = GetCandleModel(bar_index + 1); + XTPOWState tPowState = GetXTPowState( + bar_index + 1, + xSwingLength + ); + + // + XMarketState state = GetXMarketState( + bar_index + 1 + ); + + // + // Check Verifier Last Touched ... + bool isVerifierTouched = pCandle.high > state.verifier + && pCandle.low < state.verifier; + + // + // Disable Signals if a signal Failed ... + if (xFailedSignals) { + // + // TODO: Complete this ... + } + + // + // Enable Or Disable Signalling ... + if (isVerifierTouched) { + // + lastVerifierTouched = barTime; + + // + if (xWaitForLongSignals) { + xWaitForLongSignals = false; + } + + // + if (xWaitForShortSignals) { + xWaitForShortSignals = false; + } + } else { + // + int lastVerifierTouchedBarIndex = iBarShift( + _Symbol, + _Period, + lastVerifierTouched + ); + + // + int distance = MathAbs(lastVerifierTouchedBarIndex - bar_index); + + // + if ( + !xWaitForLongSignals + && distance > (xSwingLength * 2) + ) { + xWaitForLongSignals = true; + } + + // + if ( + !xWaitForShortSignals + && ( + distance > (xSwingLength * 2) + || ( + tPowState.powerDown > tPowState.powerUp + && tPowState.powerDown < 49 + ) + ) + ) { + xWaitForShortSignals = true; + } + } + + // + // Close All Long Open Trades ... + if ( + tPowState.powerDown > 55 + && tPowState.powerDown > tPowState.powerUp + ) { + // xCloseLongTrades = true; + } +} + +// +// Check and Fill Long Signal Conditions ... +void CheckXLongSignalConditions( + const int bar_index +) { + // + if ( + !enableXLong + || !enableXSignalling + || !xWaitForLongSignals + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + bool isCrossOver = false; + bool isCrossUnder = false; + + // + XMarketState cState = GetXMarketState(1); + XMarketState pState = GetXMarketState(2); + + // + isCrossUnder = + cState.fast < cState.slow + && !(pState.fast < pState.slow) + ; + + // + isCrossOver = + cState.fast > cState.slow + && !(pState.fast > pState.slow) + ; + + // + if ( + isCrossUnder + && xLongConds.startTime == 0 + ) { + // + xLongConds.startTime = barTime; + return; + } + + // + if ( + isCrossOver + && xLongConds.startTime > 0 + && xLongConds.signalTime == 0 + ) { + // + xLongConds.signalTime = barTime; + xLongConds.entryTime = barTime; + return; + } +} + +// +// Check and Fill Short Signal Conditions ... +void CheckXShortSignalConditions( + const int bar_index +) { + // + if ( + !enableXShort + || !enableXSignalling + || !xWaitForShortSignals + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + bool isCrossOver = false; + bool isCrossUnder = false; + + // + XMarketState cState = GetXMarketState(1); + XMarketState pState = GetXMarketState(2); + + // + isCrossUnder = + cState.fast < cState.slow + && !(pState.fast < pState.slow) + ; + + // + isCrossOver = + cState.fast > cState.slow + && !(pState.fast > pState.slow) + ; + + // + if ( + isCrossOver + && xShortConds.startTime == 0 + ) { + // + xShortConds.startTime = barTime; + return; + } + + // + if ( + isCrossUnder + && xShortConds.startTime > 0 + && xShortConds.signalTime == 0 + ) { + // + xShortConds.signalTime = barTime; + xShortConds.entryTime = barTime; + return; + } +} + +// +// Convert Long Signal Conditions to XSignal ... +XSignalRequest GenerateXSignal( + const ENUM_X_SIGNAL_TYPE type, // Signal Type ... + const string signalTag , // Signal Tag ... + const int bar_index +) { + // + XSignalRequest result = {}; + + // + result.hasSignal = false; + result.type = X_SIGNAL_NONE; + result.provider = X_UNKNOWN_PROVIDER; + + // + if ( + !enableXSignalling + || !(enableXLong || enableXShort) + ) { + return result; + } + + // + bool requestLong = type == X_SIGNAL_LONG; + + // + if (requestLong) { + // + if ( + !ValidateXLongConditions() + ) { + return result; + } + } else { + // + if ( + !ValidateXShortConditions() + ) { + return result; + } + } + + // + // Price Calculations ... + // + RefreshRates(); + + // + double askPrice = SymbolInfoDouble( + _Symbol, + SYMBOL_ASK + ); + + // + double bidPrice = SymbolInfoDouble( + _Symbol, + SYMBOL_BID + ); + + // + double entryPrice = requestLong ? + askPrice : + bidPrice; + + // + double exitPrice = requestLong ? + bidPrice : + askPrice; + + // + double priceGap = MathAbs(entryPrice - exitPrice); + + // + double ll = + // + GetMarketLowestLow( + bar_index, + xSwingLength + ) + ; + + // + double hh = + // + GetMarketHighestHigh( + bar_index, + xSwingLength + ) + ; + + // + double openPrice = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double closePrice = iClose( + _Symbol, + _Period, + bar_index + ); + + // + double risk = requestLong ? + MathMin(openPrice, closePrice) - ll : + hh - MathMax(openPrice, closePrice) + ; + + // + double reward = + requestLong ? + risk * xLongR2R : + risk * xShortR2R + ; + + // + double sl = requestLong ? + 0 : + 0; + double tp = requestLong ? + entryPrice + reward : + entryPrice - reward + ; + + // + XRState range = GetXRange( + bar_index, + xRangeMarketLength + ); + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + result.signal.tp = tp; + result.signal.sl = sl; + result.signal.type = type; + result.signal.time = barTime; + result.signal.tag = signalTag; + result.signal.symbol = _Symbol; + result.signal.entry = entryPrice; + result.signal.id = totalSignals + 1; + result.signal.provider = X_XXX_PROVIDER; + + // + result.hasSignal = true; + result.type = type; + result.provider = X_XXX_PROVIDER; + + // + return result; +} + +// +// Validate Signal Conditions ... +bool ValidateXLongConditions() { + // + if ( + !enableXLong + || !enableXSignalling + ) { + return false; + } + + // + bool isConditionsFilled = + xLongConds.startTime > 0 + && xLongConds.signalTime > 0 + && xLongConds.entryTime > 0 + ; + + // + bool isBLFilled = false; + if (isConditionsFilled) { + // + int startBarIndex = iBarShift( + _Symbol, + _Period, + xLongConds.startTime + ); + + // + int signalBarIndex = iBarShift( + _Symbol, + _Period, + xLongConds.signalTime + ); + + // + int entryBarIndex = iBarShift( + _Symbol, + _Period, + xLongConds.entryTime + ); + + // + isBLFilled = + // + xLongConds.signalTime > xLongConds.startTime + && xLongConds.entryTime >= xLongConds.signalTime + // && MathAbs(signalBarIndex - startBarIndex) >= 1 + ; + } + + // + bool result = + isBLFilled + && isConditionsFilled + && xWaitForLongSignals + ; + + // + // Since maybe Conditions Filled but + // Slope is Negative, for Handling Next Signals and + // Prevent from infinity loop, here we Clear Signal Conditions ... + if ( + !result + && isConditionsFilled + ) { + ClearXLongSignalConditions(); + } + + // + return result; +} + +// +// Validate Signal Conditions ... +bool ValidateXShortConditions() { + // + if ( + !enableXShort + || !enableXSignalling + ) { + return false; + } + + // + bool isConditionsFilled = + xShortConds.startTime > 0 + && xShortConds.signalTime > 0 + && xShortConds.entryTime > 0 + ; + + // + bool isBLFilled = false; + if (isConditionsFilled) { + // + int startBarIndex = iBarShift( + _Symbol, + _Period, + xShortConds.startTime + ); + + // + int signalBarIndex = iBarShift( + _Symbol, + _Period, + xShortConds.signalTime + ); + + // + int entryBarIndex = iBarShift( + _Symbol, + _Period, + xShortConds.entryTime + ); + + // + isBLFilled = + // + xShortConds.signalTime > xShortConds.startTime + && xShortConds.entryTime >= xShortConds.signalTime + ; + } + + // + bool result = + isBLFilled + && isConditionsFilled + && xWaitForShortSignals + ; + + // + // Since maybe Conditions Filled but + // Slope is Negative, for Handling Next Signals and + // Prevent from infinity loop, here we Clear Signal Conditions ... + if ( + !result + && isConditionsFilled + ) { + ClearXShortSignalConditions(); + } + + // + return result; +} + +// +// Clear Long Signal Conditions for New One ... +void ClearXLongSignalConditions() { + // + xLongConds.startTime = 0; + xLongConds.entryTime = 0; + xLongConds.signalTime = 0; +} + +// +// Clear Short Signal Conditions for New One ... +void ClearXShortSignalConditions() { + // + xShortConds.startTime = 0; + xShortConds.entryTime = 0; + xShortConds.signalTime = 0; +} + +// +// Check State for Long Signals ... +bool IsReadyForXSignals( + const XSignal &signal +) { + // + bool result = false; + + // + if ( + !enableXSignalling + || !(enableXLong || enableXShort) + ) { + return result; + } + + // + int signalBarIndex = iBarShift( + _Symbol, + _Period, + signal.time + ); + + // + // XOHCL candle = GetCandleModel(0); + XOHCL candle = GetCandleModel(signalBarIndex); + XOHCL pCandle = GetCandleModel(signalBarIndex + 1); + + // + // Retrieve Range ... + XRState range = GetXRange( + signalBarIndex, + xRangeMarketLength + ); + + // + // Retrive XMarket States ... + XMarketState xState0 = GetXMarketState(signalBarIndex); + XMarketState xState1 = GetXMarketState(signalBarIndex + 1); + XMarketState xState2 = GetXMarketState(signalBarIndex + 2); + XMarketState xStateLast = GetXMarketState(signalBarIndex + xSwingLength); + + // + // Retrieve Trend Powers ... + XTPOWState xTPow0 = GetXTPowState( + signalBarIndex, + xSwingLength + ); + XTPOWState xTPow1 = GetXTPowState( + signalBarIndex + 1, + xSwingLength + ); + + // + double hh = GetMarketHighestHigh( + signalBarIndex, + xSwingLength + ); + double ll = GetMarketLowestLow( + signalBarIndex, + xSwingLength + ); + double diffChange = (hh - ll); + bool isBigSharpOccured = + diffChange > (xSharpDetectorFactor * _Point) + ; + + // + bool isPSarVerified = false; + bool isTPowVerified = false; + bool isStateVerified = false; + bool isPriceVerified = false; + + // + // Verify Long Signals ... + if (signal.type == X_SIGNAL_LONG) { + // + // Get Price Verification for Long ... + isPriceVerified = + // + // Starter ... + true + // + && !isBigSharpOccured + // + && signal.entry < hh + // + // && signal.entry < range.hh + // && signal.entry > range.mid + // // + // && candle.high > xState0.verifier + // && signal.entry > xState0.verifier + // + // && pCandle.low != ll + && pCandle.high != hh + ; + + // + int above20TPowers = 0; + double signalSlope = 0; + int tPowUnverifyConditions = 0; + int tPowUnverifyConditionsIdx = 0; + for (int i = signalBarIndex; i < signalBarIndex + xSwingLength; i++) { + // + XTPOWState iTPowState = GetXTPowState( + i, + xSwingLength + ); + + // + // Calculate Signal Slope ... + if (i == signalBarIndex) { + // + signalSlope = iTPowState.signal; + } else if (i == signalBarIndex + 1) { + // + signalSlope = GetSlope( + 1, + iTPowState.signal, + 2, + signalSlope + ); + } + + // + if ( + iTPowState.powerUp > iTPowState.powerDown + && MathMax(iTPowState.powerUp, iTPowState.powerDown) > 20 + ) { + above20TPowers++; + } + + // + if (tPowUnverifyConditionsIdx < 3) { + // + if ( + iTPowState.powerUp < iTPowState.powerDown + || iTPowState.signal > MathMax(iTPowState.powerUp, iTPowState.powerDown) + ) { + tPowUnverifyConditions++; + } + + // + tPowUnverifyConditionsIdx++; + } + } + + // + isTPowVerified = + above20TPowers > 1 + && tPowUnverifyConditions == 0 + ; + + // + isPSarVerified = + xState0.psar < signal.entry + && xState0.psar < candle.low; + + // + isStateVerified = + // + // Start ... + true + // + // && xState0.open < xState0.slow + ; + + // + result = + // + // Starter ... + true + // + && isPSarVerified + // + && isTPowVerified + // + && isStateVerified + // + && isPriceVerified + ; + } else + // + // Verify Short Signals ... + if (signal.type == X_SIGNAL_SHORT) { + // + isPSarVerified = + xState0.psar > signal.entry + && xState0.psar > candle.high + ; + + // + // Get Price Verification for Short ... + isPriceVerified = + // + // Starter ... + true + // + && !isBigSharpOccured + // + && signal.entry > ll + && pCandle.low != ll + ; + + // + int above20TPowers = 0; + double signalSlope = 0; + int tPowUnverifyConditions = 0; + int tPowUnverifyConditionsIdx = 0; + for (int i = signalBarIndex; i < signalBarIndex + xSwingLength; i++) { + // + XTPOWState iTPowState = GetXTPowState( + i, + xSwingLength + ); + + // + // Calculate Signal Slope ... + if (i == signalBarIndex) { + // + signalSlope = iTPowState.signal; + } else if (i == signalBarIndex + 1) { + // + signalSlope = GetSlope( + 1, + iTPowState.signal, + 2, + signalSlope + ); + } + + // + if ( + iTPowState.powerUp > iTPowState.powerDown + && MathMax(iTPowState.powerUp, iTPowState.powerDown) > 20 + ) { + above20TPowers++; + } + + // + if (tPowUnverifyConditionsIdx < 3) { + // + if ( + iTPowState.powerUp > iTPowState.powerDown + || iTPowState.signal < MathMax(iTPowState.powerUp, iTPowState.powerDown) + ) { + tPowUnverifyConditions++; + } + + // + tPowUnverifyConditionsIdx++; + } + } + + // + isTPowVerified = + above20TPowers < 1 + && tPowUnverifyConditions == 0 + && MathAbs(xTPow0.powerUp - xTPow0.powerDown) > 50 * _Point + ; + + // + isStateVerified = + // + // Start ... + true + // + // && (xStateLast.verifier - xState0.verifier) >= 0 + // + && xState0.verifier > signal.entry + // + && MathAbs(signal.entry - xState0.verifier) < (xSharpDetectorFactor * _Point) + ; + + // + result = + // + // Starter Condition ... + true + // + && isPSarVerified + // + && isTPowVerified + // + && isStateVerified + // + && isPriceVerified + ; + } + + // + return result; +} +// +// END Functions ... +// + +// +// START Data Provider ... +// +XMarketState GetXMarketState( + const int bar_index +) { + // + XMarketState result = {}; + + // + double fast = GetMA( + bar_index, + xSwingLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double open = GetMA( + bar_index, + xSwingLength, + 0, + MODE_SMA, + PRICE_OPEN + ); + + // + double slow = GetMA( + bar_index, + xSwingLength * 2, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double oscillator = GetMA( + bar_index, + xSwingLength, + 0, + MODE_EMA, + PRICE_CLOSE + ); + + // + double oscillatorVerifier = GetMA( + bar_index, + xSwingLength, + 0, + MODE_EMA, + PRICE_WEIGHTED + ); + + // + int dailyCount = GetDailyCandleCount(); + double verifier = GetMA( + bar_index, + dailyCount, + 0, + MODE_EMA, + PRICE_MEDIAN + ); + + // + double psar = iSAR( + _Symbol, + _Period, + xPSarStep, + xPSarMaximum, + bar_index + ); + + // + result.psar = psar; + result.fast = fast; + result.open = open; + result.slow = slow; + result.verifier = verifier; + result.oscillator = oscillator; + result.oscillatorVerifier = oscillatorVerifier; + + // + return result; +} +// +// END Data Provider ... +// diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xr.signal.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xr.signal.lib.mq4 new file mode 100644 index 0000000..53785cf --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xr.signal.lib.mq4 @@ -0,0 +1,1142 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 X Signal Global Library +// --------------------------------------------------- +// saherelm useful tools and definitions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes library ... +#include "../Libraries/x-saherelm.lib.mq4" + +// +// Includes Indicator library ... +#include "../Libraries/x-saherelm.indicator.lib.mq4" + +// +// Includes Models library ... +#include "../Libraries/x-saherelm.models.lib.mq4" + +// +// START Inputs ... +// +// +input string xRStarter = "- XR Signal Provider -"; // --> XR Signal Provider <-- + +// +input bool enableXRSignalling = false; // XR Signalling Enable + +// +input bool enableXRLong = true; // XR Signalling Enable Long +input bool enableXRShort = true; // XR Signalling Enable Short + +// +input double xRShortR2R = 1.5; // XR Short Risk To Reward Ratio +input double xRShortLotsPerTradePercent = 0.0002; // XR Lots Percent per Short Trades +input double xRShortMaxDrawdownPerTradePercent = 0.15; // XR Max Allowed DrawDown Percent per Short Trade + +// +input double xRLongR2R = 1.5; // XR Long Risk To Reward Ratio +input double xRLongLotsPerTradePercent = 0.0002; // XR Lots Percent per Short Trades +input double xRLongMaxDrawdownPerTradePercent = 0.15; // XR Max Allowed DrawDown Percent per Long Trade + +// +input int xRMaximumCandlesPerTrade = 96; // XR Maximum Candles which a Trade can open + +// +input int xRSwingLength = 48; // XR Swing Length +// +// END Inputs ... +// + +// +input double xRSharpDetectionFactor = 1350; // XR Sharp Detection Factor + +// +// START Global Requirement Functions ... +// +// +// XR Market State ... +struct XRMarketState { + // + double fast; + double slow; + double open; + + // + double range; + double rangeFast; + double rangeSlow; + double rangeOpen; + + // + double verifier; +}; + +// +// XR Based Signal Conditions ... +struct XRSignalConditions { + datetime startTime; + datetime signalTime; + datetime entryTime; +}; + +// +static XRSignalConditions xRLongConds; +static bool xRCloseLongTrades = false; +static bool xRWaitForLongSignals = true; + +// +static XRSignalConditions xRShortConds; +static bool xRCloseShortTrades = false; +static bool xRWaitForShortSignals = true; + +// +// Count Number of Closed Maximum DrawDown Trades ... +static int xRFailedSignals = 0; + +// +double xRMaximumDrawDown = 0; + +// +int fastLength = 0; +int slowLength = 0; + +// +int verifierLength = 0; + +// +int rangeFastLength = 0; +int rangeSlowLength = 0; +// +// END Global Requirement Functions ... +// + +// +// START Functions ... +// +// +// Check and Fill Long and Short Signal Handlers ... +void CheckXRSignalHandler( + const int bar_index +) { + // + // Check Market For Enable/Disable Signal Handlers ... + // Checking Market for Long Signals ... + + // + if ( + !enableXRSignalling + || !(enableXRLong || enableXRShort) + ) { + return; + } +} + +// +// Check and Fill Long Signal Conditions ... +void CheckXRLongSignalConditions( + const int bar_index +) { + // + if ( + !enableXRLong + || !enableXRSignalling + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + // Read Prices ... + XPrice prices = GetPrice(); + + // + // Read XPVTState ... + XPvtState pvt0 = GetPVTState( + bar_index, + xRSwingLength + ); + + // + // Double Length Pivots ... + XPvtState dblPvt0 = GetPVTState( + bar_index, + (xRSwingLength * 2) + ); + + // + // Reading Required Candles ... + XOHCL candle0 = GetCandleModel(bar_index); + XOHCL candle1 = GetCandleModel(bar_index + 1); + XOHCL candle2 = GetCandleModel(bar_index + 2); + XOHCL candle3 = GetCandleModel(bar_index + 3); + + // + // Reding Required XRMarketStates ... + XRMarketState state0 = GetXRMarketState(bar_index); + XRMarketState state1 = GetXRMarketState(bar_index + 1); + XRMarketState state2 = GetXRMarketState(bar_index + 2); + XRMarketState state3 = GetXRMarketState(bar_index + 3); + + // + // Reading required XRangeStates ... + XRState range0 = ReadXRange( + bar_index + xRSwingLength, + xRSwingLength + ); + XRState range1 = ReadXRange( + bar_index + xRSwingLength + 1, + xRSwingLength + ); + XRState range2 = ReadXRange( + bar_index + xRSwingLength + 2, + xRSwingLength + ); + + // + XRState cRange0 = ReadXRange( + bar_index, + xRSwingLength + ); + + // + // Validate Farest Range Values ... + if ( + range2.hh == 0 + || + range2.ll == 0 + || + range2.mid == 0 + ) { + return; + } + + // + // Reading Required XTPowStates ... + XTPOWState tPow0 = GetXTPowState( + bar_index, + xRSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + bar_index + 1, + xRSwingLength + ); + XTPOWState tPow2 = GetXTPowState( + bar_index + 2, + xRSwingLength + ); + + // + // if state verifier below range middle + // this means market is bullish ... + // + // if state verifier above range middle + // this means market is bearish ... + // + + // + bool isMarketBullish = + state0.verifier < range0.mid + && state1.verifier < range1.mid; + bool isMarketBearish = + state0.verifier > range0.mid + && state1.verifier > range1.mid; + bool isMarketGoingBullish = + state0.verifier > range0.mid + && !(state1.verifier > range1.mid); + bool isMarketGoingBearish = + state0.verifier < range0.mid + && !(state1.verifier < range1.mid); + + // + // Check Highest High Conditions ... + bool isHHVerified = + !( + pvt0.hh == dblPvt0.hh + ) + ; + + // + int sharpDetectionLength = 7; + double sharpDetectionValue = xRSharpDetectionFactor * _Point; + + // + int sharpHHIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + sharpDetectionLength, + bar_index + ); + double sharpHH = iHigh( + _Symbol, + _Period, + sharpHHIdx + ); + + // + int sharpLLIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + sharpDetectionLength, + bar_index + ); + double sharpLL = iLow( + _Symbol, + _Period, + sharpLLIdx + ); + + // + double sharpDiff = sharpHH - sharpLL; + bool isSharpOccered = + sharpDiff > sharpDetectionValue; + + // + XRMarketState lastState = GetXRMarketState( + bar_index + sharpDetectionLength + ); + + // + double stateFSDiff = (state0.fast - state0.slow) - (lastState.fast - lastState.slow); + + // + // Start Calculating Long Conditions ... + bool longCondition1 = + // + // Starter ... + true + // + && isMarketBullish + // + && + ( + candle2.high < range2.mid + || ( + candle2.high > range2.mid + && candle2.low < range2.mid + ) + ) + && candle1.low > range1.mid + ; + + // + if ( + // + ( + longCondition1 + ) + // + && xRLongConds.startTime == 0 + && xRLongConds.entryTime == 0 + && xRLongConds.signalTime == 0 + ) { + // + xRLongConds.startTime = barTime; + xRLongConds.entryTime = barTime; + xRLongConds.signalTime = barTime; + + // + return; + } +} + +// +// Check and Fill Short Signal Conditions ... +void CheckXRShortSignalConditions( + const int bar_index +) { + // + if ( + !enableXRShort + || !enableXRSignalling + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + // Read Prices ... + XPrice prices = GetPrice(); + + // + // Read XPVTState ... + XPvtState pvt0 = GetPVTState( + bar_index, + xRSwingLength + ); + + // + // Double Length Pivots ... + XPvtState dblPvt0 = GetPVTState( + bar_index, + (xRSwingLength * 2) + ); + + // + // Reading Required Candles ... + XOHCL candle0 = GetCandleModel(bar_index); + XOHCL candle1 = GetCandleModel(bar_index + 1); + XOHCL candle2 = GetCandleModel(bar_index + 2); + XOHCL candle3 = GetCandleModel(bar_index + 3); + + // + // Reding Required XRMarketStates ... + XRMarketState state0 = GetXRMarketState(bar_index); + XRMarketState state1 = GetXRMarketState(bar_index + 1); + XRMarketState state2 = GetXRMarketState(bar_index + 2); + XRMarketState state3 = GetXRMarketState(bar_index + 3); + + // + // Reading required XRangeStates ... + XRState range0 = ReadXRange( + bar_index + xRSwingLength, + xRSwingLength + ); + XRState range1 = ReadXRange( + bar_index + xRSwingLength + 1, + xRSwingLength + ); + XRState range2 = ReadXRange( + bar_index + xRSwingLength + 2, + xRSwingLength + ); + + // + XRState cRange0 = ReadXRange( + bar_index, + xRSwingLength + ); + + // + // Validate Farest Range Values ... + if ( + range2.hh == 0 + || + range2.ll == 0 + || + range2.mid == 0 + ) { + return; + } + + // + // Reading Required XTPowStates ... + XTPOWState tPow0 = GetXTPowState( + bar_index, + xRSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + bar_index + 1, + xRSwingLength + ); + XTPOWState tPow2 = GetXTPowState( + bar_index + 2, + xRSwingLength + ); + + // + // if state verifier below range middle + // this means market is bullish ... + // + // if state verifier above range middle + // this means market is bearish ... + // + + // + bool isMarketBullish = + state0.verifier < range0.mid + && state1.verifier < range1.mid; + bool isMarketBearish = + state0.verifier > range0.mid + && state1.verifier > range1.mid; + bool isMarketGoingBullish = + state0.verifier > range0.mid + && !(state1.verifier > range1.mid); + bool isMarketGoingBearish = + state0.verifier < range0.mid + && !(state1.verifier < range1.mid); + + // + // Check Highest High Conditions ... + bool isHHVerified = + !( + pvt0.hh == dblPvt0.hh + ) + ; + + // + int sharpDetectionLength = 7; + double sharpDetectionValue = xRSharpDetectionFactor * _Point; + + // + int sharpHHIdx = iHighest( + _Symbol, + _Period, + MODE_HIGH, + sharpDetectionLength, + bar_index + ); + double sharpHH = iHigh( + _Symbol, + _Period, + sharpHHIdx + ); + + // + int sharpLLIdx = iLowest( + _Symbol, + _Period, + MODE_LOW, + sharpDetectionLength, + bar_index + ); + double sharpLL = iLow( + _Symbol, + _Period, + sharpLLIdx + ); + + // + double sharpDiff = sharpHH - sharpLL; + bool isSharpOccered = + sharpDiff > sharpDetectionValue; + + // + XRMarketState lastState = GetXRMarketState( + bar_index + sharpDetectionLength + ); + + // + double stateFSDiff = (state0.fast - state0.slow) - (lastState.fast - lastState.slow); + + // + // Start Calculating Long Conditions ... + bool shortCondition1 = + // + // Starter ... + true + // + && isMarketBearish + // + && + ( + candle2.low > range2.mid + || ( + candle2.high > range2.mid + && candle2.low < range2.mid + ) + ) + && candle1.high < range1.mid + ; + + // + if ( + // + ( + shortCondition1 + ) + // + && xRShortConds.startTime == 0 + && xRShortConds.entryTime == 0 + && xRShortConds.signalTime == 0 + ) { + // + xRShortConds.startTime = barTime; + xRShortConds.entryTime = barTime; + xRShortConds.signalTime = barTime; + + // + return; + } +} + +// +// Convert Long Signal Conditions to XSignal ... +XSignalRequest GenerateXRSignal( + const ENUM_X_SIGNAL_TYPE type, // Signal Type ... + const string signalTag , // Signal Tag ... + const int bar_index +) { + // + XSignalRequest result = {}; + + // + result.hasSignal = false; + result.type = X_SIGNAL_NONE; + result.provider = X_UNKNOWN_PROVIDER; + + // + if ( + !enableXRSignalling + || !(enableXRLong || enableXRShort) + ) { + return result; + } + + // + bool requestLong = type == X_SIGNAL_LONG; + + // + if (requestLong) { + // + if ( + !ValidateXRLongConditions() + ) { + return result; + } + } else { + // + if ( + !ValidateXRShortConditions() + ) { + return result; + } + } + + // + // Price Calculations ... + XPvtState pvts = GetPVTState( + bar_index, + xRSwingLength + ); + XPrice prices = GetPrice(); + + // + double entryPrice = requestLong ? + prices.longEntry : + prices.shortEntry + ; + + // + double openPrice = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double closePrice = iClose( + _Symbol, + _Period, + bar_index + ); + + // + double risk = requestLong ? + MathMin(openPrice, closePrice) - pvts.ll : + pvts.hh - MathMax(openPrice, closePrice); + if (risk <= 0) { + // + risk = requestLong ? + MathAbs(pvts.hh - entryPrice) : + MathAbs(pvts.ll - entryPrice) + ; + } + + // + double reward = + requestLong ? + risk * xRLongR2R : + risk * xRShortR2R + ; + + // + double sl = requestLong ? + 0 : + 0; + + // + double tp = requestLong ? + entryPrice + reward : + entryPrice - reward + ; + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + result.signal.tp = tp; + result.signal.sl = sl; + result.signal.type = type; + result.signal.time = barTime; + result.signal.tag = signalTag; + result.signal.symbol = _Symbol; + result.signal.entry = entryPrice; + result.signal.id = totalSignals + 1; + result.signal.provider = X_XR_PROVIDER; + + // + result.hasSignal = true; + result.type = type; + result.provider = X_XR_PROVIDER; + + // + return result; +} + +// +// Validate Long Signal Conditions ... +bool ValidateXRLongConditions() { + // + if ( + !enableXRLong + || !enableXRSignalling + ) { + return false; + } + + // + bool isConditionsFilled = + xRLongConds.startTime > 0 + && xRLongConds.signalTime > 0 + && xRLongConds.entryTime > 0 + ; + + // + bool isBLFilled = false; + if (isConditionsFilled) { + // + isBLFilled = + // + xRLongConds.signalTime >= xRLongConds.startTime + && xRLongConds.entryTime >= xRLongConds.signalTime + ; + } + + // + bool result = + isBLFilled + && isConditionsFilled + && xRWaitForLongSignals + ; + + // + // Since maybe Conditions Filled but + // Slope is Negative, for Handling Next Signals and + // Prevent from infinity loop, here we Clear Signal Conditions ... + if ( + !result + && isConditionsFilled + ) { + ClearXRLongSignalConditions(); + } + + // + return result; +} + +// +// Validate Short Signal Conditions ... +bool ValidateXRShortConditions() { + // + if ( + !enableXRShort + || !enableXRSignalling + ) { + return false; + } + + // + bool isConditionsFilled = + xRShortConds.startTime > 0 + && xRShortConds.signalTime > 0 + && xRShortConds.entryTime > 0 + ; + + // + bool isBLFilled = false; + if (isConditionsFilled) { + // + isBLFilled = + // + xRShortConds.signalTime >= xRShortConds.startTime + && xRShortConds.entryTime >= xRShortConds.signalTime + ; + } + + // + bool result = + isBLFilled + && isConditionsFilled + && xRWaitForShortSignals + ; + + // + // Since maybe Conditions Filled but + // Slope is Negative, for Handling Next Signals and + // Prevent from infinity loop, here we Clear Signal Conditions ... + if ( + !result + && isConditionsFilled + ) { + ClearXRShortSignalConditions(); + } + + // + return result; +} + +// +// Clear Long Signal Conditions for New One ... +void ClearXRLongSignalConditions() { + // + xRLongConds.startTime = 0; + xRLongConds.signalTime = 0; + xRLongConds.entryTime = 0; +} + +// +// Clear Short Signal Conditions for New One ... +void ClearXRShortSignalConditions() { + // + xRShortConds.startTime = 0; + xRShortConds.signalTime = 0; + xRShortConds.entryTime = 0; +} + +// +// Check State for Long Signals ... +bool IsReadyForXRSignals( + const XSignal &signal +) { + // + bool result = false; + + // + if ( + !enableXRSignalling + || !(enableXRLong || enableXRShort) + ) { + return result; + } + + // + // Find Signal Bar Index ... + int signalBarIndex = iBarShift( + _Symbol, + _Period, + signal.time + ); + + // + // Read Prices ... + XPrice prices = GetPrice(); + + // + // Read XPVTState ... + XPvtState pvt0 = GetPVTState( + signalBarIndex, + xRSwingLength + ); + + // + // Reading Required Candles ... + XOHCL candle0 = GetCandleModel(signalBarIndex); + XOHCL candle1 = GetCandleModel(signalBarIndex + 1); + XOHCL candle2 = GetCandleModel(signalBarIndex + 2); + XOHCL candle3 = GetCandleModel(signalBarIndex + 3); + + // + // Reding Required XRMarketStates ... + XRMarketState state0 = GetXRMarketState(signalBarIndex); + XRMarketState state1 = GetXRMarketState(signalBarIndex + 1); + XRMarketState state2 = GetXRMarketState(signalBarIndex + 2); + XRMarketState state3 = GetXRMarketState(signalBarIndex + 3); + + // + // Reading required XRangeStates ... + XRState range0 = ReadXRange( + signalBarIndex + xRSwingLength, + xRSwingLength + ); + XRState range1 = ReadXRange( + signalBarIndex + xRSwingLength + 1, + xRSwingLength + ); + XRState range2 = ReadXRange( + signalBarIndex + xRSwingLength + 2, + xRSwingLength + ); + + // + // Reading Required XTPowStates ... + XTPOWState tPow0 = GetXTPowState( + signalBarIndex, + xRSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + signalBarIndex + 1, + xRSwingLength + ); + XTPOWState tPow2 = GetXTPowState( + signalBarIndex + 2, + xRSwingLength + ); + + // + double hhllDiff = MathAbs(pvt0.hh - pvt0.ll); + double sharpDetectionValue = xRSharpDetectionFactor * _Point; + bool isSharpOccured = hhllDiff > sharpDetectionValue; + + // + // Calculate State Min Max Diff ... + // + double state0Min = MathMin(state0.fast, state0.slow); + state0Min = MathMin(state0Min, state0.open); + state0Min = MathMin(state0Min, state0.rangeFast); + state0Min = MathMin(state0Min, state0.rangeSlow); + state0Min = MathMin(state0Min, state0.rangeOpen); + state0Min = MathMin(state0Min, state0.verifier); + + // + double state0Max = MathMax(state0.fast, state0.slow); + state0Max = MathMax(state0Max, state0.open); + state0Max = MathMax(state0Max, state0.rangeFast); + state0Max = MathMax(state0Max, state0.rangeSlow); + state0Max = MathMax(state0Max, state0.rangeOpen); + state0Max = MathMax(state0Max, state0.verifier); + + // + double state0MinMaxDiff = (state0Max - state0Min); + + // + bool isTPowValid = false; + bool isStateValid = false; + bool isRangeValid = false; + + // + // Verify Long Signals ... + if (signal.type == X_SIGNAL_LONG) { + // + // Retrieve TPow Verifications ... + isTPowValid = + // + // Starter ... + true + ; + + // + // Retrieve XMarket Verifications ... + isStateValid = + // + // Starter ... + true + // + // && !(state0MinMaxDiff > sharpDetectionValue) + ; + + // + // Retrieve XRange Verifications ... + isRangeValid = + // + // Starter ... + true + ; + + // + result = + // + // Starter ... + true + // + && isTPowValid + && isStateValid + && isRangeValid + ; + } else + // + // Verify Short Signals ... + if (signal.type == X_SIGNAL_SHORT) { + // + // Retrieve TPow Verifications ... + isTPowValid = + // + // Starter ... + true + ; + + // + // Retrieve XMarket Verifications ... + isStateValid = + // + // Starter ... + true + ; + + // + // Retrieve XRange Verifications ... + isRangeValid = + // + // Starter ... + true + ; + + // + result = + // + // Starter ... + true + // + && isTPowValid + && isStateValid + && isRangeValid + ; + } + + // + return result; +} +// +// END Functions ... +// + +// +// START Data Providers ... +// +// +XRMarketState GetXRMarketState( + const int bar_index +) { + // + XRMarketState result = {}; + + // + // Calculate Market Lengths ... + + // + if (fastLength == 0) { + fastLength = xRSwingLength; + } + + // + if (slowLength == 0) { + slowLength = xRSwingLength * 2; + } + + // + if (verifierLength == 0) { + verifierLength = (GetDailyCandleCount() * 2); + } + + // + if (rangeFastLength == 0) { + rangeFastLength = (int)(verifierLength / 2); + } + + // + if (rangeSlowLength == 0) { + rangeSlowLength = verifierLength; + } + + // + // Reading Values ... + + // + double fast = GetMA( + bar_index, + fastLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double slow = GetMA( + bar_index, + slowLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double open = GetMA( + bar_index, + fastLength, + 0, + MODE_SMA, + PRICE_OPEN + ); + + // + double rangeFast = GetMA( + bar_index, + rangeFastLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double rangeSlow = GetMA( + bar_index, + rangeSlowLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double rangeOpen = GetMA( + bar_index, + rangeFastLength, + 0, + MODE_SMA, + PRICE_OPEN + ); + + // + double verifier = GetMA( + bar_index, + verifierLength, + 0, + MODE_EMA, + PRICE_MEDIAN + ); + + // + // Filling Result ... + result.fast = fast; + result.slow = slow; + result.open = open; + result.verifier = verifier; + result.rangeFast = rangeFast; + result.rangeSlow = rangeSlow; + result.rangeOpen = rangeOpen; + + // + return result; +} +// +// END Data Providers ... +// \ No newline at end of file diff --git a/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xtpw.signal.lib.mq4 b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xtpw.signal.lib.mq4 new file mode 100644 index 0000000..4bf02ce --- /dev/null +++ b/XAUUSD-15M-V1.0/MQ4/Libraries/x-saherelm.xtpw.signal.lib.mq4 @@ -0,0 +1,1332 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL4 XTPW Signal Global Library +// --------------------------------------------------- +// XSaherElm EA Signal Provider based on +// XTPow Indicator... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes library ... +#include "../Libraries/x-saherelm.lib.mq4" + +// +// Includes Indicator library ... +#include "../Libraries/x-saherelm.indicator.lib.mq4" + +// +// Includes Models library ... +#include "../Libraries/x-saherelm.models.lib.mq4" + +// +// START Inputs ... +// +// +input string xTPWStarter = "- XTPW Signal Provider -"; // ---> XTPW Signal Provider <--- + +// +input bool enableXTPWSignalling = true; // XTPW Signalling Enable + +// +input bool enableXTPWLong = true; // XTPW Signalling Enable Long +input bool enableXTPWShort = true; // XTPW Signalling Enable Short + +// +input double xTPWShortR2R = 2; // XTPW Short Risk To Reward Ratio +input double xTPWShortLotsPerTradePercent = 0.0002; // XTPW Lots Percent per Short Trades +input double xTPWShortMaxDrawdownPerTradePercent = 0.3; // XTPW Max Allowed DrawDown Percent per Short Trade + +// +input double xTPWLongR2R = 2; // XTPW Long Risk To Reward Ratio +input double xTPWLongLotsPerTradePercent = 0.0002; // XTPW Lots Percent per Short Trades +input double xTPWLongMaxDrawdownPerTradePercent = 0.3; // XTPW Max Allowed DrawDown Percent per Long Trade + +// +input int xTPWMaximumCandlesPerTrade = 206; // XTPW Maximum Candles which a Trade can open + +// +input double xTPWPSarStep = 0.02; // XTPW Parabolic Sar Step +input double xTPWPSarMaximum = 0.2; // XTPW Parabolic Sar Maximum + +// +input int xTPWSwingLength = 7; // XTPW Signal Swing Length +// +// END Inputs ... +// + +// +input double xTPWSharpDetectionFactor = 650; // XTPW Sharp Detection Factor + +// +// START Global Requirement Functions ... +// +// +// XTPW Based Signal Conditions ... +struct XTPWSignalConditions { + datetime startTime; + datetime signalTime; + datetime entryTime; +}; + +// +struct XTPWMarketState { + // + double psar; + + // + double scFast; + double scSlow; + double scWeight; + + // + double mcFast; + double mcSlow; + double mcWeight; + + // + double lcFast; + double lcSlow; + double lcWeight; +}; + +// +struct XLHS { + // + double scHH; + double scLL; + + // + double mcHH; + double mcLL; + + // + double lcHH; + double lcLL; +}; + +// +static XTPWSignalConditions xTPWLongConds; +static bool xTPWCloseLongTrades = false; +static bool xTPWWaitForLongSignals = true; + +// +static XTPWSignalConditions xTPWShortConds; +static bool xTPWCloseShortTrades = false; +static bool xTPWWaitForShortSignals = true; + +// +// Count Number of Closed Maximum DrawDown Trades ... +static int xTPWFailedSignals = 0; + +// +double tPowerVerifier = 20; +double tPowerMaxVerifier = 55; + +// +int scFastLength = 0; +int scSlowLength = 0; + +// +int mcFastLength = 0; +int mcSlowLength = 0; + +// +int lcFastLength = 0; +int lcSlowLength = 0; + +// +datetime lastTurnOffLongTradesTime; +datetime lastTurnOffShortTradesTime; +// +// END Global Requirement Functions ... +// + +// +// START Functions ... +// +// +// Check and Fill Long and Short Signal Handlers ... +void CheckXTPWSignalHandler( + const int bar_index +) { + // + // Check Market For Enable/Disable Signal Handlers ... + // Checking Market for Long Signals ... + + // + if ( + !enableXTPWSignalling + || !(enableXTPWLong || enableXTPWShort) + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + XOHCL candle0 = GetCandleModel(bar_index); + XOHCL candle1 = GetCandleModel(bar_index + 1); + XOHCL candle2 = GetCandleModel(bar_index + 1); + + // + XTPOWState tPow0 = GetXTPowState( + bar_index, + xTPWSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + bar_index + 1, + xTPWSwingLength + ); + XTPOWState tPow2 = GetXTPowState( + bar_index + 2, + xTPWSwingLength + ); + + // + XTPWMarketState state0 = GetXTPWMarketState( + bar_index + ); + XTPWMarketState state1 = GetXTPWMarketState( + bar_index + 1 + ); + XTPWMarketState state2 = GetXTPWMarketState( + bar_index + 2 + ); + + // // + // // Disable Long Conditions ... + // if ( + // xTPWWaitForLongSignals + // && + // ( + // isRangeCrossOverRangeWeight + // || + // isRangeCrossUnderRangeWeight + // || + // isTPowUpperAboveMaxVerifier + // ) + // ) { + // // + // xTPWWaitForLongSignals = false; + // lastTurnOffLongTradesTime = barTime; + // } + + // // + // // Enable Long Conditions ... + // if ( + // !xTPWWaitForLongSignals + // && lastTurnOffLongTradesTime > 0 + // && ( + // // isFastCrossOverSlow + // // || + // // isFastCrossUnderSlow + // isRangeCrossOverRangeWeight + // || + // isRangeCrossUnderRangeWeight + // || + // isTPowUpperBelowMaxVerifier + // ) + // ) { + // // + // // Find Last Turn Off Bar Index ... + // int lastTurnOffLongTradesBarIndex = iBarShift( + // _Symbol, + // _Period, + // lastTurnOffLongTradesTime + // ); + + // // + // // the Distance must be bigger than market length ... + // if (MathAbs(lastTurnOffLongTradesBarIndex - bar_index) > xTPWSwingLength) { + // // + // xTPWWaitForLongSignals = true; + // lastTurnOffLongTradesTime = 0; + // } + // } +} + +// +// Check and Fill Long Signal Conditions ... +void CheckXTPWLongSignalConditions( + const int bar_index +) { + // + if ( + !enableXTPWLong + || !enableXTPWSignalling + || !xTPWWaitForLongSignals + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + // Retrieve TPow States ... + XTPOWState tPow0 = GetXTPowState( + bar_index, + xTPWSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + bar_index + 1, + xTPWSwingLength + ); + XTPOWState tPow2 = GetXTPowState( + bar_index + 2, + xTPWSwingLength + ); + + // + // Retrieve TPowMarket State ... + XTPWMarketState state0 = GetXTPWMarketState( + bar_index + ); + XTPWMarketState state1 = GetXTPWMarketState( + bar_index + 1 + ); + XTPWMarketState state2 = GetXTPWMarketState( + bar_index + 2 + ); + + // + // Retrieve XPrice Model ... + XPrice prices = GetPrice(); + + // + // Retrieve Candles ... + XOHCL candle0 = GetCandleModel(bar_index); + XOHCL candle1 = GetCandleModel(bar_index + 1); + XOHCL candle2 = GetCandleModel(bar_index + 2); + + // + XLHS lhs = GetXTPWLHS(bar_index); + + // + bool isHHSame = + lhs.scHH == lhs.mcHH + && lhs.mcHH == lhs.lcHH + ; + + // + bool isLLSame = + lhs.scLL == lhs.mcLL + && lhs.mcLL == lhs.lcLL + ; + + // + bool startCondition = false; + bool signalCondition = false; + bool entryCondition = false; + + // + bool longCondition1 = + // + true + // + && !isHHSame + // + && !( + lhs.scLL == lhs.mcLL + ) + // + && !( + lhs.scHH == lhs.mcHH + ) + // + && !( + prices.longEntry + && candle0.high < state0.scFast + && candle0.high < state0.scSlow + && candle0.high < state0.mcFast + && candle0.high < state0.mcSlow + && candle0.high < state0.lcFast + && candle0.high < state0.lcSlow + ) + // + && tPow0.powerDown > tPowerMaxVerifier + && tPow1.powerDown > tPowerMaxVerifier + && tPow0.powerDown < MathMax(tPow1.powerUp, tPow1.powerDown) + && MathMax(tPow1.powerUp, tPow1.powerDown) > tPowerMaxVerifier + ; + + // + // Start Conditions ... + startCondition = ( + longCondition1 + ) + ; + + // + if ( + startCondition + && xTPWLongConds.startTime == 0 + && xTPWLongConds.signalTime == 0 + && xTPWLongConds.entryTime == 0 + ) { + // + xTPWLongConds.startTime = barTime; + xTPWLongConds.signalTime = barTime; + xTPWLongConds.entryTime = barTime; + + // + return; + } +} + +// +// Check and Fill Short Signal Conditions ... +void CheckXTPWShortSignalConditions( + const int bar_index +) { + // + if ( + !enableXTPWShort + || !enableXTPWSignalling + || !xTPWWaitForShortSignals + ) { + return; + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + // Retrieve TPower State ... + XTPOWState tPow0 = GetXTPowState( + bar_index, + xTPWSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + bar_index + 1, + xTPWSwingLength + ); + XTPOWState tPow2 = GetXTPowState( + bar_index + 2, + xTPWSwingLength + ); + + // + // Retrieve TPWMarket State ... + XTPWMarketState state0 = GetXTPWMarketState( + bar_index + ); + XTPWMarketState state1 = GetXTPWMarketState( + bar_index + 1 + ); + XTPWMarketState state2 = GetXTPWMarketState( + bar_index + 2 + ); + + // + // Retrieve Candles ... + XOHCL candle0 = GetCandleModel(bar_index); + XOHCL candle1 = GetCandleModel(bar_index + 1); + XOHCL candle2 = GetCandleModel(bar_index + 2); + + // + XPrice prices = GetPrice(); + XLHS lhs = GetXTPWLHS(bar_index); + + // + double sharpDetectionValue = + xTPWSharpDetectionFactor * _Point; + + // + bool isHHSame = + lhs.scHH == lhs.mcHH + && lhs.mcHH == lhs.lcHH + ; + + // + bool isLLSame = + lhs.scLL == lhs.mcLL + && lhs.mcLL == lhs.lcLL + ; + + // + bool startCondition = false; + bool signalCondition = false; + bool entryCondition = false; + + // + bool shortCondition1 = + // + true + // + && tPow1.powerDown > tPowerMaxVerifier + && tPow2.powerDown < tPowerMaxVerifier + ; + + // + startCondition = ( + shortCondition1 + ) + ; + + // + if ( + startCondition + && xTPWShortConds.startTime == 0 + && xTPWShortConds.signalTime == 0 + && xTPWShortConds.entryTime == 0 + ) { + // + xTPWShortConds.startTime = barTime; + xTPWShortConds.signalTime = barTime; + xTPWShortConds.entryTime = barTime; + + // + return; + } +} + +// +// Convert Long Signal Conditions to XSignal ... +XSignalRequest GenerateXTPWSignal( + const ENUM_X_SIGNAL_TYPE type, // Signal Type ... + const string signalTag , // Signal Tag ... + const int bar_index +) { + // + XSignalRequest result = {}; + + // + result.hasSignal = false; + result.type = X_SIGNAL_NONE; + result.provider = X_UNKNOWN_PROVIDER; + + // + if ( + !enableXTPWSignalling + || !(enableXTPWLong || enableXTPWShort) + ) { + return result; + } + + // + bool requestLong = type == X_SIGNAL_LONG; + + // + // Check Condition Validations ... + if (requestLong) { + // + // Check Long Condtion is Valid, if Long Requested ... + if ( + !ValidateXTPWLongConditions() + ) { + return result; + } + } else { + // + // Check Short Condtion is Valid, if Short Requested ... + if ( + !ValidateXTPWShortConditions() + ) { + return result; + } + } + + // + double ll = + // + GetMarketLowestLow( + bar_index, + xTPWSwingLength + ) + ; + + // + double hh = + // + GetMarketHighestHigh( + bar_index, + xTPWSwingLength + ) + ; + + // + double openPrice = iOpen( + _Symbol, + _Period, + bar_index + ); + + // + double closePrice = iClose( + _Symbol, + _Period, + bar_index + ); + + // + // Price Calculations ... + XPrice prices = GetPrice(); + + // + // Read State ... + XTPWMarketState state0 = GetXTPWMarketState(bar_index); + + // + XOHCL candle0 = GetCandleModel(bar_index); + XOHCL candle1 = GetCandleModel(bar_index + 1); + XOHCL candle2 = GetCandleModel(bar_index + 2); + XOHCL candle3 = GetCandleModel(bar_index + 2); + + // + double risk = requestLong ? + // + MathMin(openPrice, closePrice) - ll : + hh - MathMax(openPrice, closePrice) + ; + + // + double longR2R = xTPWLongR2R; + double shortR2R = xTPWShortR2R; + + // + double sharpDetectorValue = xTPWSharpDetectionFactor * _Point; + + // + if ( + risk > 0 + && requestLong + ) { + return result; + } + + // + // Define Entry Price ... + double entryPrice = requestLong + ? + prices.longEntry + : + prices.shortEntry + ; + + // + // Fix TP Detects for Short Signals ... + if (!requestLong) { + risk = 0; + } + + // + double reward = requestLong ? + risk * longR2R : + risk * shortR2R + ; + + // + if (risk == 0) { + // + // Calculate Reward ... + reward = requestLong + ? + MathAbs(hh - entryPrice) + : + MathAbs(hh - entryPrice) + ; + + // + // Detect Sharp Change Occured or not ... + bool isSharpOccured = reward > sharpDetectorValue + || MathAbs(reward - sharpDetectorValue) < (50 * _Point); + + // + // Change Rewards on Special Conditions ... + if ( + ( + requestLong + && isSharpOccured + && ( + state0.lcFast < state0.lcSlow + || ( + state0.mcFast > state0.mcSlow + && state0.mcWeight < state0.mcSlow + ) + ) + ) + ) { + reward = reward / 2; + } + + // + if (reward < 50 * _Point) { + reward = (50 * _Point) + prices.priceGap; + } + + // // + // if (!requestLong) { + // reward = reward * shortR2R; + // } + } + + // + double sl = requestLong ? + 0 : + 0; + double tp = requestLong ? + entryPrice + reward : + entryPrice - reward + ; + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index + ); + + // + result.signal.tp = tp; + result.signal.sl = sl; + result.signal.type = type; + result.signal.time = barTime; + result.signal.tag = signalTag; + result.signal.symbol = _Symbol; + result.signal.entry = entryPrice; + result.signal.id = totalSignals + 1; + result.signal.provider = X_XTPW_PROVIDER; + + // + result.hasSignal = true; + result.type = type; + result.provider = X_XTPW_PROVIDER; + + // + return result; +} + +// +// Validate Signal Conditions ... +bool ValidateXTPWLongConditions() { + // + if ( + !enableXTPWLong + || !enableXTPWSignalling + ) { + return false; + } + + // + bool isConditionsFilled = + xTPWLongConds.startTime > 0 + && xTPWLongConds.signalTime > 0 + && xTPWLongConds.entryTime > 0 + ; + + // + bool isBLFilled = false; + if (isConditionsFilled) { + // // + // int startBarIndex = iBarShift( + // _Symbol, + // _Period, + // xTPWLongConds.startTime + // ); + + // // + // int signalBarIndex = iBarShift( + // _Symbol, + // _Period, + // xTPWLongConds.signalTime + // ); + + // // + // int entryBarIndex = iBarShift( + // _Symbol, + // _Period, + // xTPWLongConds.entryTime + // ); + + // // + // int startSignalDiff = (signalBarIndex - startBarIndex); + // int entrySignalDiff = (entryBarIndex - signalBarIndex); + // int maxDiff = MathMax(startSignalDiff, entrySignalDiff); + + // + isBLFilled = + // + // Starter ... + true + // + && xTPWLongConds.signalTime >= xTPWLongConds.startTime + && xTPWLongConds.entryTime >= xTPWLongConds.signalTime + // + // && maxDiff < (xTPWSwingLength * 2) + ; + } + + // + bool result = + isBLFilled + && isConditionsFilled + && xTPWWaitForLongSignals + ; + + // + // Since maybe Conditions Filled but + // Slope is Negative, for Handling Next Signals and + // Prevent from infinity loop, here we Clear Signal Conditions ... + if ( + !result + && isConditionsFilled + ) { + ClearXTPWLongSignalConditions(); + } + + // + return result; +} + +// +// Validate Signal Conditions ... +bool ValidateXTPWShortConditions() { + // + if ( + !enableXTPWShort + || !enableXTPWSignalling + ) { + return false; + } + + // + bool isConditionsFilled = + xTPWShortConds.startTime > 0 + && xTPWShortConds.signalTime > 0 + && xTPWShortConds.entryTime > 0 + ; + + // + bool isBLFilled = false; + if (isConditionsFilled) { + // // + // int startBarIndex = iBarShift( + // _Symbol, + // _Period, + // xTPWShortConds.startTime + // ); + + // // + // int signalBarIndex = iBarShift( + // _Symbol, + // _Period, + // xTPWShortConds.signalTime + // ); + + // // + // int entryBarIndex = iBarShift( + // _Symbol, + // _Period, + // xTPWShortConds.entryTime + // ); + + // + isBLFilled = + // + // Starter ... + true + // + && xTPWShortConds.signalTime >= xTPWShortConds.startTime + && xTPWShortConds.entryTime >= xTPWShortConds.signalTime + ; + } + + // + bool result = + isBLFilled + && isConditionsFilled + && xTPWWaitForShortSignals + ; + + // + // Since maybe Conditions Filled but + // Slope is Negative, for Handling Next Signals and + // Prevent from infinity loop, here we Clear Signal Conditions ... + if ( + !result + && isConditionsFilled + ) { + ClearXTPWShortSignalConditions(); + } + + // + return result; +} + +// +// Clear Long Signal Conditions for New One ... +void ClearXTPWLongSignalConditions() { + // + xTPWLongConds.startTime = 0; + xTPWLongConds.entryTime = 0; + xTPWLongConds.signalTime = 0; +} + +// +// Clear Short Signal Conditions for New One ... +void ClearXTPWShortSignalConditions() { + // + xTPWShortConds.startTime = 0; + xTPWShortConds.entryTime = 0; + xTPWShortConds.signalTime = 0; +} + +// +// Check State for Long Signals ... +bool IsReadyForXTPWSignals( + const XSignal &signal +) { + // + bool result = false; + + // + if ( + !enableXTPWSignalling + || !(enableXTPWLong || enableXTPWShort) + ) { + return result; + } + + // + int signalBarIndex = iBarShift( + _Symbol, + _Period, + signal.time + ); + + // + // XOHCL candle = GetCandleModel(0); + XOHCL candle0 = GetCandleModel(signalBarIndex); + XOHCL candle1 = GetCandleModel(signalBarIndex + 1); + + // + // Retrieve TPow State ... + XTPOWState tPow0 = GetXTPowState( + signalBarIndex, + xTPWSwingLength + ); + XTPOWState tPow1 = GetXTPowState( + signalBarIndex + 1, + xTPWSwingLength + ); + + // + // Retrive XMarket States ... + XTPWMarketState state0 = GetXTPWMarketState(signalBarIndex); + XTPWMarketState state1 = GetXTPWMarketState(signalBarIndex + 1); + XTPWMarketState state2 = GetXTPWMarketState(signalBarIndex + 2); + + // + bool isPSarVerified = false; + bool isTPowVerified = false; + bool isStateVerified = false; + bool isPriceVerified = false; + + // + // Calculate Sharp Detection Value ... + double sharpDetectionValue = + xTPWSharpDetectionFactor * _Point; + + // + // Find State0 Min ... + double state0Min = MathMin(state0.scFast, state0.scSlow); + state0Min = MathMin(state0Min, state0.mcFast); + state0Min = MathMin(state0Min, state0.mcSlow); + state0Min = MathMin(state0Min, state0.lcFast); + state0Min = MathMin(state0Min, state0.lcSlow); + + // + // Find State0 Min ... + double state0Max = MathMax(state0.scFast, state0.scSlow); + state0Max = MathMax(state0Max, state0.mcFast); + state0Max = MathMax(state0Max, state0.mcSlow); + state0Max = MathMax(state0Max, state0.lcFast); + state0Max = MathMax(state0Max, state0.lcSlow); + + // + // Find Distance Between State0 Min and Max ... + double state0MinMaxDistance = MathAbs(state0Max - state0Min); + + // + // Verify Long Signals ... + if (signal.type == X_SIGNAL_LONG) { + // + // Get Price Verification for Long ... + isPriceVerified = + // + // Starter ... + true + // + ; + + // + isTPowVerified = + // + // Starter ... + true + // + && tPow0.powerDown > tPowerMaxVerifier + && tPow1.powerDown > tPowerMaxVerifier + && tPow0.powerDown < MathMax(tPow1.powerUp, tPow1.powerDown) + && MathMax(tPow1.powerUp, tPow1.powerDown) > tPowerMaxVerifier + ; + + // + isPSarVerified = + // + // Starter ... + true + // + ; + + // + isStateVerified = + // + // Start ... + true + // + && state0.mcFast > state0.mcSlow + && state1.mcFast > state1.mcSlow + // + && !( + state0.lcFast > state0.mcSlow + && state0.lcFast < state0.mcFast + ) + // + && MathAbs(state1.mcFast - state1.mcSlow) > (50 * _Point) + ; + + // + result = + // + // Starter ... + true + // + && isPSarVerified + // + && isTPowVerified + // + && isStateVerified + // + && isPriceVerified + ; + } else + // + // Verify Short Signals ... + if (signal.type == X_SIGNAL_SHORT) { + // + isPSarVerified = + // + // Starter ... + true + ; + + // + // Get Price Verification for Short ... + isPriceVerified = + // + // Starter ... + true + ; + + // + isTPowVerified = + // + // Starter ... + true + // + && tPow0.signal > MathMax(tPow0.powerUp, tPow0.powerDown) + ; + + // + isStateVerified = + // + // Start ... + true + // + && ( + // + state0.scFast < state0.scSlow + && state0.mcFast < state0.mcSlow + && state0.lcFast < state0.lcSlow + ? + signal.entry > state0.scFast + : + // + // Find Minimum and Maximum Distance of State ... + state0MinMaxDistance > sharpDetectionValue + ? + signal.entry > state0Min + : + true + ) + // + && MathAbs(state0.mcFast - state0.mcSlow) > 50 * _Point + ; + + // + result = + // + // Starter Condition ... + true + // + && isPSarVerified + // + && isTPowVerified + // + && isStateVerified + // + && isPriceVerified + ; + } + + // + return result; +} +// +// END Functions ... +// + +// +// START Data Provider ... +// +// +// Retrieve Market State ... +XTPWMarketState GetXTPWMarketState( + const int bar_index +) { + // + XTPWMarketState result = {}; + + // + int dayCount = GetDailyCandleCount(); + int halfDayCount = (int)(dayCount / 2); + + // + if (scFastLength == 0) { + scFastLength = xTPWSwingLength; + } + + // + if (scSlowLength == 0) { + scSlowLength = xTPWSwingLength * 2; + } + + // + if (mcFastLength == 0) { + mcFastLength = halfDayCount; + } + + // + if (mcSlowLength == 0) { + mcSlowLength = dayCount; + } + + // + if (lcFastLength == 0) { + lcFastLength = halfDayCount * 3; + } + + // + if (lcSlowLength == 0) { + lcSlowLength = dayCount * 3; + } + + // + double scFast = GetMA( + bar_index, + scFastLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double scSlow = GetMA( + bar_index, + scSlowLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double scWeight = GetMA( + bar_index, + scSlowLength, + 0, + MODE_EMA, + PRICE_MEDIAN + ); + + // + double mcFast = GetMA( + bar_index, + mcFastLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double mcSlow = GetMA( + bar_index, + mcSlowLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double mcWeight = GetMA( + bar_index, + mcSlowLength, + 0, + MODE_EMA, + PRICE_MEDIAN + ); + + // + double lcFast = GetMA( + bar_index, + lcFastLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double lcSlow = GetMA( + bar_index, + lcSlowLength, + 0, + MODE_SMA, + PRICE_CLOSE + ); + + // + double lcWeight = GetMA( + bar_index, + lcSlowLength, + 0, + MODE_EMA, + PRICE_MEDIAN + ); + + // + double psar = iSAR( + _Symbol, + _Period, + xTPWPSarStep, + xTPWPSarMaximum, + bar_index + ); + + // + result.psar = psar; + result.scFast = scFast; + result.scSlow = scSlow; + result.mcFast = mcFast; + result.mcSlow = mcSlow; + result.lcFast = lcFast; + result.lcSlow = lcSlow; + result.scWeight = scWeight; + result.mcWeight = mcWeight; + result.lcWeight = lcWeight; + + // + return result; +} + +// +// Retrieve Highest Highs and Lowest Lows in Cycles ... +XLHS GetXTPWLHS( + const int bar_index +) { + // + XLHS result = {}; + + // + // Retrieve LL and HH (s) ... + + // + // SC HH ... + double scHH = GetMarketHighestHigh( + bar_index, + scFastLength + ); + + // + // SC LL ... + double scLL = GetMarketHighestHigh( + bar_index, + scFastLength + ); + + // + // MC HH ... + double mcHH = GetMarketHighestHigh( + bar_index, + mcFastLength + ); + + // + // MC LL ... + double mcLL = GetMarketHighestHigh( + bar_index, + mcFastLength + ); + + // + // LC HH ... + double lcHH = GetMarketHighestHigh( + bar_index, + lcFastLength + ); + + // + // LC LL ... + double lcLL = GetMarketHighestHigh( + bar_index, + lcFastLength + ); + + // + result.scHH = scHH; + result.scLL = scLL; + result.mcHH = mcHH; + result.mcLL = mcLL; + result.lcHH = lcHH; + result.lcLL = lcLL; + + // + return result; +} +// +// END Data Provider ... +// diff --git a/XAUUSD-15M-V1.0/Version.txt b/XAUUSD-15M-V1.0/Version.txt new file mode 100644 index 0000000..630faf8 --- /dev/null +++ b/XAUUSD-15M-V1.0/Version.txt @@ -0,0 +1 @@ +packed at: Tue Oct 10 2023 01:05:43 GMT+0330 (Iran Standard Time) \ No newline at end of file diff --git a/XEU5-0/Classes/.gitkeep b/XEU5-0/Classes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Classes/x-saherelm.class.lib.mq5 b/XEU5-0/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 0000000..4cfbd0e --- /dev/null +++ b/XEU5-0/Classes/x-saherelm.class.lib.mq5 @@ -0,0 +1,10286 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XClass +// Description: provides all classes for use ... +// +// +// 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 +#include +#include +#include +#include +#include +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Constant Definitions ... +// + +static uchar _md5_PADDING[64] = + { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define _md5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define _md5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define _md5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define _md5_I(x, y, z) ((y) ^ ((x) | (~z))) +#define _md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define _md5_FF(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_F((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define _md5_GG(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_G((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define _md5_HH(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_H((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define _md5_II(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_I((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +#define _md5_INIT_STATE_0 0x67452301 +#define _md5_INIT_STATE_1 0xefcdab89 +#define _md5_INIT_STATE_2 0x98badcfe +#define _md5_INIT_STATE_3 0x10325476 + +#define _md5_S11 7 +#define _md5_S12 12 +#define _md5_S13 17 +#define _md5_S14 22 + +#define _md5_S21 5 +#define _md5_S22 9 +#define _md5_S23 14 +#define _md5_S24 20 + +#define _md5_S31 4 +#define _md5_S32 11 +#define _md5_S33 16 +#define _md5_S34 23 + +#define _md5_S41 6 +#define _md5_S42 10 +#define _md5_S43 15 +#define _md5_S44 21 + +// +// END Constant Definitions ... +// + +// +// START Model Definitions ... +// + +// +string X_SIGNAL_TP = "TP"; +string X_SIGNAL_SL = "SL"; +string X_SIGNAL_TYPE = "TY"; +string X_SIGNAL_TICKET = "T"; +string X_SIGNAL_RISKFREE_STEP = "RFS"; +string X_SIGNAL_RISKFREE_RATE = "RFR"; + +// +// Model Signal Handler Result on XCTrade Class ... +struct XTraderHandlerResult +{ + // + // List Of Closed On SL Signals ... + XSignal sl[]; + + // + // List Of Closed On TP Signals ... + XSignal tp[]; + + // + // List Of Risk Free Signals ... + XSignal rf[]; +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerResult +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; +}; + +// +// Model Guard Action Applied Signals ... +struct XGuardHandlerResult +{ + // + // Critical Guard ... + XSignal criticals[]; + + // + // Max Guard ... + XSignal maxes[]; + + // + // Old ... + XSignal olds[]; + + // + // Determines Stopout Action Cals or not ... + bool isStopOut; +}; + +// +// Define Volume States ... +struct XVolumeInfo +{ + // + // Current Available Static Volume ... + double staticVolume; + + // + // Static Volume Calculation Method ... + string staticVolumeCalculationMethod; + + // + // Current Maximum Appliable Volume ... + double maxAllowedVolume; + + // + // Static Volume Increase Multiplier ... + double volumeIncreaseMultiplier; + + // + // Multiply Volume Based On Balance Growing ... + double balanceGowingToApplyMultiplier; + + // + // Where to Increase MaxAllowed Volume ... + double balanceGrowingToIncreaseMaxAllowedVolume; +}; + +// +// Model a Simple Provider Status ... +struct XSignallerInfo +{ + // + // Provider Name ... + string name; + + // + // Number of Longs ... + int longs; + + // + // Number of Shorts ... + int shorts; +}; + +// +// Model Some of Usefull Signals and Market Data ... +struct XSummaryInfo +{ + // + // Define Max Signal Volume ... + double maxSignalVolume; + + // + // Max DrawDown ... + double maxDrawDown; + + // + // Max DrawUp ... + double maxDrawUp; + + // + // Max Number of Same Time Signals ... + int maxSameTimeSignals; + + // + // Number of Long Trades ... + int longSignals; + + // + // Number of Short Trades ... + int shortSignals; + + // + // Number of TPs Attached ... + int numberOfTPs; + + // + // Number of SLs Attached ... + int numberOfSLs; +}; + +// +// Model Account info ... +struct XAccountInfo +{ + // + // User Account ... + string user; + + // + // Name of Client ... + string name; + + // + // Trade Server Name ... + string server; + + // + // Broker Name ... + string broker; + + // + // Account Trade Mode ... + ENUM_ACCOUNT_TRADE_MODE mode; + + // + // Account Leverage ... + long leverage; + + // + // Currency ... + string currency; + + // + // Deposit ... + double deposit; + + // + // Balance ... + double balance; + + // + // Min Balance for Open Trades ... + double minBalanceForOpenTrades; +}; + +// +// this is a Model Which holds Reports for Specific Time Periods ... +struct XReport +{ + // + datetime start; + + // + datetime end; + + // + XAccountInfo accountInfo; + + // + XVolumeInfo volumeInfo; + + // + XSignallerInfo signallersInfo[]; + + // + XSummaryInfo summaryInfo; +}; + +// +// an Enumeration Object which determines Report Type ... +enum ENUM_XREPORT_TYPES +{ + // + // Main Report ... + XREPORT_MAIN, + // + // Daily Report ... + XREPORT_DAILY, + // + // Weekly Report ... + XREPORT_WEEKLY, + // + // Monthly Report ... + XREPORT_MONTHLY, +}; + +// +// a Signal Protection Structure ... +struct XProtectedSignal +{ + // + ulong ticket; + + // + datetime time[]; + + // + double profit[]; +}; + +// +// Represent Collector State Based on Time ... +struct XCollector +{ + // + // time in checking ... + datetime time; + + // + // Signal Volume ... + double volume; + + // + // Max DrawDown in Check Time ... + double maxDrawDown; + + // + // Max Allowed Volume in Check Time ... + double maxAllowedVolume; + + // + // Minimum required Balance for Opening Trades at Check Time ... + double minBalanceForOpenTrade; +}; + +// +// the Action which Guard Handler Can Done when Attacked ... +enum ENUM_X_GUARD_ACTIONS +{ + // + // Do Nothing ... + X_GUARD_DO_NOTHING, + // + // Close All Open Positions ... + X_GUARD_CLOSE_ALL, + // + // Close Max In Drawdown Position ... + X_GUARD_CLOSE_MAX_IN_DD, + // + // Partial Close Max In Drawdown Position by 1% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1, + // + // Partial Close Max In Drawdown Position by 2% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_2, + // + // Partial Close Max In Drawdown Position by 3% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_3, + // + // Partial Close Max In Drawdown Position by 5% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5, + // + // Partial Close Max In Drawdown Position by 10% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10, + // + // Partial Close Max In Drawdown Position by 15% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_15, + // + // Partial Close Max In Drawdown Position by 20% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_20, + // + // Partial Close Max In Drawdown Position by 25% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25, + // + // Partial Close Max In Drawdown Position by 30% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30, + // + // Partial Close Max In Drawdown Position by 40% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40, + // + // Partial Close Max In Drawdown Position by 50% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50, + // + // Partial Close Max In Drawdown Position by 60% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60, + // + // Partial Close Max In Drawdown Position by 70% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_70, + // + // Partial Close Max In Drawdown Position by 75% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75, +}; + +// +// Guard Reason ... +enum ENUM_X_GUARD_REASONS +{ + // + // Critical ... + X_GUARDED_CRITICAL, + // + // Max ... + X_GUARDED_MAX, + // + // Old ... + X_GUARDED_OLD +}; + +// +// All Suuported Support Positions Guard ... +enum ENUM_X_GUARD_SUPPORT_METHODS +{ + // + // Ignore Supporting ... + X_SUPPORT_DO_NOTHING, + // + // Full Both Side Support ... + X_SUPPORT_FULL, + // + // Indirectional Supports On Drawing Down ... + X_SUPPORT_IN_DRAWDOWN_INDIRECTIONAL, + // + // Directional Supports On Drawing Up ... + X_SUPPORT_IN_DRAWUP_DIRECTIONAL, +}; + +// +// END Model Definitions ... +// + +// +// START Overrides ... +// + +// +// XBase Class ... +class XCBase +{ + // + // Public ... +public: + // + // Protected ... +protected: + // + void AddItemToBuffer( + double item, // Specified Item + double &buffer[] // Specified Buffer + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; + } + void AddItemToBuffer( + datetime item, // Specified Item + datetime &buffer[] // Specified Buffer + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; + } + void AddItemToBuffer( + XSignal &item, + XSignal &buffer[]) + { + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + } + void AddItemToBuffer( + XCollector &item, // Specified Item + XCollector &buffer[] // Specified Buffer + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; + } + void AddItemToBuffer( + XSignallerInfo &item, + XSignallerInfo &buffer[]) + { + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + } + void AddItemToBuffer( + XProtectedSignal &item, // Item ... + XProtectedSignal &buffer[] // Buffer ... + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + buffer[bufferSize] = item; + } + + // + void CleanBuffer(double &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XDeal &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XOrder &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XSignal &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XCollector &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XSignallerInfo &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XProtectedSignal &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + + // + void CopyBuffer( + const XSignallerInfo &source[], // Source Buffer ... + XSignallerInfo &dest[] // Dest Buffer ... + ) + { + // + CleanBuffer(dest); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < sourceCount; i++) + { + // + XSignallerInfo iInfo = source[i]; + + // + AddItemToBuffer( + iInfo, + dest); + } + } + void CopyBuffer( + XProtectedSignal &source[], // Source Buffer to Copy + XProtectedSignal &dest[] // Fill this buffer using source + ) + { + // + CleanBuffer(dest); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + XProtectedSignal iItem = source[i]; + + // + AddItemToBuffer( + iItem, + dest); + } + } + + // + // Private ... +private: +}; + +// +// XCTrade Base Class ... +class XSCTrade : 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 ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +// XCMD5 a library for Hashing ... +class XCMD5 : public XCBase +{ + // + // Public Provides ... +public: + // + // Protected Provides ... + + // + // Constructor ... + XCMD5(void) {} + + // + // Deconstructor ... + ~XCMD5(void) {} + + // + // Hash Specified Char Array ... + string Hash( + uchar &source[], // Specify Char Array to Hash + int length = 0 // Specify Length of Char Array which required to hash + ) + { + // + string result = ""; + + // + int sourceCount = ArraySize(source); + + // + // Validate Args ... + if ( + sourceCount <= 0 || + (sourceCount > 0 && length > sourceCount)) + { + return result; + } + + // + // Normalize Args ... + if (length == 0) + { + length = sourceCount; + } + + // + // Init MD5 ... + MD5Init(); + + // + // Update Buffer ... + MD5Update(source, length); + + // + // Calculate Result ... + result = MD5Final(); + + // + return result; + } + + // + // Hash Specified String ... + string Hash( + string source // Specified String + ) + { + // + string result = ""; + + // + // Converts String to Char Array ... + uchar bytes[]; + StringToCharArray( + source, + bytes, + 0, + StringLen(source)); + + // + result = Hash( + bytes, + ArraySize(bytes)); + + // + return result; + } + +protected: + // + // Private Provides ... +private: + // + uint m_lMD5[4]; + uint m_nCount[2]; + uchar m_lpszBuffer[64]; + + // + // Convert Byte to DWord ... + void ByteToDWord(int &out[], uint &in[], uint len) + { + // + uint i = 0; + uint j = 0; + + // + for (; j < len; i++, j += 4) + { + out[i] = (int)in[j] | (int)in[j + 1] << 8 | (int)in[j + 2] << 16 | (int)in[j + 3] << 24; + } + } + + // + // Convert DWord to Byte ... + void DWordToByte(uchar &out[], int &in[], uint len) + { + // + uint i = 0; + uint j = 0; + + // + for (; j < len; i++, j += 4) + { + // + out[j] = (uchar)(in[i] & 0xff); + out[j + 1] = (uchar)((in[i] >> 8) & 0xff); + out[j + 2] = (uchar)((in[i] >> 16) & 0xff); + out[j + 3] = (uchar)((in[i] >> 24) & 0xff); + } + } + + // + // Init MD5 Array ... + void MD5Init() + { + // + ArrayInitialize(m_lpszBuffer, 64); + + // + m_nCount[0] = m_nCount[1] = 0; + m_lMD5[0] = _md5_INIT_STATE_0; + m_lMD5[1] = _md5_INIT_STATE_1; + m_lMD5[2] = _md5_INIT_STATE_2; + m_lMD5[3] = _md5_INIT_STATE_3; + } + + // + // Update MD5 ... + void MD5Update(uchar &inBuf[], uint inLen) + { + // + int i, ii; + int mdi; + + // + uint in[16]; + int i0 = 0; + + // + mdi = (int)((m_nCount[0] >> 3) & 0x3F); + + // + if ((m_nCount[0] + ((uint)inLen << 3)) < m_nCount[0]) + { + m_nCount[1]++; + } + + // + m_nCount[0] += ((uint)inLen << 3); + m_nCount[1] += ((uint)inLen >> 29); + + // + while ((inLen--) > 0) + { + // + m_lpszBuffer[mdi++] = inBuf[i0++]; + if (mdi == 0x40) + { + // + for (i = 0, ii = 0; i < 16; i++, ii += 4) + { + in[i] = (((uint)m_lpszBuffer[ii + 3]) << 24) | (((uint)m_lpszBuffer[ii + 2]) << 16) | (((uint)m_lpszBuffer[ii + 1]) << 8) | ((uint)m_lpszBuffer[ii]); + } + + // + Transform(m_lMD5, in); + + // + mdi = 0; + } + } + } + + // + // Finalize an MD5 Expression ... + string MD5Final() + { + // + uchar bits[8]; + int nIndex; + uint nPadLen; + const int nMD5Size = 16; + uchar lpszMD5[16]; + string temp; + string out = ""; + int i; + + // + DWordToByte(bits, m_nCount, 8); + nIndex = (int)((m_nCount[0] >> 3) & 0x3f); + nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex); + MD5Update(_md5_PADDING, nPadLen); + MD5Update(bits, 8); + DWordToByte(lpszMD5, m_lMD5, nMD5Size); + + // + for (i = 0; i < nMD5Size; i++) + { + // + if (lpszMD5[i] == 0) + { + temp = "00"; + } + else if (lpszMD5[i] <= 15) + { + temp = StringFormat("0%x", lpszMD5[i]); + } + else + { + temp = StringFormat("%x", lpszMD5[i]); + } + + // + out += temp; + } + + // + lpszMD5[0] = '\0'; + + // + return (out); + } + + // + // Transform Buffers ... + void Transform(uint &buf[], uint &in[]) + { + // + uint a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + // + _md5_FF(a, b, c, d, in[0], _md5_S11, 0xD76AA478); + _md5_FF(d, a, b, c, in[1], _md5_S12, 0xE8C7B756); + _md5_FF(c, d, a, b, in[2], _md5_S13, 0x242070DB); + _md5_FF(b, c, d, a, in[3], _md5_S14, 0xC1BDCEEE); + _md5_FF(a, b, c, d, in[4], _md5_S11, 0xF57C0FAF); + _md5_FF(d, a, b, c, in[5], _md5_S12, 0x4787C62A); + _md5_FF(c, d, a, b, in[6], _md5_S13, 0xA8304613); + _md5_FF(b, c, d, a, in[7], _md5_S14, 0xFD469501); + _md5_FF(a, b, c, d, in[8], _md5_S11, 0x698098D8); + _md5_FF(d, a, b, c, in[9], _md5_S12, 0x8B44F7AF); + _md5_FF(c, d, a, b, in[10], _md5_S13, 0xFFFF5BB1); + _md5_FF(b, c, d, a, in[11], _md5_S14, 0x895CD7BE); + _md5_FF(a, b, c, d, in[12], _md5_S11, 0x6B901122); + _md5_FF(d, a, b, c, in[13], _md5_S12, 0xFD987193); + _md5_FF(c, d, a, b, in[14], _md5_S13, 0xA679438E); + _md5_FF(b, c, d, a, in[15], _md5_S14, 0x49B40821); + + // + _md5_GG(a, b, c, d, in[1], _md5_S21, 0xF61E2562); + _md5_GG(d, a, b, c, in[6], _md5_S22, 0xC040B340); + _md5_GG(c, d, a, b, in[11], _md5_S23, 0x265E5A51); + _md5_GG(b, c, d, a, in[0], _md5_S24, 0xE9B6C7AA); + _md5_GG(a, b, c, d, in[5], _md5_S21, 0xD62F105D); + _md5_GG(d, a, b, c, in[10], _md5_S22, 0x02441453); + _md5_GG(c, d, a, b, in[15], _md5_S23, 0xD8A1E681); + _md5_GG(b, c, d, a, in[4], _md5_S24, 0xE7D3FBC8); + _md5_GG(a, b, c, d, in[9], _md5_S21, 0x21E1CDE6); + _md5_GG(d, a, b, c, in[14], _md5_S22, 0xC33707D6); + _md5_GG(c, d, a, b, in[3], _md5_S23, 0xF4D50D87); + _md5_GG(b, c, d, a, in[8], _md5_S24, 0x455A14ED); + _md5_GG(a, b, c, d, in[13], _md5_S21, 0xA9E3E905); + _md5_GG(d, a, b, c, in[2], _md5_S22, 0xFCEFA3F8); + _md5_GG(c, d, a, b, in[7], _md5_S23, 0x676F02D9); + _md5_GG(b, c, d, a, in[12], _md5_S24, 0x8D2A4C8A); + + // + _md5_HH(a, b, c, d, in[5], _md5_S31, 0xFFFA3942); + _md5_HH(d, a, b, c, in[8], _md5_S32, 0x8771F681); + _md5_HH(c, d, a, b, in[11], _md5_S33, 0x6D9D6122); + _md5_HH(b, c, d, a, in[14], _md5_S34, 0xFDE5380C); + _md5_HH(a, b, c, d, in[1], _md5_S31, 0xA4BEEA44); + _md5_HH(d, a, b, c, in[4], _md5_S32, 0x4BDECFA9); + _md5_HH(c, d, a, b, in[7], _md5_S33, 0xF6BB4B60); + _md5_HH(b, c, d, a, in[10], _md5_S34, 0xBEBFBC70); + _md5_HH(a, b, c, d, in[13], _md5_S31, 0x289B7EC6); + _md5_HH(d, a, b, c, in[0], _md5_S32, 0xEAA127FA); + _md5_HH(c, d, a, b, in[3], _md5_S33, 0xD4EF3085); + _md5_HH(b, c, d, a, in[6], _md5_S34, 0x04881D05); + _md5_HH(a, b, c, d, in[9], _md5_S31, 0xD9D4D039); + _md5_HH(d, a, b, c, in[12], _md5_S32, 0xE6DB99E5); + _md5_HH(c, d, a, b, in[15], _md5_S33, 0x1FA27CF8); + _md5_HH(b, c, d, a, in[2], _md5_S34, 0xC4AC5665); + + // + _md5_II(a, b, c, d, in[0], _md5_S41, 0xF4292244); + _md5_II(d, a, b, c, in[7], _md5_S42, 0x432AFF97); + _md5_II(c, d, a, b, in[14], _md5_S43, 0xAB9423A7); + _md5_II(b, c, d, a, in[5], _md5_S44, 0xFC93A039); + _md5_II(a, b, c, d, in[12], _md5_S41, 0x655B59C3); + _md5_II(d, a, b, c, in[3], _md5_S42, 0x8F0CCC92); + _md5_II(c, d, a, b, in[10], _md5_S43, 0xFFEFF47D); + _md5_II(b, c, d, a, in[1], _md5_S44, 0x85845DD1); + _md5_II(a, b, c, d, in[8], _md5_S41, 0x6FA87E4F); + _md5_II(d, a, b, c, in[15], _md5_S42, 0xFE2CE6E0); + _md5_II(c, d, a, b, in[6], _md5_S43, 0xA3014314); + _md5_II(b, c, d, a, in[13], _md5_S44, 0x4E0811A1); + _md5_II(a, b, c, d, in[4], _md5_S41, 0xF7537E82); + _md5_II(d, a, b, c, in[11], _md5_S42, 0xBD3AF235); + _md5_II(c, d, a, b, in[2], _md5_S43, 0x2AD7D2BB); + _md5_II(b, c, d, a, in[9], _md5_S44, 0xEB86D391); + + // + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; + } +}; + +// +// XSaherElm Account Info Class ... +class XCAccountInfo : public XCBase +{ + // + // Public properties ... +public: + // + // Constructro ... + void XCAccountInfo() + { + // + mAccountInfo = new CAccountInfo(); + + // + mInitialBalance = mAccountInfo.Balance(); + } + + // + // Deconstructor ... + void ~XCAccountInfo() + { + // + mInitialBalance = 0; + } + + // + // 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 Initial Deposit Balance ... + double GetInitialBalance() + { + return mInitialBalance; + } + + // + // 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; + } + + // + // Protected properties ... +protected: + // + // Private properties ... +private: + // + // Initial Account Balance ... + double mInitialBalance; + + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// XSaherElm Report Info Class ... +class XCReporter : public XCBase +{ + // + // Public Provided ... +public: + // + // Constructro ... + void XCReporter() + { + // + mAccountInfo = new XCAccountInfo(); + + // + Reset(); + } + + // + // Deconstructor ... + void ~XCReporter() + { + } + + // + // Reset Specific Report ... + void Reset( + ENUM_XREPORT_TYPES type // Specify Report Type + ) + { + CleanReport(type); + } + + // + // Reset All Reports ... + void Reset() + { + // + CleanReport(XREPORT_MAIN); + CleanReport(XREPORT_MONTHLY); + CleanReport(XREPORT_WEEKLY); + CleanReport(XREPORT_DAILY); + } + + // + // Update Volume Info ... + void UpdateReportVolumeInfo( + ENUM_XREPORT_TYPES type, // Specified Report Type + // + double staticVolume, // Current Available Static Volume + string staticVolumeCalculationMethod, // Static Volume Calculation Method + double maxAllowedVolume, // Current Maximum Appliable Volume + double volumeIncreaseMultiplier, // Static Volume Increase Multiplier + double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing + double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume + ) + { + // + // Filling Account Info ... + FillReportAccountInfo(type); + + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + // + FillingVolumeInfo( + mMainReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + // + FillingVolumeInfo( + mMonthlyReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + // + FillingVolumeInfo( + mWeeklyReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + + // + // Daily ... + case XREPORT_DAILY: + // + FillingVolumeInfo( + mDailyReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + } + } + + // + // Update Volume Info on All Reports ... + void UpdateReportsVolumeInfo( + double staticVolume, // Current Available Static Volume + string staticVolumeCalculationMethod, // Static Volume Calculation Method + double maxAllowedVolume, // Current Maximum Appliable Volume + double volumeIncreaseMultiplier, // Static Volume Increase Multiplier + double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing + double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume + ) + { + // + // Main ... + UpdateReportVolumeInfo( + XREPORT_MAIN, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Monthly ... + UpdateReportVolumeInfo( + XREPORT_MONTHLY, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Weekly ... + UpdateReportVolumeInfo( + XREPORT_WEEKLY, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Daily ... + UpdateReportVolumeInfo( + XREPORT_DAILY, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + } + + // + // Add Specific Signal to Report ... + void AddSignalToReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + const XSignal &signal, // Specified Signal + const string &providers[] // Specified Signal Providers + ) + { + // + // + // Filling Account Info ... + FillReportAccountInfo(type); + + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + AddSignalToReport( + mMainReport, + signal, + providers); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + AddSignalToReport( + mMonthlyReport, + signal, + providers); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + AddSignalToReport( + mWeeklyReport, + signal, + providers); + break; + + // + // Daily ... + case XREPORT_DAILY: + AddSignalToReport( + mDailyReport, + signal, + providers); + break; + } + } + + // + // Add Specific Signal to All Reports ... + void AddSignalToReports( + const XSignal &signal, // Specified Signal + const string &providers[] // Specified Signal Providers + ) + { + // + // Main ... + AddSignalToReport( + XREPORT_MAIN, + signal, + providers); + + // + // Monthly ... + AddSignalToReport( + XREPORT_MONTHLY, + signal, + providers); + + // + // Weekly ... + AddSignalToReport( + XREPORT_WEEKLY, + signal, + providers); + + // + // Daily ... + AddSignalToReport( + XREPORT_DAILY, + signal, + providers); + } + + // + // Report a TP for Specific Report ... + void AddTradeTPInReport( + ENUM_XREPORT_TYPES type // Specified Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + AddTradeTPInReport(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + AddTradeTPInReport(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + AddTradeTPInReport(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + AddTradeTPInReport(mDailyReport); + break; + } + } + + // + // Report a TP for All Reports ... + void AddTradeTPInReports() + { + // + // Main ... + AddTradeTPInReport(XREPORT_MAIN); + + // + // Monthly ... + AddTradeTPInReport(XREPORT_MONTHLY); + + // + // Weekly ... + AddTradeTPInReport(XREPORT_WEEKLY); + + // + // Daily ... + AddTradeTPInReport(XREPORT_DAILY); + } + + // + // Report a SL for Specific Report ... + void AddTradeSLInReport( + ENUM_XREPORT_TYPES type // Specified Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + AddTradeSLInReport(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + AddTradeSLInReport(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + AddTradeSLInReport(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + AddTradeSLInReport(mDailyReport); + break; + } + } + + // + // Report a SL for All Reports ... + void AddTradeSLInReports() + { + // + // Main ... + AddTradeSLInReport(XREPORT_MAIN); + + // + // Monthly ... + AddTradeSLInReport(XREPORT_MONTHLY); + + // + // Weekly ... + AddTradeSLInReport(XREPORT_WEEKLY); + + // + // Daily ... + AddTradeSLInReport(XREPORT_DAILY); + } + + // + // Update Number of Same Time Trades in Specific Report ... + void UpdateMaxSameTimeTradesInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + int value // number of same time trades + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMaxSameTimeTradesInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMaxSameTimeTradesInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMaxSameTimeTradesInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMaxSameTimeTradesInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Number of Same Time Trades in All Report ... + void UpdateMaxSameTimeTradesInReports( + int value // number of same time trades + ) + { + // + // Main ... + UpdateMaxSameTimeTradesInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMaxSameTimeTradesInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMaxSameTimeTradesInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMaxSameTimeTradesInReport( + XREPORT_DAILY, + value); + } + + // + // Update Max DrawDown in Specific Report ... + void UpdateMaxDrawDownInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + double value // draw down value + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMaxDrawDownInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMaxDrawDownInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMaxDrawDownInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMaxDrawDownInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Max DrawDown in All Report ... + void UpdateMaxDrawDownInReports( + double value // draw down value + ) + { + // + // Main ... + UpdateMaxDrawDownInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMaxDrawDownInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMaxDrawDownInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMaxDrawDownInReport( + XREPORT_DAILY, + value); + } + + // + // Update Max DrawUp in Specific Report ... + void UpdateMaxDrawUpInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + double value // draw up value + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMaxDrawUpInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMaxDrawUpInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMaxDrawUpInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMaxDrawUpInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Max DrawUp in All Report ... + void UpdateMaxDrawUpInReports( + double value // draw up value + ) + { + // + // Main ... + UpdateMaxDrawUpInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMaxDrawUpInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMaxDrawUpInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMaxDrawUpInReport( + XREPORT_DAILY, + value); + } + + // + // Update Min Balance for Open Trades in Specific Report ... + void UpdateMinBalanceForOpenTradesInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + double value // min balance for open trades + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMinBalanceForOpenTradesInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMinBalanceForOpenTradesInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMinBalanceForOpenTradesInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMinBalanceForOpenTradesInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Min Balance for Open Trades in All Report ... + void UpdateMinBalanceForOpenTradesInReports( + double value // min balance for open trades + ) + { + // + // Main ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_DAILY, + value); + } + + // + // Gnerate Specific Type Of Report String Representation ... + string GenerateReportString( + ENUM_XREPORT_TYPES type, // Specified Report Type + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + result = GenerateReportString( + mMainReport, + separator); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + result = GenerateReportString( + mMonthlyReport, + separator); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + result = GenerateReportString( + mWeeklyReport, + separator); + break; + + // + // Daily ... + case XREPORT_DAILY: + result = GenerateReportString( + mDailyReport, + separator); + break; + } + + // + return result; + } + + // + // Protected Provided ... +protected: + // + // Private Provided ... +private: + // + // Account Info Instance ... + XCAccountInfo mAccountInfo; + + // + // Main Report ... + XReport mMainReport; + + // + // Monthly Report ... + XReport mMonthlyReport; + + // + // Weekly Report ... + XReport mWeeklyReport; + + // + // Daily Report ... + XReport mDailyReport; + + // + // Clean Specific Report ... + void CleanReport( + XReport &report // Specified Report + ) + { + // + datetime time = TimeCurrent(); + + // + // Reset Times ... + report.start = time; + report.end = -1; + + // + // Reset Account Info ... + FillReportAccountInfo(report); + + // + // Reset Summary Info ... + report.summaryInfo.maxDrawUp = 0; + report.summaryInfo.maxDrawDown = 0; + report.summaryInfo.longSignals = 0; + report.summaryInfo.numberOfTPs = 0; + report.summaryInfo.numberOfSLs = 0; + report.summaryInfo.shortSignals = 0; + report.summaryInfo.maxSignalVolume = 0; + report.summaryInfo.maxSameTimeSignals = 0; + + // + // Reset Volume Info ... + report.volumeInfo.staticVolume = 0; + report.volumeInfo.maxAllowedVolume = 0; + report.volumeInfo.volumeIncreaseMultiplier = 0; + report.volumeInfo.balanceGowingToApplyMultiplier = 0; + report.volumeInfo.staticVolumeCalculationMethod = NULL; + report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = 0; + + // + // Reset Signallers Info ... + CleanBuffer(report.signallersInfo); + } + void CleanReport( + ENUM_XREPORT_TYPES type // Specify Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + CleanReport(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + CleanReport(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + CleanReport(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + CleanReport(mDailyReport); + break; + } + } + + // + // Update Specific Reports End Time ... + void FillReportEndTime( + XReport &report // Specified Report + ) + { + // + datetime time = TimeCurrent(); + report.end = time; + } + + // + // Filleing Report Account Info ... + void FillReportAccountInfo( + XReport &report // Specified Report + ) + { + // + FillReportEndTime(report); + + // + report.accountInfo.user = (string)mAccountInfo.GetUserAccount(); + report.accountInfo.name = mAccountInfo.GetName(); + report.accountInfo.server = mAccountInfo.GetServerName(); + report.accountInfo.broker = mAccountInfo.GetCompany(); + report.accountInfo.mode = mAccountInfo.GetTradeMode(); + report.accountInfo.leverage = mAccountInfo.GetLeverage(); + report.accountInfo.currency = mAccountInfo.GetCurrency(); + report.accountInfo.deposit = mAccountInfo.GetInitialBalance(); + report.accountInfo.balance = mAccountInfo.GetBalance(); + } + void FillReportAccountInfo( + ENUM_XREPORT_TYPES type // Specify Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + FillReportAccountInfo(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + FillReportAccountInfo(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + FillReportAccountInfo(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + FillReportAccountInfo(mDailyReport); + break; + } + } + + // + // Filling Volume Info ... + void FillingVolumeInfo( + XReport &report, // Specified Report + // + double staticVolume, // Current Available Static Volume + string staticVolumeCalculationMethod, // Static Volume Calculation Method + double maxAllowedVolume, // Current Maximum Appliable Volume + double volumeIncreaseMultiplier, // Static Volume Increase Multiplier + double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing + double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume + ) + { + // + FillReportEndTime(report); + + // + report.volumeInfo.staticVolume = staticVolume; + report.volumeInfo.maxAllowedVolume = maxAllowedVolume; + report.volumeInfo.volumeIncreaseMultiplier = volumeIncreaseMultiplier; + report.volumeInfo.staticVolumeCalculationMethod = staticVolumeCalculationMethod; + report.volumeInfo.balanceGowingToApplyMultiplier = balanceGowingToApplyMultiplier; + report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = balanceGrowingToIncreaseMaxAllowedVolume; + } + + // + // Add Signal to Report ... + void AddSignalToReport( + XReport &report, // Specified Report + const XSignal &signal, // Specified Signal + const string &providers[] // Specified Signal Providers + ) + { + // + FillReportEndTime(report); + + // + double volume = signal.volume; + bool isLong = signal.type == X_SIGNAL_LONG; + + // + // Update Longs and Shorts ... + if (isLong) + { + report.summaryInfo.longSignals++; + } + else + { + report.summaryInfo.shortSignals++; + } + + // + // Chack Max Volume ... + if (volume > report.summaryInfo.maxSignalVolume) + { + report.summaryInfo.maxSignalVolume = volume; + } + + // + // Update Signallers Info ... + for (int i = 0; i < ArraySize(providers); i++) + { + // + string iProvider = providers[i]; + + // + AddOrUpdateSignaller( + report, + iProvider, + signal); + } + } + + // + // Add or Update Signaller Info of Specific Report ... + void AddOrUpdateSignaller( + XReport &report, // Specified Report + const string provider, // Signal Provider name + const XSignal &signal // Specified Signal + ) + { + // + int providerIdx = -1; + int signallersInfoCount = 0; + bool isLong = signal.type == X_SIGNAL_LONG; + + // + // Prepare New One Provider ... + XSignallerInfo info = {}; + info.name = provider; + if (isLong) + { + info.longs = 1; + } + else + { + info.shorts = 1; + } + + // + // Find Provider idx if Exists ... + providerIdx = FindProviderInSignallersInfo( + provider, + report.signallersInfo); + + // + // Check IDX ... + if (providerIdx > -1) + { + // + // Update Exists ... + if (isLong) + { + report.signallersInfo[providerIdx].longs++; + } + else + { + report.signallersInfo[providerIdx].shorts++; + } + } + else + { + // + // Add New One ... + AddItemToBuffer( + info, + report.signallersInfo); + } + } + + // + // Add TP in Report ... + void AddTradeTPInReport( + XReport &report // Specified Report + ) + { + // + FillReportEndTime(report); + + // + report.summaryInfo.numberOfTPs++; + } + + // + // Add SL in Report ... + void AddTradeSLInReport( + XReport &report // Specified Report + ) + { + // + FillReportEndTime(report); + + // + report.summaryInfo.numberOfSLs++; + } + + // + // Update Number of Same Time Trades in Report ... + void UpdateMaxSameTimeTradesInReport( + XReport &report, // Specified Report + int value // number of same time trades + ) + { + // + // Validate Args ... + if (value <= report.summaryInfo.maxSameTimeSignals) + { + return; + } + + // + FillReportEndTime(report); + + // + report.summaryInfo.maxSameTimeSignals = value; + } + + // + // Update Number of Same Time Trades in Report ... + void UpdateMaxDrawUpInReport( + XReport &report, // Specified Report + double value // draw up value + ) + { + // + // Validate Args ... + if (value <= report.summaryInfo.maxDrawUp) + { + return; + } + + // + FillReportEndTime(report); + + // + report.summaryInfo.maxDrawUp = value; + } + + // + // Update Number of Same Time Trades in Report ... + void UpdateMaxDrawDownInReport( + XReport &report, // Specified Report + double value // draw down value + ) + { + // + // Validate Args ... + if (value <= report.summaryInfo.maxDrawDown) + { + return; + } + + // + FillReportEndTime(report); + + // + report.summaryInfo.maxDrawDown = value; + } + + // + // Update Min Balance for Open Trades Value in Report ... + void UpdateMinBalanceForOpenTradesInReport( + XReport &report, // Specified Report + double value // min balance for open trades + ) + { + // + // Validate Arg ... + if (value <= 0) + { + return; + } + + // + FillReportEndTime(report); + + // + report.accountInfo.minBalanceForOpenTrades = value; + } + + // + // Generate Specific Report String Representation ... + string GenerateReportString( + XReport &report, // Specified Report + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Start and End Date ... + result += "Start: " + (string)report.start + separator; + result += "End: " + (string)report.end + separator; + + // + // Account Info ... + string accountStr = GenerateAccountInfoReportString(report.accountInfo); + result += "Account: " + separator + accountStr + separator; + + // + // Summary Info ... + string summaryStr = GenerateSummaryInfoReportString(report.summaryInfo); + result += "Summary: " + separator + summaryStr + separator; + + // + // Volume Info ... + string volumeStr = GenerateVolumeInfoReportString(report.volumeInfo); + result += "Volume: " + separator + volumeStr + separator; + + // + // Signallers Info ... + string signallersStr = GenerateSignallersInfoReportString(report.signallersInfo); + result += "Signallers: " + separator + signallersStr + separator; + + // + return result; + } + + // + // Generate Account info String Representation ... + string GenerateAccountInfoReportString( + XAccountInfo &info, // Specified Account Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Generate Report ... + result += "user: " + info.user + separator; + result += "name: " + info.name + separator; + result += "server: " + info.server + separator; + result += "broker: " + info.broker + separator; + result += "mode: " + EnumToString(info.mode) + separator; + result += "leverage: " + (string)info.leverage + separator; + result += "currency: " + info.currency + separator; + result += "deposit: " + (string)info.deposit + separator; + result += "balance: " + (string)info.balance + separator; + result += "minBalanceForTrading: " + (string)info.minBalanceForOpenTrades + separator; + + // + return result; + } + + // + // Generate Summary info String Representation ... + string GenerateSummaryInfoReportString( + XSummaryInfo &info, // Specified Summary Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Generate Report ... + result += "longSignals: " + (string)info.longSignals + separator; + result += "shortSignals: " + (string)info.shortSignals + separator; + result += "numberOfTps: " + (string)info.numberOfTPs + separator; + result += "numberOfSLs: " + (string)info.numberOfSLs + separator; + result += "maxDrawUp: " + (string)info.maxDrawUp + separator; + result += "maxDrawDown: " + (string)info.maxDrawDown + separator; + result += "maxSignalVolume: " + (string)info.maxSignalVolume + separator; + result += "maxSameTimeSignals: " + (string)info.maxSameTimeSignals + separator; + + // + return result; + } + + // + // Generate Volume info String Representation ... + string GenerateVolumeInfoReportString( + XVolumeInfo &info, // Specified Volume Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Generate Report ... + result += "staticVolume: " + (string)info.staticVolume + separator; + result += "staticVolumeCalculationMethod: " + info.staticVolumeCalculationMethod + separator; + result += "maxAllowedVolume: " + (string)info.maxAllowedVolume + separator; + result += "volumeIncreaseMultiplier: " + (string)info.volumeIncreaseMultiplier + separator; + result += "balanceGowingToApplyMultiplier: " + (string)info.balanceGowingToApplyMultiplier + separator; + result += "balanceGrowingToIncreaseMaxAllowedVolume: " + (string)info.balanceGrowingToIncreaseMaxAllowedVolume + separator; + + // + return result; + } + + // + // Generate Signallers info String Representation ... + string GenerateSignallersInfoReportString( + XSignallerInfo &infos[], // Specified Signallers Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Validate Signallers Array Size ... + int signallersCount = ArraySize(infos); + if (signallersCount <= 0) + { + // + result += "EMPTY" + separator; + return result; + } + + // + // Generate Report ... + for (int i = 0; i < signallersCount; i++) + { + // + XSignallerInfo iSignaller = infos[i]; + + // + result += "name: " + iSignaller.name + separator; + result += "longs: " + (string)iSignaller.longs + separator; + result += "shorts: " + (string)iSignaller.shorts + separator; + + // + if (i < signallersCount - 1) + { + result += separator; + } + } + // + return result; + } + + // + // Find a Provider Index in SignallersInfo ... + int FindProviderInSignallersInfo( + string provider, // Specified Provider Name ... + XSignallerInfo &infoBuffer[] // Specified XSignallerInfo Buffer ... + ) + { + // + int result = -1; + + // + int bufferSize = ArraySize(infoBuffer); + if (bufferSize <= 0) + { + return result; + } + + // + // Loop through buffer to find provider index ... + for (int i = 0; i < bufferSize; i++) + { + // + XSignallerInfo iInfo = infoBuffer[i]; + + // + if (iInfo.name != provider) + { + continue; + } + + // + result = i; + } + + // + return result; + } +}; + +// +// a Class For Collectiong Info ... +class XCCollector : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCCollector() + { + Reset(); + } + + // + // Deconstructor ... + ~XCCollector() {} + + // + // Reset All Collectors ... + void Reset() + { + Clean(); + } + + // + // Count Data ... + int Count() + { + // + int result = 0; + + // + result = ArraySize(mTimes); + + // + return result; + } + + // + // TODO: Implement Business Logic here ... + + // + // Add Specific item to Collection ... + bool Add( + XCollector &item // Specified Info + ) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid( + item, + false); + if (!result) + { + return result; + } + + // + // Add Items Values to Buffers ... + // + AddItemToBuffer( + item.time, + mTimes); + + // + AddItemToBuffer( + item.volume, + mVolumes); + + // + AddItemToBuffer( + item.maxDrawDown, + mMaxDrawDowns); + + // + AddItemToBuffer( + item.maxAllowedVolume, + mMaxAllowedVolumes); + + // + AddItemToBuffer( + item.minBalanceForOpenTrade, + mMinBalanceForTradePrices); + + // + return result; + } + + // + // Retrieve Specific Item ... + bool Get( + XCollector &item, // Hold's Result + int index = 0 // Specified Index to Retrieve + ) + { + // + bool result = false; + + // + result = IsValidIndex(index); + if (!result) + { + return result; + } + + // + // Filling Item ... + item.time = mTimes[index]; + item.volume = mVolumes[index]; + item.maxDrawDown = mMaxDrawDowns[index]; + item.maxAllowedVolume = mMaxAllowedVolumes[index]; + item.minBalanceForOpenTrade = mMinBalanceForTradePrices[index]; + + // + return result; + } + XCollector Get( + int index = 0 // Specified Index to Retrieve + ) + { + // + XCollector result = {}; + + // + bool isValidIndex = IsValidIndex(index); + if (!isValidIndex) + { + return result; + } + + // + // Filling Item ... + result.time = mTimes[index]; + result.volume = mVolumes[index]; + result.maxDrawDown = mMaxDrawDowns[index]; + result.maxAllowedVolume = mMaxAllowedVolumes[index]; + result.minBalanceForOpenTrade = mMinBalanceForTradePrices[index]; + + // + return result; + } + bool Get( + XCollector &item, // Hold's Result + datetime time // Specified Index to Retrieve + ) + { + // + bool result = false; + + // + if (time <= 0) + { + return result; + } + + // + int timesCount = ArraySize(mTimes); + result = timesCount > 0; + if (!result) + { + return result; + } + + // + int index = -1; + for (int i = 0; i < timesCount; i++) + { + // + datetime iTime = mTimes[i]; + + // + if (iTime == time) + { + // + index = i; + break; + } + } + + // + result = index >= 0; + if (!result) + { + return result; + } + + // + result = Get( + item, + index); + + // + return result; + } + XCollector Get( + datetime time // Specified Index to Retrieve + ) + { + // + XCollector result = {}; + + // + if (time <= 0) + { + return result; + } + + // + int timesCount = ArraySize(mTimes); + if (timesCount <= 0) + { + return result; + } + + // + int index = -1; + for (int i = 0; i < timesCount; i++) + { + // + datetime iTime = mTimes[i]; + + // + if (iTime == time) + { + // + index = i; + break; + } + } + + // + if (index <= -1) + { + return result; + } + + // + result = Get( + index); + + // + return result; + } + + // + // Retrieve All ... + void GetAll( + XCollector &result[], // Hold's Result + bool reversal = false // Extract Direction + ) + { + // + CleanBuffer(result); + + // + int timesCount = ArraySize(mTimes); + if (timesCount <= 0) + { + return; + } + + // + if (!reversal) + { + // + for (int i = 0; i < timesCount; i++) + { + // + XCollector iCollector = Get(i); + + // + AddItemToBuffer( + iCollector, + result); + } + } + else + { + // + for (int i = timesCount - 1; i >= 0; i--) + { + // + XCollector iCollector = Get(i); + + // + AddItemToBuffer( + iCollector, + result); + } + } + } + + // + // Extract History ... + void Extract( + XCollector &result[], // Hold's Result + int start, // Start Index + int end // End Index + ) + { + // + CleanBuffer(result); + + // + // Validate Args ... + if ( + end < 0 || + start < 0 || + (start == 0 && end == 0) || + MathAbs(start - end == 0)) + { + return; + } + + // + // Validate Start and End Index ... + bool isValidEnd = IsValidIndex(end); + bool isValidStart = IsValidIndex(start); + if (!isValidEnd || !isValidStart) + { + return; + } + + // + bool direction = end > start; + if (direction) + { + // + for (int i = start; i < end - 1; i++) + { + // + XCollector iCollect = Get(i); + + // + AddItemToBuffer( + iCollect, + result); + } + } + else + { + // + for (int i = end - 1; i >= start; i--) + { + // + XCollector iCollect = Get(i); + + // + AddItemToBuffer( + iCollect, + result); + } + } + } + + // + // Validate an Item ... + bool IsValid( + XCollector &item, // Specified Info + bool ignoreTime = true // Ignore Times Checking ... + ) + { + // + bool result = false; + + // + // Check Each Items contains Correct Value ... + // + result = item.volume >= 0; + if (!result) + { + return result; + } + + // + result = item.maxDrawDown >= 0; + if (!result) + { + return result; + } + + // + result = item.maxAllowedVolume >= 0; + if (!result) + { + return result; + } + + // + result = item.minBalanceForOpenTrade >= 0; + if (!result) + { + return result; + } + + // + // Check Time has Proper Value ... + result = item.time > 0; + if (!result) + { + return result; + } + + // + // Check time bigger than last Time ... + int timesCount = ArraySize(mTimes); + if ( + !ignoreTime && + timesCount >= 0) + { + // + // Retrieve Last Added Times ... + datetime lastTime; + result = GetLastItem(lastTime, mTimes); + if (!result) + { + return result; + } + + // + // Compare Last Time by current Time ... + result = item.time > lastTime; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Generate Logging String Representation ... + string GenerateString( + XCollector &item, // Specified Info + string separator = "\n" // Separator Character + ) + { + // + string result = ""; + + // + result += "time: " + (string)item.time + separator; + result += "volume: " + (string)item.volume + separator; + result += "maxDrawDown: " + (string)item.maxDrawDown + separator; + result += "maxAllowedVolume: " + (string)item.maxAllowedVolume + separator; + result += "minBalanceForOpenTrade: " + (string)item.minBalanceForOpenTrade + separator; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Max Draw Up touched till now ... + double mMaxDrawUp; + + // + // Max Draw Down touched till now ... + double mMaxDrawDown; + + // + // Last Time for Checks ... + datetime mTimes[]; + + // + // Volume at the Check Time ... + double mVolumes[]; + + // + // DrawDown for each Check ... + double mMaxDrawDowns[]; + + // + // Max Allowed Volume for each check ... + double mMaxAllowedVolumes[]; + + // + // Min Balance for Open Trades for Each Check ... + double mMinBalanceForTradePrices[]; + + // + // Reset ... + void Clean() + { + // + mMaxDrawUp = 0; + mMaxDrawDown = 0; + + // + CleanBuffer(mTimes); + CleanBuffer(mVolumes); + CleanBuffer(mMaxDrawDowns); + CleanBuffer(mMaxAllowedVolumes); + CleanBuffer(mMinBalanceForTradePrices); + } + + // + // Validate Index ... + bool IsValidIndex( + int index // Specified Index + ) + { + // + bool result = false; + + // + int bufferSize = ArraySize(mTimes); + if (bufferSize <= 0) + { + return result; + } + + // + result = index <= bufferSize - 1; + + // + return result; + } +}; + +// +// a Class for Managing Volumes ... +class XCVolumeManager : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCVolumeManager( + double staticVolumeRate, // Static Volume Calculation Mutiplier + ENUM_STATIC_VOLUME_METHODS volumeMethod = X_STATIC_VOLUME_BASED_ON_DEPOSIT, // How to Calculate Static Volume + double volumeMultiplier = 0, // Volume Multiplier + double volumeMultiplierAppliedRate = 0, // Apply Volume Multiplier when Balance Increased by this rate + double maxAllowedVolume = 0, // Max Allowed Volume + double increaseMaxAllowedVolumeRate = 0 // Increase Max Allowed Volumes when Balance Increased by this rate + ) + { + // + mAccountInfo = new XCAccountInfo(); + + // + ResetForceVolumeMultiplier(); + + // + mVolumeMethod = volumeMethod; + mStaticVoluemRate = staticVolumeRate; + mVolumeMultiplier = volumeMultiplier; + mMaxAllowedVolume = maxAllowedVolume; + mVolumeMultiplierAppliedRate = volumeMultiplierAppliedRate; + mIncreaseMaxAllowedVolumeRate = increaseMaxAllowedVolumeRate; + } + + // + // Deconstructor ... + ~XCVolumeManager(void) {} + + // + // Check Volume Multiplier ... + bool CanUseVolumeMultiplier() + { + // + bool result = false; + + // + result = + mVolumeMultiplier > 0 && + mVolumeMultiplierAppliedRate > 0; + + // + return result; + } + + // + // Check Max Volume ... + bool CanUseMaxVolume() + { + // + bool result = false; + + // + result = + mMaxAllowedVolume > 0; + + // + return result; + } + + // + // Calculate Volume for Position ... + double CalculateVolume( + int numberOfOpenPositions = 0, // Number Of Open Signals + string symbol = NULL // Specify Symbol + ) + { + // + double result = 0; + + // + // Normalize Symbol ... + if (StringLen(symbol) == 0) + { + symbol = _Symbol; + } + + // + // Static Volume ... + result = GetStaticVolume(); + + // + double multiplier = GetVolumeMultiplier(); + result *= multiplier; + + // + // Check Max Allowed Volume Exists ... + double maxAllowedVolume = GetMaxAllowedVolume(); + if (maxAllowedVolume > 0) + { + // + result = + result > maxAllowedVolume + ? maxAllowedVolume + : result; + } + + // + // Check Number of Open Positions ... + if (numberOfOpenPositions >= 0) + { + // + // Decrease Volume ... + result /= (1 + numberOfOpenPositions); + } + + // + // Apply Force Volume Multiplier ... + result *= mForceVolumeMultiplier; + + // + // Retrieve Symbol Volume Info ... + result = NormalizeVolume(result, symbol, 2); + + // + return result; + } + + // + // Calculate Volume Multiplier ... + double GetVolumeMultiplier() + { + // + double result = 1; + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + bool canUseVolumeMultiplier = CanUseVolumeMultiplier(); + if ( + balance < deposit || + !canUseVolumeMultiplier) + { + return result; + } + + // + // Apply Multiplier to Volume ... + double baseGrowBalance = deposit * mVolumeMultiplierAppliedRate; + double balanceGrows = balance - deposit; + if (balanceGrows < baseGrowBalance) + { + return result; + } + + // + double applyMultiplierTimes = balanceGrows / baseGrowBalance; + double roundedApplyMultiplierTimes = MathRound(applyMultiplierTimes); + + // + if (applyMultiplierTimes < roundedApplyMultiplierTimes) + { + applyMultiplierTimes -= (1 - (roundedApplyMultiplierTimes - applyMultiplierTimes)); + } + + // + // Calculate result ... + result = applyMultiplierTimes * mVolumeMultiplier; + + // + return result; + } + + // + // Retrieve Required Balance Grows for Increase Max Allowed Volume ... + double GetIncreaseMaxAllowedVolumeBalance() + { + // + double result = 0; + + // + if ( + mMaxAllowedVolume <= 0 || + mIncreaseMaxAllowedVolumeRate <= 0) + { + return result; + } + + // + result = mAccountInfo.GetInitialBalance() * mIncreaseMaxAllowedVolumeRate; + + // + return result; + } + + // + // Calculate Max Allowed Volume ... + double GetMaxAllowedVolume() + { + // + double result = 0; + + // + // Validate Args ... + result = + mMaxAllowedVolume <= 0 + ? 0 + : mMaxAllowedVolume; + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + bool canUseMaxAllowedVolume = CanUseMaxVolume(); + if ( + balance <= deposit || + !canUseMaxAllowedVolume || + mIncreaseMaxAllowedVolumeRate <= 0) + { + // + return result; + } + + // + // Apply Multiplier to Volume ... + double baseGrowBalance = GetIncreaseMaxAllowedVolumeBalance(); + double balanceGrows = balance - deposit; + if (balanceGrows < baseGrowBalance) + { + return result; + } + + // + double applyMultiplierTimes = balanceGrows / baseGrowBalance; + double roundedApplyMultiplierTimes = MathRound(applyMultiplierTimes); + + // + if (applyMultiplierTimes < roundedApplyMultiplierTimes) + { + applyMultiplierTimes -= (1 - (roundedApplyMultiplierTimes - applyMultiplierTimes)); + } + + // + result *= applyMultiplierTimes; + + // + return result; + } + + // + // Get Static Volume ... + double GetStaticVolume() + { + // + double result = 0; + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + + // + switch (mVolumeMethod) + { + // + case X_STATIC_VOLUME_BASED_ON_DEPOSIT: + result = mStaticVoluemRate * deposit; + break; + + // + case X_STATIC_VOLUME_BASED_ON_BALANCE: + result = mStaticVoluemRate * balance; + break; + } + + // + return result; + } + + // + // Reset Froce Volume Multiplier ... + void ResetForceVolumeMultiplier() + { + mForceVolumeMultiplier = 1; + } + + // + // Retrieve Current Force Volume Multiplier ... + double GetCurrentForceVolumeMultiplier() + { + return mForceVolumeMultiplier; + } + + // + // Retrieve Next Increase Multiplier Price ... + double GetIncreaseMultiplierBalance() + { + return mAccountInfo.GetInitialBalance() * mVolumeMultiplierAppliedRate; + } + + // + // Change Force Volume Multiplier ... + void ChangeForceVolumeMultiplier( + double rate // Change rate + ) + { + // + // Normalize rate ... + if (rate <= 1) + { + rate = 1; + } + + // + mForceVolumeMultiplier = rate; + } + + // + // Increase Force Volume Multiplier ... + void IncreaseForceVolumeMultiplier() + { + mForceVolumeMultiplier += 0.5; + } + + // + // Decrease Force Volume Multiplier ... + void DecreaseForceVolumeMultiplier() + { + // + if (mForceVolumeMultiplier <= 1) + { + return; + } + + // + mForceVolumeMultiplier -= 0.5; + } + + // + // Generate Current State Log String ... + string GenerateStateString( + string separator = "\n" // Log Separator ... + ) + { + // + string result = ""; + + // + // Normallize Separator ... + if (StringLen(separator) == 0) + { + separator = "\n"; + } + + // + result += "ForceVolumeMultiplier: " + (string)mForceVolumeMultiplier + separator; + // + result += "StaticVoluemRate: " + (string)mStaticVoluemRate + separator; + result += "StaticVoluem: " + (string)GetStaticVolume() + separator; + result += "VolumeMethod: " + EnumToString(mVolumeMethod) + separator; + // + result += "VolumeMultiplier: " + (string)mVolumeMultiplier + separator; + result += "VolumeMultiplierAppliedRate: " + (string)mVolumeMultiplierAppliedRate + separator; + // + result += "MaxAllowedVolume: " + (string)mMaxAllowedVolume + separator; + result += "IncreaseMaxAllowedVolumeRate: " + (string)mIncreaseMaxAllowedVolumeRate + separator; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // an Instance of Account Info for reading Balance and Deposit and etc ... + XCAccountInfo mAccountInfo; + + // + // Force Volume Rate Multiplier ... + double mForceVolumeMultiplier; + + // + // Static Volume Calculation Mutiplier ... + double mStaticVoluemRate; + + // + // How to Calculate Static Volume ... + ENUM_STATIC_VOLUME_METHODS mVolumeMethod; + + // + // Volume Multiplier ... + double mVolumeMultiplier; + + // + // Apply Volume Multiplier when Balance Increased by this rate ... + double mVolumeMultiplierAppliedRate; + + // + // Max Allowed Volume + double mMaxAllowedVolume; + + // + // Increase Max Allowed Volumes when Balance Increased by this rate + double mIncreaseMaxAllowedVolumeRate; +}; + +// +// a Class For Managing Signals Additional Data ... +class XCSignalManager : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCSignalManager(void) + { + CleanData(); + } + + // + // Deconstructor ... + ~XCSignalManager(void) {} + + // + void Reset() + { + CleanData(); + } + + // + // Retrieve All Signals ... + void GetAll( + XSignal &result[] // Hold's Result + ) + { + // + CleanBuffer(result); + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + AddItemToBuffer( + iSignal, + result); + } + } + + // + // Count Items ... + int Count() + { + return ArraySize(mSignals); + } + + // + // Retrieve Specific Signal by Ticket ... + XSignal Get( + ulong ticket // Signals Ticket ... + ) + { + // + XSignal result = {}; + + // + // Check Exists ... + bool isExists = IsExists(ticket); + if (!isExists) + { + return result; + } + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket == ticket) + { + // + result = iSignal; + break; + } + } + + // + return result; + } + + // + // Check Signal Exists or not ... + bool IsExists( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket == ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + bool IsExists( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket == signal.ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + + // + // Add Signal ... + bool Add( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Validate Args ... + if (signal.ticket <= 0) + { + return result; + } + + // + // Chekc Signal Exists ... + bool isExists = IsExists(signal); + if (isExists) + { + return result; + } + + // + AddItemToBuffer( + signal, + mSignals); + result = true; + + // + return result; + } + + // + // Update Specific Buffer ... + bool Update( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Validate Args ... + if (signal.ticket <= 0) + { + return result; + } + + // + // Chekc Signal Exists ... + bool isExists = IsExists(signal); + if (!isExists) + { + return result; + } + + // + // Remove Signal ... + Remove(signal); + + // + // Add new One ... + AddItemToBuffer( + signal, + mSignals); + + // + result = true; + + // + return result; + } + + // + // Remove Signal ... + bool Remove( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + // Check Signal Exists ... + bool isExists = IsExists(ticket); + if (!isExists) + { + return result; + } + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + XSignal signals[]; + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket != ticket) + { + AddItemToBuffer( + iSignal, + signals); + } + } + + // + // Now we have to Clean All Signals and Replace them by signals[] buffer ... + UpdateData(signals); + + // + result = true; + return result; + } + bool Remove( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Check Signal Exists ... + bool isExists = IsExists(signal); + if (!isExists) + { + return result; + } + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + XSignal signals[]; + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket != signal.ticket) + { + AddItemToBuffer( + iSignal, + signals); + } + } + + // + // Now we have to Clean All Signals and Replace them by signals[] buffer ... + UpdateData(signals); + + // + result = true; + return result; + } + + // + // Add Or Update ... + bool AddOrUpdate( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Validate Args ... + if (signal.ticket <= 0) + { + return result; + } + + // + // Chekc Signal Exists ... + bool isExists = IsExists(signal); + if (!isExists) + { + result = Add(signal); + } + else + { + result = Update(signal); + } + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Holds Signals ... + XSignal mSignals[]; + + // + // Clean All Exists Data ... + void CleanData() + { + CleanBuffer(mSignals); + } + + // + // Update Data ... + void UpdateData( + XSignal &source[] // a Buffer which needs to Replace ... + ) + { + // + CleanData(); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + XSignal iSignal = source[i]; + + // + AddItemToBuffer( + iSignal, + mSignals); + } + } +}; + +// +// XSaherElm Trade Class ... +class XCTrade : public XCBase +{ + // + // all public features ... +public: + // + // Constructor ... + void XCTrade( + string tag, // Specify a Tag for Trader instance + string symbol, // Specify Trader Symbol + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + bool useVirtualTPSL, // Use Virtual TP SL + int maxAllowedTrades, // Specify Max Allowed Trades + double minBallanceForOpenTrades, // Specify Minimum Balance for Open Trades + double minAllowedFreeMarginForOpenTrades, // Specify Minimum Free Marging for Open Trades + bool useSignalProtector = true // Specify Use Signal Protector or not + ) + { + // + mTag = tag; + mSymbol = symbol; + mSlippage = slippage; + mMagicNumber = magicNumber; + mUseVirtualTPSL = useVirtualTPSL; + mMaxAllowedTrades = maxAllowedTrades; + mMinBallanceForOpenTrades = minBallanceForOpenTrades; + mMinAllowedFreeMarginForOpenTrades = minAllowedFreeMarginForOpenTrades; + + // + mTrader = new XSCTrade(); + + // + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + mSignalManager = new XCSignalManager(); + + // + Reset(); + } + + // + // Deconstructor ... + void ~XCTrade() + { + } + + // + // START Configuring Class Functions ... + // + + // + // Reset all Variables ... + void Reset() + { + // + mSignalManager.Reset(); + + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + } + + // + // END Configuring Class Functions ... + // + + // + // START Count ... + // + + // + // Count Open Positions ... + int Count() + { + // + int result = 0; + + // + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + result++; + } + + // + return result; + } + + // + // Count Longs ... + int CountLongs() + { + int result = CountByType(X_SIGNAL_LONG); + return result; + } + + // + // Count Shorts ... + int CountShorts() + { + int result = CountByType(X_SIGNAL_SHORT); + return result; + } + + // + // Count Specific Type Of Positions ... + int CountByType(ENUM_POSITION_TYPE type) + { + // + int result = 0; + + // + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + if (mPositionInfo.PositionType() != type) + { + continue; + } + + // + result++; + } + + // + return result; + } + + // + // Count By Type ... + int CountByType(ENUM_X_SIGNAL_TYPE type) + { + // + // Validate Args ... + ENUM_POSITION_TYPE mType = POSITION_TYPE_BUY; + if (type == X_SIGNAL_LONG) + { + mType = POSITION_TYPE_BUY; + } + else if (type == X_SIGNAL_SHORT) + { + mType = POSITION_TYPE_SELL; + } + + // + int result = CountByType(mType); + return result; + } + + // + // END Count ... + // + + // + // START Retrieve ... + // + + // + // Retrieve Specified Position by it's Ticket ... + XSignal GetSignal( + ulong ticket // Specified Ticket + ) + { + // + XSignal result = {}; + + // + result = PositionToSignal(ticket); + + // + return result; + } + + // + // Get Last Signal ... + XSignal GetLastSignal() + { + // + XSignal result = {}; + + // + XSignal signals[]; + GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + result = signals[0]; + + // + return result; + } + + // + // Retrieve Last Executed Signal ... + bool GetLastSignal(XSignal &signal) + { + // + bool result = false; + + // + XSignal signals[]; + GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + signal = signals[0]; + result = true; + + // + return result; + } + + // + // Retrieve All Positions ... + void GetSignals( + XSignal &result[] // Holds Result ... + ) + { + // + CleanBuffer(result); + + // + int totalPositions = PositionsTotal(); + for (int i = 0; i < totalPositions; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + // Position to Signal ... + XSignal signal = PositionToSignal(i); + Add( + signal, + result); + } + } + + // + // Retrieve Type Specific Signals ... + void GetSignals( + XSignal &result[], // Holds Result ... + ENUM_X_SIGNAL_TYPE type // Specified Sginal Type ... + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals(signals); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = signalsCount - 1; i >= 0; i--) + { + // + XSignal iSignal = signals[i]; + + // + if (type == X_SIGNAL_UNKNOWN) + { + Add( + iSignal, + result); + } + else if (iSignal.type == type) + { + Add( + iSignal, + result); + } + } + } + + // + // Filter Signals By Searching Comments ... + void FilterSignals( + XSignal &result[], // Holds Result ... + const string query, // Search in Comment Qeury ... + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specified Sginal Type ... + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + + // + // Validate Args ... + if ( + StringLen(query) <= 0 || + signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + int queryPos = StringFind( + iSignal.comment, + query); + bool isContains = queryPos > -1; + if (!isContains) + { + continue; + } + + // + Add( + iSignal, + result); + } + } + + // + // Get All Trades Which Candle Passed after Open ... + void GetOldSignals( + XSignal &result[], // Holds Result + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + // Normalize Period ... + if (period == NULL) + { + period = _Period; + } + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Current Time Frame Candle Index ... + int currentBarIndex = 0; + + // + // Loop through Positions ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + // Retrieve Trade Open Bar Index based on Current Period ... + int tradeOpenBarIndex = iBarShift( + mSymbol, + period, + iSignal.time); + + // + // Calculate Trade Life ... + int diff = MathAbs(currentBarIndex - tradeOpenBarIndex); + + // + bool isPassed = diff >= life; + if (isPassed) + { + // + Add( + iSignal, + result); + } + } + } + + // + // Get In Profit Signals ... + void GetInProfitSignals( + XSignal &result[], // Holds Result + double minProfit = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isPassed = minProfit <= 0 && iSignal.profit > 0 + ? true + : iSignal.profit >= minProfit; + if (isPassed) + { + Add( + iSignal, + result); + } + } + } + + // + // Get In Drawdown Signals ... + void GetInDrawdownSignals( + XSignal &result[], // Holds Result + double maxDrawDown = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isPassed = maxDrawDown <= 0 && iSignal.profit < 0 + ? true + : iSignal.profit >= (-1 * maxDrawDown); + if (isPassed) + { + Add( + iSignal, + result); + } + } + } + + // + // Retrieve Max In Draw Down Trade ... + XSignal GetMaxInDrawdownSignal( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + XSignal result = {}; + + // + XSignal signals[]; + GetInDrawdownSignals( + signals, + 0, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + result = + (result.ticket <= 0 && + result.profit == 0) || + result.profit > iSignal.profit + ? iSignal + : result; + } + + // + return result; + } + + // + // Calculate Profits Of all Open Signals ... + double GetSignalsProfit( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + double result = 0; + + // + XSignal signals[]; + GetSignals(signals, type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + result += iSignal.profit; + } + + // + return result; + } + + // + // END Retrieve ... + // + + // + // START Signal Execution Actions ... + // + + // + // Execute a Signal in Market ... + ENUM_EXECUTION_SIGNAL_RESULT ExecuteSignal( + XSignal &signal, // Specified Signal + bool ignoreNumberOfTraes = false, // Ignore Number of Trades + bool checkAccountConditions = true // Check Account Balance, Equity and Free Margin for Signal Execution + ) + { + // + ENUM_EXECUTION_SIGNAL_RESULT result = X_TRADER_UNKNOWN_ERROR; + + // + // Validate Signal ... + bool isValid = IsValidSignal(signal); + if (!isValid) + { + // + result = X_TRADER_INVALID_SIGNAL_ERROR; + return result; + } + + // + // Check Account Equity ... + bool isEquityPassed = !checkAccountConditions + ? true + : IsEquityReadyForTrade(); + if (!isEquityPassed) + { + // + result = X_TRADER_NOT_ENOUGH_EQUITY_ERROR; + return result; + } + + // + // Check Account Balance ... + bool isBalancePassed = !checkAccountConditions + ? true + : IsBalanceReadyForTrade(); + if (!isBalancePassed) + { + // + result = X_TRADER_NOT_ENOUGH_BALANCE_ERROR; + return result; + } + + // + // Check Account FreeMargin ... + bool isFreeMarginPassed = !checkAccountConditions + ? true + : IsFreeMarginReadyForTrade(); + if (!isFreeMarginPassed) + { + // + result = X_TRADER_NOT_ENOUGH_MARIGIN_ERROR; + return result; + } + + // + // Check Number of Open Trades ... + int openTradesCount = Count(); + bool isTradeCountPassed = ignoreNumberOfTraes + ? true + : openTradesCount < mMaxAllowedTrades; + if (!isTradeCountPassed) + { + // + result = X_TRADER_MAX_TRADES_REACHED_ERROR; + return result; + } + + // + bool isExecuted = + signal.type == X_SIGNAL_LONG + ? Buy( + signal.volume, + signal.entry, + mUseVirtualTPSL + ? 0 + : signal.sl, + mUseVirtualTPSL + ? 0 + : signal.tp, + signal.comment) + : signal.type == X_SIGNAL_SHORT + ? Sell( + signal.volume, + signal.entry, + mUseVirtualTPSL + ? 0 + : signal.sl, + mUseVirtualTPSL + ? 0 + : signal.tp, + signal.comment) + : false; + if (isExecuted) + { + // + ulong ticket = PositionGetTicket(PositionsTotal() - 1); + + // + signal.id = ticket; + signal.ticket = ticket; + + // + AddOrUpdateSignalInfo(signal); + + // + result = X_TRADER_SUCCEED_EXECUTION; + } + + // + return result; + } + + // + // This Function, Handling Following Works on Open Positions: + // - Close On SL if Reached ... + // - Close On TP if Reached ... + // - Make Risk Free Trades ... + bool HandleSignals( + XTraderHandlerResult &handlerResult, // Holds Result + bool ignoreRiskFree = false // Ignore Risk Free Trdaes + ) + { + // + bool result = false; + + // + // Cleanup Result ... + CleanBuffer(handlerResult.sl); + CleanBuffer(handlerResult.tp); + CleanBuffer(handlerResult.rf); + + // + // Reading Open Positions ... + XSignal signals[]; + GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + double deviation = mSlippage * GetPoints(mSymbol); + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isLong = iSignal.type == X_SIGNAL_LONG; + double entry = GetEntry(iSignal.symbol, iSignal.type); + double exit = GetExit(iSignal.symbol, iSignal.type); + double spread = GetSpread(iSignal.symbol); + double appliedTPPrice = + iSignal.tp > 0 + ? isLong + ? iSignal.tp - deviation + : iSignal.tp + deviation + : 0; + double appliedSLPrice = + iSignal.sl > 0 + ? isLong + ? iSignal.sl + deviation + : iSignal.sl - deviation + : 0; + + // + double usedPrice = exit; + + // + bool isSLTouched = + isLong + ? usedPrice <= appliedSLPrice + : usedPrice >= appliedSLPrice; + + // + bool isTPTouched = + isLong + ? usedPrice >= appliedTPPrice + : usedPrice <= appliedTPPrice; + + // + // Handle SL ... + if ( + // + iSignal.sl > 0 + // + && + // + isSLTouched + // + && + // + mUseVirtualTPSL) + { + // + string comment = GenerateSignalSLComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + AddItemToBuffer( + iSignal, + handlerResult.sl); + } + } + + // + // Handle TP ... + if ( + // + iSignal.tp > 0 + // + && + // + isTPTouched + // + && + // + mUseVirtualTPSL) + { + // + string comment = GenerateSignalTPComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + AddItemToBuffer( + iSignal, + handlerResult.tp); + } + } + + // + // Handle Risk Free ... + if ( + // + !ignoreRiskFree + // + && + // + iSignal.riskFreeStep > 0 + // + && + // + iSignal.riskFreeRate > 0 + // + ) + { + // + // Make Signals Risk Free Only if Signal In Profit ... + if (iSignal.profit <= 0) + { + continue; + } + + // + // Base Price is ENTRY, then Last Level, in each level SL is Last Level ... + // + // Calculate Risk Free Level/Multiplier ... + double level = 0; + double roundedLevel = 0; + double rStepPrice = PipsToPrice(iSignal.riskFreeStep); + double rBasePrice = + iSignal.sl > 0 && + iSignal.sl > iSignal.entry + ? iSignal.sl + : iSignal.entry; + + // + double exit = GetExit(iSignal.type); + + // + // Check Base Price for Signal reached with Exit Price ... + bool isExitPriceReachedBasePrice = + isLong + ? exit > rBasePrice + : exit < rBasePrice; + if (!isExitPriceReachedBasePrice) + { + continue; + } + + // + // Calculate Risk Free Step Multiplier ... + level = MathAbs(exit - rBasePrice) / rStepPrice; + + // + // Check Level Must Bigger than 1 ... + if (level < 1) + { + continue; + } + + // + // Normalize Level ... + roundedLevel = MathRound(level); + if (level < roundedLevel) + { + level -= (1 - (roundedLevel - level)); + } + else if (level > roundedLevel) + { + level -= (level - roundedLevel); + } + + // + // Generate Comment ... + string comment = GenerateSignalRFComment(iSignal, (int)level); + + // + // Calculate SL ... + double slDistance = spread; + double sl = + isLong + ? exit - slDistance + : exit + slDistance; + + // + // Increase TP One Level if Exists ... + double tp = iSignal.tp; + if (iSignal.tp > 0 && (isLong + ? iSignal.tp < rBasePrice + rStepPrice + : iSignal.tp > rBasePrice - rStepPrice)) + { + // + tp = + isLong + ? iSignal.tp + rStepPrice + : iSignal.tp - rStepPrice; + } + + // + double rVolume = NormalizeVolume((iSignal.volume * iSignal.riskFreeRate), iSignal.symbol); + + // + // Update Signal Volume ... + double volume = iSignal.volume - rVolume; + + // + bool isClosedPartial = + ClosePartial( + iSignal.ticket, + rVolume, + comment); + if (isClosedPartial) + { + // + bool isModified = true; + if (!mUseVirtualTPSL) + { + // + isModified = Modify( + iSignal.ticket, + sl, + tp, + comment); + } + + // + if (isModified) + { + // + // Try to Update Signal ... + XSignal s = mSignalManager.Get(iSignal.ticket); + + // + // Apply Changes on Signal ... + s.sl = sl; + s.tp = tp; + s.volume = volume; + + // + // Update Signal ... + bool isUpdated = false; + bool isRemoved = false; + if (volume == 0) + { + isRemoved = mSignalManager.Remove(s); + } + else if (volume > 0) + { + isUpdated = mSignalManager.AddOrUpdate(s); + } + if ( + isUpdated || + isRemoved) + { + // + AddItemToBuffer( + s, + handlerResult.rf); + } + } + } + else + { + mSignalManager.Remove(iSignal.ticket); + } + } + } + + // + result = + ArraySize(handlerResult.tp) > 0 || + ArraySize(handlerResult.sl) > 0 || + ArraySize(handlerResult.rf) > 0; + + // + return result; + } + + // + // Close All Trades ... + void CloseSignals( + XSignal &result[], // Holds Result + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalForceCloseComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // Close Pyramid Signals ... + void CloseInPyramidSignals( + XSignal &result[], // Holds Result + double pyramid = 0, // Close Pyramid Profit + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + double profit = 0; + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + profit += iSignal.profit; + } + + // + // Normalize Pyramid ... + if (pyramid < 0) + { + pyramid = 0; + } + + // + if (profit > pyramid) + { + CloseSignals(result); + } + } + + // + // Close All Trades Which Candle Passed after Open ... + void CloseOldSignals( + XSignal &result[], // Holds Result + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetOldSignals( + signals, + life, + period, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalAgeComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // Close In Profit Signals ... + void CloseInProfitSignals( + XSignal &result[], // Holds Result + double minProfit = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetInProfitSignals( + signals, + minProfit, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalProfitComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // Close In Drawdown Signals ... + void CloseInDrawdownSignals( + XSignal &result[], // Holds Result + double maxDrawDown = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetInDrawdownSignals( + signals, + maxDrawDown, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalProfitComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // END Signal Execution Actions ... + // + + // + // START Actions ... + // + + // + // Force Open a Buy/Long Position ... + bool Buy( + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + const string comment = "" // comment + ) + { + // + bool result = false; + + // + result = mTrader.Buy( + volume, + mSymbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + 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; + + // + result = mTrader.BuyLimit( + volume, + price, + mSymbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + 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; + + // + result = mTrader.BuyStop( + volume, + price, + mSymbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Force Open a Sell/Short Position ... + bool Sell( + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + const string comment = "" // comment + ) + { + // + bool result = false; + + // + result = mTrader.Sell( + volume, + mSymbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + 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; + + // + result = mTrader.SellLimit( + volume, + price, + mSymbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + 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; + + // + result = mTrader.SellStop( + volume, + price, + mSymbol, + 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 + const string comment = "" // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + if (tp <= 0 && sl <= 0) + { + result = false; + return result; + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment); + if (result) + { + // + if (mSignalManager.IsExists(ticket)) + { + // + XSignal signal = GetSignal(ticket); + + // + mSignalManager.Update(signal); + } + } + + // + 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); + if (result) + { + // + if (mSignalManager.IsExists(ticket)) + { + mSignalManager.Remove(ticket); + } + } + + // + return result; + } + + // + // 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); + if (result) + { + // + if (mSignalManager.IsExists(ticket)) + { + // + XSignal signal = GetSignal(ticket); + + // + mSignalManager.Update(signal); + } + } + + // + return result; + } + + // + // END Actions ... + // + + // + // START Account Related ... + // + + // + // Retrieve Minimum Balance For Open Trades ... + double GetMinBalanceForOpenTrades() + { + // + double result = mMinBallanceForOpenTrades; + + // + double balance = mAccountInfo.GetBalance(); + double deposit = mAccountInfo.GetInitialBalance(); + if (balance > deposit) + { + // + double rate = mMinBallanceForOpenTrades / deposit; + + // + double ratedBalance = balance * rate; + + // + result = MathMax(mMinBallanceForOpenTrades, ratedBalance); + } + + // + return result; + } + + // + // Check Account Has Minimum Balance For Trade ... + bool IsBalanceReadyForTrade() + { + // + bool result = false; + + // + double minBalance = GetMinBalanceForOpenTrades(); + result = mAccountInfo.GetBalance() >= minBalance; + + // + return result; + } + + // + // Check Free Margin Has Enough For Trade ... + bool IsFreeMarginReadyForTrade() + { + // + bool result = false; + + // + double freeMargin = mAccountInfo.GetFreeMargin(); + + // + result = freeMargin >= mMinAllowedFreeMarginForOpenTrades; + + // + return result; + } + + // + // Check Equity Has Enough For Trade ... + bool IsEquityReadyForTrade() + { + // + bool result = false; + + // + double equity = mAccountInfo.GetEquity(); + + // + result = equity >= mMinAllowedFreeMarginForOpenTrades; + + // + return result; + } + + // + // END Account Related ... + // + + // + // START Signal Related ... + // + + // + // Validate Signal ... + bool IsValidSignal( + XSignal &signal // Specified Signal for Execution + ) + { + // + bool result = false; + + // + // Validate Signal Type ... + result = signal.type != X_SIGNAL_UNKNOWN; + if (!result) + { + return result; + } + + // + // Check Symbol ... + result = StringLen(signal.symbol) == 0 ? true : signal.symbol == mSymbol; + if (!result) + { + return result; + } + + // + // Check magic number ... + result = signal.magicNumber <= 0 ? true : signal.magicNumber == mMagicNumber; + if (!result) + { + return result; + } + + // + // Check Entry ... + result = signal.entry > 0; + if (!result) + { + return result; + } + + // // + // // Check SL ... + // // For Fix RiskFree Issues Ignore this ... + // result = signal.sl == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.sl < signal.entry + // : signal.sl > signal.entry; + // if (!result) + // { + // return result; + // } + + // + // Check TP ... + result = signal.tp == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.tp > signal.entry + : signal.tp < signal.entry; + if (!result) + { + return result; + } + + // + // Check Volume ... + result = signal.volume > 0; + if (!result) + { + return result; + } + + // + // Check Time ... + result = signal.time > 0; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Get Signal InDirection (Reversal) Type ... + ENUM_X_SIGNAL_TYPE GetSignalIndirectionType( + XSignal &signal // Specified Signal + ) + { + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + switch (signal.type) + { + // + case X_SIGNAL_LONG: + result = X_SIGNAL_SHORT; + break; + + // + case X_SIGNAL_SHORT: + result = X_SIGNAL_LONG; + break; + } + + // + return result; + } + + // + // Get Signal InDirection (Reversal) Type ... + ENUM_X_SIGNAL_TYPE GetIndirectionSignalType( + ENUM_X_SIGNAL_TYPE type // Specified Type + ) + { + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + switch (type) + { + // + case X_SIGNAL_LONG: + result = X_SIGNAL_SHORT; + break; + + // + case X_SIGNAL_SHORT: + result = X_SIGNAL_LONG; + break; + } + + // + return result; + } + + // + // Calculate SignalAge ... + int GetSignalAge( + datetime time // Signal Execution Time + ) + { + // + int result = 0; + + // + // Validate Arg ... + if (time <= 0) + { + return result; + } + + // + int sIndex = iBarShift( + mSymbol, + _Period, + time); + + // + datetime cTime = iTime( + mSymbol, + _Period, + 0); + int cIndex = iBarShift( + mSymbol, + _Period, + cTime); + + // + result = MathAbs(cIndex - sIndex); + + // + return result; + } + int GetSignalAge( + datetime time, // Signal Execution Time + ENUM_TIMEFRAMES period // Specify Time Frame + ) + { + // + int result = 0; + + // + // Validate Arg ... + if (time <= 0) + { + return result; + } + + // + int sIndex = iBarShift( + mSymbol, + period, + time); + + // + datetime cTime = iTime( + mSymbol, + period, + 0); + int cIndex = iBarShift( + mSymbol, + _Period, + cTime); + + // + result = MathAbs(cIndex - sIndex); + + // + return result; + } + int GetSignalAge( + XSignal &signal // Specified Signal + ) + { + // + int result = 0; + + // + // Validate Arg ... + if ( + signal.time <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalAge(signal.time); + + // + return result; + } + int GetSignalAge( + XSignal &signal, // Specify Signal + ENUM_TIMEFRAMES period // Specify Time Frame + ) + { + // + int result = 0; + + // + // Validate Arg ... + if ( + signal.time <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalAge( + signal.time, + period); + + // + return result; + } + + // + // Prepare a Signall ... + XSignal GenerateSignal( + ENUM_X_SIGNAL_TYPE type, // Signal Type + double tp = 0, // Take Profit + double sl = 0, // Stop Loss + double volume = 0, // Volume + double riskFreeStep = 0, // Risk Free Step Price + double riskFreeRate = 0 // Risk Free Rate + ) + { + // + XSignal result = {}; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + // Check Signal Type ... + bool isLong = type == X_SIGNAL_LONG; + + // + // Retrieve entry Price ... + double entry = GetEntry(mSymbol, type); + double spread = GetSpread(mSymbol); + + // + result.tp = tp; + result.sl = sl; + result.type = type; + result.entry = entry; + result.symbol = mSymbol; + result.magicNumber = mMagicNumber; + result.riskFreeStep = riskFreeStep; + result.riskFreeRate = riskFreeRate; + result.time = iTime(mSymbol, _Period, 0); + result.volume = NormalizeVolume(volume, mSymbol); + + // + // Since we Use signal instance to Generate Comment, this must be at the end ... + result.comment = GenerateSignalComment(result); + + // + return result; + } + + // + // Convert a Signal to String Representation ... + string ToString( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + if (!IsValid(signal, mMagicNumber) || signal.ticket <= 0) + { + return result; + } + + // + // TICKET ... + // it is very importants since they hold position info ... + result += X_SIGNAL_TICKET + "(" + (string)signal.ticket + ")"; + + // + // TYPE ... + string typeStr = GetSignalType(signal.type); + result += "_" + X_SIGNAL_TYPE + "(" + typeStr + ")"; + + // + // TP ... + result += "_" + X_SIGNAL_TP + "(" + (string)signal.tp + ")"; + + // + // SL ... + result += "_" + X_SIGNAL_SL + "(" + (string)signal.sl + ")"; + + // + // RFS ... + result += "_" + X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.riskFreeStep + ")"; + + // + // RFR ... + result += "_" + X_SIGNAL_RISKFREE_RATE + "(" + (string)signal.riskFreeRate + ")"; + + // + return result; + } + + // + // Generate Comments for Specific Signal ... + string GenerateSignalComment( + ENUM_X_SIGNAL_TYPE type, // Specify Kind Signal Type + double volume, // Signal Volume + bool isCrossSignal = false // Specify Signal Cross + ) + { + // + string result = ""; + + // + string typeStr = GetSignalType(type); + if ( + volume <= 0 || + StringLen(typeStr) == 0) + { + return result; + } + + // + volume = NormalizeVolume(volume, mSymbol); + + // + result = mTag + (!isCrossSignal ? "" : "_Cross_") + "_" + typeStr; + + // + return result; + } + string GenerateSignalComment( + XSignal &signal, // Specified Signal + bool isCrossSignal = false // Specify Signal Cross + ) + { + // + string result = GenerateSignalComment( + signal.type, + signal.volume, + isCrossSignal + // + ); + + // + return result; + } + + // + // Generate Signal RF TP Comment ... + string GenerateSignalRFComment( + XSignal &signal, // Specified Signal + int level // Which Step of RFS + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + double exit = NormalizePrice(GetExit(signal.symbol, signal.type), signal.symbol); + + // + string prefix = X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.ticket + ")"; + // + result = + // + level > 0 + ? prefix + "_" + (string)level + ": " + (string)exit + : prefix + ": " + (string)exit; + // + ; + + // + return result; + } + + // + // Generate Signal TP Comment ... + string GenerateSignalTPComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + double exit = NormalizePrice(GetExit(signal.symbol, signal.type), signal.symbol); + + // + result = + // + X_SIGNAL_TP + "(" + (string)signal.ticket + "): " + (string)exit; + // + ; + + // + return result; + } + + // + // Generate Signal SL Comment ... + string GenerateSignalSLComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + double exit = NormalizePrice(GetExit(signal.symbol, signal.type), signal.symbol); + + // + result = + // + X_SIGNAL_SL + "(" + (string)signal.ticket + "): " + (string)exit; + // + ; + + // + return result; + } + + // + // Generate Signal Profit Comment ... + string GenerateSignalProfitComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + result = + // + "Profit(" + (string)signal.ticket + "): " + (string)signal.profit; + // + ; + + // + return result; + } + + // + // Generate Signal Force Close Comment ... + string GenerateSignalForceCloseComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + result = + // + "FC(" + (string)signal.ticket + "): " + (string)signal.profit; + // + ; + + // + return result; + } + + // + // Generate Signal Age Comment ... + string GenerateSignalAgeComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + int age = GetSignalAge(signal); + + // + result = + // + "(" + (string)signal.ticket + ") A: " + (string)age + ", P:" + (string)signal.profit; + // + ; + + // + return result; + } + + // + // Generate a Signal Object name for Draw Events On Chart ... + string GenerateSignalObjectName( + ulong ticket // Specify Ticket + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + // TICKET ... + // it is very importants since they hold position info ... + result += "T(" + (string)ticket + ")"; + + // + return result; + } + string GenerateSignalObjectName( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (!IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GenerateSignalObjectName(signal.ticket); + + // + return result; + } + + // + // Genrate a Signal Event Object Name ... + string GenerateSignalEventObjectName( + ulong ticket // Specify Ticket + ) + { + // + string result = ""; + + // + result = GenerateSignalObjectName(ticket) + "_Event"; + + // + return result; + } + string GenerateSignalEventObjectName( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + result = GenerateSignalEventObjectName(signal.ticket); + + // + return result; + } + + // + // END Signal Related ... + // + + // + // START Deals ... + // + + // + // Count Deals ... + int DealsCount( + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + int result = 0; + + // + XDeal deals[]; + GetDeals( + deals, + start, + end); + result = ArraySize(deals); + + // + return result; + } + + // + // Retrieve All Deals ... + void GetDeals( + XDeal &result[], // Hold's Result + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + CleanBuffer(result); + + // + // Select History if Start and End date provided ... + if (start > -1) + { + // + // Normalize End date ... + if (end == -1) + { + end = TimeCurrent(); + } + + // + bool isSelect = HistorySelect(start, end); + if (!isSelect) + { + return; + } + } + + // + int total = HistoryDealsTotal(); + if (total <= 0) + { + return; + } + + // + // Loop ... + for (int i = total - 1; i >= 0; i--) + { + // + // Select by Index ... + bool isSelect = mDealInfo.SelectByIndex(i); + if (!isSelect) + { + continue; + } + + // + // Check Magic ... + ulong magic = mDealInfo.Magic(); + bool isMagicSame = magic == mMagicNumber; + if (!isMagicSame) + { + continue; + } + + // + // Check Symbol ... + string symbol = mDealInfo.Symbol(); + bool isSymbolSame = symbol == mSymbol; + if (!isSymbolSame) + { + continue; + } + + // + XDeal deal = ToXDealByIndex(i); + + // + Add( + deal, + result); + } + } + + // + // Retrieve Last Deal ... + XDeal GetLastDeal() + { + // + XDeal result = {}; + + // + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount <= 0) + { + return result; + } + + // + result = deals[0]; + + // + return result; + } + + // + // END Deals ... + // + + // + // START Orders ... + // + + // + // Count Orders ... + int OrdersCount( + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + int result = 0; + + // + XOrder orders[]; + GetOrders( + orders, + start, + end); + result = ArraySize(orders); + + // + return result; + } + + // + // Retrieve Orders ... + void GetOrders( + XOrder &result[], // Hold's Result + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + CleanBuffer(result); + + // + // Select History if Start and End date provided ... + if (start > -1) + { + // + // Normalize End date ... + if (end == -1) + { + end = TimeCurrent(); + } + + // + bool isSelect = HistorySelect(start, end); + if (!isSelect) + { + return; + } + } + + // + int total = HistoryOrdersTotal(); + if (total <= 0) + { + return; + } + + // + // Loop ... + for (int i = total - 1; i >= 0; i--) + { + // + // Select by Index ... + bool isSelect = mOrderInfo.SelectByIndex(i); + if (!isSelect) + { + continue; + } + + // + // Check Magic ... + ulong magic = mOrderInfo.Magic(); + bool isMagicSame = magic == mMagicNumber; + if (!isMagicSame) + { + continue; + } + + // + // Check Symbol ... + string symbol = mOrderInfo.Symbol(); + bool isSymbolSame = symbol == mSymbol; + if (!isSymbolSame) + { + continue; + } + + // + XOrder order = ToXOrderByIndex(i); + + // + Add( + order, + result); + } + } + + // + // Retrieve Last Order ... + XOrder GetLastOrder() + { + // + XOrder result = {}; + + // + XOrder orders[]; + GetOrders(orders); + int ordersCount = ArraySize(orders); + if (ordersCount <= 0) + { + return result; + } + + // + result = orders[0]; + + // + return result; + } + + // + // END Orders ... + // + + // + // START OnTrade Handlers ... + // + + // + // Handle OnTrade Event ... + void HandleOnTradeEvent( + XOnTradeHandlerResult &result // Hold's Result + ) + { + // + if (mScanStarted) + { + ProcessOnTradeContext(result); + } + else + { + InitOnTradeContext(); + } + } + + // + // END OnTrade Handlers ... + // + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + // all protected features ... +protected: + // + // all private features ... +private: + // + // Specified Unique Tag ... + string mTag; + + // + // which Symbol ... + string mSymbol; + + // + // using deviation, it must be in Point ... + int mSlippage; + + // + // using magic number ... + ulong mMagicNumber; + + // + // Detect Using Virtual TP or SL ... + bool mUseVirtualTPSL; + + // + // Specify Max Allowed Trades + int mMaxAllowedTrades; + + // + // Minimum Free Marging for Open Trades + double mMinAllowedFreeMarginForOpenTrades; + + // + // Minimum Balance for Open Trades + double mMinBallanceForOpenTrades; + + // + // using CTrade instance ... + XSCTrade mTrader; + + // + // Deals Info ... + CDealInfo mDealInfo; + + // + // Order Info ... + COrderInfo mOrderInfo; + + // + // An Instance Of XCAccount Info for Handling Account Related Actions ... + XCAccountInfo mAccountInfo; + + // + // using PositionInfo instance ... + CPositionInfo mPositionInfo; + + // + // Signal Manager ... + XCSignalManager mSignalManager; + + // + // START OnTrade Handlers ... + // + + // + 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( + XOnTradeHandlerResult &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) + { + // + LogMessage("Failed to Load OnTrade Context History ..."); + + // + 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(); + + // + // load history ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + // + LogMessage("Failed to Load OnTrade Context History ..."); + + // + return; + } + + // + // get the current value ... + mOrdersCount = OrdersTotal(); + mPositionsCount = PositionsTotal(); + mDealsCount = HistoryDealsTotal(); + mHistoryOrdersCount = HistoryOrdersTotal(); + + // + mScanStarted = true; + } + + // + // END OnTrade Handlers ... + // + + // + // START Signal Private ... + // + + // + // Add Or Update Signal ... + void AddOrUpdateSignalInfo( + XSignal &signal // Specified Signal + ) + { + // + bool isExists = mSignalManager.IsExists(signal); + if (isExists) + { + mSignalManager.Remove(signal.ticket); + } + + // + bool isAddOrUpdated = mSignalManager.AddOrUpdate(signal); + if (isAddOrUpdated) + { + // + color longColor = clrAqua; + color shortColor = clrFuchsia; + + // + DrawSignalShape( + signal, + longColor, + shortColor); + } + } + + // + // Retrieve Signal String From Chart Event ... + XSignal RetrieveSignal( + ulong ticket // Specify Position Ticket + ) + { + // + XSignal result = {}; + + // + if (ticket <= 0) + { + return result; + } + + // + result = mSignalManager.Get(ticket); + + // + return result; + } + void RetrieveSignal( + XSignal &signal // Specified Signal + ) + { + + // + XSignal tSignal = mSignalManager.Get(signal.ticket); + + // + // Fill signal by tSignal Data ... + // since tese properties may change in signal manipulation times ... + signal.tp = tSignal.tp; + signal.sl = tSignal.sl; + signal.riskFreeStep = tSignal.riskFreeStep; + signal.riskFreeRate = tSignal.riskFreeRate; + } + + // + // Convert Position to Signal by Index ... + XSignal PositionToSignal(int index) + { + // + XSignal result = {}; + + // + if (!mPositionInfo.SelectByIndex(index)) + { + return result; + } + + // + ulong ticket = mPositionInfo.Ticket(); + result = PositionToSignal(ticket); + + // + return result; + } + + // + // Position To Signal by Ticket ... + XSignal PositionToSignal(ulong ticket) + { + // + XSignal result = {}; + + // + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + bool isExists = mSignalManager.IsExists(ticket); + if (isExists) + { + result = RetrieveSignal(ticket); + } + + // + // Ticket ... + result.ticket = mPositionInfo.Ticket(); + + // + // ID ... + result.id = mPositionInfo.Identifier(); + + // + // Symbol ... + result.symbol = mPositionInfo.Symbol(); + + // + // Type ... + ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)mPositionInfo.PositionType(); + ENUM_X_SIGNAL_TYPE type = pType == POSITION_TYPE_BUY ? X_SIGNAL_LONG : X_SIGNAL_SHORT; + result.type = type; + + // + // MagicNumber ... + result.magicNumber = mPositionInfo.Magic(); + + // + // Entry/Open Price ... + result.entry = mPositionInfo.PriceOpen(); + + // + // Take Profit ... + result.tp = result.tp <= 0 && mPositionInfo.TakeProfit() > 0 + ? mPositionInfo.TakeProfit() + : result.tp; + + // + // Stop Loss ... + result.sl = result.sl <= 0 && mPositionInfo.StopLoss() > 0 + ? mPositionInfo.StopLoss() + : result.sl; + + // + // Profit ... + result.profit = mPositionInfo.Profit(); + + // + // Time ... + result.time = mPositionInfo.Time(); + + // + // Volume ... + result.volume = mPositionInfo.Volume(); + + // + // Comment ... + result.comment = mPositionInfo.Comment(); + + // + return result; + } + + // + // Converts a Deal to XDeal by Index ... + XDeal ToXDealByIndex(int index) + { + // + XDeal result = {}; + + // + bool isSelect = mDealInfo.SelectByIndex(index); + if (!isSelect) + { + return result; + } + + // + // Read Deal Ticket ... + ulong ticket = mDealInfo.Ticket(); + result = ToXDealByTicket(ticket); + + // + return result; + } + + // + // Converts a Deal to XDeal by Ticket ... + XDeal ToXDealByTicket(ulong ticket) + { + // + XDeal result = {}; + + // + mDealInfo.Ticket(ticket); + + // + result.time = mDealInfo.Time(); + result.swap = mDealInfo.Swap(); + result.magic = mDealInfo.Magic(); + result.order = mDealInfo.Order(); + result.entry = mDealInfo.Entry(); + result.price = mDealInfo.Price(); + result.ticket = mDealInfo.Ticket(); + result.symbol = mDealInfo.Symbol(); + result.type = mDealInfo.DealType(); + result.profit = mDealInfo.Profit(); + result.volume = mDealInfo.Volume(); + result.comment = mDealInfo.Comment(); + result.positionId = mDealInfo.PositionId(); + result.commission = mDealInfo.Commission(); + result.reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + return result; + } + + // + // Convert an Order to XOrder by Index ... + XOrder ToXOrderByIndex(int index) + { + // + XOrder result = {}; + + // + bool isSelect = mOrderInfo.SelectByIndex(index); + if (!isSelect) + { + return result; + } + + // + ulong ticket = mOrderInfo.Ticket(); + result = ToXOrderByTicket(ticket); + + // + return result; + } + + // + // Convert an Order to XOrder by Ticket ... + XOrder ToXOrderByTicket(ulong ticket) + { + // + XOrder result = {}; + + // + bool isSelect = mOrderInfo.Select(ticket); + if (!isSelect) + { + return result; + } + + // + result.state = mOrderInfo.State(); + result.magic = mOrderInfo.Magic(); + result.ticket = mOrderInfo.Ticket(); + result.symbol = mOrderInfo.Symbol(); + result.type = mOrderInfo.OrderType(); + result.comment = mOrderInfo.Comment(); + result.stopLoss = mOrderInfo.StopLoss(); + result.typeTime = mOrderInfo.TypeTime(); + result.timeDone = mOrderInfo.TimeDone(); + result.timeSetup = mOrderInfo.TimeSetup(); + result.positionId = mOrderInfo.PositionId(); + result.priceOpen = mOrderInfo.PriceOpen(); + result.takeProfit = mOrderInfo.TakeProfit(); + result.typeFilling = mOrderInfo.TypeFilling(); + result.priceCurrent = mOrderInfo.PriceCurrent(); + result.volumeInitial = mOrderInfo.VolumeInitial(); + result.volumeCurrent = mOrderInfo.VolumeCurrent(); + result.timeExpiration = mOrderInfo.TimeExpiration(); + result.priceStopLimit = mOrderInfo.PriceStopLimit(); + result.reason = (ENUM_ORDER_REASON)HistoryOrderGetInteger( + ticket, + ORDER_REASON); + + // + return result; + } + // + // END Signal Private ... + // +}; + +// +// a Class For Guard Account ... +class XCGuard : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCGuard( + int oldAge, // Age for Old Trades + ENUM_X_GUARD_ACTIONS oldGuardAction, // Guard Action for Too Old State + double criticalFactor, // Critical DrawDown Factor based On Balance + ENUM_X_GUARD_ACTIONS criticalAction, // Guard Action for Critical State + double maxFactor, // Max DrawDown Factor based on Balance + ENUM_X_GUARD_ACTIONS maxAction, // Guard Action for Max State + int GuardStopoutFiredAfterTouches, // Guard Stopout if Max State touched + ENUM_X_GUARD_SUPPORT_METHODS supportMethod // How to Support Signals + ) + { + // + mSupportPrefix = "SPT"; + mDirectional = "SPD"; + mInDirectional = "SPIND"; + + // + mOldAge = oldAge; + mOldGuardAction = oldGuardAction; + + // + mMaxFactor = maxFactor; + mMaxAction = maxAction; + mCriticalFactor = criticalFactor; + mCriticalAction = criticalAction; + mGuardStopoutFiredAfterTouches = GuardStopoutFiredAfterTouches; + + // + mSupportMethod = supportMethod; + + // + mAccountInfo = new XCAccountInfo(); + + // + double deposit = mAccountInfo.GetInitialBalance(); + + // + if ( + maxFactor > 0 && + maxFactor < 1) + { + mMaxValue = maxFactor * deposit; + } + + // + if ( + criticalFactor > 0 && + criticalFactor < 1) + { + mCriticalValue = criticalFactor * deposit; + } + + // + Reset(); + ResetMaxDrawDownTouches(); + } + + // + // Deconstructor ... + ~XCGuard() {} + + // + // Reset List ... + void Reset() + { + // + CleanBuffer(mGuardedSignals); + CleanBuffer(mSupportedSignals); + } + + // + // Reset Consecutive Max DrawDown Touches ... + void ResetMaxDrawDownTouches() + { + mOccuredconsecutiveMaxDraDownTouches = 0; + } + + // + // Calculate and Retrieve Critical DrawDown Value ... + double GetCriticalValue() + { + // + double result = mCriticalValue; + if (mCriticalFactor <= 0) + { + return result; + } + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + + // + if (balance > deposit) + { + // + double balanceBasedCriticalDrawDown = mCriticalFactor * balance; + + // + result = MathMax( + mCriticalValue, + balanceBasedCriticalDrawDown); + } + + // + return result; + } + + // + // Calculate and Retrieve Max Allowed DrawDown Value ... + double GetMaxValue() + { + // + double result = mMaxValue; + if (mMaxValue <= 0) + { + return result; + } + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + + // + if (balance > deposit) + { + // + double balanceBasedMaxAllwedDrawDown = mMaxFactor * balance; + + // + result = MathMax( + mMaxValue, + balanceBasedMaxAllwedDrawDown); + } + + // + return result; + } + + // + // Guard Account Protection ... + bool Guard( + XGuardHandlerResult &guardResult, // Hold's Message + string &message, // Hold's Message + XCTrade &trader, // Specified Trader + ENUM_TIMEFRAMES period = NULL // Specified Time Frame for Detecting Signal Ages + ) + { + // + message = ""; + + // + // Clean Result of Guard ... + CleanBuffer(guardResult.olds); + CleanBuffer(guardResult.maxes); + CleanBuffer(guardResult.criticals); + + // + bool result = false; + + // + // So Important is to Guard DrawDowns ... + result = GuardDrawDown( + guardResult, + message, + trader); + if (result) + { + return result; + } + + // + // Then we have to Guard Old Trades ... + result = GuardOlds( + guardResult, + message, + trader); + + // + return result; + } + + // + // Handle Guard Old Trades ... + bool GuardOlds( + XGuardHandlerResult &guardResult, // Hold's Message + string &message, // Hold's Message + XCTrade &trader, // Specified Trader + ENUM_TIMEFRAMES period = NULL // Specified Time Frame for Detecting Signal Ages + ) + { + // + // Cleanup Message ... + message = ""; + + // + // Clean Result of Guard ... + CleanBuffer(guardResult.olds); + + // + bool result = false; + + // + // Validate Args ... + if ( + mOldAge <= 0 || + mOldGuardAction == X_GUARD_DO_NOTHING) + { + return result; + } + + // + // Normalize Args ... + if (period == NULL) + { + period = _Period; + } + + // + // Retrieve Old Trades ... + XSignal oldSignals[]; + trader.GetOldSignals( + oldSignals, + mOldAge, + period); + int oldSignalsCount = ArraySize(oldSignals); + if (oldSignalsCount <= 0) + { + return result; + } + + // + result = DoGuardAction( + guardResult, + message, + trader, + mOldGuardAction, + X_GUARDED_OLD, // Specify Guard Reason + period // Specified Running Time Frame for Signal Age Calculations + ); + + // + return result; + } + + // + // Hnadle Guard DrawDown ... + bool GuardDrawDown( + XGuardHandlerResult &guardResult, // Hold's Message + string &message, // Hold's Message + XCTrade &trader // Specified Trader + ) + { + // + message = ""; + + // + // Clean Result of Guard ... + CleanBuffer(guardResult.maxes); + CleanBuffer(guardResult.criticals); + + // + bool result = false; + + // + // Check State for Guard ... + bool isCriticalGuardEnabled = mCriticalFactor > 0; + bool isMaxGuardEnabled = mMaxFactor > 0; + bool isGuardEnabled = + isMaxGuardEnabled; + + // + if (!isGuardEnabled) + { + return result; + } + + // + double maxValue = GetMaxValue(); + double criticalValue = GetCriticalValue(); + + // + double profitSums = trader.GetSignalsProfit(); + + // + bool isMaxReached = + profitSums < 0 && + isMaxGuardEnabled && + MathAbs(profitSums) >= maxValue; + bool isCriticalReached = + profitSums < 0 && + isCriticalGuardEnabled && + MathAbs(profitSums) >= criticalValue; + + // + if (!isMaxReached && !isCriticalReached) + { + // + // Reset Consecutive Max DrawDown Touches ... + ResetMaxDrawDownTouches(); + + // + return result; + } + + // + // Check For Critical Guard ... + if (isCriticalReached && !isMaxReached) + { + // + result = DoGuardAction( + guardResult, + message, + trader, + mCriticalAction, + X_GUARDED_CRITICAL); + } + else if (isMaxReached) + { + // + result = DoGuardAction( + guardResult, + message, + trader, + mMaxAction, + X_GUARDED_MAX); + + // + // Handle Guard StopOut Action ... + mOccuredconsecutiveMaxDraDownTouches++; + if ( + mMaxAction != X_GUARD_DO_NOTHING && + mMaxAction != X_GUARD_CLOSE_ALL && + mGuardStopoutFiredAfterTouches > 0 && + mOccuredconsecutiveMaxDraDownTouches >= mGuardStopoutFiredAfterTouches) + { + // + XSignal closed[]; + trader.CloseSignals(closed); + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + // + XSignal iSignal = closed[i]; + + // + AddItemToBuffer( + iSignal, + guardResult.maxes); + } + + // + message = "Guard StopOut Action Closed (" + (string)closedCount + ") Signals and Release Account ..."; + + // + guardResult.isStopOut = true; + + // + result = true; + } + } + } + + // + return result; + } + + // + // Do Signal Protections and apply Support ... + bool ProtectSignals( + XSignal &mResult[], // Hold's Result + XCTrade &trader, // Specified Trader + int numberOfItemsCheck = 30 // Number of Items to check + ) + { + // + bool result = false; + + // + CleanBuffer(mResult); + + // + // Check Supports Enabled ... + result = IsSupportEnabled(); + if (!result) + { + return result; + } + + // + // Update Supports ... + XSignal signals[]; + trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount > 0) + { + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isExists = IsSupportExists(iSignal.ticket); + if (isExists) + { + UpdateSupport(iSignal); + } + } + } + + // + // Count Supporteds ... + XProtectedSignal supporteds[]; + GetAllSupports(supporteds); + int supportedCount = ArraySize(supporteds); + result = supportedCount > 0; + if (!result) + { + return result; + } + + // + // Loop through ... + for (int i = 0; i < supportedCount; i++) + { + // + XProtectedSignal iP = supporteds[i]; + + // + bool canDoDirectional = CanDoDirectionalSupport( + trader, + iP.ticket, + numberOfItemsCheck); + bool canDoInDirectional = CanDoInDirectionalSupport( + trader, + iP.ticket, + numberOfItemsCheck); + + // + if ( + !canDoDirectional && + !canDoInDirectional) + { + continue; + } + + // + // Do Directional ... + if (canDoDirectional) + { + // + // Generate Propper Signal ... + XSignal sdSignal = GenerateDirectionalSupportSignal( + iP.ticket, + trader); + + // + ENUM_EXECUTION_SIGNAL_RESULT executionResult = trader.ExecuteSignal( + sdSignal, + true, + false); + bool isExecuted = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (isExecuted) + { + // + XSignal eSignal = trader.GetSignal(sdSignal.ticket); + + // + AddItemToBuffer( + eSignal, + mResult); + } + } + // + // Do Indirectional ... + else if (canDoInDirectional) + { + // + // Generate Propper Signal ... + XSignal sindSignal = GenerateDirectionalSupportSignal( + iP.ticket, + trader); + + // + ENUM_EXECUTION_SIGNAL_RESULT executionResult = trader.ExecuteSignal( + sindSignal, + true, + false); + bool isExecuted = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (isExecuted) + { + // + XSignal eSignal = trader.GetSignal(sindSignal.ticket); + + // + AddItemToBuffer( + eSignal, + mResult); + } + } + } + + // + result = ArraySize(mResult) > 0; + + // + return result; + } + + // + // Validate State ... + bool Validate() + { + // + bool result = false; + + // + result = + mMaxFactor > 0 && + (mCriticalFactor > 0 + ? mCriticalFactor < mMaxFactor + : true); + + // + return result; + } + + // + // START Guarded Signals Functions ... + // + + // + // Add new Protecte Signal ... + bool Add( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsExists(signal.ticket); + if (isExists) + { + return result; + } + + // + XProtectedSignal item; + + // + datetime time = TimeCurrent(); + + // + item.ticket = signal.ticket; + + // + AddItemToBuffer( + time, + item.time); + + // + AddItemToBuffer( + signal.profit, + item.profit); + + // + AddItemToBuffer( + item, + mGuardedSignals); + + // + return result; + } + + // + // Get All ... + void GetAll( + XProtectedSignal &result[] // Hold's Result + ) + { + // + CopyBuffer( + mGuardedSignals, + result); + } + + // + // Get ... + XProtectedSignal Get( + ulong ticket // Specified Signal Ticket + ) + { + // + XProtectedSignal result; + + // + bool isExists = IsExists(ticket); + if (!isExists) + { + return result; + } + + // + int protectedCounts = ArraySize(mGuardedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mGuardedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = iProtected; + break; + } + } + + // + return result; + } + + // + // Remove ... + bool Remove( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + result = IsExists(ticket); + if (!result) + { + return result; + } + + // + int protectedCounts = ArraySize(mGuardedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + XProtectedSignal cleared[]; + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mGuardedSignals[i]; + + // + if (iProtected.ticket != ticket) + { + AddItemToBuffer( + iProtected, + cleared); + } + } + + // + // Update Source by Cleared ... + CopyBuffer( + cleared, + mGuardedSignals); + + // + result = true; + + // + return result; + } + + // + // Update ... + bool Update( + ulong ticket, // Specified Signal Ticket + datetime time, // Specified Last Checked time + double profit // Specified Signal Profit + // XProtectedSignal &item // Specified which object to Update + ) + { + // + bool result = false; + + // + int protectedCounts = ArraySize(mGuardedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + result = IsExists(ticket); + if (!result) + { + return result; + } + + // + // Retrieve Struct ... + XProtectedSignal item = Get(ticket); + AddItemToBuffer( + time, + item.time); + AddItemToBuffer( + profit, + item.profit); + + // + result = Remove(ticket); + if (!result) + { + return result; + } + + // + AddItemToBuffer( + item, + mGuardedSignals); + result = true; + + // + return result; + } + bool Update( + XProtectedSignal &item // Specified Protected Item + ) + { + // + bool result = false; + + // + datetime time; + result = GetLastItem( + time, + item.time); + if (!result) + { + return result; + } + + // + double profit; + result = GetLastItem( + profit, + item.profit); + if (!result) + { + return result; + } + + // + result = Update( + item.ticket, time, profit); + + // + return result; + } + bool Update( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + ulong ticket = signal.ticket; + datetime time = TimeCurrent(); + double profit = signal.profit; + + // + result = Update( + ticket, + time, + profit); + + // + return result; + } + + // + // Add Or Update ... + bool AddOrUpdate( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsExists(signal.ticket); + if (!isExists) + { + result = Add(signal); + } + else + { + result = Update(signal); + } + + // + return result; + } + + // + // Check Exists ... + bool IsExists( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + int protectedCounts = ArraySize(mGuardedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mGuardedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + + // + // Count Protecteds ... + int Count() + { + // + int result = 0; + + // + result = ArraySize(mGuardedSignals); + + // + return result; + } + + // + // END Guarded Signals Functions ... + // + + // + // START Supported Signals Functions ... + // + + // + // Check can Handle Support Signals or not ... + bool IsSupportEnabled() + { + // + bool result = false; + + // + result = + mSupportMethod != X_SUPPORT_DO_NOTHING; + + // + return result; + } + + // + // Retrieve List Of Supported Signals ... + void GetSupportSignals( + XSignal &result[], // Hold's Result ... + XCTrade &trader // Specified Trader class Instance ... + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = -0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isSupport = IsSupport(iSignal.comment); + if (isSupport) + { + AddItemToBuffer( + iSignal, + result); + } + } + } + + // + // Retrieve List Of Specific Signals Supported Signals ... + void GetSignalSupports( + XSignal &result[], // Hold's Result ... + XCTrade &trader, // Specified Trader class Instance ... + ulong ticket // Specified Signal Ticket ... + ) + { + // + CleanBuffer(result); + + // + // Validate Args ... + if (ticket <= 0) + { + return; + } + + // + // Check Signal Exists using Trader ... + XSignal parentSignal = trader.GetSignal(ticket); + bool isValid = + parentSignal.ticket > 0 && + parentSignal.ticket == ticket && + StringLen(parentSignal.comment) > 0; + if (!isValid) + { + return; + } + + // + XSignal supportSignals[]; + GetSupportSignals( + supportSignals, + trader); + int supportSignalsCount = ArraySize(supportSignals); + if (supportSignalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < supportSignalsCount; i++) + { + // + XSignal iSignal = supportSignals[i]; + + // + bool isBelongsToParent = IsBelongsToParent( + ticket, + iSignal.comment); + if (isBelongsToParent) + { + AddItemToBuffer( + iSignal, + result); + } + } + } + + // + // Check Specific Support Conditions for Opening Directional Support ... + bool CanDoDirectionalSupport( + XCTrade &trader, // Specified Trader class Instance ... + ulong ticket, // Specified Signal Ticket ... + int numberOfItemsCheck = 30 // Number of Items to check ... + ) + { + // + bool result = false; + + // + // Check Supports Enabled ... + result = IsSupportEnabled(); + if (!result) + { + return result; + } + + // + // Check Support Method Allows Directional ... + result = + mSupportMethod == X_SUPPORT_FULL || + mSupportMethod == X_SUPPORT_IN_DRAWUP_DIRECTIONAL; + if (!result) + { + return result; + } + + // + // Validate Ticket ... + result = ticket > 0; + if (!result) + { + return result; + } + + // + // Check Supports Count ... + int supportedCount = ArraySize(mSupportedSignals); + result = supportedCount > 0; + if (!result) + { + return result; + } + + // + // Check Ticket Exists in Supports ... + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + // Check signal Doesn't have any Support ... + XSignal supports[]; + GetSignalSupports( + supports, + trader, + ticket); + int supportsCount = ArraySize(supports); + result = supportsCount <= 0; + if (!result) + { + return result; + } + + // + // Retrieve Support Model ... + XProtectedSignal sInfo = GetSupport(ticket); + + // + // Validate Model ... + int sTimesCount = ArraySize(sInfo.time); + int sProfitsCount = ArraySize(sInfo.profit); + result = + sInfo.ticket == ticket && + sTimesCount == sProfitsCount && + sTimesCount >= numberOfItemsCheck && + sProfitsCount >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Validate Signal Age ... + XSignal sSignal = trader.GetSignal(ticket); + int sSignalAge = trader.GetSignalAge(sSignal.time); + result = sSignalAge >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Extrat Profits ... + double lastProfits[]; + for (int i = sProfitsCount - 1; i >= (sProfitsCount - numberOfItemsCheck); i++) + { + // + double iProfit = sInfo.profit[i]; + + // + AddItemToBuffer( + iProfit, + lastProfits); + } + + // + string logMsg = ToString(lastProfits); + LogMessage("" + (string)ticket + " lastProfits: \n" + logMsg); + + // + result = false; + + // + // Now implement Business Logics ... + + // + return result; + } + + // + // Check Specific Support Conditions for Opening InDirectional Support ... + bool CanDoInDirectionalSupport( + XCTrade &trader, // Specified Trader class Instance ... + ulong ticket, // Specified Signal Ticket ... + int numberOfItemsCheck = 30 // Number of Items to check ... + ) + { + // + bool result = false; + + // + // Check Supports Enabled ... + result = IsSupportEnabled(); + if (!result) + { + return result; + } + + // + // Check Support Method Allows Directional ... + result = + mSupportMethod == X_SUPPORT_FULL || + mSupportMethod == X_SUPPORT_IN_DRAWDOWN_INDIRECTIONAL; + if (!result) + { + return result; + } + + // + // Validate Ticket ... + result = ticket > 0; + if (!result) + { + return result; + } + + // + // Check Supports Count ... + int supportedCount = ArraySize(mSupportedSignals); + result = supportedCount > 0; + if (!result) + { + return result; + } + + // + // Check Ticket Exists in Supports ... + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + // Check signal Doesn't have any Support ... + XSignal supports[]; + GetSignalSupports( + supports, + trader, + ticket); + int supportsCount = ArraySize(supports); + result = supportsCount <= 0; + if (!result) + { + return result; + } + + // + // Retrieve Support Model ... + XProtectedSignal sInfo = GetSupport(ticket); + + // + // Validate Model ... + int sTimesCount = ArraySize(sInfo.time); + int sProfitsCount = ArraySize(sInfo.profit); + result = + sInfo.ticket == ticket && + sTimesCount == sProfitsCount && + sTimesCount >= numberOfItemsCheck && + sProfitsCount >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Validate Signal Age ... + XSignal sSignal = trader.GetSignal(ticket); + int sSignalAge = trader.GetSignalAge(sSignal.time); + result = sSignalAge >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Extrat Profits ... + double lastProfits[]; + for (int i = sProfitsCount - 1; i >= (sProfitsCount - numberOfItemsCheck); i++) + { + // + double iProfit = sInfo.profit[i]; + + // + AddItemToBuffer( + iProfit, + lastProfits); + } + + // + string logMsg = ToString(lastProfits); + LogMessage("" + (string)ticket + " lastProfits: \n" + logMsg); + + // + result = false; + + // + // Now implement Business Logics ... + + // + return result; + } + + // + // Generate Directional Support Signal for Parent Signal ... + XSignal GenerateDirectionalSupportSignal( + ulong ticket, // Specified Parent Signal Ticket ... + XCTrade &trader // Specified Trader Class ... + ) + { + // + XSignal result = {}; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + XSignal pSignal = trader.GetSignal(ticket); + bool isValidParent = + pSignal.ticket > 0 && + pSignal.ticket == ticket && + StringLen(pSignal.comment) > 0; + if (!isValidParent) + { + return result; + } + + // + ENUM_X_SIGNAL_TYPE type = pSignal.type; + bool isLong = IsLong(type); + + // + double entry = GetEntry( + pSignal.symbol, + type); + double exit = GetExit( + pSignal.symbol, + type); + + // + double reward = PipsToPrice( + pSignal.symbol, + 6); + double risk = PipsToPrice( + pSignal.symbol, + 1); + + // + double tp = + isLong + ? entry + reward + : entry - reward; + + // + double sl = + isLong + ? exit - risk + : exit + risk; + + // + double rfStep = 2; + double rfRate = 0.5; + + // + double volume = NormalizeVolume( + pSignal.volume / 2, + pSignal.symbol, + 2); + + // + // Generate Signal using Trader Class Instance ... + result = trader.GenerateSignal( + // + type, + tp, + sl, + volume, + rfStep, + rfRate + // + ); + + // + return result; + } + + // + // Generate InDirectional Support Signal for Parent Signal ... + XSignal GenerateInDirectionalSupportSignal( + ulong ticket, // Specified Parent Signal Ticket ... + XCTrade &trader // Specified Trader Class ... + ) + { + // + XSignal result = {}; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + XSignal pSignal = trader.GetSignal(ticket); + bool isValidParent = + pSignal.ticket > 0 && + pSignal.ticket == ticket && + StringLen(pSignal.comment) > 0; + if (!isValidParent) + { + return result; + } + + // + ENUM_X_SIGNAL_TYPE type = trader + .GetIndirectionSignalType(pSignal.type); + bool isLong = IsLong(type); + + // + double entry = GetEntry( + pSignal.symbol, + type); + double exit = GetExit( + pSignal.symbol, + type); + + // + double reward = PipsToPrice( + pSignal.symbol, + 6); + double risk = PipsToPrice( + pSignal.symbol, + 1); + + // + double tp = + isLong + ? entry + reward + : entry - reward; + + // + double sl = + isLong + ? exit - risk + : exit + risk; + + // + double rfStep = 2; + double rfRate = 0.5; + + // + double volume = NormalizeVolume( + pSignal.volume / 2, + pSignal.symbol, + 2); + + // + // Generate Signal using Trader Class Instance ... + result = trader.GenerateSignal( + // + type, + tp, + sl, + volume, + rfStep, + rfRate + // + ); + + // + return result; + } + + // + // Generate Specific Signals Support Signal Comment ... + string GenerateSupportSignalComment( + ulong ticket, // Specified Parent Signal Ticket + ENUM_X_SIGNAL_TYPE type, // Specified Support Signal Type + bool isInDirectional = false // Specified Support Signal Direction + ) + { + // + string result = ""; + + // + if (ticket <= 0) + { + return result; + } + + // + string typeString = GetSignalType(type); + string directionStr = GenerateSupportDirection(isInDirectional); + + // + result = + mSupportPrefix + "(" + (string)ticket + ")_" + + X_SIGNAL_TYPE + "(" + typeString + ")_" + + directionStr; + + // + return result; + } + + // + // Get Support Direction String Representation ... + string GenerateSupportDirection( + bool isInDirectional = false // Specified Support Signal Direction + ) + { + // + string result = ""; + + // + result = + isInDirectional + ? mInDirectional + : mDirectional; + + // + return result; + } + + // + // Check an String Is Directional Or not ... + bool IsDirectionalSupport( + string comment // Specified Comment ... + ) + { + // + bool result = false; + + // + result = IsSupport(comment); + if (!result) + { + return result; + } + + // + int sPos = StringFind( + comment, + mDirectional); + result = sPos >= 0; + + // + return result; + } + + // + // Check an String Is In Directional Or not ... + bool IsInDirectionalSupport( + string comment // Specified Comment ... + ) + { + // + bool result = false; + + // + result = IsSupport(comment); + if (!result) + { + return result; + } + + // + int sPos = StringFind( + comment, + mInDirectional); + result = sPos >= 0; + + // + return result; + } + + // + // Check an String Is Support or not ... + bool IsSupport( + string comment // Specified Comment ... + ) + { + // + bool result = false; + + // + int sPos = StringFind( + comment, + mSupportPrefix); + result = sPos >= 0; + + // + return result; + } + + // + // Extract Parent of Support Signal Ticket from a comment ... + ulong ExtractParentTicket( + string comment // Specified Comment ... + ) + { + // + ulong result = 0; + + // + bool isSupport = IsSupport(comment); + if (!isSupport) + { + return result; + } + + // + // TICKET ... + string ticketStr = ExtractString( + comment, + mSupportPrefix + "(", + ")"); + if (StringLen(ticketStr) > 0) + { + result = (ulong)ticketStr; + } + + // + return result; + } + + // + // Check a Comment belongs to Support Signal or not ... + bool IsBelongsToParent( + ulong ticket, // Specified Parent Signal Ticket + string comment // Specified Support Signal Comment + ) + { + // + bool result = false; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + result = IsSupport(comment); + if (!result) + { + return result; + } + + // + ulong spTicket = ExtractParentTicket(comment); + result = spTicket == ticket; + + // + return result; + } + + // + // Add new Protecte Signal ... + bool AddSupport( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsSupportExists(signal.ticket); + if (isExists) + { + return result; + } + + // + XProtectedSignal item; + + // + datetime time = TimeCurrent(); + + // + item.ticket = signal.ticket; + + // + AddItemToBuffer( + time, + item.time); + + // + AddItemToBuffer( + signal.profit, + item.profit); + + // + AddItemToBuffer( + item, + mSupportedSignals); + + // + return result; + } + + // + // Get All ... + void GetAllSupports( + XProtectedSignal &result[] // Hold's Result + ) + { + // + CopyBuffer( + mSupportedSignals, + result); + } + + // + // Get ... + XProtectedSignal GetSupport( + ulong ticket // Specified Signal Ticket + ) + { + // + XProtectedSignal result; + + // + bool isExists = IsSupportExists(ticket); + if (!isExists) + { + return result; + } + + // + int protectedCounts = ArraySize(mSupportedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mSupportedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = iProtected; + break; + } + } + + // + return result; + } + + // + // Remove ... + bool RemoveSupport( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + int protectedCounts = ArraySize(mSupportedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + XProtectedSignal cleared[]; + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mSupportedSignals[i]; + + // + if (iProtected.ticket != ticket) + { + AddItemToBuffer( + iProtected, + cleared); + } + } + + // + // Update Source by Cleared ... + CopyBuffer( + cleared, + mSupportedSignals); + + // + result = true; + + // + return result; + } + + // + // Update ... + bool UpdateSupport( + ulong ticket, // Specified Signal Ticket + datetime time, // Specified Last Checked time + double profit // Specified Signal Profit + ) + { + // + bool result = false; + + // + int protectedCounts = ArraySize(mSupportedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + // Retrieve Struct ... + XProtectedSignal item = GetSupport(ticket); + AddItemToBuffer( + time, + item.time); + AddItemToBuffer( + profit, + item.profit); + + // + result = RemoveSupport(ticket); + if (!result) + { + return result; + } + + // + AddItemToBuffer( + item, + mSupportedSignals); + result = true; + + // + return result; + } + bool UpdateSupport( + XProtectedSignal &item // Specified Protected Item + ) + { + // + bool result = false; + + // + datetime time; + result = GetLastItem( + time, + item.time); + if (!result) + { + return result; + } + + // + double profit; + result = GetLastItem( + profit, + item.profit); + if (!result) + { + return result; + } + + // + result = UpdateSupport( + item.ticket, time, profit); + + // + return result; + } + bool UpdateSupport( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + ulong ticket = signal.ticket; + datetime time = TimeCurrent(); + double profit = signal.profit; + + // + result = UpdateSupport( + ticket, + time, + profit); + + // + return result; + } + + // + // Add Or Update ... + bool AddOrUpdateSupport( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsSupportExists(signal.ticket); + if (!isExists) + { + result = Add(signal); + } + else + { + result = Update(signal); + } + + // + return result; + } + + // + // Check Exists ... + bool IsSupportExists( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + int protectedCounts = ArraySize(mSupportedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mSupportedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + + // + // Count Protecteds ... + int CountSupports() + { + // + int result = 0; + + // + result = ArraySize(mSupportedSignals); + + // + return result; + } + + // + // END Suppoprted Signals Functions ... + // + + // + // START Getter/Setter(s) ... + // + + // + int GetOldAge() + { + return mOldAge; + } + + // + bool SetOldAge(int value) + { + // + bool result = false; + + // + result = + value > 0 && + mOldAge != value; + if (!result) + { + return result; + } + + // + mOldAge = value; + + // + return result; + } + + // + ENUM_X_GUARD_ACTIONS GetOldGuardAction() + { + return mOldGuardAction; + } + + // + bool SetOldGuardAction(ENUM_X_GUARD_ACTIONS value) + { + // + bool result = false; + + // + result = value != mOldGuardAction; + if (!result) + { + return result; + } + + // + mOldGuardAction = value; + + // + return result; + } + + // + double GetCriticalFactor() + { + return mCriticalFactor; + } + + // + bool SetCriticalFactor(bool value) + { + // + bool result = false; + + // + result = + value > 0 && + value < 1 && + mCriticalFactor != value; + if (!result) + { + return result; + } + + // + mCriticalFactor = value; + + // + double deposit = mAccountInfo.GetInitialBalance(); + mCriticalValue = deposit * value; + + // + return result; + } + + // + ENUM_X_GUARD_ACTIONS GetCriticalAction() + { + return mCriticalAction; + } + + // + bool SetCriticalAction(ENUM_X_GUARD_ACTIONS value) + { + // + bool result = false; + + // + result = + value != mCriticalAction; + if (!result) + { + return result; + } + + // + mCriticalAction = value; + + // + return result; + } + + // + double GetMaxFactor() + { + return mMaxFactor; + } + + // + bool SetMaxFactor(bool value) + { + // + bool result = false; + + // + result = + value > 0 && + value < 1 && + mMaxFactor != value; + if (!result) + { + return result; + } + + // + mMaxFactor = value; + + // + double deposit = mAccountInfo.GetInitialBalance(); + mMaxValue = deposit * value; + + // + return result; + } + + // + ENUM_X_GUARD_ACTIONS GetMaxAction() + { + return mMaxAction; + } + + // + bool SetMaxAction(ENUM_X_GUARD_ACTIONS value) + { + // + bool result = false; + + // + result = + value != mMaxAction; + if (!result) + { + return result; + } + + // + mMaxAction = value; + + // + return result; + } + + // + ENUM_X_GUARD_SUPPORT_METHODS GetSupportMethod() + { + return mSupportMethod; + } + + // + bool SetSupportMethod(ENUM_X_GUARD_SUPPORT_METHODS value) + { + // + bool result = false; + + // + result = + value != mSupportMethod; + if (!result) + { + return result; + } + + // + mSupportMethod = value; + + // + return result; + } + + // + // END Getter/Setter(s) ... + // + + // + // Generate Signal Guard Attacked Message ... + string GenerateGuardedSignalComment( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason // Specified Guard Reason + ) + { + // + string result = ""; + + // + string reasonMessage = + ( + // + reason == X_GUARDED_OLD + ? "Because of Old Issue" + : reason == X_GUARDED_CRITICAL + ? "Because Of Crtical Drawdown Isuue" + : reason == X_GUARDED_MAX + ? "Because of Max Drawdown Issue" + : "" + // + ) + + " On Profit: " + (string)signal.profit; + + // + result += "Guard Attacked (" + (string)signal.ticket + "), " + reasonMessage + " ..."; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + string mSupportPrefix; + string mDirectional; + string mInDirectional; + + // + XProtectedSignal mGuardedSignals[]; + XProtectedSignal mSupportedSignals[]; + + // + int mOldAge; + ENUM_X_GUARD_ACTIONS mOldGuardAction; + + // + // Critical DrawDown Factor based On Balance ... + double mCriticalFactor; + double mCriticalValue; + + // + // Guard Action for Critical State ... + ENUM_X_GUARD_ACTIONS mCriticalAction; + + // + // Max DrawDown Factor based on Balance ... + double mMaxFactor; + double mMaxValue; + // + // Guard Stopout if Max State touched ... + int mOccuredconsecutiveMaxDraDownTouches; + int mGuardStopoutFiredAfterTouches; + + // + // Guard Action for Max State ... + ENUM_X_GUARD_ACTIONS mMaxAction; + + // + // How to Support Signals ... + ENUM_X_GUARD_SUPPORT_METHODS mSupportMethod; + + // + // Account Info Instance ... + XCAccountInfo mAccountInfo; + + // + // Get Volume Multiplier for Specified Guard Action ... + double GetGuardActionVolumeMultiplier( + ENUM_X_GUARD_ACTIONS action = X_GUARD_DO_NOTHING // Specified Action + ) + { + // + // Partial Close Max In Drawdown Trade ... + double result = 0.0; + if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1) + { + result = 0.01; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_2) + { + result = 0.02; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_3) + { + result = 0.03; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5) + { + result = 0.05; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10) + { + result = 0.10; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_15) + { + result = 0.15; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_20) + { + result = 0.20; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25) + { + result = 0.25; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30) + { + result = 0.30; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40) + { + result = 0.40; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50) + { + result = 0.50; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60) + { + result = 0.60; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_70) + { + result = 0.70; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75) + { + result = 0.75; + } + + // + return result; + } + + // + // Do Specified Guard Action ... + bool DoGuardAction( + XGuardHandlerResult &guardResult, // Hold's Result ... + string &message, // Hold's Message ... + XCTrade &trader, // Specified Trader Class ... + ENUM_X_GUARD_ACTIONS action, // Specified Which Action to Do ... + ENUM_X_GUARD_REASONS reason, // Specified Guard Reason ... + ENUM_TIMEFRAMES period = NULL // Specified Time Frame for Detecting Signal Ages ... + ) + { + // + bool result = false; + + // + message = ""; + + // + string reasonString = + reason == X_GUARDED_OLD + ? "Because of Age Issue" + : "Because of DD " + ( + // + reason == X_GUARDED_CRITICAL ? "Critical" : "Max" + // + ) + + " Issue"; + + // + // Validate Args ... + if (action == X_GUARD_DO_NOTHING) + { + // + message = "Max Allowed Drawdown Reached, but nothing Happens ..."; + + // + return result; + } + + // + // Normalize Period ... + if (period == NULL) + { + period = _Period; + } + + // + // Close All Signals ... + XSignal closed[]; + XSignal maxInDDSignal; + + // + // Handle Perform Guard Action ... + switch (action) + { + // + // Close All ... + case X_GUARD_CLOSE_ALL: + { + // + trader.CloseSignals(closed); + int closedCount = ArraySize(closed); + result = closedCount > 0; + if (!result) + { + break; + } + + // + message = "Closed (" + (string)closedCount + ") Trades by Guard, " + reasonString + " ..."; + } + break; + + // + case X_GUARD_CLOSE_MAX_IN_DD: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_2: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_3: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_15: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_20: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_70: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75: + { + // + // Retrieve Max In Drawdown Trade ... + maxInDDSignal = trader.GetMaxInDrawdownSignal(); + bool isValid = IsValid(maxInDDSignal, trader.GetMagicNumber()) && maxInDDSignal.ticket > 0; + if (!isValid) + { + break; + } + + // + // Close Max In Drawdown Trade ... + if (action == X_GUARD_CLOSE_MAX_IN_DD) + { + // + string comment = "Signal (" + (string)maxInDDSignal.ticket + ") Closed by Guard ..."; + result = trader.Close( + maxInDDSignal.ticket, + comment); + if (result) + { + message = comment; + } + + // + break; + } + + // + int signalAge = 0; + bool canGuard = true; + bool isGuardedBefore = false; + + // + // Do Some Additional Verifications if Guard for Olds Trades ... + if (reason == X_GUARDED_OLD) + { + // + // Retrieve Signal Age ... + signalAge = trader.GetSignalAge( + maxInDDSignal, + period); + + // + // Check Guarded Before Or Not ... + isGuardedBefore = IsExists(maxInDDSignal.ticket); + if (isGuardedBefore) + { + // + // Now We Have to Check Signal Age growse required times to apply Guard Action again ... + // First Calculate Guard Grow Step ... + int ageGrowStep = mOldAge / 10; + + // + XProtectedSignal guardItem = Get(maxInDDSignal.ticket); + datetime lastGuardTime = 0; + if (GetLastItem(lastGuardTime, guardItem.time)) + { + // + int lastGuardIndex = iBarShift( + maxInDDSignal.symbol, + period, + lastGuardTime); + + // + canGuard = + MathAbs(lastGuardIndex) >= ageGrowStep; + } + } + else + { + // + // Check Signal age ... + canGuard = signalAge >= mOldAge; + } + } + + // + // Prevent Moving Forward ... + if (!canGuard) + { + // + result = false; + break; + } + + // + // Partial Close Max In Drawdown Trade ... + double volumeRate = GetGuardActionVolumeMultiplier(action); + + // + double volume = NormalizeVolume( + maxInDDSignal.volume * volumeRate, + maxInDDSignal.symbol); + + // + string commentPrefix = "Signal (" + (string)maxInDDSignal.ticket + ") Partial Closed (" + (string)volumeRate + ") by Guard"; + string comment = commentPrefix + " ..."; + + // + result = trader.ClosePartial( + maxInDDSignal.ticket, + volume, + comment); + if (result) + { + // + reasonString = + reasonString + + (reason == X_GUARDED_OLD + ? " (" + (string)signalAge + ")" + : " (" + (string)maxInDDSignal.profit + ")"); + + // + // Update Guarded Signals ... + if (isGuardedBefore) + { + // + XSignal tSignal = trader.GetSignal(maxInDDSignal.ticket); + + // + if (tSignal.ticket > 0 && tSignal.volume > 0) + { + // + // Update In Guardeds ... + Update(tSignal); + } + else + { + // + // Remove From Guardeds ... + Remove(tSignal.ticket); + } + } + else if (reason == X_GUARDED_OLD) + { + // + // Added to Guardeds ... + Add(maxInDDSignal); + } + + // + message = commentPrefix + reasonString + " ..."; + } + } + break; + + // + // Nothing ... + // Default ... + default: + message = "Max Allowed Drawdown Reached ..."; + break; + } + + // + result = StringLen(message) > 0; + if (!result) + { + return result; + } + + // + if (result) + { + // + if (reason == X_GUARDED_OLD) + { + // + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + AddItemToBuffer( + closed[i], + guardResult.olds); + } + } + + // + if (maxInDDSignal.ticket > 0) + { + AddItemToBuffer( + maxInDDSignal, + guardResult.olds); + } + } + else if (reason == X_GUARDED_CRITICAL) + { + // + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + AddItemToBuffer( + closed[i], + guardResult.criticals); + } + } + + // + if (maxInDDSignal.ticket > 0) + { + AddItemToBuffer( + maxInDDSignal, + guardResult.criticals); + } + } + else if (reason == X_GUARDED_MAX) + { + // + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + AddItemToBuffer( + closed[i], + guardResult.maxes); + } + } + + // + if (maxInDDSignal.ticket > 0) + { + AddItemToBuffer( + maxInDDSignal, + guardResult.maxes); + } + } + } + + // + return result; + } +}; + +// +// END Global Definitions: Variables, Properties and etc ... +// diff --git a/XEU5-0/Classes/x-saherelm.nn.lib.mq5 b/XEU5-0/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 0000000..8fa40f5 --- /dev/null +++ b/XEU5-0/Classes/x-saherelm.nn.lib.mq5 @@ -0,0 +1,258 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 NN Class Library +// ---------------------------------------- +// Name: XNNClass +// Description: provides all classes for implementing +// Neural Network ... +// +// +// 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 Global Definitions: Variables, Properties and etc ... +// +class XCNNBase +{ + // + // Public Definitions ... +public: + // + // Constructor ... + void XCNNBase( + int nodes = 10, // Number of Input Nodes + double starterWeight = 0.5, // start weight for each input + double coEfficient = 0.1, // COEfficient Multiplier + double upperRange = 1, // Upper Normal Range Value + double lowerRange = -1, // Lower Normal Range Value + double learningRates = 0.1 // Back Propagation Learning Rate + ) { + // + mNodes = nodes; + mUpperRange = upperRange; + mLowerRange = lowerRange; + mCoEfficient = coEfficient; + mLearningRates = learningRates; + mStarterWeight = starterWeight; + + // + ReConstructWeights(); + } + + // + // Deconstructor ... + void ~XCNNBase() {} + + // + // Protected Definitions ... + void NormalizeInputs(double &inputs[], double &result[]) + { + // + ArrayFree(result); + ArrayResize(result, 1); + + // + // Validate inputs ... + if (ArraySize(inputs) != mNodes) + { + return; + } + + // + // Prepare Result ... + ArrayResize(result, mNodes); + + // + // Calculating min and max range value ... + double minRangeValue = inputs[ArrayMinimum(inputs)]; + double maxRangeValue = inputs[ArrayMaximum(inputs)]; + + // + // Loop through Inputs nd Normalize them ... + for (int i = 0; i < mNodes; i++) + { + // + double normalValue = (((inputs[i] - minRangeValue) * (mUpperRange - mLowerRange)) / (maxRangeValue - minRangeValue)) + mLowerRange; + result[i] = normalValue; + } + } + + // + // Hyperbolic Tangent Activation Function ... + double TanHActivationFunction(double weightedInputs) + { + // + double result = (exp(weightedInputs) - exp(-weightedInputs)) / (exp(weightedInputs) + exp(-weightedInputs)); + return result; + } + + // + // Calculate Weighted Inputs ... + double CalculateWeightedInputs( + double &inputs[], + bool applyCOEfficient = true) + { + // + double result = 0; + + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) + { + // + result = -1; + return result; + } + + // + for (int i = 0; i < mNodes; i++) + { + result += inputs[i] * mWeights[i]; + } + + // + // Multiply if required ... + if (applyCOEfficient) + { + result *= mCoEfficient; + } + + // + return result; + } + + // + // Calculate Hidden Layers ... + virtual double CalculateHiddenLayer(double &inputs[]) + { + // + // this is Default Activation Function which used ... + // you can override this by writing your own ... + double totalWeightedInputs = CalculateWeightedInputs(inputs); + double result = TanHActivationFunction(totalWeightedInputs); + + // + return result; + } + + // + // Calculate Output Layers ... + double CalculateOutputLayer(double &inputs[]) + { + // + double result = -1; + + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) { + return result; + } + + // + double normalizedInputs[]; + NormalizeInputs(inputs, normalizedInputs); + if (ArraySize(normalizedInputs) != mNodes) { + return result; + } + + // + double hiddenLayerResult = CalculateHiddenLayer(normalizedInputs); + + // + result = 1 * hiddenLayerResult; + + // + return result; + } + + // + // Basck Propaggation Learning ... + void BackPropagation( + double &inputs[], + double &outputs, + double targetOutput + ) { + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) { + return; + } + + // + double normalizedInputs[]; + NormalizeInputs(inputs, normalizedInputs); + if (ArraySize(normalizedInputs) != mNodes) { + return; + } + + // + double error = targetOutput - outputs; + double derivative = 1 - MathPow(outputs, 2); + + // + for (int i = 0; i < mNodes; i++) { + // + double gradient = error * derivative * inputs[i]; + mWeights[i] = mLearningRates * gradient; + } + } + +protected: + // + // Private Definitions ... +private: + // + // Number of Input Nodes ... + int mNodes; + + // + // Specify Upper range of Normal Values ... + double mUpperRange; + + // + // Specify Lower range of Normal Values ... + double mLowerRange; + + // + // Starter Weight for each input node ... + double mStarterWeight; + + // + // double Input Node Weights ... + double mWeights[]; + + // + // CoEfficient is a multiplyer for weighted inputs ... + double mCoEfficient; + + // + // Back Propagation Learning Rates ... + double mLearningRates; + + // + // ReConstruct Weights ... + void ReConstructWeights() { + // + ArrayFree(mWeights); + ArrayResize(mWeights, mNodes); + + // + for (int i = 0; i< mNodes; i++) { + mWeights[i] = mStarterWeight; + } + } +} +// +// END Global Definitions: Variables, Properties and etc ... +// diff --git a/XEU5-0/Documents/.gitkeep b/XEU5-0/Documents/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Documents/Reports/.gitkeep b/XEU5-0/Documents/Reports/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Documents/Settings/.gitkeep b/XEU5-0/Documents/Settings/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Documents/Settings/xeu5ea.set b/XEU5-0/Documents/Settings/xeu5ea.set new file mode 100644 index 0000000000000000000000000000000000000000..1c8b53c6a53f2102bf6ccddc8f557a03dc431b7d GIT binary patch literal 7562 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 Ly*!A^@aO*neWa-s literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xeu5ea_just_xtam_and_xstfi_xtam_signaller.set b/XEU5-0/Documents/Settings/xeu5ea_just_xtam_and_xstfi_xtam_signaller.set new file mode 100644 index 0000000000000000000000000000000000000000..a2caf3482d900be8582db122c01db7dc6dce3590 GIT binary patch literal 18988 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 PXAjZnULM3{`1Ah(Rne&t literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xeu5ea_xtam_signaller.final.set b/XEU5-0/Documents/Settings/xeu5ea_xtam_signaller.final.set new file mode 100644 index 0000000000000000000000000000000000000000..d459e7a03ceb9c43b83d454c14123cdfc3f00a54 GIT binary patch literal 18990 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 IxDJ2*6P1Rko&W#< literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xeu5ea_xtam_signaller_shorts.final.set b/XEU5-0/Documents/Settings/xeu5ea_xtam_signaller_shorts.final.set new file mode 100644 index 0000000000000000000000000000000000000000..243aa1fcd07891ab3fef463bdcc2cc13447678cb GIT binary patch literal 18992 zcmcgzYfl`>746TF@*n00Bo5#Q_C|cbc%5AdY|F!X{nddnMhgZpIL1+ady;eN%%$$_ zuI`@coub%;}bmP^-tAf zoPVmGR=d@ot3Oqoe_MU2&H-goea86$kS5hhf^-YW=YYs}JYQGeFnWUXr|JfOml%7C zznjJED_jxY4EMKb##!|@K)OzMmw58;#nVZ3SN#>EJ^?r9&w%$5l-}X$8>oAP^C!TX z;mI|QH-Ip~lT&a?T8Syse}#A7@RXFFr;(&qobef{A-$yRtoo7Oh(<#G3+_*V{~X6Z zaD52q#3Y_G6q5;QA~odxEAUe4pK+udiS5^WNl|W;;XfC&8pQ{gafu(bHNWSBc+c=7 z?PuvJ;d3^165s9t?hSCys{i2k8KW)||Ge8u&;0v0_c-gpg|5zxp zC)x^mzo;U-$Z5Q55oGig zI{i|>u^ugC8NCND*TAQ!vsa5&!?ob0v?&}>PV2xDJ^vU|VXiT+H)}h>Q)Ysb%6sA- zeC%2E0-1daapM{8tbzcmQ=SdVu>){LRyi#efR`xOU5r|pE_mCJ54xK z%whdUkNSYQ7b(BZs@Hf*c(j#0(8Y?GznukKyJzhzO!-Ok8RagXA{TAg`=ngr#8ZC+ zE-n&R*EpX;XX1jC?j&A}W|O+n$9vC7iR%3n6_|tiaMq=0Scy$Gn6c3gg-y?NZ_lFK zWKmOa$@nCHrnP%|tRAsATB2pVELhW@K)UQo=+~zy%H6?hx@dc!Y>qKCbL{02d1u!{ zIoOXm2(R43g5HEVWIz}(QN62>udyEVj@z^6W5-=ve!u==6^A+stJEU2+pGU~H z7G)km!X7v8GKaJ>yXR9<8}(Pm{SR1=^cbU>aVmaIdQEtxh`S6wnTIF$GTlm5Mdn7U z2f8nFQ^MZHk@AIEM>|J(KCO)_2dw39p%vy)`rSV2NA-xu>D>vk6npu-g=WN?A}6)c zl-kRrch)E;nCbQX8W7p}Nq8jD9yXN?Dl}{6cDyl7i7?_>qOu8e*uxVd`dS_|t^Pye{ew2mRyr{i%%jS|y7vePo!;5Gv2H5Mt3cgt8s#Ii}PO_5job;ePB8jD=UyFQ)?pMIa$9oMBXLhjes7;B3dHmj>+ zMC|4CrIB8u-s2T>$40Lye4g}pEbG&oU~gJ?bu63I-`naX^4Vea%Mu=!$9n0mUx#Hp z>(XL|zF9q%@N80(2hbt&zyW^!(bJFKtTx*)txKOC{$@2=#`G{cJwh&8MXMbDPj(JHxH=Yh-(wtee;0Y^|&^t-TDrs_QFpWYb{!3_5I~>>QlIe z700Nnot@1lx94fiAg{vtdF5GsE3;Y=s^hX1 zQ?A5v)%q%}$z^Q9<=4*DyQ#}4NlTK@`@^&|ge$^cewxSK3a*RUJbpdGQFhi`-j!#sB70#h$xv8yY?Gm?xi(wk+bF-?1^0Fq zblycyIFmo_1ahCwWT#P0YVJ~9d5B}4;VEysT#QDk*mndq787bnv z(+fa->ekQHBev_5@7r|hF-CDl$+!FrUCWN7YqQNMGIbjte#`-^ zf|fu#uMaeb2Q*kj{`?Q9| za}~3SXng`p;2uoW0O^f%jN_bKFmHBq9!IUtd7M9-^9W}g=gelbF=n(jjr%dHbM0pj z=h;IU%CS1?_S(QYZl4*nJJGchqFGbKYwkXrA-{3=zZ}Q8lV{N=U(qx5MmBHWvK-{D z*m;LY!}Xa=-C@csr5rPkwi4V(S`wB*H+Twn9F4x?W zE%{omEn*r?xdWJ_j*2<{$0CzzOdi30TJJx=>-gOSYoJ}&gzfgm>*lU9-*@f(wqs;1 zVfx@+t8(idcEG8D5{-w+p0!u~19Sb}d(I`2vCnX2$=m^2)SAbsw_Yl&yi6+bx+xXD zUrj2)x4cX=z9bRZimb#kR<0PMmD5KUA=)g(-k0r!^_EE_UNn7KH-)|pvY|F}GoNaJTQ2kbS49w&BO)hgaW4OMd zQ8j2ItUuAXJZk99h`|*+_HU)^!Kz=eAYZ8()V(ah?5_{z1$b=lP~vR%hiw$8Y9s}^ z$`o1mQl_X0Gg4IQP>d@5*Mt200J(tw4>5C{j30LZJvOtNjX1>InA_OO03CR9FfA2*9kc{Hh7M{|3_+wmqoV?DSwBuW?&yO6h+V9(JN}dws z_b$p<(K9Fq^N!zp!Z%{IQ)ggK!KS*C{JDyPj=i^_&InK$X1QQ;?}Ft%LZy z8s}58J~oxRc#o0R+?>&8!<3})s>)XDjgcA~L8^v*Z|o^GXry=uH04`^NZ(Rl$N#{X zKn7jjc!c*|-gwmTMqBT)v+SU`?q&24!bAEY@eT7s@jBcOCChB#(GLmTG(F4@J%k~C z=;voDm-j=?ulwOM)YOd1wvOhtUiZLUfj2F--|sy2 z=0HVO9nIs)(VBA~(%*=0n7@h3;r=EmW=oF#M(E@G%|jUCZ+?EJa(RE_{JOt!Rd73b z+%7857mJ?TypA*KUPs@2jFoQo1Nnb;Kf(g72A3R7R^_bcc^U709@=>CsV&j!}#il9&7oyE~V2lX3ei0jxHu3O%6oeZVL zYO34IS@D@1qgPrdV`uqAxuYR2LNd)qNZZKCw*H>4)M4|!?B9ep%)dEvynna%Eyk_c z;V}Oul?GvmfBX4E{G0Pl^WIZSy^C>d`t{>W{foCf^YB#vMOX;O?nxLl`XFig)82L0H)R%g2_doZbq9;|WxSkBO#Io^ZYJ0auK zEN_?x`+9wd2mATngS~uo-CO}Q4outLBip+nn`Qd-v${GW&f{8Ye}48n8ExbI*+VqC K*9UPO{``OAd#S1b literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller.final.set b/XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller.final.set new file mode 100644 index 0000000000000000000000000000000000000000..c5fadaec790594f9cadc9f74b348fbcbbf6eac15 GIT binary patch literal 7576 zcmcgw+j0^?5bbBH{0BZj5u&-M#RDeBSY=2mB+4to1}Py>Tnt)%yL!&_4l}bXE@872 z1ZynBRylow$JBZuEhr0L7Eah`IeG=ZSLGA?Dk^IKz7OMuv zevT?;&cEMSV$_W+vZ=T}f`4xt`2(YWUMU(+j1}5GkWgM|X*gPE_YiUz*ZCze{-^MA zen~ucEqO0Di1m_O!j~fx*Xf~`GrQRwDfH^Y6Iyep@F6=pa@aKy!JWEae>KWNS^w9o9!D2@QyWRi_*&KP z0&IoW)o~`+TQYyK`Xn`D-C32>#2)s4JW-#qcVOyUB&V3AJjO~5da+~XXD^m($LymO z$<3_Jk@qx~*P&;zoMwry{W+`{7^}v(_Te+Nf|~9bTddBOb*mr8z9nf|*G*Pn4a&ky zvS?9>rZMQy7>A0cb2_$jX%W?gmCR3io*C`FKDHmRc{ELz{9Lf7?|@xCmGE45O_p2W z)cjAkD-(0fsm@}bkI;5L^^gbqA&W^q*cG!1-9z#OT2QY`czz76YUa6*yZEF>S^B?> zk(FuZIFp5DbKR-2JA$q30mliu3Tj50gsEVT{&m&E>n=utn0S8+j9>NnmVs|_>{|-g-L=5Q37%6|SNqSRy2^jL zTV0>8^HBuXe`$r!qUk8~)aD8NcjF5RE)lo$@VU_EO=9L&lGaF(Q$!!x=Dw|oZ zDwbCw6w7LeP%Nj{$Wxo~sw=a&-Tq0hg)^@hMYEekDU#s}d51jvNzOKiUAH!iVRP@%H;6 htaJUYcqi7bm=Cdb#eL&}+&6Z}ePf5*`&f_3{XbOZJ?#Jh literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller_longs.final.set b/XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller_longs.final.set new file mode 100644 index 0000000000000000000000000000000000000000..d2b9f2984efe16e61217963390888a853463d9cf GIT binary patch literal 8324 zcmcgw+j81S5bftw?LY7VS%RI|@n(w$V#k|Q+1O>AEUzrcgbEmn%bINMx9{ehX$>^sc9m3Q)5 zPUIJPA$)!*Uu6U-HF>~w3`sTV8%aw@9zi1S@j8{e8BH+rPdrRe*8fMPF-`-%fj4XOnaeV~;-gD%Sjs8WYXgo1iX!}?~d7-7@D9i2%1phB?&$^a zpC5ltatD#E5m!`p$k!cwwJ^JcJS#tAT_j(yo^ii|KgO{0R_O0yIY8vKsch;+?)*Y4 zErTasESv=FSuW0@-4vQGpw|dYXwO}ML+?oxj=-5(K~0a1Emmjib*mr8z9nf| zw@g)F56Z(#deNd1O=HlZF%A_?=X7l6LceK5bzmjyljbv{-PgzNM{FHU)1|mCxTo*K zyF8UJuLq{et&uf9)9ud09BZnx*!M?hJ5N3IgZ7w$3|ckK zxsOjBnG=*^^8Dv;>>OwE&}^-{G4vMwuORmfD8=C9(fN^eB&E zRkN0=z1Dl%^3p2qF7`MZ-fVo@FuMw8jlMn5ak@2W=vfwNzp&AfZIOGP(Z)9i+{-V) z3i~MYu7&-ho)PcOy*|1W&+^Tf8MRF-C)wEc+Iz!0_b7cl>GORFi9GM{jl*N2r!sn- z-`qb|IO`>1QqTU=K)UrCJe7^CET&ca9tN4vyDh*BkQ9dy=w*0`!l&M2Rm z@7_F?#TX^$^W|shzHEgE)pB)@n!Ouey3+TkpYvLEi=2A9s8ib*<*}x+t7a~VlFeQi z72zl=qmwoAM&6^NUCGBCGS02d<1o}E9A#-{PvTwdJFHGVPFXxU>D4lshLg?Z{@I>n z@*Etp51iwZUp@WRzL(Q7GUP8D<+GWER2HAU{Aw9ZM>-6r*XTw2u*&s^;x&m?KC?tP e6t^MPq1bKj$!`0A?1orXu-iT$yFON#?EV0o+QwM` literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller_shorts.final.set b/XEU5-0/Documents/Settings/xeu5ea_xtsfi_signaller_shorts.final.set new file mode 100644 index 0000000000000000000000000000000000000000..de350ab10c3fda9507a3ff310808326130d31ce1 GIT binary patch literal 7578 zcmcgw+j8PY5bftwZHvSw5H_9W*_tC<-g zRv1~73Zxm$^yxm`(>t2+d$8+_?_VY zXZc0Gm+yr0=ki$wkW!OJ+=q}%V z(4M;)efbHJCayI?&);cpO_uT_MsU z%xR$i81EM7rRD=SlG>_e?4vf+mzwqEt9zq5Qt}UI_kcgZ|6h3i0O>?ho4pj{ggQ|h zTK@!Gvi^vF@<_DzE2hXBIs7x#)fhj=j1ew+Yqqk3xP4sIz3+M{pR?(c_-zw%r@&6+ zA6$i`}PW>{(&mL@WZ^4>sxu_s2MwzWs&&t!)>$4rJXyPa?IWWEEJ3+On+ zN{{8oGUL{!=*dI4NF%B$`G0`p1i7d>3$DP?6MXtP2jg|T;5oX5Efe5r)@f$4)$U#h zS*i*n=IJ$1;+1~~R#avx!(9pkCtGJV{4n)c}$3`d`) z>oZ=B9YnwY{$Wk;Ll0uuI<~vYsz>uT*-;bf&fHCDS|jJK{+MlCldKibuBNfpc@}2C z-#z}k)Tq2(^o^ihbA4AxABjmf>8X)r0Wj1AzJHOaU z^Wbq13&)Z7%opd-ZVXLl&}#rsXw99$huqnb!v_};eqW(6p-~n`(zo?$rP0N`sYOyY zzK9abyarpbbuFw3?k$0l1`e_T7ld5bT-yaKej_l^0aQb ztiT#ngqda0P>H57=+PL5il%+qw!WA*ji?T+WPZ~1%xDkwvHghU(L7zsbHP1*5A5<( z!gc-NvfL7@=3Bbmx|m~5^%jSG#J2O)LmuoRi&;LnD`pjXhU6)^S!PGwME~)95LkY0QJsfm*J2Z zk7qHnZ__fNE=5<^T+b*lc+V8D-XHFSU*Rm&N`a(W8Ehvzl3| z_8NQZ^71n7HuiWMj#ix3-LAr0qhAlSoo`JZ`X-CCURZQ&w#d(CwDHRU_wsXig>{tc zu7&-ho)PcdyB?|(&+^UGGisY=PI_aVwKvZ1+@tg`GxYZ*B=Wq&FAh(cn#$<)y!j_) zIAe)e#jDuX6ZxB>DsoM~M2oYP&-_ze&LS<&Hm>e?KND7cer4d79Q#UfzdE1ZgNqBC zQ`bj_XHgv$p6=Gim)rR$g5Txwn+W%hAx^m+WER2iBgDdBrGZ_tE8h?%J52;A`=iyYz@wL1`ru`uAwuoLowutB0=D1bNfX6B3I%M)SaH{0`94s^Eo#QIb72)V= x`3{k)Wjr5gKb&9T`}a#&=lFf`PON<~A7kx{`}PaDZ|{-&_8z$pv0jt={{es@K0*Kh literal 0 HcmV?d00001 diff --git a/XEU5-0/Documents/Settings/xts.tpl b/XEU5-0/Documents/Settings/xts.tpl new file mode 100644 index 0000000000000000000000000000000000000000..f5487f1732bbcb3f7e4228d50b8202fe2d107eeb GIT binary patch literal 7966 zcmeI1ZEGVp5Xbep(C?6!EnLz#555GFgX4M!g{G8V3iqO5Hnx+vXU8VC^Ux39_W#qY zqSdZ!CrwSu5zHoDX*4sMhyRS^zy3UOU3cjUckO2Gjr-bta(ZMzT0t! z`uke%Eq&*`rIFX3dg|`o$ep>d8*0^i_pAFw&qw#YpY6H6n@Ym9xK1QtAi670H`mzM zZMYlFZ}=4(S_7A%*9J`{TFuI_H0o&ey&pMt+n#qiI~Cm@qCb{?tnKOjLeEV6!x-|r z?z4DB>TS0re(_^+$DShSi|m1R33rpto(gH&7q4^8-7T5vd+kS}V&^R{59_tOROB_e zg*Aoe%o?a$?qJE9mgaN%oq2mMp6SR3>?P=y+9K+9EdTF#+m5_Putv+jpX>d)Vx0@` zHKNF@b>sayZ&;8Bz~6yxsz@Bjp0mtI)n`QCmi)ZyV{)&QVtz2oO~e_$=e!%DfY=H< z7)$a{K8^2J-nU(iTFe9;iC?@PXF7`hS?OE6d8QRTzYfa4v5-EW8>7VfRI8C<)Ml}s z#_!7=STyJI$acv5OnWILwg140IrC1O!@5YrTlWw1w_bKnqqo`@F|_B7&$g}bJ+!K?0SCqHTWjvVrN(hil0tVy5X@+Ss`08C0X-!|M9QBR=rbj@pl%t__Tb4RhP24T*P|ft!^eG0U^wDm0Oi1bWBp+`X5?eM; z6eTHD^OfGMnx5zzRM1a6)nysyh2AI9GU61~!7vJRWDg;8VvXu}ZfH(EM2#(nRVc=jaKVjtfH?ZYp<-k z+xqs(udv!i=F~Ml@^Ly*K7g`@qG&@`6m&T7x}R&OIah0bEjGv_Gmo_atq-;8vLl)3w^*cIyAaXaL_Do7?A4ye@6z;?gbaV?CP`{ z7fzKw{{|{l^WQpdI$my5+RFMm3eY>-ZA-|X#~=Y&{IhZ{+?9~6h6efkX7oh#AP03l zWH;k)g_HDM)!a7>S$FP(3(YRn?9d!fyAHauW>tD#Z@SLzgZ^ntwx>56$lCP$)*-)i zA9hY$)B|sNPje4R1|61hzPQH?^?ETyy$j|<%+04|(DSZx+0Y2g zsO$0gUWqek#6auxa=nkuyx?DYmcv8w%>J~~7hUX^jDOtN6VISXxDU%C5PkDL4H=Y2ixvb*PmUB}I*p1$A=M@}yA$G_`Fzf+w)HrzWet9t4}Hm8{9pSi3~famm8 z@XejCY`orU#e1qxIt8KWPixe)j?d54^<<5@#*^%GwfwL~Ex9M9Q#epX=iYRYuDOa~ zXy4UYmQ%gm0_J*SJLMZSzu<5Sz;89PY=@mvq&>S;nUrFcL@F4lyjWsNk&~EGtdhw6 c!m=G!=X27k^Q&a7@17xl)?hULvhc?J4c$cMcmMzZ literal 0 HcmV?d00001 diff --git a/XEU5-0/Experts/.gitkeep b/XEU5-0/Experts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Experts/x-saherelm.xeu5.ea.ex5 b/XEU5-0/Experts/x-saherelm.xeu5.ea.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..dcacd4413a739309c74e38eb91c4307fd302d9fb GIT binary patch literal 191218 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%0Ac7>K%&j2k@l z0gDEQ)L$=@h}!y_SbF*ScD(KKQd~FToKDa9Y331@G==#vXA$d2=W^I&4MQl$mt&`t zO&u7jqY6yz=DH;JjD^v*W_VQx{<|9ui%D=;I;WCy2j(TjpFJeev!#leS{?E`?~`C) zFwKp2FfSxxZuBitK%(KkJCEsI;LiCt(s%X_9la==GL)?9a0&Qpbwe2u6$5(YsjSlI z9x&b!?g;d*wo*fvFMcNW1pV`AT)c`!{`t*4#--F*0)EQf`T+x}nFFYJ*y)(RGgWQ? zyOUVSpg;}K;4=3So)KM}=UXb!%E$iF6nb223{T;>4N@^2{HV3yOB$*IMO z{IqLhY42RItTONXTuHop=gh5>!nZ}sgE7JGXK&*TE{tQ@%o{2lPdatRP6jcZ4mFpw z@L>Wo)NX^tD?a`2HEzn*PDuRfS+>;2#vCa^lEZzy{{8irU!{~!P%i|>Wl-SQ|5jQZ zSg2n5p>h4v;^R>1;YMsriH*KzjuJW{YGS>u|8%IvxoB4AOS2w9dIbFA4lsisGY5t; zz6<&)+o;qCBvJ^+F8cyK$}0yAfJ%_DZc@#!ykdatBhTWHB)Mu8svzzgk$g3H%_31oNfGOy| zXmf|5Z9ku6GKB`XlxyN0)p<4T=zcvinLn&F=)NKrz)vR^i^@wG-&By2iy?YLJZUA? z5@*qaZ-Rud#Mc(3c@Ee-Q6MOlnw0Xh??C~5c?$Ka36s=XZ*Md>opcZHPv$CjC?Cro zUvwlHFrfHZ)2U(_0v1pbPd+VrA-#2bBF5!xw3Tn>IYVkFk$9GG;iBf&rm4_pafs(Y zWg}lau?ta)!H65)s5SS1v$w>>tVQrx<38p-PMs)UWD+wmv%&Rg%ZSN_)-k=hU-Bi&IQP)TpIxZl;W8vA`?3x{<&YzRb~l2P-xu?NNXSC) zAQ3R|(JI#IIIIz=N>;n+RZuXet7cE1bB!6FO|tB^cO9!Su8SHKbmuf)PltOnm(`fJ z%_Zirned_UVQeOZeY09p?aexl+V>=c>C(RWgm=4PGxJ6bJ^AEY1proFgb(0P5$Oo$ ztOQU;#ZvhRISMMJ)sIfrOSTvi`r~y02xeaMoDfgWS%XB!{lS4K%t_E;$ZSb`e5T&4 zEc{&X;fLRCeOR3*(~{M^3ir1WQoxx`449JCMn%^Fto34kaA#_utT^9$`E4hG)ZRsf zc(0YGRAP7z#xxb4A{H6-sL(ayC3NANV1d!4f2F)y&<=m5!R;Hyg|T@}oG>RXCdG>h zS3AJuy=JMoUvkw@+Fx@j8B8Z`PqdDco+1L%B(xzN!wz8x$~lULpyI;+j`8;nu}7-r zerU+_91hOFgT4>!DqMm`4hmnJHmX@im6BjCcK0qK;8GqHRRkVxMU)Ql1#xy4as{xF zWpbIkhhj|Igu5ni8>O^Zy4#b}@QNB)IGEw5gVZ;U4OEtt*CEe|fkd?3)*QG^8<)$U!s?s*DLqvrM3N(1da50 zliu*HmFLY8yB)+g?XhTT3aSmn`iGEg zt&>$T6Y;s;O)ApNsP6i*zVOOn+6``4+PR zJ()u>j^RXrdaDq=*co+QEvB&m?%rqUHJmn`GPwXh-1jj&KbeS|+Eo^2Uu|CKx>JFV zC_ln!-tV)xbpt3q%I_lQan=38vng#adoa;p|B97AEMOU$3|EHHnYUKE6q0G+hOX~I z(vjVmIarP)j4C+U{#bP}wXK!Wzc0A_m@=X+Rz}fZu;VsII8E|<1F9&d{#Ywc)K3I! zs0k8G6#Eg55*0Y%>{>_XSZH#XxxEjxJSA`V(>$pm41Qlrkq?l`aPsImZ$%SG@gOgv zvk?~cDcZ`&zwF>6GAe^v;UArX1X`B=oQ5#%{F_bH8I4g(|$||ynl_7YhTI0|^i|AvDmJ11Bx|s+tN}r+JtDfKL3U7)ZkKP{l$?UhkeIZ}tOKy+tB^zmNL=Q8}CgFKj>@i_lfF~g@oG(B3 zwNE1uQS4thruU5=y!4kZlI#ymdv%MM%>%*V&1GZu*~;q-snq+o^!~4gCAl1>&k{yE zQiDj;!v6|PQb8i}emgp|rQ5;DT_Yg3k!qcoe5cX^o(OS2vg5WKPBZ8lWfP{DIVBda zec&!NPhQG0yM(00zp^-?8l_N6Lar*ON@r_s!gT=rqhr5#U4Lc5bOMEx0|-Zk#H z)2LOcesR~e;_)(ueL-M!hca_V-}9Hl&m#5&fp5yQfO7X0ZUJwUWk)#P(v1#a{B`>* z`XNR&jikJ=t`8wW?@4#8qZ|)FpQjvMCG$hB=9J4`!Zr3hUHo5`*??1Tiw<}hO>Z0b zWpQ%wIVYlpbHsZpRBo_Ii)_u!LKmG+k8F;0nNz12->Il@9@*XZvQGfsn2ZWBbVzdo z!1VLO^M11_e*wZW@~@ghrM(o5%G)HQ!KKa`0;1oy3wQ@OE$^JL0zRF$`u#Y2dMp0n zL|5fKX)V~wvT}Shxyb^g0N!+f@#$U*o>v$hkkt%_#9DjJ1MF?JVjPCE_0$1H3Bj=C zuq{m^Hzy;}V?;DaH>wfIJ~uL*62D&d@<$moy3jT@05Cu-Zv6Hm?_;-Qx6c>-G0M1DRMF^ zrW~vh1+9o*V+&K1W5hW-g;Z^!`DbPMZ$}4et)2vQSa=jT<;r5XQM7`hlZgrbD>x2m zK|xyCIDS(`R4MQ5&}AgfxoY1fY)?FZxzhQql;PERg2pbVt-OUx=>@1q9w~;-@TZ7S zZ-%+dpC;Oiu9YqkI@5OIJ?Bx1GPv!|dgj?n)a6PBT;!C#3G01m&Lc(FKYm!6Hs570 z|1DXeolPM0t$c$JMCf#3TE&=&_-9W}6peVD)TyGOkG7S05t3|VfmO6_EeP&d*Q+X* z7S{AAj`qVL=aSYNL5(c`!m@Z!l(OT7uE@PLY5f7WL~ z=%`I2v+85c>3j;E))!pfO}Y2tz^ecx`B$ldrl2JOH>*U{l2j`&n6eu&c{pEN0jAocr8mPKo$c*;;{qf5t{5ibT z0ffoeP|_`Qo*6`J=F@)u&_30YLYMuEbOd5W>sG4OBZ-6d43QBNYC&7L^`}X=tiK@$ z%?FT74G-OKa(sMVlfA^L!S%&`P4N;CVx3TZOSxfI78ZKXUW7Y#>WP`<;7S$N>Pk5E zIahf1D&ST(z#>Wk+o8^4o#o4qm5jeLT;^S|0(C3@r_+J zEl2o&Y?4f~+@qVS+{wu}O`QP@>tjz|aTAk|Kd%lB_q%ebri-b!APFWtCztK30GngJ zwZJX3v+Y`Lb1cXC-J6OtaYq<(jkqr^mZ8HLViU=H6s>ayxO`2Z zmT8S?U1os@GSQYjh(C?|NxcF`{^irAT;hh;qZz!#ARJ4qu*KNERp_E#@;@5QD6ZCG zRIEmeu)GL8a!;+>4uBIJwWb!Mm8+%c`UPk!WBABzA43?vOko~a?~5kYnN%{A_9nMo zK<0M{Vvq8F6;O_~^@)1v&AH%}-yVV&M?Fk1_8NL`(K(R>?7^;oLTyA8Q|$Z*TjE+T zJr&19NsrDVqG5nFSCH|ZvAPQWwYXcv=h64ww-K(e{d$-R5s$t<=`bW#KJ!;eC9y_i z3|*53plIc9R1i!R1SkHbD7k1Sfsb(~4z>skO17DODz5DP;_)q~>23#oE^i6uQ%$Eu zV~0^jr65H9W=5cSHw;r+VsT(!S2ax5b3J`3XVu-IR?-lv&F9V zt*JNLlhML$M@-5Y)W!1Zs%Rn7Py8MbsGGIfdLl8EJhsTM5|horn9JN7cG?$+)Matl zR8;WxpgOTqP!Ti7`b(u)- zZ~KmCLiYzU>#12qgIMlfes^BBO@blIyYVtS6TcjJu-$Bik({WtCJ6$D5?Zl8B~XXs zG=?p7uo`-c^OfHNT`P4FOcD>zrOp8Bqw}hIBLz%wr0*xcQ4MG>Oloq7;gRV85wD_@ zPxXzo0V`a-5;`jm@X6fq<^r`Tq#+ZV26v^i zRQk48K}u$1GnT}0254~v>7jt$mETr0eoCL^3AC2gKEZl-LA@EXHJ%!Pm+~C;XZ;ZR zEP;zn1=uEv6yf-aXP(}$t8oH6nBfR~Rp9NZIh`)URSEN(Yg^~|yZ$~VklcS8h&<*S z&w{$cJg%C^CG#^in7tVaessG#I>I_q;;QTEU*(kpg^_yEuo~>-Ilr<{!v^|-N_E%G4+HO$@GEtHh2yZ4@Yh3)4{RK)wJdMB# z0m;wF&Z{)9{o%6KQC-v`tZbI1NVVI`C{EJc=XiPN&wTYyw#kSHn;y?{jcQH5bmgH( zd_NSU#=aTVbEdtwctn+dzA{_2G=Cg%^VOO7*5x#v=|?`y0$+5&1OcDQVtHq2R=W)| zY*7Yg!!OLz&kjAa8t(5e>f7ng>Nq%>u0rJ6V5R2_Nm|^h*Zm_R!B2YgauN3@MZ~c7 zpf^a|S;&EqQ;E@Nddh*nXY9mSOUIb4t5#A<)X?tre85@Gj|cLn_uytABEqF`3ASD1 z+7j&;mjX%?_+@rE*LD!T1cl?M8DoV@&U_EI_m}*`mx7~nW?NHOA#pzXq_TderF=eg zu~uHIdBbxo{$}U^Kd_>~c>c!b#U3nXN}PS=gEKi1&_`u{PvLvvKe6#A9oHH~3*>$+ zW`DNqD$x5nN+&RdO8_Y}GUak_ER}U=bGqD2o(tqUwhQc&jF^w5kf6Ge2*|XHmtrt* znE?ST%;d3=d;Ts$I@tIOGfLH+bfl)S$+vhW?jD?%&9Om=yl~KgnyGjL6*c(cw-gwa zaHWID1Tg&2sXROE(7WZwJg!*rvD8o{y&I&6Ljd=*v!4aX00^Q8H3zD0SjyTPh33KxnPxjznk#c_GtIgzq80Va2b3d{+ zQ>7u5F^92I%~LK?2VEew1+b8jYqNTo<>pmU|ElZ6_(ek<=0%ewb3^8%C^_?4Muf)g zeDA~i8oJNpE5k~%I4JUnXZ>BKb!<9~%Mr{K9G-~;@F2qVzyNTWQQ@66WAqGgVQWvN zKmQ?)1JE@EQM#-kn$M`Y!{I9d+V{`pii0I|AX~=jTI4--051s@r68m~@vHWr^Sid+ zLtBT>r}+kvkH}BRbGk$3>+!2Z&<2e!OnS*R7Ir2wW~Ba@EuPr8y_rm_@HGYeR7O!5SkH*U{>hn?@lYh$^w#Q{ z2J>_8Dx*QHX7S4R!ixtck7Hxt!w-a`go2IWj^<~~^l49_df}E9XOU*?a>65oj4Tnyi_r6?CF#p$++ z*{dG{b*_yDN~=OsA0&do6E{PQ#S8|g3qCvB-B1DC8aS*i;^y`cp zcwjzG!)dpMlZ|j7ussaB_57o?u>CM{r{QNGaVO#Jls;&dN(d!%oee*C9aJW8Vxfus zjJ`+E1a&-R2Vv%UW$(fKS@00*o=22rc0h+wV|erA7A>smIg!qtCD|$Vb^ckxsxJN@ z(G&qB0v3A6jkdxyR)^AIJ)TN$>)I7-sdy!1SV=LDIa2CF%@R~ec)ML{o}O`_3SeV= z!l=E?l>e+NG(|;$!{`B7y9?^;du_~6pp?X9C45{Tr)k!hg@?s;+{x(*!1&3(L!RD$dqjv* zy)&}4dw}hm$)q6fUjXN9*-XRd+>txs3Ghs9yDLFP1+|9)V26bxy`$b|@^AFp28ccF z{X`CGA=3MvQ09s8hg{9N&7X!R2niMRFU+b ziU1c5BbI&7QKRGX!fr?Y$B)iB;d7_-mS<4U@nyTfvgxVsdJYS&wC_P8NQVhc3(W7y z=eU$W3L;T0R_!+B7F$M6b{Iv$Pfo>Bu2b&RQXKS=kP#n~GfPc=WD$scM%`_Vr4vfvji zrM$|9nVFsVX7YakGeFG0D!sMPqS3(^j4%WmG{WnPJ=SZWkz1^lKyk#xZ)L}7JVlyC zdU2TcF|+PvZKS+>mQJuobGZTp?BJdc^~wM`0x~+g*yl2$G&q`h!&3k$b9z^@6Q>fH zcVrz+k(Ot)>8&S*$(6_%Ehy$zQwLAGk&aP9yTQ6Fu4xZ4<95*a_@H7TuZ@J=K6G%D}dO!R}gSn$?8Vi^9TXK-0Wq5*@8;VXm&gQk?ig;w3G*phQWhUmdGMoru z^ffp&@Km-s|2ALaNjtp+Li;FsCYu>s^MsyUiD<0nogoZYyw+OEcXw0A%vAfKk-Pd~ z6a04ivm}*zr90PU++gIU0g_OwK8j0Aa8UDeH%Oee-phTUVB_^$_TBas$?hXHt+HyF z8VGqUW77q})D&c8V9O8pSzLKB{dy#>YwjdPJrJX;6V?lHqaxJnLXz#iU{q-ALPk;$ z=x(@BLz7AuWkEJIV7G0`JX(*_`kwWrKSbG**6$W)l?@`~8aut^2A_9e9XMuNIbR=3 zJmZ+tEYdfVZQM(#k5dp>aRZuzTgQi&eLCtV;*IqsM5%czayi&Co1%yw~L=3ucVcwJ&WV&YXerMI=w)95L}_C_ptp=f**Pt+Eq1sh#oTC{;!7C zkjZx-UBsg!@XacM+Oy)ZcDu0UKJ5o5j)kof*O*R?0gm&?2W)UflDb7^gGql)k}b@r zEsoWKsEfoC(62H%iqj!VujaLs>ujhAskr^L`K{wNZn29`u&=YDIA#YROO~=$)QVs0 zG1EhtZzU`D*B0y@GmSlNqF`7zT)JP>qzz(T`IZ_Jd#FZ&U3)_XF0-7iPVOl(dm~xL zv$X-&LixZB6nRd^O8|x5zAx6*H~Fu|>K?*ab`9l7fzzRA1c=L6TSj*Lz}N9*xo=xn zp*Vt)_-sX3B1e1B;aiPmv@P+ZB`Z>L-O)cEleorf)A9;2ox!+_h@3wo63&?@_sdCK zubwvG{2^MQQW5G-5qrcfm=fu>Q`Pn$+efp0`N_^0Y`LAT7AC*PFC9V+p*}m#@K*87 z16=M&)G=DigD=@w6Y$5Z{0j{yP3s5|T@1#XvuI6HVnc*4+T2F2x`qKf3( zk_CzT0l%1}n^N9&_OV;VA56;M9}&7(Oa&*&ykVok=a<2Eb~J?J{-U(bRF|~C*YXe+ zfvwS^B7pFsaHv%DahqVHR+7!H*(&5(p=cZ5X>TS39$j1FmwyAoA?X3%^T1uW>xy`P zRo4uzwTlJbBJ;Wa!1qU$)o07|$fi!0+BYtdlE>Dzt*{Po-Z9Yy_$B3WWBnw~HXTt! zf1|S#t!9a~He}+9$GjA`0UexP`aZhk&FwTK^foS$I>xcp>tf?PrlMA-eV+SwVW=YS z|1ra9>MPQlinnef@(R`_p%s5`{E= zi1sR@kNITDaupDkF8oEh5GN3(B-rlxI<4UC7M+j?<&07{2AI*7m-Kb=L&WfBjM%6xjzf}@6DE+Rm3Zb@K&bf&13yuga9EzY zCMX0vHFvB{QJVY)1_+ctM6pRW>`-v`#4kr&j7PXfHJlX5U9#c7Fc{J$ z{9Nmo-wET`FdzoUFVl3cAL|js19DPYvYc6I)K!^wLD!-cDb)wOn_Jh1o&lU3&7fnt zJv!dVBfHYxL;hVoKwzUda*iJbBn;Gebo=AFiPSMZd3jF2I$i6vzEhs4R*C2i2AT>Hr9*2IAQO5D z|LLtEH-Hj)GK9gX=2KFnrdC?O4vo3|#m0b(UBY{0>%09d(|y8aPj zNAAy+P==f>!WT-J_S$_i_!>jgR`FhC(Zz(9;9PGj~C&LCS`3%IsoBzPu77 z)(CcC%JI5Lp}Ca9*SlUF3fr6s;f?!a(T3Vi8`SCN4;i7gRUQO%GDNdlflTA(#I;~b z6wEM|CDyog(B*mDc>cyP777c4*W`1iViPScriy?YhkZ`UTsUFp^vw4fa{M8Kd~(Pq zkR%h3O5>L8#WrDGEAD>vWS1M)klIy1@udvkDCt@YE&*dKq;A|=hf+i%G{>E)VOn?l zETa#|{OJUQ1vkMWOoXSV`o<_17>9x5Pz0_#3D;HIoS83g=!=sSI|MZ4h1D|Z&#xWd z?3aB9jzgiAd_%3;GO&fIc)ENZr6s9SW(~!?Uyq1hFOPPYS4qgEEwxy=*p? zNbz~VqT?!QNinY{KS{8X+{5{YW&sbX*kmgI}xn$;EA zv(ickhWBP@0wVWTRR$delXuhNwpwtEqHyaPd?I52V~n(b)jiy~-Zk4ZaTbb9KPPD%#u9`?ZRnXf zU+>QAd9eEbS;g~(O_5$M7LxOW9|MJeeHem~JxkvK%c(tgz_V|snrvfF=u!0Q{ac$& zrfamNHZV~;Dw1@}W|%aeXgMlNd$c2e1Jtf)ITcCYJ4&)(WjB%Jn>XT&0e>0RSSc2rBRJ#Fv$-{;bHX4S|hGCzZ||T~N#HOn>2e zAL}gcXM5MhjsEr14!}DR)~$?^=&9{i1SC3elkp^}LAK8WvSpusgoBuxCgB-v#zBVZ zE$Q|#cSEZ?9y1=iYD>9KGS|19ywApjH?WIhdCMVYcjj%(`m|Zd_0PBB4u!3#7G$^R z?Z-IOm`PO{@OyObm3#@R;T|dyK+tJ6TuYj&@g*(0dN;b&Gt<$h$!kF&T6p>`jlquoB_k*c+sY+3 zn4A~PFp@rB9C%x`mjhkDt*EbMk=C;Mc%q8a1rV>+7wN;UkPaB)D|JAL#?W@%`-d`Y ztGkjf8{1rh+J$u3SEZ@zKioDF4V;_5$~mh6ApcVjNCF$@cK8<>>Yfb9=0HO;{;KAN znkUDwIa95IrbfTbz*kHk@Y|@IiTZuj$*{1q^7{ze5Q|+WB{VOZ6an9|?%f6c;6iDg z?r3R)W8#&}ieW?SyGk6kU@noY%f3)&crnzZhwEDP#RCrS9I29VD!q}V=x*K^ALWxI z{6HaPHE{(QNT%- z*6Cy5AL%)uaO)>>{itpZr;$VO*5!E`j=m4-LCN*TXu@w7OeJ?SlpU?WD6--ThKvX= zKKbYQnf;}N9eEjP+~;ttJ#rvWec!_tK0HLR?YSbp#VZ;!3QdnZ8HtoY)tM($#-j_0 zzDR)%4x@p5Oz3;jY3J{Rk4#WXw}k>Ll{4dIY8nn~5{njtt--Y4W&!gYi6&TvS{r$S zCq96x)or5qLDEPdXOH)wHxRhumwIYLImRIKC1aJh&!%E1UREuABUHvnsqz>5b{}bn zr?|l1WJ?LSTGFlpRP0*EYM1tSmznICsrmE;(Vy+s+`(s#zw&%dG4h%VA9n^4a0TVrQNtZAD0`>ZL0b$R zd#>b)Lw(A+8}rtT2`WB>uqrf5bv1*P@+PEj!My-Ti8bpR2RW2bxL)OZI$xvZ(}%ka z)o0-67&`^6+C=DJflrk#8a?t3pA0Vgh$o}Dx+(hOO`4w(>`+OTkT=>X#_dd3L(e(f zDK|W2_O65~6-0pkVMz=o%=Aob4f|b+jiKw3reyhm{ z4rwg#_+UD&K-@VkAYn61HRhgpzh!`XQvjUIW`lwq3UuyzZMF{Aa=cg?N&jN% zRJ&vMW6P^pC(C03D;p;bMz8AWNXbAFnZf&nqi9*RM_GMLYUV8gavJfC%c>W- z2aku%F!lfGAiBQI9kIaTH=`PR`kr#HFe|hE?_l`XXDHDKuycx~Cd@;Sxm`hdCZ-{Q z*o#5@8eFJE(zfftEY(L3gOkE3^WP)oqZpBcZ2vpJx!({x#D`HC-8rAN$cj5}+bsc9 z^T*!kU`?!uTT&t3Dot$#A|FnDTxd%+Dxo|qLtD5x_IXj zLlOqb81EH4K;8xLrWUJwi>ghXdn( z-;*gNe+{hsFVdi2!OyRLapAEF8{D!4I%j@@%-VCq^Ks zp3ah^aSbQW#*7_tr0k&=M*Sgq$f&GZjrwWy8}mudF-fn_Ejx&@DrstsmD$V)EI?Ct z+ILjXACUOWb%Mx6VmNfqJ&>s-MT~?WFnnGOM=a2Al0CHif#ZJzUWO-hZa7Q@!rPgM zyT^p#Mn*avApnftYNW&3g>Z{4B5@5sj{pgc z0-#2Dq3AQ5HOp!=SfCt$r5_n(ZYG0Rv73g8e{MTH5Wz@ZYIprG!5mOl->y4ohLL zNsmw)OZEW_-*q*8NBxM74Ou0^2|=s3e@_T`Vnjt=q5sg364uLFyq$F8K-@>2EYaWs+4 zvyx-3r>?_nQyj2%TW}ATz6Wb92N=V62;~+tB>`?QH|~w{?Ohe}3AMimib9MOenEZ(MUcGc*d;N zHL&8U-$tkuUiQ3UT`TBn_?;ufh8FhnaWp27gHfC3znM+9z?LUo%|?C=DOIh%wCkBK z$7lh766F9<;8BQwY9NEzgWr;Us%S*n)wJJZrk#S}M9bk`7Lzt5_#@;*` zcdd{89485Eu7U*T3JypM#$Uon$B{Cd9O+`P7wy*~J8fkG%yGOQ8Mo>szAgB78HM%A zB01ok^Xf?+LXcx4v`4d`p^sG=ak^XZWmKOnqkdZdeCtd?mFCkXZT+CfD|s`~Gt^1W z?~P$3NjWvhtC=Vc+|*YlPRZ0DbqlzJUuBdzj%Q3R z4ZECJRfi-m;wp3_un;oplm2(%cKC;4wLqQ7Io|QcH!rGZx2Frum0eb~Kw8G<W(UU^)u_Q8Evm@x{cO|ru(we25+#RkThlIe88jCqi&j_Jf0sj zBbFT>rH-T1K$J_Ox_k}zQPBrwcucraiK`j%e?i)<%Mxr*!;Ei0f65jR;y#X3`-j0U zKh)}G&HS=`OMe?E#dwZ-(d!Vr?Gd)mn;^~~>j}|R$BN;l4B!*R4;ar{kFU&P5f(vr z;QP^hNk%VT?I2mPQyN0w#dn1Qi6nX#)cV zb;pQGVk_OgJm#KNE|yqX1mE~b%P3PX6l!e_$$5S;F5!@A1I*snl`_q!eO+A!!)llI z8o~gwz59t~fPUkmSC$*eG2Ks?L>XRUQ~-*j{uU|DC=^g!v{A zZGa|<#Il=`DD|tX#8pAec~rXjnrZ=x0go;y`84cm?}}r^xIJit_P1`-3X6ClX$qhj zRu9taVh6ixUF8;GXS%9+57g+ffMH=!zoG`f%f0e8V8^r=H?0a!w@%pHSCkiME);CSP8uVh z!IQKBzirx50$e>e5vF^N1t}We>Y4S51=;!)i2%$BSpSkvG^as zrABSj&}q`8Y`Q8VH5of%DuzOxLt=tsdi>e$JZ(0>kX~zbDZgS`wc6Q3BdIp_lFfM}uAivKJJ)$( z$T-5TMC)_&WlnBH{kN=bQ>6yu4$O2NIZjC#W@YElXR`iYSAKD@4d13}U}9dzBxRs& z5+xW3s2n~(5;@kIvpT_NmtS=Z*9tq^XMZEMpJSm*ZxHU6fRgqnoI*ag+fQf7<_C&u1_Anja}nw@?FKxhU{F;LirAY5*5d zLZ}J*yMxie1#pjJ*inJ;;O}^S{DQBQwP~TlNjI2=l+77VzopsB8**zJvDz)L zFy%i`xw07yMsy`zCrlage#({!pUh_bf{3{am>h8yF3o1mj$H3%n*sEO#I#YJVq*R3 zsq4j=jN8HI^~7@XgJV_vwX@Z=E0CR2n$%<8*+Vf4g|^*mt2Y9!U1X$+Y)N%v-8quc zq~S1+6XCNM-4l8LMxxB-lVBJ%~QI2W(j`q)2;A}<SB$E zOEHjdo_rCNZxKZ{mLXV9gh}{!v1rG|(HR{Xow+1d?K`+tzB=U73nlcqsUu6cN04=J zPi_}g0=4XVU4WTkc)!Lql^m-FhiH055G1UDTTpjd^OOyCLO^o*;y$aff8kuiL;?T+ z2G{pL9J%0SYcB;^`CkDm`khflMFr&Wu+P#3IXzsyt}6$Ho$iRm+w$O;VW&iZMou6_ zRH=+><_wUAk{}%@*sw#;y9S@5PwgxSFQq{n&Z%~TaGGzeJ%azR9@@6kC?1}aC#4#f z@7g-!t7)4=^`yp``ECwq8>rVTq8&eR*d$+cn1E=nM0TUe)DRG%Nd@+v=ZB*cM-T+$ zOF(UwG`mzXGpwTtVONh`1cp)o$I|2C|Ddr$y_1EkCnD%+!N;Ol5RbQ<#*G*tk~)|} z6(trBo=)!}*9!3KZh4F=?_Vf?N?rwbK5v-+Ql)F$rD+0Fnco;pF(PWNaGZ)^mH3Wn zKqZexE}o%p>*olwW7v8oqwtr=!6karOv$*Rc%^fM%h3nJjBZmDZ6%BjQ;=H9ykW|x z15s@{f9z$K`^ueT4KMrjSXJ~ zD{uY(!*2RIs79-)QZxc3cO5=|RZY>vj48xh3NP%PHZg=|Tdb(TX zZ?9bAp}80Fh*mTGvR$J0nybrfOn|4Z?`u|5l*YuSP_>t^Ctp z8Q1s^)28pT2-rUcEriSu`GV%yV?jtNuD+5Tda*4)sYh*}|h zTclpKb2p5e zqEP9HVf632^%6iB?A8?dyJBlQGmkb=(4Xyb7PY7yDm6ThgiKDeF=_7?ecg5z^Q=&? z+lC^ncFEmbhurXWjE^JaL9Eyl+Y|%_9ixcOl{QlUy?h3ROZ%Wm^OEMN)M#$Dg|uRp ztc%aD^^Pqqp#!}K*12JXYz;U1k@A?B1wmF^-XU$sm2?tx|4+|LT4oaDDg+kjUm&jX zxM!JTFuSHqI(XQjIJ?AuU>@3oaGRKk=uW)h1GG@n&audgU%R^xYr7 zE;=PNH-ct9zgbV28`rTZh>aGeC=TukRUv_v(VAA{!QP9^J68&CF zk}j^tg;`Mz#poKwRN|%;)C#!3{Zd;V92?X$GFx4vP%s(uVJgUFV&e|~u-;Ti9@_t! znamgDSJYP`Gy)mTD5+F#7QPcqJw(B!2~e!=(b!yu>%TFYu(QakxT5hB12r3^QUg;Ck$tK>T734vsvv@@LzUArrcZQX!DF+L}4Q zd2g#OeUYWmYfUk7N$1xbhg5vGeN+C;9eJV~;VCq3f?|w;zJD_uDU>4H+;6zpFr)8q z4);yPqb!X!(?WwO_Am3zK}+J&=p>+r_T8y06nc#1iSY6x;kA0!V!@QuW%25go-;0v zIYa@q6Nd%UibGpHU85iyVLbdA_I0lFi~eaH+cpUc%TzULPPa8c53+AYjP1NM^o*mw zZd6{*leK&)aJP6IMZ})jkNHWtUS~7fk%Mlb$m#5ycQfU1n#=?qUQHa~Y z`tVqyuhk@QNp1i+`}zVt5T##4dDwJMW+_b8-sp+vJjm9Sal>rGMDS2rJ!Wetyn{i& zBXz>0ht79jAW3141@|vjPsmWQ438NwlSeUjF$pV8#ns@5=k8t_(>SMxXCeiFYLaL# zk;}Hc#~vl~IM=vpe*}-4f|{-RevweQq<{&&dy54v=_X6q$(k`W7osz5+xrNU-Lo%v zg|r6l5L15Os(Q6zQ@l1xJTOapu25U?b39KT)sm{QnX`@ucac3nW?dK36Nm6|@>q|C z$C?rnVrQv#GO~H!Z4jB`wA41PA;4+$7GD7F%4*&O+gh=6H@0{JCR4Br-cUL|Bz!_h`~o9 zr7mx=#TRA|@^uOfmE)6v=eSolK~n+(R{LWCP_rc$*t<41OmK^&k6c4wW&axQHUYJ! z`s**Bv}u2M5SVFA;2^@aW8|+r&cioxyylg?w&ffdRcEqi>W$g!_?MThY|5?l*qWNU zwo(vOyJF;TlHeJFH-|$^9+xgBQy2r7{>i8=mv1D55CX~dckaWz3-UXwWnU(Z z4_y*e*8Shm>e|S$`98Efo?JF=xOaB{aTOkkHsv^hxq(Ws2sOYfgxTS!)r?vRL+3(T zDv<7?s?Jf%p=j^Q{EA67cUKNt4H%&G;*|9=&R+v^v@@D(w+V*-!4$tUYyq=cm z;#B6Z@;Pi@u1zy60AH~xB&rI0$$ybrq~|`j>QBLLs~a%iat0(WXtSdz z&d2e&!XAalI{u}{X1o$>#SI>!zd`PUuW84PtNN`nyA4=h3SjDJX}_8kUKe z6-C~eoZ^!hFT`U$fhJ1aM3C>`G$)$V{*B~xfq!yqu-AEB1jR*tzsW>L)IwY_&#o>b zP~sX^IS9*D1T9ZLpdyh@$h0Cmr#%+#|dj2e`TN6 zQx8wmxbFq8a5@(XeUIr`Cu>Y*{~+vg_;dv^O4tPac4Dd=sjQ&Fd}O1{;Z%JLnk0xl zQcjnuGEFA46yuYK+bjkB;v)$N`GdC4%$c(ka8A1}WN@KiF;=d^&jIg?1+W`Y$z0vD zfOL!Uy$aRvXSIL2!t+OOSSg;m?|a6&4nIu8 ztBREqPK}w!iCE`dS6Um}!~A=_q+B6iC;o(?66#mEG$gpb!vSV{8+{evQ1mT=i!C|| zOcZ=trMkLmRAJx?hXkL-5N2Mgl3yLwI+o}&K@0GxeWTZy`aqIDS~l%}wJydWW_A1r zphBMi1ZV#U@J3i(vT4&z3NLA!IFHC~ovL9p9u0(A)M4-{n|bnd zCgfe2r!lyq=6(}Zv3W-h08uhhOKSxt-Ob?3<4G9~BzJ*A38;B@|EeVjKt%YAgQN+S zS!|<;-)@0sZm+g9=6KRoiYHbspW%FT-qcf3AmTgyakzBiuk43_a7L`+f-YoOVp#%r zkhaJxVYQJaTo$qB!yGGaETyp0dEI#cr7SC#gsfTT-5_z72Gga-IcH93U_B`Ag?X$1os_55a$a3{n39z=$tY=_#>y-}i3z45FB=UwUfy zPau}FyRL>SDQMEO0+0r7wUKmwMMoTdObdw;(qIA&LSWBlwB*+SSoL-IDdiN|S?I7( zRIVmql2`T;n3}ORVGOQPgtge;mS4%EA!;O08&QDYqX)b2L=o3)!RZdBg_A7N65Lce z$7^U$ioVh96Hqv!4dM0!iJMH-N-Okrad&VgM4eUnn}yt~IaW)W?}-`3L-H<~OO&jW z7ci8UHnW1`M4!)25{VYrW~X|x^=IuF3i+2Izo045t7B}QR)AJWuSdJ+oca~ig6rb5 zzJ3W-r55)8JTIwZ%wEIrr5GZN3K@2jE*f#-+6i3&YOq(%v?yPJ>c8o){PraCTB--Pz+_y90&XT}BKW$v0a-w}r zhnN0yv4Pk~kO(_T&1^`T`P}RKp(!$%IX%<@U_cfJmDUko0KO zxGPUi&s-D5ZWlBBRczP=JPTc37Z(G^uWFMGpniIHz#LmxYZZ#^^8W-5U&q`K&tH2q{45!!9ZHRA%~X! zEEqTpsPaa;^Hwmj@&d(YwAN)YAI5CS6Qzvi5n%6Gli@#&JSvA405S#9E_$qXM(;@^ zn8&WZ!Z`dnz6o7B0uwhwuSD;3XdPgLCNU;0V(VZ(xA~2pEDx;N;GjrQ>XcvgFY~gZV7uvuCjJeE`-dW~SZk;tYO~8ZsJ|^8 ztG0t}me;iI7#+f!m>M8~iC58s!c_U;RKbzF$}sD_uw0Q7k{~{rKP+Imh&Wa-y9!wW zCfmyuydm(pN^N@{jSV7lPUnf}3BWl2P$~B$#S*s$?GsBQCc1pD%R+z(TR9Q*2!8n) zI&yEQ6LovBnpL@NFxdI9-3Ebro_4TVsPDVyi4s8{-TeFeu=A*iIsa$s?}5~c_mDre z(Ko_}lp8Jiy`bn`b6;6*HdmYDq1# zLxe+ty*nq9lpaq>Xvq~3WX%-O&kCJ@sxx(>TjijQ`Gn6tvs8Q#*AKq?8$If~Cyx;^ z8Jg~MA2^>l*U2HxFy7BWE=;UxMb7R8I)lGGcQ20cZc4a*2SwiERrVmauoHBPYRVW& zTS^c=i``9c2%IQ$HdDv4e+4(*cYH6Xp!zdNR4=v}Pq9p29HJ_z~yKlnJXp zt68hiR(JP`wIoH7e26LDLB$Zgf;?@PDBA=wkyb1bKJcC6f=tYhorRo6_LX(>)1ia@sCi)SR}xC0HrAk zmQqtIIh(~FdKq=?-v~IjI|;@^qKO_^#^?OA%;Y6Cz zK$Li`Ey!h{SfApSP5325lU`Md6&?u}3T8GLRt#=cz~{P*_}bY5Ld$OxaTwXUriEY2 z*V^AG)8C$651j^Pa73k=x6Pl7RNC|*c7v>k<;`^a9O1@x`W=P^T(O15ApyZr2X^8* z{@w~~*Pw<@&e{Vy*9#v@I&&W)31K|mamw1}k?n<=f;W2wl^@vjv_li zW#hjt3nCOiHOoLepz_{+ALR%7)g}M=sr!#WkK9NT% z_MMq}|I0iqEA2d*Pt=0SO1J7{28F9j+vg!=NMlB^w#Ag7Lsr)N){W@%3PX~5IGMDN zmWxov7Mgj%DfB2H7R<~E=<`Ziukj`%H0^wN&mg$C%F@8ev@BzPVHPOJlixH~AsvkoM4~)RBRQoUyq^A3!3rbGKs5M#d7TRM_P;H>9Pa4U z%1LW`@}RG6KkoGY}+0}HMjhjE{1 zvQ5Eg^6w7zk?ac5pKjk*atqe0o4`*A=JyZu&EQ_|zW(K!2$Lm~14o|PUpna@$HtJt zuh-)8dj2CgYw^4g2wzhkkA?B?f;H03WG5jN{~>@JNGKIKl%&Isi0G3GzuB=A_5@=C zAa#o@ySg+s??O6i%{7=Kg`(`Oj5Z6AHnpGYIrTj_{-f18A9SqtrM2^#1bkcLnFZ*P zBQpn*imy0N}taKcik5SmZRKiwKMvucd+d4T5>$^p`$>)0b!m(E#~KaQcg zZ+iXi=F#Qi;?8vtC|#m^$2#3RmlcWI4UA|eGlbNjA9~vyE-Mw1`E{p{o+26vda0^O z`h0qAPxGDNS48UUpr3V2aB-{YgM4>ZHa-dhdu6Xg=adL%2DkhMY;ElHl?HQTqp>^0 zGHN}3!jGFq8kwb^(Zr;&4jx;{>#=!6gE#9OMgdGi;h`$9@7lov*H=`z`b_X25YCV9 ziF_%pet4Tt>69w?Uqox4ZIJqJyCSeH9c8OgTc?1Xl?WzQJ%cC42N-_Ix`=S>|A0XM3#4YhrLX9y6cYeMdmvO8_^Dg3~WL8R2xm}bZ?FBHI^kmnbzB}7=3AnaUlwP zDaXLj05RwMFV$HuDrY})sUrERxbH&nqdsV;lttKL(E)Bytf#vV^=fl}9=GpSf? zPdLE4b}Gvvl)0L_p1&N&%48OJRlq|jt(|-gWG@)yln#)r^(|e*xI4VAnP3oI6%lDV z<$s~rkS;QUj+ZwWQ7?P+N^#P|@Y@%vh?*&?aCn}e!PR~G1KBr8-ymB`Ok6orot;~L zqg=36K`i=TE_nf6y%p1R0ueVL-UA;my`WmL4&98izDq^BPtl7HURYb?I$W68k*}qJ z=gMpwJ?fxj+FdLS69Y|iE7N|K)5WVj8nZxHVvjd2cK2kgUK40D8Ec_=a~InSd1`1= z7N<3(T}97a=RCTdc8)A+=ABFWXS`-P&51fPsUd4O;A(JhAIJMi*{m>z{iJEf8_k4uS#3fTS@t&5?#!Z z&9yEVou)yS)tl8n8S`Y|aIr*GMjWzYv!k>+GnB$eUu536(fk%jEri}y%(am;5vmV&=bw{{>wGe}6>-1muQRh;$wkRH&~&gr(eP(?<SMp9MLd@zC(4#{MPaOV1vA^mxB-mjS$+Y`|9LQ`S!fK=W4Pm-3ZqYbhFD&*qF_FSoIUlF>3Z~{z6FJ4kX}CphQF4u&{)f<1oI$kbTC` z5XT$G$idPPHa~dlDkIZ27IapclyYmam~^4XjA>fCOmHD$E>z*v#p#4K3wpEA@6%Ga9P}~EO6}-q7o3zr$x}aBH=ZF7q0#yq>ZboC{ zSAq9Mr&97SnVR{WI!VXDU^UcdQVey=jQ42cO%7P3OFI(YS$)WUCK3tESiDIi3sYo` z&$Y2Fl?ySA!701!r_A`N2MpxsRlpo?+eI#t=K zvd<-h2(TWD06}Z`6vrSc2v?Hz8%?&;uNF7kObOyT*1Hpn_6DR6%24E}z052kaR%s2 zHfK*4<}%q|w@I307F?G(0P8W`6?*$ycckDAcE{s@XV9g$(OnByP;se*>K}OGb1%GW z6@LcJ>;jTD8uxV*>wdmfKL~UHK|sF0ZM42Qa5rJ|=bRcRBeL~lU;I=Ti>8y$(y>hZ zi=v~E3}_U~6?K3a%@q}^ub0z!LhZDy6b}a1yGPl&;K3SwA+5Wn&vL^=n9Sh!S58Dx zz6$^x@g?nP!><}!c}F4vK~Ok#!V@s}3WhRm#4^@8v@e>?^kBZujA3S=!ZwgHG_&iV zSkzU8Qkh)4*nBE+Q?#csl7pNYGe*tEVvQ!2H2Wz>g&NH3G7pfD62UTZQs8@Rp}a6q6K3?qsRhl5&1 zmM#PdtTBNgpLGr`hy;mxpSjb`K1C1-L7WvE#cSv`7E6vfZ)dCe7lia!FpIfW{1&-n zf94Ul!C3m;G*;brKMnb{5BA$)b`&WhPp%G;Y&aYiY?Ch*ICc$Y@vIw-!VuK}k80$E z#>k-Clw95jM}T-RGKmwOecs13Wugu9HzpBM;QoC2fu6oVh;}@Yr{yV)=i)V;z%n894UBn#%ek)pSM2@f5(GELb(7{(!Gc zKg6(vo*HJ5Gtmrr116_X1i$Ee@QgpcOPSB=+f??R*qI9dz;Y)@_!g>MG>xA;}YMb1m0n( zwl-L)Y4Opm!-HhK25!jxP;>HwAo;!0+nOi+J&{PS05*Rec%(389{QMgXX>SWqBcEx z<>f0Ou=RzOqW|0cVmXo27Or*1`FW?uY$>G(qx|W0a+h*3wrwrQ1J>^#ki3Pn$3beE zsArJ!Qn8wsd>zj9=h^>UFAt7brYMKWnXGHXbm;`+=)@9Wa#H}K1+yH#Z5oEm;{HWd z?J-yH=`X3d{OJ7vPaWuGm7TH;wV^4Hf8ipp|HMFoujlM?A}*NTjvv1KhVPK&bWKZS z(b$Z-X?fL=ng7Xps@9rdW6FjT=+ZU@38hrIgTE7NF`1Hv@-;jOC%+H(dvEp&M{ zfdq9PSd4|Zwq1nB;hqlOr!2=FB_F}?iK(*1hm>c=VM>Serx(^rSl&oH^~TP2+-CG; z;?0C50zU!uaGjCE7x_w>zz0wX?Qxj~GW-&z?=x#LmL1tJZ;o9uma~Lf*bqqN!V}D2 zHM~KGK~?_(m(HPWGI%?^KDJD<mH4@ynh!jYNz=VR(_VB$qIN1;YOi{(`K57vnFS=U$(==$RtYZ1^ z+<_@C30=9Pv?#`0Yr!Cs0=gv%XShaVP6M-?0+5u*NvNld}h|Z}iDbvSx0mHUeK?jiq21CUDp~ z>LZP`2XKr|Er_4b_dDfZ+wS;n%*pcXli{n4p|x#einqLYb8^hXQV8YGVEZ8K%k%J; zNOs=4v6f2e`Y}*x_l8*Ip)HZU3;gF+Juf(z>etbNZ>t{S(5J$?5EbX1#spLNbk~v> zW(eq3Y%zb>yX?Qs>xA#wLgI0fP6^tB@pNPQ9a?S=y*aG%y)R#s13nA-DTRt(NF(9G zg)=2KzuCcSV$?{?$zQacLTo1nUAaSm9y&E67hf3&u{ZyN>uf+8R|o*K*nB&`y7NOZ z)NhT*1lFC!%bp@Rm8TKPjLOZ^2!w~m$eQkpyeRQj3-hj4t-icF=cTxoY7Xp zF~)LV`eTnbdbcs*EHEF##U3yj_uMfflxfVfqS94cC=rE9qb-3v00XLeYP9PaxJ?J^ zOn9Aw+Oj+m;IgVEet4;8JQ~Ke|3LHEE??o*;^Fd3$(^7|=s=OWxA=r5O(u{?XSd%@ zW5)ZEo5z{;6{`_Mx&ig`g#ft{lc@+{VeAD?IUBx=gI@uVn1^woa5M9LE&Kj58~M|o zUC@)Qg^q?!WN; z1pVIlUZeycyWk3ujgsWFb78ECS3K}!o6l(IGVrn&-Mf+rYi~=qe#3}H)I&rwtobz; zUsP0S;POdeVZfT$zTVr-bthb!M->s|fY1Fy*x?_>wv83_0AvoT=Y$Vf04P$Hz!4cK1-op)FxEK65A$_5iD z;v##`h(Z>Aiy&mR&zwJng`&pIa%c+)_A<8wpsx9qR?D2{TFe$=G57)TaAsICTp@j+`qiJarKdgOg`Et>a1*SncjCsa8h+rMqT58p>y|ZT zz6j)lW0JS+hnIjoX11vs7x~)10oN=6`aG}iJ37BHU&P%9b9b1DTmFN+?MK8L=;-u| zVWm(H;)v*prPq_KTjCnGK6+?)_0;hcNQLX^a|Dz8`miSL7N*ScV1K-|Fx_kFs59XH z^5dR~c5ZQ#k2dei)&Hfc6$|a@=tcc`U=mtLq}`l)-BT5-Q68FB#2Z1q$3+28&z7Q5 zpRpwC8cz)tK1H=qZTchiJHQ`^(G)%D%prPqLfDFcl$5$y88mb#_>#*E6_gBpJ*35v zJfjaWGNbwAMRXrzlK(o0%H>5Fm~s*7=)Haiyan)L5kh^CTe%VfGip6p1BC6_S0KgN z6{m!>&=EmUJ?p8CQ$+lNlHEQY$C`KgFONR2J$PolJ5`{pga$o=99 zsnQ3f(6G(Hlr?xl_Epk0hv#LgAT@5xH z1RC06^F@^7{Uu>MzK`DLLOO!_U&=kSFK`YPZtcRo0OMwV zRFT5kkq#LAMpwz?kS=rJO~>HjTbMCIM*zb*`O&!pMKQ>-jonHp{c{fi3Mm5N;rc6L zvUfYXclDg)yY{3(EPdvW0qx)f{wz3T8f~sju^C=k?^)4ku6Y7Hwb7wFOV(R zG#?4rNqZyN5K;f^A?-=(b6@quE|ams;{!oY^`izgn!z`K>la|r#>Kva(&8e|!i|nB zmcYO2NRrl;^Y9C*CoYNk#doc6^D{7&UYwJm#!vCOW6=L1p5pi zQnS8-9w}u{4A~!k7v9ZwjM%61Un2C77)iFpF`3QrRv6EL1-~uF85bmG?a(f`!#5oa$g?w(AZwjp%Avpd zlP12*zE!+>5o8%P5IewbBV(oSrc#<;cOEnuOgg&gS+! zrJr%#D8L?4)3{ixU7o#?5`^9Fll$Q?H_IIT&Zk{*N#C(Du$=qM?t;8F88jU{{{J9z zUjE_iw(z!{NAobk%75dLnnP@4Tc#j0Sb%}nT-@!xaC~+%+`Kb&FFxn-O zPomTOn|p^*YhJ4EZxIM|2#Px*;x%Bp^(Y8rf(rsyE?x!=X+N~?tWkVQ@b61$eTkifKYudqNb7UTVom z(thWK2-y8eWDD&5B=KTL7t(b!E9YF$eei#%u_ty#P1KWg-f#YU4RaVxEf~k+bfW6! zW1`J*>qzhL+D0!lyl`9T3(SiFKm%jK5B&ZzS?BG&Z0rnV{)=Hg`CdDOvR>mwNDiDw zn|ii?KVfc5x4lE7&|`_KS3$hvZW&3ph(^Ivo8I8VAr@jRX>F_CzJxa^GVGOJAgCW; zuHYxG?h;C{6$7>66~bU|`dvFPnEtp3lrSI8{{4ng21K$(BKcU}{!_%?;t}h&>p-7z ziztPb$GQ3?%e`=i_VS28mA8hz>AF35XZYzM5bT1JN4Jl|3rgd#oDxAbpxF5N-MPZ*s}Zbg4QKmBbbu!}u4Ri~B%7ZO&X zkl$q)cQ6-rxT&O!yY7koAvnx6Vn^MX)r_s4X$6LE{-AnC+HxZWu2Y4N;Q;Q1pz{|s zHnJ>RanvlbuCrCD5BqN}g>)4gKYy027C4+1r`1>K>%+0&6UV*c>b( zX@mL&!+Qp*1Ste<;N~fB%0VytKpWq{1~P`hd(xRS`J64uu@#mDv%ftnrC)X@-9OX7 zRjSH~esD(SnFpuz5x0zGnZN)E;eub$4e^L{ON77p1neo9s zh0057N%g5HtCC3~NAp*PBetWyMr%)n5Ja#bhAwnylXK})zB&S{HDFyxfPDB~=&MN1 zWZff#FAhN4!Ty*)3r8>>V%q1F8uLwv#EqnXPc#+ z0LcQ=_x%XJR&}z+_q_hI!J$L2BlR1dam{@aDbDk#ebZMvkC*mV9b^zfg}Kr(|6ri0 z7xqn&p#-DObG7VCxkoCF%a_i;x~og5bx=C?023nz>3H07W5lfHk9NC%d&|5IXBmq9^UDCW#y!XsJ3PF#taw;X}C14Wp3cID^9?Vp>hJ=`ik<;z?8LJgT1vu)lv;mk-#+k;{+c z5qd0DOz?Q}51waIrDT**TA`rFAd~Hk1*}K+2y4#Oo3ue@HTR zmt=ewSsgh!gTLn>`a42mu71GUliS+4&GDHhD!!iCPO@piG3QDJ0kOT71rdL8QVh6T z*3Vv?wS%T3Qcao>)e2xO&smWq=JWWj6Ps?DgdW@Ps~y@k9uX9JU>Et~F_I9Cdi#lW z4rOFw(IoPptut2=>;~?8`he^|V!<;Tsn{XTSBvU;W&@Y>NABexROU^xUU_{AZdNWEWkkHquZbYdPGpIxcIhZ=0s+; zM;}`7*6Ws;uicy>H_8MhI>tm+a%HV|-iGbzuSTW$?FD#pAGTv-Uj4n3&fg%^>}TO2 z1mvvutcqlTb{H=6%4g$R@DYA`}dTYUHa1$A03iUaEK{kIRDh+Z9u|d2+oM%|b5@2=lt4oB(=k9` z2}F^rJC)D$ijl-GE@Ai)(X%>RF3RUDjIp9S96A=;kNZ;8 z{pJIGQ)CuA`VyyT;@&$tzbSf6MqG8`&gRbk{p?Iv@YyXFY+`-*>%=NQcf^ddr|AI* z7VyLEom3OB1RXH0GH?7!{_k422UquXD0#HVL7L5k^M^w=akqvcZU zP*s8R38Y*yhx)DYQ;DJ^ApWKoK=DUNA2suXIL9{VRL{;>b2KC~D2HPuaiS(jIrwZT z9Zw1-!M4*(*XmRv#*O&76RBUvpo(Q`@*gIFtv#ofTXvwAp+BbyI_q7KvyJw$#HQT% zjRDTc!3Gc|g*r`twNz%sXT+hAq6kuJE6BdqnL^R2y~YVy|Bv5sS$@)NL{9i>)2FfX zCQ;>nF|qbGl-j-OT+E5rs-${s5DtdBi}9-V<636KWzJ#-qT8X`yvca71}S19WM(M} z^b$2G(*<<#BEd!tQ9)Ge?X)-MI7AN#*!U~a>WhR{=zR0G5vK5GZ2mYTB~uQoXRO4< zMzx4wEID8usm?lK8T=j^I>C)6(lj@N6+IVh- z^t~-5qqQGZ)LlO;o*!<$!~|Qr>Y$19FMA2c+Mp*0Q7?G^R@2&i9XHYP&2`M(uW%8| zHO2eP zi=Q{O_u{6Jk*i!#ZBVJ4IWg{cC*l08l|4%^^TVsEDz-6~}uwZh>Q#ukXO~Y#ak|Ta)$mPgwEYzw9u)S9EVi>>8 zMxTq#+Z3iEVQTEzK{jP;F=Tr~kS3Iu&PP@{r|e0hXf&^{O2xItr-CH2oz;~`H{5iy zmLP#5@4STK(>yH=qdd<*XyzdH5+Z+>N|(s_KQuj#|(^>-&VU+NP27%1@sfDR-pU zVyNR^`0IQ;kPkRjZw#oQC)Ay`z(H2&f362S3XXPP_yGvwP@1oayJgGOmbe5tO8ToI z7ln~%y`cT~=KEmDA^=D)dcC83-CkFp&GNykKzIh25%t{MrideG;)W=ya4+@zyC@GSoj7)3pUiKq;d) z_)H2{ma-Dv$_Y;#DOQbMqnKozp~|^)K#2-wsmmC^-%~xY9KKe+GSlXL--|-zX5A$~ z2cv||A$c}eS!JD-Vx^9p2#7P;-p&d8S#Y<8vU6}LwNU$CSYxyLDGj)c8w`9^53Ypj zV2PcFQHr_C%4mJiJ`5iAdVqmjK=b}VRkEA43_O7X^Tth-Om=ShD-Hw&FexxVM__PN zg6xrMrSmS|b$1f{Y90vy)E8?AacYlG+M*^L1Z=86Ou9&nRYs+PJioOFOf#?eNB`|) z&~@rIA+8pzRbPi$d#<5!^aw4=i<-ymImS9A*_k~4Pte}{WB#YXjL~?+nd${{o^13e zho_btY!R=A^UX@Nay$Lcma|vRFR&L-u=)GBQo(1Xfl*8JH;Z~wtoqAL_Q{M&{CecT zWWDkGh)bqG=vSap^ULqef4OICQZ`qB#)m(M<&Kh$hKHcOY`_S#s&Y2!V;`x0$t=^C z+V~1_{Y)0RN=_Xs$$-vTF^UhZ{$tq63{{eT4<`zbmrJ=GQOxGb)uC9%eg+QS0&@j0 zFF>4vyb`s+g>(@6($>&TmRQI%K*e#!@~SBh2<= z0dK;>@dYExjD-g3d zjvabsd9C%f&Srb82iTt8z`~BBRQ~5= zBe)N#c18Crq0yl3_n}1BL`_-Ukid?oK-gu?RMa~{P(eau_v~PIsmEA8uVYUSSJ{xA zXJN=SX~Q9K>APw~C~Mi2IC{w?b}e$<0e}&|aU4S4^lwoA*B1WY-+Y5QdFd?p|;hl*RCJLz<5`MBKmNCm} z5>%4&5#)00?5RY$u@`O-rqgjD8}0RZ6zymoKgv#A09c-|pj#hk3;qH9{6GgAV;^X* zY_vKa!BGDIw831|16|u+9uJ8I>LDrk26mVb#i7VYGE-G3`-p6d55}G}y?lhG8sCx<8yfPxEb9AsBueOqt zy+P* z(mkFF8_THKa3oT_N`D%J1+xuh3_ehGy73p-c2gViGq|d}J5Wo-_;4(({aWT4;-akd zDgspHrQ?**2N2#-9v%sul3CH>LWS})+@nY;)>@&m8?~o=El%?Jjl<6hTnvf1T7Yl% z_4YV!m*r2Uw-d>YAMbxnMR;nrOfcZTb6*E@{1pWaySQqGajuFwtJ|JzQ~(!yEY-$; zrR97TYrBZJpO&la*R9)np&*geBTg2eVD+t1N3mI&8x4U1m<_$U9}s z6@KdLe|K_W|01zwj7b*=PxhU(3;d*;qwCh(n-2rg>^gc-6%LbHCgxxGZx|d8T-*T) z@t~y(Jfo8JW?g5$2M5pJEiEXChqvrH0W(+SUvZW|h8NaiAZ8RQAhIDP>XeWJsy9BZ zCxGw#63z_m5d!CjEBY$M$7`V_HrAT)5}f6ok*_jv*{}z35F9#F1Y6h^M@+XLQ!x*} zhid;0{V3$sH1dvNc~|~uC_3$?r{H506hWY(CaR*H!=)e+&z zWyG66YKymo(Z6O72f*^j|4S=x>9s0x8O?Z3eopcb_TFGny*TJQ#X;bV_Q_xY&esIN zzE(M@1={U`e3)Z^s&1BWx@Yl90ujA zn@H2Q7(;(-$k0J5r;E)FykcU@Q%aV1QcwXJQ9hU0=~0l(5j~n%RD`SpiwpzqsBdXR z0kkE%!)MH1F34JcHl4sHrVf@oSQm9UG}EZZ0Q3W52B-bS>Ep!nQx5U6^knO5|& z{)7i8p1loDpI5iN$OepXGAzj6+j@0~oiVM43;j3(L&4x{gHP^3j~a@Wf@8p_T2H5d zVXH=`+)$AQM%;}1VR=g7lLh%ij(Y58h~TvXpa`oh zUM7Wy7411-zKUo-Km98fM~U#Z05wm%yCyA zEF#h$Nch|4qQ`?J?tkdGJQ$!X1>9RiTLslo+J9G3muD;8Yg7tkdMTFVR%(T;u%91^o zbB}%=2<#nX!uvo9`X+KfqmWOqUbQyFTV!}-wHbi~G^>mb;OCAEHmY+`I_;ryiBNXF zVyy^Me{xH2kd%Yd_vPAVQZq|5g1urj!TxOOV}GV|bPvlixUONOJ9fbX+qs~a11Tqf zi^1IJxp}{=qhbSxC=Y!G`TXVVAjf~M=?!-nN z*1PR50Hr3cM}uG@v0;pdBGd@LKC zE)?5#p@G-DSN>qfNCRi_JHO*3~$td&z{g8!jzM)NtClC2+fzf ze3_OoYWF(%Dptsi()d*I6;7!BYffA^qg5rb+@w?m(M3|}Zn)GN>MhXy`D*PK))#ot zlZyTlhE+on>L^WZ&YLvhoTSVIq1|Wvj{GBqY^kcL?tYzGpQVTba%aay0$GqEZUazZ8Pl zx=ZxNf}}VccW*lf8Iqg#0_oJXF!y-n?(z>wZDMvNB)DpO*-33cm(vFBwfLGltX^;8 zyTV}!nVm@(PHx`{%PJ4EfvP5gZ#8EB|Ek#I&XPgOX_?G>%M%|e0T8E%U-?YU@F}}B zBICQD3Y`Z{6-{v7Bcr&%p6=yiS?GivvVuM!b2D(mN4{nyUC21$31n)ozH++7278c< zK%%9mHh7?F_`A$oqrG0;6M(42UKs!jF;cuXgq*_`+Kst|EztCt$(Vc>|d@2FL zA=_GF?*X9uch?0KN7lmiS17A3Rj&hAZWklx9?uNQ!1Vd~l3OlmRiH`M7d3I3! zkbnibM;)EkTX&Q_9*L1vkPTseT<*u@)=QTV05btmfL03y#hHO_SM4Nx{D>^@ra?A!`_>o7SJ&!UN zm`@&dHRxjOf{siTUgJdH;CP_hEC+*k6IbCP{k1CMN^h%-$e+p4omDj|UX6RM$fBkC zVeSA#vzEEyvM+qf2f7;ij?^@axQ`~Va}#`nME!gX?El@WbX#99} zOA8hY<2gkAz}BaHKPQD{jH3XK2yISW4~xF{MMcEmll!E$p@Fpx0s#I3$dQKxRL-}5kIZZMDT^gm#s#2p!=GZG7Tp+_@VW- z%EcBh%$R$wVm|Jyzwkc_u_r#uCDq;d562O&ZZY~ZqiEp{plEfPlj!Zf-32VFb)vL; zkd0;kWLzgSMBC+ycr7wIV0Bz|)&+y^N!D(SiyjW>dpD$}r&XfruYATtPOi49z{%Aj=f_R@&py~Jh_J*Dmf z9Z4Z|Hw}KjL=dkMZWr}WGDLTmp)ZGS6URn&ynhsTq-3GPyo$W6;U~1CyuPiF;N}|w z6Pg9DAaAmwhzQ-ugb-S8-0^p)uxNqByy-5V+R>MzwDmOX2G*^vm+C2u3*y1lQ@jFf z{iTBz9($%(`kt&?DvP7A9^^P^Eqio}lnOuTP@rvDG9;b4TQs-QJPy1;q3EYO1&!%3 z@fh3C&E=ZMSP@^^i|e%k=)42|5|wk45E&PT_khx647pl>36r|C2-`BT1$_Owna!ap ze*+4562T;6Z#SA7cqt*nsopwuiA3EcH|ErWYT90y{}{3pwb8{%Mejo|?FnY_hX_lq z%wwN5ZNF&a&jPH!hs>Y1yTPMUL5+}@V2J4P7e1g3JUqpYpg(lv!bm$LzAt&W2p6bUu!A7o&3~IN@3RAPA8Au0A8rfu zcwe`Gu!V`7XKYqQ_V-GQXKFn&Dj<&vaFdXUn@+CDEe?oVdb!90I+xnol-)s z)VIm5H?}{9`MWQm85KtcI2=yg2R+}~bQp<@OnnQ^Yota4@;6D7esBv-#fb%^6P5;{ zaQkhJyI%Nar|n%%9iFh~QFEY0A&ts{2Hci7|4M2*;o;V(ZNxG?k^MG*VR9#I@|6D) zmZJJip-H(SdsfLv8qamW6!j_KaPh+4QHRcOhMpPCCT&iPb!CA{MYX~2mKN8b$Dj7y z-ACTdrlEsT)1W}EgU`mS3Wf6^lik}l7CS6fOe&0?m-f+F+QO+75Xd8O!u zq+=87ol!YfG=FqA%0%s z09v+CE7eG3w*tq+#9@UqS-#>wT{daOVqw?fr79Nn<~fG;YBE;Z!QAu}Gh3Gp`5Op? zZR=VI~0S(32`-UjeuZV1-G6+?e<=h%BQ(#gb-v?OwSML_=SEbg?(9I6B5I| z3z6hJ7O1M40xNl!sac!;QzLlnZR{oGC_9s!-tnioUO`0QE4V`{rygiee4N@Y-CqIx zwOk#uyEzks1nseR%ugOBoPy}Q@Yb*>QijT>i2>I>Nf#&vV2-mnF7l?gp`B*(79utp zD5}bj5hOuvMR@rPTLU)k_YR0d`L4ob`YR&rPorp@9|Y%qNHVt{?c+!9RYp1M zZU{xKTA{Y`9SW>Rm7tR2;76#n@lG>0j)#L>IL#8+OD zDmEpRuf_BaN9{C zm`c5iWR52ZN50&N#a9Yvkm{HRCufEWrT+MI+q!EFff(SMPagJ$2+<*Ey2G@P|X^2o>D%Uuq9NWSZ{K1jUbXzKw$@onfN8rVdqU9Dm4~pt4_&K#vsHKa38l! zb7UOJE0yjMwkS4ZtZvlxPlF3InjYMvf=kM%vb!^ zy9+mKnM@^O^>Cb;CD^8TvdtT!_Y#V(%F_Jqftw#h}Y0UuVbx z+HRJU(qBQbENCswqk2&{RjQI%uA_0zP_A+%3>={M7vOlV1-`#7p`*qYlfW$xRv8;B zkGXArp)JMm9uGQx+lKm|=bom7Zl5|18R~I@P*Jbz*g(!7xYssxn&CWaR#RS`e4T%%Fr&q`&oyB+oh-(n#|G74BPVLH=(m?3Lio9Z?|N5K%Em8lyKo5DYDy^*@6}^?_5bi6_ab9Ricqr zXL)tfg$*I^jMd1dd-EaosIi3a6ZtOUt@Uq0p!GfbgQjCHVY6Lg&P9&HLIzy}8D%}# z@H#7+al^iahlf^V&SP80#@R9x%5p8WwD=hrM_cQmBzf;6{ehD~&y2)|1KVS?^ZUhu z*==Z~M_n6EX*I3sQA-a1gdho^iIPSxWa0G-ViE%LX%a5J4-F!DYzH z5cE6bu>8g74t)?|Mi6qiU{B1dI(21w={R8i@Le4NG{{qmEChTJb1Y)Z9$_~<=-DQDGKGq&1Jv@jj zVCxuXIduWVb?1#oOMZzQ9 zGLTm#vmMD@l~l(LEVBD896Puhm_~%BF`282Vj4K@+_6rOUOQplQDf9v&Z>$0P69kxLa>TLC(c~ zjtGcgh%VRGF~qu?Uy|4TODt7MU8iaTDe|H|lXImih6LrGs4>h6uN$MeVAj!V3OHaq zPvLfrwT6WMF3&7>d&j!*kRE zb9O6-nh@lMmhG3Y#<$FRzr)!cV6=chv|0{=irKH_>m}Ou3*(JmU;Y9r@$WzO8QkWX z8%v4uMTZw)dkyc!&l}l>iFcRjgeQj>6Hbi|pq3VfRBO_$Ot+_ z3Mee;Oo?16a_u+!#)N5>U-lkix$nxQExSikFXYe!&f%#W$l*#DO#xn(P+s{FXWt|l`x z;Nu%&0_rJv!&Z~zTLHHWYKy5cRi@`It(W~j=X=p|D70^ZLcWVxgW#K;dhp0*qm7%Y z*BxmeN;;J!R^`9EuDeD?8;YZWiT~b{cVk-BTJWV%|MSfv%U(wUFx?61^woXv3C*{xyIISJz-J8(Ed#dfms2m_DI{KAIUav z)59M65mc6YwTe1WJ~oG{e{?Lz|IR>9{oW|N9>SoN4 zt1+z9T>Ir>;gh=hvcgGNJ1!-)wRd$*H%stKa;7tp_OpYF!I@&>N&cw#FYsOsHd#oaVI^1yw-msaNHX zoC;?Zt|5cl&B4vbl*8Jw)}3+ZBDce?@D=QGE~H~I#fG8bhUuA2efr1QS0hZd{2BT> zKnP!WKK7yj9&JvTcOC&J;mwn-I^*?*jSVJdTV2<$ZyA1v0slv6N~vxN($Wt~`1-&5 z5x?XE0%ID5MLa)PU{fFkx;|FGP10*IAT?^$OK_bmFlmLSuI>QRCyR?ZW4*38u?;-9 zGm`KxJ6lXk3(2o%dEuN#MgPhb%3+>9S~i|x{93}1D}huQwuK&?GV+l)m23F@+fI*r zo0Ig=phBapo4pB{$=`%zyjS@2y}%Q~L^)3Mbt`;rIv8cpai(lA`A>d0+xCrUtLn)5tsa%gm&}KptaQ@H=oR;fZRees*sFKwGKW#3GOC z7pM*LGL~Hj6Y0eOEPt4)XFk~anhtuH@FXjmN;xJ_=ixjT=$5Q3>Va;~al%j3J&;s) zeX({%5<8M-)9j^)kZ45A)yB+AZS(iGjS@g8Bub>o%;?G`x8CNtt!#x(Ut$4;zy>Ux z>X%wU@Yfnd9ka9ff@DKjFvlfP7a!uoU+R7vO9Kxk<>GB=y<<&!bs+;JSXSiy7`BF! zyY@$xnbNko?6Wp_EYs=EdP57k0~Ok5bV|TA)p|eKVV+9C0U&H~$@QGL)%$F=k`Fmn zrqt!`ux7z^Lv^Y}xYpmY>%(ZMG{x{{2wk$n8Rp+H#4FD;cJu=o-T zxc&mF8_4eJ5imJ8;CzucZtVJn)z`Rvzu5RmGmdS`c6b?>VvEj;nV~qgwws!kP5+?& zyewcUfUfe$=vhcYv1Gu`NQU%t1nxd|ZXqM?riS~w@5&AOJrQ{9#L~C85OM4moEqD3 zRo-I$HZ@pj0fYSh1vR}+!IcKeRYLB(k!dT?jZ-ng(0f-K6sQWLTh$qo@BGId>_J6U z<{hF>0`vi|Muo&H7)jzqS*fxVa7f<2vOkj)VW{$kq91VGnV#iUiU+`S5;D&iQ_j1j za=(-XXGsa1$jJ-!#nv{x872(nH2KQQ>lm4tg4~SN2jQZP6G2+fd+=!DDSo)XPa@}3 zO}x7>+bAP1t!4^I1z`8p@Gd2&Tk}qPBwNKxsW|Uid_x8J%rFkEX>cF6 zhoMkmXj){4*k{?UL>6P0x4R{&GOmTF+o|K3Qs0z z6vM_hZ@H#PiN`!{5fxz4sK;nMq5#i}KAWQrggMHvf65Bvqq6iG_4Y#dj=_T!u^Yog zC40%kcXRQukQOT>qtp?<1kvoMVSA(Uy%~@ zL)*3i_I}MRsdwwYKVg;qTGgu-*o~w=RHTpm$U&@41lTuNo6}rL3C^owV16#li7|;F zDf6AYrv#%@kk$%nwdL$vd|E@KdTbv|;UB4-U1y2w1y+W<9DvK(zYON%j6pEPue~jM zu8nvJm#20A=5GlU6#LMYN6+ridj_#(>Sy6!JsTf@fELxsOn_$%8nPdV-2i0JHslou zVauBV!Es+DP(@VZVObr+BaU9V%uIeO4gv!y((n5?fGz`hci}T6kx3k|kYkUgl+(Tp z4_l9=RFdr6l{eVm+iDpsWl%&mHgcs=sk>%1NDqDf_1sx4wV}=E%dR~a0zTKd#wqXt z(hos>+v#kVtY!r6Tpyo5wh<_<16CN`qBYC5{K$VGg-I?XL4R&e{9AU#?y=lOw7{}K zSzTV`Id1zBVbL~$+AiHL=DO$kby)=SHDWq0_R@62;SNl>&z!6RK5+xGzVu}IXL*Ny z1&Q$>5XS#XSN_+zJ8v_i(LUe&BRNj1Kw%Yx@N*O1Ut!K#!ejFM)Qk?c44(0=Pk>S? zl$!X?7=7YJI=Spu@#iCF)6#$ey#eWDZpQxKkbN@vZAS%#dyM zE&3ea3UFWvI_2I;O&FFw1@M+QOsp{W%-T1DbMxKZW<}N4GuMWfYZhI4Mh!LWQ_LI; zeDh+15N{~ePH@RK6wv0FC%`||O0{#r#DoC(T$`-QV4Z=>E>0kEeV8=+2lzb-39~Fl z49^-I`$AXg23kGEALEa;t8h7`^~D7^CGUfnpK>`7>vRV4tHc{Ph@E(SfEJ*3ELeQ) ziOwmAFF1_{vR0_z0SkFGzm=@M(6OrF7b$YvIPhEJN4{gFdRo?pVar^`cRH9BD`YF zCGhV zU*I^-s|q!{7d992-m|HIDN7=hujH}i3psDF^`#huY4X`#^kAnb%|q`>Lw0Kdd>2VZj|JSrlXI%z&k)pg zo=lqGt>tDFzeR5@WEsMOQrH^~=s!abe@ju7LEtqKZ0RVq1BmvAoqQzot$o1aO;g2u z05(*zT)Z|D;FKbQ;%GSAC3E<@9DxQTe1H)`=im3othiSgX2f82TSf)ij|R#!fc~PF zlgp~3zgqRe>J{ZciYbe%%vid)Dq-Q31j3pwMMSs?qsOHR`L)|u7oUyCJFe10a!wMJEBEpubxmWvY;>5dT~Sh4 zog%E740mn`x5JP18A~xv!&l~+*JVx(AhyM<%HDLC3Zv`|`^sb_O~od}G$|6SfM-27 z#laukgo)E^0Ajv-x6^8Ag-IrN~5TENjLYrsUcBE*35Stg(Xm?b5p1@zec z1a+wAew{Ev85@vNtE?xw6KIQC>Y`M3m=1{39g(J2gFq4rrsp_*UNBiFc)$^A8CxUw zu2KPMIqaOSg{nk|qXRR^rtp78v7915Y|+|5^O=e!Ey75DGo9n&vjMNu=yJaRcwL2Dqa*#N(=|#kL-2c4z9-X)0@ro z-)Ub*X3wyosp)5I{^~o3ks!w>WG>%Ek#*g4gHffG%<$?5R+^p=o~~fCVu-##@fb4$ zs3t}3vD8pn0Fu~QHShv}RiS?mjA&Yzj^qr&o@Oi@W?zKRTXQInnYGADWV2&TFk#>* z7!R%5GKWeZdoCin6=~4^Fv*Wasinot@G3coQ=<1^IfSvWVU-g5 z|N1l*u`(UQ{_~?yL5m{gdqyBTQRMcf!&H=K9ZB?N!@$~}ukQg6Gq}+cT78SRj zYr1F-nFNv^Wvrd5wVDh$yGmk=`H!U>DT>!RTUR}k9ws;?dOB(SMx5P1tyPUt(MKbG z-K^=Du9ls5uGvn5nWA(nhA zCA;4NLs{n?|LY%{+^YE`2ufb#v18RkF8awxD;#s(kqZ^+L$lfp?hEb%9Vd*fM+XF==j+k4@V80MU#&+-$W_pjZjNf z#pc@XS4lP?m(8Uh>rG)86;|LIr2-mG&tJE zaCih5;BUyzV^oP+qApL8_zWX!@gq3py1n7S;R<-eOD9hnSu&(Ol>QWAvcbIa}xN}T~*wT0y6S(da7Rrd-jmT z@m<1UMg-*X2Nu8nHb?@=zt-F?O!epir1p{(dnP(IoqH-+fU5za9-TuSaZ5lJV)FFrt%5sSZ#3)U5yvY3&{iR9!8t|mha#? zWg%#L?noHCae9bX0ZAF3SDZ+I>+i;1b3jE&C75mt=FC_NGY9ZFwUPqv$rSs$ zIP&}!j4GL-E@{S5LSI_2staWfHBtU|AN=GM)PtdiBgEq7BFJ}0TFTVKZuWsiM-xCi zV%c+)9U;TIk6{Qo@X5i8TkMW3s8YblQ;*-qR$r6Hf-_KfFzo-q;W-`ZUiYsMT`?jm zQie8lsqAqNU!2ql+djz&8n!#eJdh&3EGrIFA2q$B)9;DtPFOLRlI5GzAI7-AtecF=$7IkI;H$VwwQa(l-m419kMYbN}o@x4#4=|oZP#58l6 zPtL*$s4<65&yVpM0R)b|xnh2?=FXOeuqeRrj2^Hbmnhlx;QD6|GgWgF^i>c-srsnZ zAUY5W|ClVd{p*C6dDzPqPc4EtM@BDA;cOu&uNpFmJceHHQ?KO2id{{F(l?4XM}jozSd4r%hqfBhH6;u`_0moDg~!Bw7fE3Op2_?_9u}ENz7+`YVXTSl%#a7S?fShrB)}WbO3XGm<_mDH z{hygbGG2XsSk?)vEkE12(1IF4NgUK02imOZ#T!Xrd1n%SViTSv>*3%wxkDn#c*K+r zfnk=!;0_YLQ+fJKZbyxrr5>HVnQT^M(Qc5FlEI&{3&u4Do@?ED-+(^QHCFiVTuHItvzUm+%Nnh2g4OhOmaS2ebsd^2LHu5a2IE zs&k5oR$GVP)`RKyuwQ|GUb+<%ra34b0q~x`Ghn#1&<}n5z4Y19v$UxqFUMQ_*uVc8 zJQsoU2(jIWHnNqi*lAuP^$O(?2xOztayLbf>b`X2zSEbol^0^h$Gdnj$&Qc*Y~WiN z;9iw#JP$P_uEJ8&=Iz0@WAv6{7PGOlSsrK<_v>EEKj^^+z89fg-d_Ur(PQOp!IVc( zYfzt}DJ|+C6Z~Q?tZ-l~@QL>5Mc6AVPVw}uVduZaPj;*1wtR{V8MEXb@6THqXdIveP|FY*z3| zdvZZ%A#7G$lC>YdkJUTW_d|>e$J9H@#r%gGQ(Cq3>4_beE0TuF5A z70_nr^rLB-Gcc4OEe7A0sq|{Bt`tZ~X;tkH0n6>u)}tubU4fsm(wgmDEQJ_$koS}A z961ibTW|Z8*ZL;pGjf;V)`7z=?rXG~04!8;IAK%Lv|YNsAJZ>CQ(25QCwh1Q2FX!* zOh7$Ehqe0NDhRgiECk}gEDl_?R@{qkARqaz7cWNz{P8laMVT>$W=B>0lxt}3e|~KF zPy`vp;NlQrtU9gpYh&?SLlY!`$BeboD3hj&4**~zAzy)e;D8If!VI7`SX_9#4bK$ZE-EA``T z!&&-ryt%8a+65+5vjO_L9a+K)4brhAbUk@L8N`?Z!>Jj$BzPxbUWU=5!!r2&RH#YY zPp3T1R*D9eAs6LCgiO&I)g8e9WC$`lYL+7-L&GwT9@BeeiUN9SHH8Z-RtI@X(ea@x zeF6RN96`4!h2V03(W=NX=b0O**aBVO4>1A4&fgFklW~~P{qpkUlmumAb0`!HNL6zT5N*B>w9TDQ zApI9~VT@QW8(A-ZNb~7TRoDkNT*AroyYbJ z7GdQ&YNt4@4yO@>h^^Af&U%;*4?}LX#L--fVL#bh{s2Tn7(QzvClcsbhnQN=PfZ@P z5K@ONmJLfk`a8d~Wu)t0YH=pq=9xgOOQ!Z@e`Z(6BsICyH;urj<6E^fbx>Yw^gZeF zr(fO)hsWTIP%vNZu4k-_)JaK>Is~lZorz8U+lW%pcc&5*9&CuUAr3>*{w)Mc7Yp%4 z{`IM34)lnnDq2`R_Z9hU=3x4#T!(Q38LMGf8Aq36=SAhD%_a?g@mVd@f}5M)T$O!( z_Y{KR;eM7Y>)}AT(Su-6bB)a@PvcrbD(^TEGw>IIbGwTQ;q#q>{VRjHmrYj<3I#+2 zI$p#9hcUl=#;L}!rTSEmQ6w%hcFsaRkPeicNJgb>L|8zXqHgR!0%Q9gvPkZ6S5>mk z>9Bq}idxkmh#>9Kxa3U`81^%(diK0uyAMv9q7WJD_C9T>FlR=AOow7A%O@bCj?t1{ zoNDje317uQEh2cGshmmW9VImVDgn>>?Ez0xorv|0NP{Edd(+BruV-v%lVj+5OG2f@ zMd~`yb&O6-BgI4n+kc)7K-UKFbaLOBD{W-MnsB6Y$!Zp9&JPN9 zSTWNJLgZArhUH}?Zxm87v8jynBG~#LZn@;_;;|L#sAc}hM(XPw$krZhVK1}H%y(<) z8%E-UVZmJH9dVU^b`6N|RnVsijJz_%faWqU5^b^PhNw}NLYq}UCBE)>Eg!d<+MP+< zx=at5%%v|j|2>7R{L)u_hRe=C44Q*v3qk1>yS%ObYwZVvik0sSj>1lM2CDqU%c{X4 z#I7s?!;^Ze6q6w*x;SPho6rFkF1@TdUZ+_!%rw|8NBs7a)88P71_PULu7UZ zs|Bc?Zb)p3x+P+|go0z$jHbsT5O86y9PCy*3kw)A19jpHuVAB<$SkLgQ-O;}_O_3P z9VbokdSSTqDT<(!fE)0GOZn3SEg}1~tt0atDyU9GaAB`~W}T8>1yu1?&GjbVl5``G zHahKbo9yw<+^wo(PLy$k{KSx87hy%8!{cklhIm}X*!4J1a^zVbMop~cm6aaI~vQ^y8!*4A-U9vK#?2BSprpIwM8bHl$BizF!Q+NT|Q3Vy5 zXNJ^p;8v-kSOZ`9v-mDxdmL9-hVgVZmbfMad5ApeYI}ocL!DM_qZIVhf)fcYUe_nBHiYTyp*>?8}=@wJ*-nKar zDG285>_qt>Pu2^aLia(v>UNFBDq0jP2bLCfwcZ(e z7ByV(H-&Mwyv`_+S0psn|4*ZvX(W+j*cd&d zs_w%ts#06gPw=|04w?lB3G!kB27PbM)oOe>=fe2uBHGxg##xO=3|H0351!8%axy4d zY~NgWWw_aJw=1bzJ32-pzRSDbIsKReBtA|K$J0LhOr|N-&zT3=XtJbjj5op66opC0 zE&jX?KhWusQ{F5Q>Akjsq&&gY9}Ce?kml^9Y^6*^qNxW7x< zpSs-IJ!_WDDJt?d`ZZc?D=rtgQ7{QSDJd(jwtrW_l~5T+xn!voS-%4lgM0QQTc^R> zJq2gK#ObH4;7Kox9(^fMu{z}xNc|t@GCs;*%p-!ie1uID_?;*Vk9FEpXCBJutyq|- zU4pB~u=r|&*%(3++wSJ?45-R<-fcW(`)owq--2>G>tx$07Sf0uDd_T?rk3nZYMTD| zy6_Zic{fJ|jRvaod8)}Kh`MfIQ{CM>Ejab##jC7ZZ@_*sV zHP$!)XBbbyv2*xI-x#wKl9h);1o2S#ii;&^+p}af=mC*x#C!$^E9WX`4Zl-fgKKE9 zbXzvC@R)@Qseh9m6lxP~9^*b}R#qzgjDc<9nMU-Cv(}cZ^hW81GL59ambo#|D%!04 zHAYg5>nGtaaZ;YsiYBue4u&6O3A-?G{k8`lmHPBn2}r^kA+7q6bi7J-U2@ai{^@v| zVUvJ(kw?P@jZHI34!|rc<3Lv^YFzSH`tR9*-d2kaO?3b9#H^wA3td;lsY}PJEHG)x zd~gtsMk?e1b}8yS&PgO+fCj%!$5@Xxjb(-{?0f|0?YbD#X z$(37Zp4!+`o|IJNbIv~+ND!3(7cwd?4r}I&{AV-j%zM1m9Q=j%K+VQA5H5K#E$!V+ z0ZuvY|3ivJ^3}*ALcGJiOt_v|V@&N_X5itE_w#NL#`x7&do_p}N_mGoo$;Y|*%#kc zKl|`yUwwx`VAe(RiGTlCN4J%`9PztmEHB?-i%i48>@-4!A_C;)ER`rw1P&zlx)S@l z4qvp-s{i~wA*~1ZXeyck47r7t4*xE?Ct)eXi4_q;4_-g-^IlbEy* zKyO`7K7~E?IAP($BZ{EpK@1AjW!>f%3K`hUxLTqeoSS>-aGe3&#@B1cjHNMH` zPT5NxOX;JZJzg_BYY)5S{G^LFI()pxooQRlslDuWuQ9KVk%{p+X|i(nQ7yVsCIFn2 zSi2JxT>ec-X*})s3_>3BxQTgEP(4VcKwJ-(9;H25k4Ks2no)V^3WgTN%y|oJwsj%< z8u@zDq#j+%%ORNusJ2fzz`>29o#xPUHEH!YFP^jj6GnZZ-a!M=rC*LN)o;m4`IGH~ zQm_DJ2It(M37nuxcU^js#4mq-d?aERc3+1_`4ddT)s8=G_>z>AcC_hP(lV2R&Rg}w zY6?=)srf&nvGoIdW2`9_B-E>^Ku;qIu}4uoRh*Ep^G~q(j2zhm^zOinl6g}4`gG{d zhDc5e>b=4u?}M1`q1nzjYf%@$jB+E(c+Y@_9K zxUScn(1?yt6Qr~v>_W$$e0DhO57rkQ6c^TmUj@V&|G;4S4)A8;2$Y0Exgc_ayV@LZ z@yi1Y{hu}JXUT=6b>lkp_~uC-Cn&Tw9rY!h!y4X(yjqO z*mMa_^lRwY@y>M1v?FtiUnOKgju~yyUOkCIZRG)<{JuYimY%fBA2VK|_Wt<7KJ;J= z+&7RSI663A6|Uia^mBNIjr%452nd*(UPJVw1P8?Z;nd?ev&P)TNy>sCE<33?>-2&0 zuIu~D$}=KZ9FBC;znEBXWepB+wFy=DIF`8xdv3k6cjArDaJ-+im+yf*&pz zK#Klmd?tj)ENdGo{U;%bSYhezoF$s$%c&RO2SC462f%a#^^1bO83LrVBxXM`O1KKN zh(k=;oG3OrO=?*3DC-rzu*1St@N#mo_`4K&x2D18XOAl*yzm11MuXBm1YFkhVSli@ z7Q4F;>(4ijp6foV@fI{Jk4J2{-nr-Dl~rNLYYDbMWORcGxW2#cv!giOl+0e7_Bd zmZbi09@KXjNsr`Jt0Bz&CRE)1LsSfKvQzrks}Jp0AOB%o;1F#8fQWesJx^-U=ynzD zJQzVc38P}PgZwC(;rE7}o%?RSu7-HR-p>4=(Y@wJo;9iHw<3rAA8TLgLP;hZK3WCF zBImD7s?hI;gQEp(63#hfi^~<$KIo=%B)upDCiH;ydMQnMa7}LNifp}2;*wM`ZWAT= z2~tx@m^N|ykOUiZwJ^EE2vpB*;P;rL93k(SN4WEIY*XrE5iD_p+-eB@&Dw$!Zi&FU zJ5fZzEuak{^N(u;7;%q_)8krQh>2f$ph!jp!0j1fw_%1cuZ z<*aEC3)x~^(HYC7S!0SMjetzO46O|wpZHE@zv2(|YAYT^;?ez>-lUM<-9jw) zEHnXcF_Zk@bJ}sjSmZes0evDk3SiJ%9rY(q94UN==uGYriQqwL6|84(#*t!}ZXEN3 z9hq?{B0?g!d@FYOj)@i)hnYOv;9knr;LzP^P}a5l!8FL{{nhfiLLPvd8hqqCVEtA{mjp^I$^M3BF_?x`0_M`!p$t0cU$kPMUjhXP41Qb*dlLh#Wuw z!`y)KH5g~5oU_H7m|yWz7@^A#718JuLB!ZFy;edVcF`-CgEb%JChI4F;>4%u8mALz zg1Qh_oGpOj^Qfa4glJEci%ittyUbYky0640V0K?Is zME?+9u15r^7I1gh-!C>%(=zKMU>$U{Z)^P4O414tv{@kSL9nE%aAhRl;m+Y5%0CNU zW=%T0oUP95uH!DVgLQGNmY_rI}OH@Pz8B16`> z0--k86u#{`f~8qM87qrEsMfSm>DKgkEXn!~)H}Whe4dd{z|+qwAv(C4iMTX^-t}0) zW@LaTjkwTeQHX8F%xO@nzYcWuJ;ti*Bx7Dx%epyj38p zELEZC&MOu?=6c*Em2e9y zywZDdsWg1UO7N8bAn`VUMw71h3rGhNobpZNetNrN;9g=r&qjCNfZ5K_Wu6IidsZA| zs*;N#CkQ^-JwH7u$v4wd(PjWJ{mhms)icEPCSPTww7aD_-l{4606 zICGY=FWljKj5s+JN1}qm=pKfG$rc}ssyf*kf)aUYt*ml1`-ez4dMLB?xE_zVl7FCs zN!5&{>DD4YhBS2RrytHwn!M!JR<#}c^0StEko2aHY$oV)*Ki(wD^M;DGu~|_3jj(U z(Z_N&(p*Wz!aRJNsAfY!5+ZrY!r2KUA<&(eZ#uURXsoK&&31Owr`6mvL%nx<%!^dv zOK^OA9xhH175q{ZXj>ml6{q$$5-T+65Sx#IQ9)+BmBw=CA;-vq3t$naP4;3nOga{u z{M!&d&Uww%D7^AX!4Q6lX$l3dqiEJJjrI>d<|?78h0koPo-=u&0MfwkT+J$ok!5R< zDzmTvUVy?WW5kE^6d38hT#b}n*)4LqF(D)3yvBn3>V5Yu=F|$r zHapLTyy0t@k#s6;scm$vaPNM;*tJQBy5LOlm`xfPvK?-v4%H@Ax^w1ntx0q?9Zk%q zl}LE~YWF--viN1Wo7Uv~ z2lBp#I+lE^{y%;_BI}w&7kXo?ks6gGs>L&7In~=q_6!YX>-gN5=7kZyF#wnKNEbhc zQXp|DJV+~3dvky()S`mpqH~-BkZN#8(%0wp9ILIrfv(w5wnWbW;2ak3%MZen%a>ch z(M;bN_?J~YvEZEdlVX&1D<9n8TFmw08>)SMpRuuuFs9XaCX38urGW!Bzp5j@wrAQ# zU>D07kb$d+Xdqd68En@W!$lo6I-i#gZXr#;+0DTv%#;m0@F`51(l+~4Zlexx$`;?N z^6CV;BZW|LVbl37&&P2L-SUKWl%}Ow$rEXH58uh`dJ=^!MJHn{<*A046-ShXAh*!L zCecw=y0fVGMQQ7+Dh|EM5E>PQ!sdb&7K;_a+ZsBw60)j9IW-os4B{h|w7^D3rv1^O z`hB4+R?xhgm3H}8L&x)NcyT4#IgZB>h(NrsBZUzvs-pn zq`i|um^9SAJUB~rpYK59mX3-Z4)7DTv3SM4LP<%vY+pL|o51^5*TN4y#dO;uzV?$( zriWMabE+7YcAAX1+uTfzYDXbmRAKYcB0(Ggp64YP(ng=JwLP<0XfGWf`tU_UhkyJB zvtO#WxKiNO>A9UM_cBGoE9QY>t%=SlT&D#R_i;3v2F?)_9$-GV}+=bg`8kR{^I zWNp~yX-?Y|w3P5=_re%N?Cs8@b#P8-lac&-b3+{KG!HpjOZs@_x1911{p#}VS4ttb zEA;Qb>*5sFRC|LWMDpyPPm7!ufz2LXjxRRi)uj8z!rnO@-iL`YIWg!|_?JK^By* zExjx@nm%I#zV>DmH9+?&b-UFKY5dWm|G4mnd83vz3mN~g zJfVpSDfEpU*P|*M)1vgM;0sO=tG;X)%gPIv(F|I%Rr``G!ff!sUJ2~Q z4k`?X72W4N3=b;%2fY*tr&wIkj&5^r?eFPFC-F6vSb{re6RZg_Q)=Z5Fm#gkm z9|7+m3X@$D5F&X^&+y*=)SB8XYBluZKmas>Cc{H17ya?`{Fue%*kN<7(P-nwA`Z5A zlyk0rvG2uwHQ}&2PevG`KYyQ+FCcSQ@^-@HdV{IUuS%T#MTL||7G4Y%tyVJ5$+XlZ zl|upQcI>JIU^0_8rck=pHBIh<{j-$8ioiq*k0wdeP(Rxvrf5ldDvWfbo5wQ8{bzC~ zupR4|+PuO57U}%$LMjjPpgVSrOV3UOh!-X-)E7R*N@|fk6VjOrLxD|EtB4&^1ZEDK zvk7d=FDL6vA2s|jZWxIu=J?2&O13n6TQLUHo5b4 z19g=M_sKIynW{01U?K?C7 z;qU*kS^s-#@-W9*ZXbqb5%S_#SJ?8oJx|`|N>bcH)&8B66>O|yV@g<&8~JXJ zTxh6jN0TvPl9p>1bpn!6^jl-eEEW3|ftb$szTUs7NOQ6o*#^X%Tsb8tO+_WRzD4i_ z%DF)pc4}A^;1F)nvN@U%i6VcsW8j06?OkB0L^Z)fo=iPK5hB~fp4k_%u=MCIkZ(ly z9m;2ZUZ*N%p$&l88SSiU=I1`Km^_jK>U)}Nz3uHV*_qweARHitcZl@7`hfP)xFWz zyzt>?x|;zac5!G$DnJdDOdIFX@2u8!*^qG>@a79y(;7E$8TQz(<$r1mi?_r5`K3rd zvyGmC_f46yM1R$%Hs7;Nb=avDvoO%8HrE~0nsQwzdZpGTU*MlAZEp6!5{?=$V(!AV zux6mn*e3p<)YJbN$np<&UH2UmR6IS1kTOkkZy-oJMEcbIRUko^Km+P9)>(Px{UMZ zaCKNN0c8vO=WKXxh21 z;5q0r2{m0tPx>rrjN6Zpl|$f*t5a_Jw>+IDy}wE+CX1`oDkOxr@I)2&NiuP;`AGik zqPn-M9xxWpAj9Dveb6Tyz}*TaSWeY)#=x9S^Rx(`N8z=Rn>48^xUmzB3dA@E?A<>KvKH&slPwJ+t!^(#-|A5>-l6^9>!a$3pA z*0qc%i4myqFr?pQ^jG5qpP=L)_Pxog|XCl zQD)E={bfCN20Ea@ze9T3VQ`yZrPwwTKLuXaoJO~M&u(9Fhuqq31x};J3_{Qw2!R_K zPFJ#Y0-0nNP^z;q^~I6d=j|Pjfhey!$ZV|9*s9y;4&fYx{=FJ>VKqoSMS9sDdT64P z7BO8~6irIQhnt|PB~yPh({VW+FfdNjHNvK?qrdXWBB*tPwD?ziD&JU5z2|WBQteXB zkWmMI!-Fp<=gdBWKsmSU)Y9y@Y!pZqy7eHNKueIL686tSeP#%D^WtiD`$9|TP9<2S zEQ-2mX~%hBCsG+5CFxm>`Dh7KvgS)S<-JQ4Jtk|;Kj&Qvig3i5T9$2)Ect0S^W_!u z?|YpyGxK|98U=^JdBNsG`1An%U2NO8Z3aPzdiB7!|NZah%Iliabj){*cOY3Em2wt|vBPwa$MsQgY9HB`(W zA9n400W+|TYiiT~+=18LbP&_{daRp*APS)HLHYPbuE*>C|7kl+_jiue0xK}z^YOYE z@Drhn&T)<1XzKCm#6qUQngrklNR4aUJCb9RC$3uS`UQ0HjL+_~_8hEVvW7R13cT(< zF?$|h!nH6O@oQjyH(5H8oAO}wz-yD}J=IGRgO-kjHHa<6Y9F%`bWOzT1x`f6nj|rl z5PB@3mh3~-?~XW&n%+cZJvhf4+k=b>X&2xvxG+)hvAMy}X0^2`2`}{xi24@6{IUZc zn?eFnY(s8%S=Y%k3z>i*)qQ@PgLif`MYx)YFE1vch?L>gRE+jkD=Rfs7p;QsAjUhs zCGzi{Ai59sq+GbQ@}etQjt8oHAFYsq0OQFi;3CJ!k@ll=Es9MWLG=31<2<|vlUc5i=P?I?NL{A+RhT03HBglAH}l=~l16w*r#)ZM2A zNIV^(ZeH#dm|Kq2sX$bgMYT=2PdR}}j#6CeO(pk84h5bnlsdTIexlG(C`MDaV34>QshZe|F<_Yo|cKK=VgXxN$P98aSxv1@3SNfYjm11NNEvYV|BT_QGs zh1Krm?J0y;^7Jy(TZy-#Xdc~T{1`+@PY@C6YH&pY-Yc61_?oHcEQN3om5Pqq z2izHaG8vjhA-B<5wd0&YIV*vc$b^k)exD(kAMNem%6}*rPSK9QLovm=vB2;0&VEAB z%+{Us_oT+{X!q=d(FrF4v2?`JENY+`Y3As3dyGhG<9rz9n1rjPR+d&rg`*xxTgn_| z0z-SOv`tFPW5TjWCS}aeyC%H&-Ngn)>mtDxLQhPE*X#c8f%u)-wYP0nuS(`WGC>|u zcu=i2FKWE>-g~9Ab}=Ady|JBS`zNaUxfCXVh~foyXk?Es*Kb}-;^t@G7dDs%$p>c~ zt}mr7=p%a1M45S?lCf#dCnsFJ4w358x`*93cL_zUf~F!Q#uGGpSLLyF43H9SUQjy& zn1S_2Z#m(!@WGtL`L1m}gA1ZerS3YYgQpI>xK$PjY*RvHu z1FC}uj|$FqB}Lvdbl8_=Yrju3&-j#!%$*J#7lfqsT{qP|x1@9D7YD7G+@AJ5lAD=S zn>ke!&SxO^BwR}bj_%|F^7enZ`<(_X%rntr>(8x$js!?t$4rrPp&K*EUWiAM9wkR@ zb5!9@@Lr;szCCsdr>Aqy+1cE+eKs(H!VQX*3o<10==Zu6VF)hXsixm1)mGJVTnC~P z&E=8-X6L_>O|fy$?X`HNw6UfHg%$sn2#}`_^y>NQv>1A=CEj0C^k@jvc8ztrtfdXj zzjNb@z3;sh$@f{CnD6v+!NRq2u(8Q`zLy#GB@1l@t(g_e7b?f_+TiLjkp!FK+``ia zy^<{hAojtKw`Na9+iV%SCp^y%dzW_!=Makc4T3)uzF!>Eb#N(Q99I;s)}eZ5RN;pZ zCi3F*LBe^~nO~6$DnS5j1@4t9%GH-%*4dY^@Lo?5x}pS1wiX#| zwO_q?@WXFO*scSLTv9dncbMg`AOp~Zsse;WQ&7}1`%3t7PB^lOSyl1ZULB|G^isy5 zJ+X1g$gSCeI8AE7lS2@Y;oo|r48!~lwz%vzYa7P_0Q>K)QV$14K@)Rx%=gcmyMD+s z^mflTt8t9WCbSi%-!GCDXVX)pSGi;Ytd-}{IBG9Mmq}dgQLm5lgPLR|xnXt$QlNJ(%bgaq}U z&x5?b|MjH%&|M)_-MQ9G=jv{&NqDZxj<7iT6-*LH0nICwc7=IvQ*yplM*LjFNI}Sp z0;@*M0QOrw)LW6zRKVa=bo-i=r_%i};)LwSMS^@@&s{u}E<1DcYEdEYYQHiHxKZH? zciWNZNEjqkRSN;cA8|B-${YrHcg{`C*`@K3fgZ!U*M4wI_stK}N=Xv!)~Jx>L5*Y_X$)9Gg( zQz;~6MmVAZ_s@3&!YukxQ3UbCOF;*`W`mKlfPOqGC}+2jiG{43r1%6R%!fE?U&I84 zsmDo=Z#KT$ujbLQOla%ROE}EU3Bw#`AgJ^`yHhy3wCriB08cf~^KslRmO3%@{7iCP z=)5_Ab6ZpC80NH;57K#b;t2D~T3Vc6Jec3CfecE~3r3XASE`_q?fx%MBflLM%gzOJ z;XA+rU7t|aTuBqk3SP~hEXzRIj?fB zp}%n0-zew8U+NL7-rdTlV+V0>2RYpT%qh2e3B(Jkr?PlSQtxQ3;)+BUydzP`!@NoDms}>o_HYxBSqjRA zbO@tp+XAGnptJVt0Hw(S)_KQTY|r1Y!r}vZo1?&pf8oX?#let}{PYdsg+e zNm&>TFakr-7=%;kz*6`$VtABuAHJEEl!l6Z(EMlx9PQ^@VJOz4_nw41(9lm8*e;lx zB%`DNFF?@0r>vgUXwnIKryRcXj;j!v1|5`A>D7O4`|xw-MCuzc%1bBAOIk18FSc(q zCC8bnpQ|jv80CZPEpJ%-bdMq*N>CF6cM3sx3v_(Ce6csuaV~N+wGJ81FRKqTV?qb} zCm4*lMuTOGE%=g9+`_~~qSv6Q!o4)zieon}6G(1(yv&lJXa@6gmJ~LHqzZtS7yc;D z_-)}jtz`P^UnxBgK9E6Ssx#KXC6d&A8MBY)-3N#ci@)>-iGr(!l@LtKzW29v_vC^i@O!5c$l@VpYcEXYR?1@Vd;Zj|*Zk^QDCd$28Tu4O(8g-qTqYmp5%8n&2tQOl|Zq zB!N2DH-1pbYFO!u_OrsF4ZhsX*EANilPqh@wA;qYHAc(cC9}@{!0mU2!nJMi^Y*9d z;o)!R8hD422i(&#yZ#`+gXk-B$CoPS?b0k!6W~nkv>gqK+vNI527LLGlM;0d*#bbR zLoh3ZaIJ&m>^W%WuFJmGc>JL5rACG*aBM@?=x65w5a?i<`6o)RTaW3Mn% zv#jPdq{s5@CRlRa*`}RoEuk0F+|_3!f%Uwo^H-gaOa53X)rKy;lX{@C&E%}G=6$b^){W7u+|4lncKfvUvBXa!Sj}(KN zyrJ+M?T{;I1^Tg*G3lRU7GHBmmt_2{QhdpV$-rju{g(a_iEbiH?;0bxriK0vFV)O6(_E>IT4gJcy<_| z%=4lFO?8qT%cL48K-pn);!V4lG+3Aj1&o$`3k!S6Ex;S zK0p6X3UcT?l*jG+Z27pzzxDV0$P@#PeKDC_w;#A3jZ{pC9<@4e#xTIzxua%%+)fw; zoBqoipPJ(b(}T8)$@pnhvjBpwC3_XM68k1$T4b>BPU;58JsfaX+LA%6X9XhV z52Bs8Cl|Dy-L%Pd=U(h;k8^Jl{b7dzv_=XcW65AxQU^s65FB_z1$GK7Z5xnGZe=$u zVY)|X(L*AtBSY}|W%;n;=YsE7!N*IZi8}4>GPuKkYNauC#_)Dy@fJLVAVf|V+GDIG zBTzkDnL$8=9||h8t@>pd^;H`oszK7+p^@`HZV1Xg05-XN_9bZybFoQf&*9XWOpR6q z2xj(43Xf4|<88bK_`zk@J!@jx70wF9awHslGb_=q1xc~0^i#1x)&EHhr4*MmOBQ+`6p?)1#udDu4f{h`U~wOA`)emJlSD==(%7 zulH?xqJ_T^osWdb?x&?_T_j8|s$uVB-e|6j@LNcJtIiWNK7qK2hZ0xnB?s$FOs{4G zF5A6?t*b@LA?kAq0sL9Q12rN+fPS2*l0ff#K-Y#lRY7W@mXE-?&wZH6(1aea8=IR=63EMJeQfZg*fZ1GAk7jUsd zIaIdeerkN|$$cz8kBgPodH$p=^CG0w6@ZsM4kOvT%T}Xrs#UOhuA$CiW`@){?Nhcn zk2bN@jIh54v4ZcEzuVr-pfUk#}--Vz$mFM;5F%I;SS68Jmn!};xYe^G2U z+gOp&pXhrt_56|RngZ{QL(1*`QKFVsg54~Is*^QZ0&lOqJ#r=9 zvRI_>vc*#om!)t+?~KJ+-1Z20$Sf_!YB&2&8c0n8pF2rhRQ%O(A-3Cmjh@B$yVAdj z0{vVdHFXQeLf-ih49+@`L5Eu5%!Ch@3$EDg0RVV&X^0-(@0L=J8G8yiUNysI`zl)rGeb7@|sE5J(&*9&y+uhfCHqy8NXiEf?EX;VpQ%|JJms!PX@MS??0iaM6& zf+~3wy0!n?3i#%~UA zuSqX*e86q4-M+ytF@*OF&}Xc`TOmlUEAT? zdhf5Iy7T~IwFGFDy+}7H8(V@Rez}zu0x$V$Vaw{maq&G) zl_Xd|A)8-o1y01p(|&acQ3w9$(A6@W0CP|K13){P7V6jJ-MS`t6N@b2Is+j5ZWcZP z;J`#qr?W9uD7Tgc9qC-NI>r_)R94oK1!@5uyG`yuR7t%n>ft?TQ7S^`qV}R`HQ2F( zP}3n{et?{Y>uDPgk{`*Uf2xN6ZZXlB{!Y7_{Sh8CAk4{#^fs6nV?MXy^ZOvXp6qA$4A`9;UQ6i_ti9Fzur=Ih@?H89lbO6+#9wddZ{`F-snp~La5_PuV3|R9?G+^p ztc|8>_+Jc|7q#|akWjuf{C51jU_vQb^ba|SvKXZs?GHn(N!h~8{h`L@w}~-0;o-=D zO{W`{FmE1*;&^_bzeF_36uO74Z(`A?uvtk)C8r~kowKR70?NOvzooP7(CN-#WLJB+ z&`#5BK>}=n8s==}b@~^1Ch8PEcO-l#L}`g2DYZSmPr{)ozpa1k6gSAX=$Xn@MPz$je5cv=%X;ON-=N54z zv66%MQAAJ`r8$g+(gZQ1`ojK8f{8OujB`zx$bfR%7SH<{;FpzyS8Ik0W2&3mbs2MX z9sav*l6)ZG{0%CJQ9)&Kl<#A>{O6D0l&Fzw{pY-|ip(TfptAoD+~~WW`LRb>QYZ;E7Uh0eDVjlF~7L$AFY6172T!0S_V@%QZruv@ zeSV?|LFgzKXg&>s1?^Cw!9e3V#qq396ixSx%Eym|ugF)`RoJF5tS)7>Do3?a8?C$w z%58Ki5svYw1`;yUOfY%R6J}wu!_oRs*P4ImhjjG=c^JR`-b#H}*Fl%sH=6e82`#_B z*psj@ryP)UPV*ERbhQWHw@s@+@Miqg?~}S?B)$OpoLWxb#mRjUxNf2xQ-MWuOkge` z&cSa#_^UaHdQcJ!Vy9E6D7UD%_4>xx`EsZFl}%1K!Q)vIO8_ow{Yx2@euaulYUDIoPpN z=pI%f(&^~L^)ID}ouF&=GW}rnasrviDiX#2)FaWqCOZ0o*m~p8tge-ps0mIer9=Pf z#3f6oQ-M=O0%;ye^O=eqT%AuOv7p0_X5FJKCJ_`m&PiF<-%%7nukR9sHvB+bJQPgd z?GoCdHbAp5g)Tx#+Z|r{j*OJf~{^Wyolu9$ObRjhRJ3P;!djY0=rFdt*hQG3~{rZwwFH;Zuc{}~p?&2ultKv>=?WjxV z!^l6@V6PzYUBnJ**F)B-y{{cP$@&KA(O5rnDhihmczoe|eDuj_jWnMCPA$R+m9sA-HiIerD{oolciv^0@k$ejNZScRp-dcYoVeERk-4n z;M1ldIM&Glc7p6_RgzxzpBTTbU)0SfVyboTc$ZRDVe-r;PeyQHv*>AeJDYL6Jhv!} zwgB%4pAghrR$++2nlKAY>iI|>!=_idE30==;D^%S_uIMpED$ao3an)qffWcHwMBm? zophT|&sw)n-9%c+FrynkO8OuO1`NTPVCtOiE$1=Htn=at1Wo!z==(6W_P-xW3r!du zxSIjF_J2;^CU1mh8xsGieGA8azwl#1q~|_HP+~$Pd-H+;4U0OmDw=T3s>W?`tJ5iA z@V%&L`{p}sQWU?^?TA^0`Iij+$HvdLX!4&y2UBtVu0EPK(0a!mL_z2*yv`5{uv#i9 zh2VerRFmW~?JP|79D*$o$+?A40TkpE0QHab0EbR$a|0;2jYI%6KOF_*gN-FPV;PPi z7Q_zVU!&bEX>e>h%DvOC&qgrG@*+KTg0romhbvlz!9BD9ux%fa^eMS2MxA{Ud9;KX zArYt;@2HrWvMx2S*+OEer}BQ}GI*=$lxG%lmv=e!P3E*hU~H^tc)#(h_H45SXd8Q9 zc}!7%Jh5!OzXGj%7X=ED|7(XId;sVTia6SV`gP554MCkcpn*@pF-COMS%7F$IQS3WagWISht z2O;45s`x|;(lJMn9^7OslM_m*IOdt)=Ef}kAuQ?P%nSNXaG*S*RgVX?vsPq5b<^%M z8`*^))<&*Y(+Qka0C7@pUqpOVzlbPI`rmQf`2V7k3&=zlR`SznhQGV|b|XQ!@!V

7m~*Ys0e2(x6T&$R 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%0A!=t}Du5W2r8{6*;Fu3|;wL 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%0A4yQOE{v78vIpfiyk7nOgqWyds%d<$etM8znmOjd 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%0DtyzCMPVI86IqZdrN7tnM;it+V}dci3d)0UB|cz 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 O-W&J{uh+GWsJ{U}_&o~% literal 0 HcmV?d00001 diff --git a/XEU5-0/Experts/x-saherelm.xeu5.ea.mq5 b/XEU5-0/Experts/x-saherelm.xeu5.ea.mq5 new file mode 100644 index 0000000..8b925ae --- /dev/null +++ b/XEU5-0/Experts/x-saherelm.xeu5.ea.mq5 @@ -0,0 +1,347 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ---------------------------------------- +// Name: XEU5EA +// 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 XEU5 EA" +#property strict + +// +// START Inputs ... +// + +input group "Commons"; + +// +// 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" + +// +// XEU5 Signal Provider ... +#include "../Providers/x-saherelm.xeu5.provider.lib.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +bool isXEU5NewHour; +bool isXEU5NewDay; +bool isXEU5NewWeek; +bool isXEU5NewMonth; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = "XEU5EA"; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Apply default Chart Style for EA ... + ApplyChartStyle(); + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize XEU5 Provider ... + if (!XEU5InitSignalProviderLibrary()) + { + 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 ... + + // + // De Initialize XEU5 Provider ... + XEU5DeinitSignalProviderLibrary(reason); + + // + // De Init XDraw Library ... + // OnDeinitDrawLibrary(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXEU5NewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXEU5NewMonth && + xEU5EnableAlerts && + xEU5EnableMonthlyAlerts; + bool canMonthlyReport = + !isFirstMonth && + canMonthlyAlert && + xEU5EnableMonthlyReports; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + // Prepare Monthly Report ... + if (canMonthlyReport) + { + // + string report = xEU5Reporter.GenerateReportString(XREPORT_MONTHLY); + + // + message = "Last Month Report:\n" + report; + } + + // + // Reset Report ... + xEU5Reporter.Reset(XREPORT_MONTHLY); + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXEU5NewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXEU5NewWeek && + xEU5EnableAlerts && + xEU5EnableWeeklyAlerts; + bool canWeeklyReport = + !isFirstWeek && + canWeeklyAlert && + xEU5EnableWeeklyReports; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + // Prepare Weekly Report ... + if (canWeeklyReport) + { + // + string report = xEU5Reporter.GenerateReportString(XREPORT_WEEKLY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xEU5Reporter.Reset(XREPORT_WEEKLY); + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXEU5NewDay = IsNewDay(); + bool canDailyAlert = + isXEU5NewDay && + xEU5EnableAlerts && + xEU5EnableDailyAlerts; + bool canDailyReport = + !isFirstDay && + canDailyAlert && + xEU5EnableDailyReports; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + // Prepare Daily Report ... + if (canDailyReport) + { + // + string report = xEU5Reporter.GenerateReportString(XREPORT_DAILY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xEU5Reporter.Reset(XREPORT_DAILY); + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXEU5NewHour = IsNewHour(); + bool canHourlyAlert = + isXEU5NewHour && + xEU5EnableAlerts && + xEU5EnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + + // + // Prevent Going Forward if user Disable it ... + if (xEU5EnableProvider) + { + // + // Handle Processing on XEU5 Signal Provider ... + XEU5SignalProviderDoControlState(); + } + + // + if (!IsNewCandle()) + { + return; + } + + // + // Prevent Going Forward if user Disable it ... + if (xEU5EnableProvider) + { + // + // Handle Processing on XEU5 Signal Provider ... + XEU5SignalProviderHandleTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + + // + // Prevent Going Forward if user Disable it ... + if (xEU5EnableProvider) + { + // + // Handle Processing Trades on XEU5 Signal Provider ... + XEU5SignalProviderHandleTrade(); + } +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + + // + // Validate XEU5 Provider Inputs ... + result = XEU5ValidateInputs(); + if (!result) + { + return false; + } + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// END Functions ... +// diff --git a/XEU5-0/Helpers/.gitkeep b/XEU5-0/Helpers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 new file mode 100644 index 0000000..f565e41 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 @@ -0,0 +1,607 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAMA 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XAMA Indicator States ... +enum ENUM_X_XAMA_STATES +{ + X_XAMA_BULLISH = 1, + X_XAMA_BEARISH = -1, + X_XAMA_NEUTURAL = 0, +}; + +// +// XAMA Indicator Buffer Lines ... +enum ENUM_X_XAMA_BUFFER_LINES +{ + X_XAMA_MA_LINE = 0, + X_XAMA_MC_COLOR_LINE = 1, + X_XAMA_STATE_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XAMA Indicator"; + +// +// input int xAMALength = 18; // Market Length +// input int xAMAFastEMA = 2; // Fast EMA Period +// input int xAMASlowEMA = 30; // Slow EMA Period +// input int xAMAShift = 0; // Shift +// input ENUM_APPLIED_PRICE xAMAAppliedTo = PRICE_CLOSE; // Applied To + +// +// Configurations ... +int xAMALength = 18; // Market Length +int xAMAFastEMA = 2; // Fast EMA Period +int xAMASlowEMA = 30; // Slow EMA Period +int xAMAShift = 0; // Shift +ENUM_APPLIED_PRICE xAMAAppliedTo = PRICE_CLOSE; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xAMAHandler = INVALID_HANDLE; +double xAMAMaBuffer[]; +double xAMAStateBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XAMAValidateInputs() +{ + // + bool result = false; + + // + result = + xAMALength > 2 && + xAMAFastEMA < xAMALength && + xAMAFastEMA < xAMASlowEMA && + xAMAShift >= 0; + + // + if (!result) + { + // + LogMessage("XAMA Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XAMAInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Indicator Handlers ... + ResetLastError(); + + // + // XAMA Handler ... + ArraySetAsSeries(xAMAMaBuffer, true); + ArraySetAsSeries(xAMAStateBuffer, true); + xAMAHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xama.indicator", + // + // Inputs ... + xAMALength, + xAMAFastEMA, + xAMASlowEMA, + xAMAShift, + xAMAAppliedTo + // + ); + if (xAMAHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XAMA Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XAMAReleaseHandlers() +{ + IndicatorRelease(xAMAHandler); +} + +// +// Handle Reading Buffers ... +void XAMAReadBuffers( + int xAMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XAMA Ma Buffer ... + CopyBuffer( + xAMAHandler, + X_XAMA_MA_LINE, + 0, + xAMAItemsPerTick, + xAMAMaBuffer); + + // + // XAMA State Buffer ... + CopyBuffer( + xAMAHandler, + X_XAMA_STATE_LINE, + 0, + xAMAItemsPerTick, + xAMAStateBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XAMA Custom Functions ... +// + +// +// Check SC is Peak ... +bool XAMAIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xAMAMaBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XAMAIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xAMAMaBuffer + // + ); + + // + return result; +} + +// +// Check TM Crossed Up ... +bool XAMAIsStartBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BULLISH && + xAMAStateBuffer[bar_index + 1] != X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Up After Neutural State ... +bool XAMAIsStartBullishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BULLISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Up State ... +bool XAMAIsBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State ... +bool XAMAIsEndBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] != X_XAMA_BULLISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State By Neutural ... +bool XAMAIsEndBullishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_NEUTURAL && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down ... +bool XAMAIsStartBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BEARISH && + xAMAStateBuffer[bar_index + 1] != X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down After Neutural State ... +bool XAMAIsStartBearishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BEARISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Down State ... +bool XAMAIsBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State ... +bool XAMAIsEndBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] != X_XAMA_BEARISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State By Neutural ... +bool XAMAIsEndBearishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_NEUTURAL && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM In Neutural State ... +bool XAMAIsNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_NEUTURAL + // + ; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XAMAIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xAMAMaBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XAMA Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..d7071b4 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 @@ -0,0 +1,1032 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHLH Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// Cycles Enumeration ... +enum ENUM_X_XCHLH_CYCLES +{ + X_XCHLH_CYCLE_LONG, + X_XCHLH_CYCLE_MEDIUM, + X_XCHLH_CYCLE_SHORT, +}; + +// +// XCHLH Hot States ... +enum ENUM_X_XCHLH_HOT_STATES +{ + X_XCHLH_HOT_HH = 1, + X_XCHLH_NEUTURAL = 0, + X_XCHLH_HOT_LL = -1, +}; + +// +// XCHLH Buffer Lines ... +enum ENUM_X_XCHLH_BUFFER_LINES +{ + X_XCHLH_LC_HH_LINE = 0, + X_XCHLH_LC_LL_LINE = 1, + X_XCHLH_MC_HH_LINE = 2, + X_XCHLH_MC_LL_LINE = 3, + X_XCHLH_SC_HH_LINE = 4, + X_XCHLH_SC_LL_LINE = 5, + X_XCHLH_SIGNAL_T_LINE = 6, + X_XCHLH_SIGNAL_B_LINE = 7, + X_XCHLH_HOT_STATE_LINE = 8, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// // +// input group "XCHLH Oscillator"; + +// // +// // Common ... +// input group "XCHLH Hot Areas"; +// input bool xCHLHDrawHotAreas = false; // Draw Hot Areas Symbol +// input uchar xCHLHHotHHArrowCode = 234; // Hot HH Arrow Code +// input color xCHLHHotHHArrowColor = clrAqua; // Hot HH Arrow Color +// input uchar xCHLHHotLLArrowCode = 233; // Hot LL Arrow Code +// input color xCHLHHotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// // +// // LC Inputs ... +// input group "XCHLH Long Cycle"; +// input group "XCHLH LC Market"; +// input int xCHLHLcLength = 288; // Length +// input double xCHLHLcThresholdInPips = 0.3; // Threshold In Pips +// input ENUM_SERIESMODE xCHLHLcHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xCHLHLcLLMode = MODE_LOW; // Lowest Low Calculation Method +// input group "XCHLH LC Style"; +// input int xCHLHLcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHLHLcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHLHLcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHLHLcHHColor = clrAqua; // Highest High Color +// input color xCHLHLcLLColor = clrFuchsia; // Lowest Low Color +// input group "XCHLH LC Drawings"; +// input bool xCHLHLcDrawHH = true; // Draw Highest High +// input bool xCHLHLcDrawLL = true; // Draw Lowest Low + +// // +// // MC Inputs ... +// input group "XCHLH Medium Cycle"; +// input group "XCHLH MC Market"; +// input int xCHLHMcLength = 72; // Length +// input double xCHLHMcThresholdInPips = 0.3; // Threshold In Pips +// input ENUM_SERIESMODE xCHLHMcHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xCHLHMcLLMode = MODE_LOW; // Lowest Low Calculation Method +// input group "XCHLH MC Style"; +// input int xCHLHMcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHLHMcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHLHMcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHLHMcHHColor = clrLime; // Highest High Color +// input color xCHLHMcLLColor = clrRed; // Lowest Low Color +// input group "XCHLH MC Drawings"; +// input bool xCHLHMcDrawHH = true; // Draw Highest High +// input bool xCHLHMcDrawLL = true; // Draw Lowest Low + +// // +// // SC Inputs ... +// input group "XCHLH Short Cycle"; +// input group "XCHLH SC Market"; +// input int xCHLHScLength = 7; // Length +// input double xCHLHScThresholdInPips = 0.3; // Threshold In Pips +// input ENUM_SERIESMODE xCHLHScHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xCHLHScLLMode = MODE_LOW; // Lowest Low Calculation Method +// input group "XCHLH SC Style"; +// input int xCHLHScDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHLHScDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHLHScDrawStyle = STYLE_DOT; // Draw Style +// input color xCHLHScHHColor = clrLightBlue; // Highest High Color +// input color xCHLHScLLColor = clrLightSalmon; // Lowest Low Color +// input group "XCHLH SC Drawings"; +// input bool xCHLHScDrawHH = true; // Draw Highest High +// input bool xCHLHScDrawLL = true; // Draw Lowest Low + +// +// Configurations ... +// +// Common ... +bool xCHLHDrawHotAreas = false; // Draw Hot Areas Symbol +uchar xCHLHHotHHArrowCode = 234; // Hot HH Arrow Code +color xCHLHHotHHArrowColor = clrAqua; // Hot HH Arrow Color +uchar xCHLHHotLLArrowCode = 233; // Hot LL Arrow Code +color xCHLHHotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// +// LC Inputs ... +int xCHLHLcLength = 288; // Length +double xCHLHLcThresholdInPips = 0.3; // Threshold In Pips +ENUM_SERIESMODE xCHLHLcHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xCHLHLcLLMode = MODE_LOW; // Lowest Low Calculation Method +int xCHLHLcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHLHLcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHLHLcDrawStyle = STYLE_DOT; // Draw Style +color xCHLHLcHHColor = clrAqua; // Highest High Color +color xCHLHLcLLColor = clrFuchsia; // Lowest Low Color +bool xCHLHLcDrawHH = true; // Draw Highest High +bool xCHLHLcDrawLL = true; // Draw Lowest Low + +// +// MC Inputs ... +int xCHLHMcLength = 72; // Length +double xCHLHMcThresholdInPips = 0.3; // Threshold In Pips +ENUM_SERIESMODE xCHLHMcHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xCHLHMcLLMode = MODE_LOW; // Lowest Low Calculation Method +int xCHLHMcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHLHMcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHLHMcDrawStyle = STYLE_DOT; // Draw Style +color xCHLHMcHHColor = clrLime; // Highest High Color +color xCHLHMcLLColor = clrRed; // Lowest Low Color +bool xCHLHMcDrawHH = true; // Draw Highest High +bool xCHLHMcDrawLL = true; // Draw Lowest Low + +// +// SC Inputs ... +int xCHLHScLength = 7; // Length +double xCHLHScThresholdInPips = 0.3; // Threshold In Pips +ENUM_SERIESMODE xCHLHScHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xCHLHScLLMode = MODE_LOW; // Lowest Low Calculation Method +int xCHLHScDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHLHScDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHLHScDrawStyle = STYLE_DOT; // Draw Style +color xCHLHScHHColor = clrLightBlue; // Highest High Color +color xCHLHScLLColor = clrLightSalmon; // Lowest Low Color +bool xCHLHScDrawHH = true; // Draw Highest High +bool xCHLHScDrawLL = true; // Draw Lowest Low + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xCHLHHandler = INVALID_HANDLE; +double xCHLHLcHHBuffer[]; +double xCHLHLcLLBuffer[]; +double xCHLHMcHHBuffer[]; +double xCHLHMcLLBuffer[]; +double xCHLHScHHBuffer[]; +double xCHLHScLLBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XCHLHValidateInputs() +{ + // + bool result = false; + + // + result = + xCHLHScLength >= 2 && + xCHLHMcLength > xCHLHScLength && + xCHLHLcLength > xCHLHMcLength; + + // + if (!result) + { + // + LogMessage("XCHLH Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XCHLHInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XCHLH Handler ... + ArraySetAsSeries(xCHLHLcHHBuffer, true); + ArraySetAsSeries(xCHLHLcLLBuffer, true); + ArraySetAsSeries(xCHLHMcHHBuffer, true); + ArraySetAsSeries(xCHLHMcLLBuffer, true); + ArraySetAsSeries(xCHLHScHHBuffer, true); + ArraySetAsSeries(xCHLHScLLBuffer, true); + xCHLHHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xchlh.oscillator", + // + // Inputs ... + // + // Commons ... + "", + xCHLHDrawHotAreas, + xCHLHHotHHArrowCode, + xCHLHHotHHArrowColor, + xCHLHHotLLArrowCode, + xCHLHHotLLArrowColor, + // + // LC ... + "", + "", + xCHLHLcLength, + xCHLHLcThresholdInPips, + xCHLHLcHHMode, + xCHLHLcLLMode, + "", + xCHLHLcDrawWidth, + xCHLHLcDrawType, + xCHLHLcDrawStyle, + xCHLHLcHHColor, + xCHLHLcLLColor, + "", + xCHLHLcDrawHH, + xCHLHLcDrawLL, + // + // MC ... + "", + "", + xCHLHMcLength, + xCHLHMcThresholdInPips, + xCHLHMcHHMode, + xCHLHMcLLMode, + "", + xCHLHMcDrawWidth, + xCHLHMcDrawType, + xCHLHMcDrawStyle, + xCHLHMcHHColor, + xCHLHMcLLColor, + "", + xCHLHMcDrawHH, + xCHLHMcDrawLL, + // + // SC ... + "", + "", + xCHLHScLength, + xCHLHScThresholdInPips, + xCHLHScHHMode, + xCHLHScLLMode, + "", + xCHLHScDrawWidth, + xCHLHScDrawType, + xCHLHScDrawStyle, + xCHLHScHHColor, + xCHLHScLLColor, + "", + xCHLHScDrawHH, + xCHLHScDrawLL); + if (xCHLHHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XCHLH Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XCHLHReleaseHandlers() +{ + IndicatorRelease(xCHLHHandler); +} + +// +// Handle Reading Buffers ... +void XCHLHReadBuffers( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XCHLH LC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_LC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHLcHHBuffer); + + // + // XCHLH LC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_LC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHLcLLBuffer); + + // + // XCHLH MC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_MC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHMcHHBuffer); + + // + // XCHLH MC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_MC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHMcLLBuffer); + + // + // XCHLH SC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHScHHBuffer); + + // + // XCHLH SC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHScLLBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XCHLH Custom Functions ... +// + +// +// Check LC and MC has Same HH ... +bool XCHLHIsLCMCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double mcValue = xCHLHMcHHBuffer[bar_index]; + + // + result = lcValue == mcValue; + + // + return result; +} + +// +// Check LC and MC has Same LL ... +bool XCHLHIsLCMCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double mcValue = xCHLHMcLLBuffer[bar_index]; + + // + result = lcValue == mcValue; + + // + return result; +} + +// +// Check LC and SC has Same HH ... +bool XCHLHIsLCSCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = lcValue == scValue; + + // + return result; +} + +// +// Check LC and SC has Same LL ... +bool XCHLHIsLCSCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = lcValue == scValue; + + // + return result; +} + +// +// Check MC and SC has Same HH ... +bool XCHLHIsMCSCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double mcValue = xCHLHMcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = mcValue == scValue; + + // + return result; +} + +// +// Check MC and SC has Same LL ... +bool XCHLHIsMCSCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double mcValue = xCHLHMcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = mcValue == scValue; + + // + return result; +} + +// +// Check Is Same Highest Highs ... +bool XCHLHIsSameHHs( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double mcValue = xCHLHMcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = + // + lcValue == mcValue && + mcValue == scValue + // + ; + + // + return result; +} + +// +// Check Is Same Lowest Lows ... +bool XCHLHIsSameLLs( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double mcValue = xCHLHMcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = + // + lcValue == mcValue && + mcValue == scValue + // + ; + + // + return result; +} + +// +// Check Medium Cycle is On Top of Long Cycle's Mid ... +bool XCHLHIsMCOnTopOfLC( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + ENUM_X_XCHLH_CYCLES sCycle = X_XCHLH_CYCLE_MEDIUM; + ENUM_X_XCHLH_CYCLES dCycle = X_XCHLH_CYCLE_LONG; + + // + result = + // + XCHLHCheckCycleIsOnTopOfAnother( + bar_index, + sCycle, + dCycle) + // + ; + + // + return result; +} + +// +// Check Medium Cycle is In Bottom of Long Cycle's Mid ... +bool XCHLHIsMCInBottomOfLC( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + ENUM_X_XCHLH_CYCLES sCycle = X_XCHLH_CYCLE_MEDIUM; + ENUM_X_XCHLH_CYCLES dCycle = X_XCHLH_CYCLE_LONG; + + // + result = + // + XCHLHCheckCycleIsInBottomOfAnother( + bar_index, + sCycle, + dCycle) + // + ; + + // + return result; +} + +// +// Check and Validate Buffer Sizes ... +bool XCHLHIsValidBufferSizes( + int size // Specified Min Size +) +{ + // + bool result = false; + + // + result = + // + ArraySize(xCHLHLcHHBuffer) > size && + ArraySize(xCHLHLcLLBuffer) > size && + // + ArraySize(xCHLHMcHHBuffer) > size && + ArraySize(xCHLHMcLLBuffer) > size && + // + ArraySize(xCHLHScHHBuffer) > size && + ArraySize(xCHLHScLLBuffer) > size; + + // + return result; +} + +// +// Get Cycle Middle Value ... +double XCHLHGetCycleMid( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Retrieve Cycle Max Value ... + double iMax = XCHLHGetCycleMax( + bar_index, + cycle); + + // + // Retrieve Cycle Min Value ... + double iMin = XCHLHGetCycleMin( + bar_index, + cycle); + + // + result = (iMax - iMin) / 2; + + // + return result; +} + +// +// Get Cycle Max Value ... +double XCHLHGetCycleMax( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + // Long Cycle ... + case X_XCHLH_CYCLE_LONG: + result = xCHLHLcHHBuffer[1]; + break; + + // + // Medium Cycle ... + case X_XCHLH_CYCLE_MEDIUM: + result = xCHLHMcHHBuffer[1]; + break; + + // + // Short Cycle ... + case X_XCHLH_CYCLE_SHORT: + result = xCHLHScHHBuffer[1]; + break; + } + + // + return result; +} + +// +// Get Specified Cycles Max Value ... +double XCHLHGetCyclesMax( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES &cycles[] // Specified Cycle ... +) +{ + // + bool result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + ArraySize(cycles) <= 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycles); i++) + { + // + ENUM_X_XCHLH_CYCLES iCycle = cycles[i]; + + // + double iValue = XCHLHGetCycleMax( + bar_index, + iCycle); + + // + result = result == 0 || result < iValue ? iValue : result; + } + + // + return result; +} + +// +// Get Cycle Min Value ... +double XCHLHGetCycleMin( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + // Long Cycle ... + case X_XCHLH_CYCLE_LONG: + result = xCHLHLcLLBuffer[1]; + break; + + // + // Medium Cycle ... + case X_XCHLH_CYCLE_MEDIUM: + result = xCHLHMcLLBuffer[1]; + break; + + // + // Short Cycle ... + case X_XCHLH_CYCLE_SHORT: + result = xCHLHScLLBuffer[1]; + break; + } + + // + return result; +} + +// +// Get Specified Cycles Min Value ... +double XCHLHGetCyclesMin( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES &cycles[] // Specified Cycle ... +) +{ + // + bool result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + ArraySize(cycles) <= 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycles); i++) + { + // + ENUM_X_XCHLH_CYCLES iCycle = cycles[i]; + + // + double iValue = XCHLHGetCycleMin( + bar_index, + iCycle); + + // + result = result == 0 || result > iValue ? iValue : result; + } + + // + return result; +} + +// +// Check a Cycle is On Top of Another Cycle's Mid ... +bool XCHLHCheckCycleIsOnTopOfAnother( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES sourceCycle, // Specified Source Cycle which Checks ... + ENUM_X_XCHLH_CYCLES destCycle // Specified Dest Cycle which source Checked based on it ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Retrieve Min Value of Source Cycle ... + double iMin = XCHLHGetCycleMin( + bar_index, + sourceCycle); + + // + // Retrieve Mid Value of Dest Cycle ... + double iMid = XCHLHGetCycleMid( + bar_index, + destCycle); + + // + // Generate Result ... + result = + // + iMin >= iMid + // + ; + + // + return result; +} + +// +// Check a Cycle is Under Bottom of Another Cycle's Mid ... +bool XCHLHCheckCycleIsInBottomOfAnother( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES sourceCycle, // Specified Source Cycle which Checks ... + ENUM_X_XCHLH_CYCLES destCycle // Specified Dest Cycle which source Checked based on it ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Retrieve Max Value of Source Cycle ... + double iMax = XCHLHGetCycleMax( + bar_index, + sourceCycle); + + // + // Retrieve Mid Value of Dest Cycle ... + double iMid = XCHLHGetCycleMid( + bar_index, + destCycle); + + // + // Generate Result ... + result = + // + iMax <= iMid + // + ; + + // + return result; +} + +// +// END XCHLH Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..e84d762 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 @@ -0,0 +1,2229 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHMA Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XCHMA Cycles ... +enum ENUM_XCHMA_CYCLES +{ + X_XCHMA_CYCLE_LONG, + X_XCHMA_CYCLE_MEDIUM, + X_XCHMA_CYCLE_SHORT, +}; + +// +// XCHMA Oscillator Hot State Presentation ... +enum ENUM_XCHMA_HOT_STATES +{ + X_XCHMA_HOT_BULLISH = 1, + X_XCHMA_HOT_NEUTURAL = 0, + X_XCHMA_HOT_BEARISH = -1, +}; + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; + +// +// XCHMA Oscillator Buffer Lines ... +enum ENUM_X_XCHMA_BUFFER_LINES +{ + X_XCHMA_LC_FAST_LINE = 0, + X_XCHMA_LC_SLOW_LINE = 1, + X_XCHMA_LC_STATE_LINE = 6, + X_XCHMA_MC_FAST_LINE = 2, + X_XCHMA_MC_SLOW_LINE = 3, + X_XCHMA_MC_STATE_LINE = 7, + X_XCHMA_SC_FAST_LINE = 4, + X_XCHMA_SC_SLOW_LINE = 5, + X_XCHMA_SC_STATE_LINE = 8, + X_XCHMA_HOT_STATE_LINE = 9, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XCHMA Oscillator"; + +// // +// // Commons ... +// input group "XCHMA Hot Areas"; +// input bool xCHMADrawHotAreas = false; // Draw Hot Areas Symbol; +// input uchar xCHMAHotBullishArrowCode = 228; // Hot Bullish Arrow Code; +// input color xCHMAHotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color; +// input uchar xCHMAHotBearishArrowCode = 230; // Hot Bearish Arrow Code; +// input color xCHMAHotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color; + +// // +// // LC Inputs ... +// input group "XCHMA Long Cycle"; +// input group "XCHMA LC Market"; +// input int xCHMALcFastLength = 288; // Fast Length +// input int xCHMALcSlowLength = 576; // Slow Length +// input ENUM_MA_METHOD xCHMALcMethod = MODE_EMA; // Calculation Method +// input ENUM_APPLIED_PRICE xCHMALcAppliedTo = PRICE_CLOSE; // Applied To +// input group "XCHMA LC Style"; +// input int xCHMALcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHMALcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHMALcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHMALcFastColor = clrAqua; // Fast Color +// input color xCHMALcSlowColor = clrFuchsia; // Slow Color +// input group "XCHMA LC Drawings"; +// input bool xCHMALcDrawFast = true; // Draw Fast +// input bool xCHMALcDrawSlow = true; // Draw Slow +// input bool xCHMALcDrawCrosses = false; // Draw Cross Lines + +// // +// // MC Inputs ... +// input group "XCHMA Medium Cycle"; +// input group "XCHMA MC Market"; +// input int xCHMAMcFastLength = 72; // Fast Length +// input int xCHMAMcSlowLength = 144; // Slow Length +// input ENUM_MA_METHOD xCHMAMcMethod = MODE_EMA; // Calculation Method +// input ENUM_APPLIED_PRICE xCHMAMcAppliedTo = PRICE_CLOSE; // Applied To +// input group "XCHMA MC Style"; +// input int xCHMAMcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHMAMcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHMAMcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHMAMcFastColor = clrLime; // Fast Color +// input color xCHMAMcSlowColor = clrRed; // Slow Color +// input group "XCHMA MC Drawings"; +// input bool xCHMAMcDrawFast = true; // Draw Fast +// input bool xCHMAMcDrawSlow = true; // Draw Slow +// input bool xCHMAMcDrawCrosses = false; // Draw Cross Lines + +// // +// // SC Inputs ... +// input group "XCHMA Short Cycle"; +// input group "XCHMA SC Market"; +// input int xCHMAScFastLength = 7; // Fast Length +// input int xCHMAScSlowLength = 14; // Slow Length +// input ENUM_MA_METHOD xCHMAScMethod = MODE_SMA; // Calculation Method +// input ENUM_APPLIED_PRICE xCHMAScAppliedTo = PRICE_CLOSE; // Applied To +// input group "XCHMA SC Style"; +// input int xCHMAScDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHMAScDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHMAScDrawStyle = STYLE_SOLID; // Draw Style +// input color xCHMAScFastColor = clrLightBlue; // Fast Color +// input color xCHMAScSlowColor = clrLightSalmon; // Slow Color +// input group "XCHMA SC Drawings"; +// input bool xCHMAScDrawFast = true; // Draw Fast +// input bool xCHMAScDrawSlow = true; // Draw Slow +// input bool xCHMAScDrawCrosses = false; // Draw Cross Lines + +// +// Configurations ... +// +// Commons ... +bool xCHMADrawHotAreas = false; // Draw Hot Areas Symbol; +uchar xCHMAHotBullishArrowCode = 228; // Hot Bullish Arrow Code; +color xCHMAHotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color; +uchar xCHMAHotBearishArrowCode = 230; // Hot Bearish Arrow Code; +color xCHMAHotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color; + +// +// LC Inputs ... +int xCHMALcFastLength = 288; // Fast Length +int xCHMALcSlowLength = 576; // Slow Length +ENUM_MA_METHOD xCHMALcMethod = MODE_EMA; // Calculation Method +ENUM_APPLIED_PRICE xCHMALcAppliedTo = PRICE_CLOSE; // Applied To +int xCHMALcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHMALcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHMALcDrawStyle = STYLE_DOT; // Draw Style +color xCHMALcFastColor = clrAqua; // Fast Color +color xCHMALcSlowColor = clrFuchsia; // Slow Color +bool xCHMALcDrawFast = true; // Draw Fast +bool xCHMALcDrawSlow = true; // Draw Slow +bool xCHMALcDrawCrosses = false; // Draw Cross Lines + +// +// MC Inputs ... +int xCHMAMcFastLength = 72; // Fast Length +int xCHMAMcSlowLength = 144; // Slow Length +ENUM_MA_METHOD xCHMAMcMethod = MODE_EMA; // Calculation Method +ENUM_APPLIED_PRICE xCHMAMcAppliedTo = PRICE_CLOSE; // Applied To +int xCHMAMcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHMAMcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHMAMcDrawStyle = STYLE_DOT; // Draw Style +color xCHMAMcFastColor = clrLime; // Fast Color +color xCHMAMcSlowColor = clrRed; // Slow Color +bool xCHMAMcDrawFast = true; // Draw Fast +bool xCHMAMcDrawSlow = true; // Draw Slow +bool xCHMAMcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +int xCHMAScFastLength = 7; // Fast Length +int xCHMAScSlowLength = 14; // Slow Length +ENUM_MA_METHOD xCHMAScMethod = MODE_SMA; // Calculation Method +ENUM_APPLIED_PRICE xCHMAScAppliedTo = PRICE_CLOSE; // Applied To +int xCHMAScDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHMAScDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHMAScDrawStyle = STYLE_SOLID; // Draw Style +color xCHMAScFastColor = clrLightBlue; // Fast Color +color xCHMAScSlowColor = clrLightSalmon; // Slow Color +bool xCHMAScDrawFast = true; // Draw Fast +bool xCHMAScDrawSlow = true; // Draw Slow +bool xCHMAScDrawCrosses = false; // Draw Cross Lines + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xCHMAHandler = INVALID_HANDLE; +double xCHMALcFastBuffer[]; +double xCHMALcSlowBuffer[]; +double xCHMAMcFastBuffer[]; +double xCHMAMcSlowBuffer[]; +double xCHMAScFastBuffer[]; +double xCHMAScSlowBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XCHMAValidateInputs() +{ + // + bool result = false; + + // + result = + xCHMAScFastLength >= 2 && + xCHMAScSlowLength > xCHMAScFastLength && + xCHMAMcFastLength > xCHMAScSlowLength && + xCHMAMcSlowLength > xCHMAMcFastLength && + xCHMALcFastLength > xCHMAMcSlowLength && + xCHMALcSlowLength > xCHMALcFastLength; + + // + if (!result) + { + // + LogMessage("XCHMA Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XCHMAInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XCHMA Handler ... + ArraySetAsSeries(xCHMALcFastBuffer, true); + ArraySetAsSeries(xCHMALcSlowBuffer, true); + ArraySetAsSeries(xCHMAMcFastBuffer, true); + ArraySetAsSeries(xCHMAMcSlowBuffer, true); + ArraySetAsSeries(xCHMAScFastBuffer, true); + ArraySetAsSeries(xCHMAScSlowBuffer, true); + xCHMAHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xchma.oscillator", + // + // Inputs ... + "", + xCHMADrawHotAreas, + xCHMAHotBullishArrowCode, + xCHMAHotBullishArrowColor, + xCHMAHotBearishArrowCode, + xCHMAHotBearishArrowColor, + // + // Long Cycle ... + "", + "", + xCHMALcFastLength, + xCHMALcSlowLength, + xCHMALcMethod, + xCHMALcAppliedTo, + "", + xCHMALcDrawWidth, + xCHMALcDrawType, + xCHMALcDrawStyle, + xCHMALcFastColor, + xCHMALcSlowColor, + "", + xCHMALcDrawFast, + xCHMALcDrawSlow, + xCHMALcDrawCrosses, + // + // Medium Cycle ... + "", + "", + xCHMAMcFastLength, + xCHMAMcSlowLength, + xCHMAMcMethod, + xCHMAMcAppliedTo, + "", + xCHMAMcDrawWidth, + xCHMAMcDrawType, + xCHMAMcDrawStyle, + xCHMAMcFastColor, + xCHMAMcSlowColor, + "", + xCHMAMcDrawFast, + xCHMAMcDrawSlow, + xCHMAMcDrawCrosses, + // + // Short Cycle ... + "", + "", + xCHMAScFastLength, + xCHMAScSlowLength, + xCHMAScMethod, + xCHMAScAppliedTo, + "", + xCHMAScDrawWidth, + xCHMAScDrawType, + xCHMAScDrawStyle, + xCHMAScFastColor, + xCHMAScSlowColor, + "", + xCHMAScDrawFast, + xCHMAScDrawSlow, + xCHMAScDrawCrosses); + if (xCHMAHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XCHMA Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XCHMAReleaseHandlers() +{ + IndicatorRelease(xCHMAHandler); +} + +// +// Handle Reading Buffers ... +void XCHMAReadBuffers( + int xCHMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XCHMA Long Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_LC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMALcFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_LC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMALcSlowBuffer); + + // + // XCHMA Medium Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_MC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMAMcFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_MC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMAMcSlowBuffer); + + // + // XCHMA Short Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_SC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMAScFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_SC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMAScSlowBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XCHMA Custom Functions ... +// + +// +// Retrieve Max Cycles Value ... +double XCHMAGetMax( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if (!XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // SC Fast ... + result = MathMax( + result, + xCHMAScFastBuffer[bar_index]); + + // + // SC Slow ... + result = MathMax( + result, + xCHMAScSlowBuffer[bar_index]); + + // + // MC Fast ... + result = MathMax( + result, + xCHMAMcFastBuffer[bar_index]); + + // + // MC Slow ... + result = MathMax( + result, + xCHMAMcSlowBuffer[bar_index]); + + // + // LC Fast ... + result = MathMax( + result, + xCHMALcFastBuffer[bar_index]); + + // + // LC Slow ... + result = MathMax( + result, + xCHMALcSlowBuffer[bar_index]); + + // + return result; +} + +// +// Retrieve Max Cycles Value ... +double XCHMAGetMin( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if (!XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = xCHMAScFastBuffer[bar_index]; + + // + // SC Fast ... + result = MathMin( + result, + xCHMAScFastBuffer[bar_index]); + + // + // SC Slow ... + result = MathMin( + result, + xCHMAScSlowBuffer[bar_index]); + + // + // MC Fast ... + result = MathMin( + result, + xCHMAMcFastBuffer[bar_index]); + + // + // MC Slow ... + result = MathMin( + result, + xCHMAMcSlowBuffer[bar_index]); + + // + // LC Fast ... + result = MathMin( + result, + xCHMALcFastBuffer[bar_index]); + + // + // LC Slow ... + result = MathMin( + result, + xCHMALcSlowBuffer[bar_index]); + + // + return result; +} + +// +// Short Cycle Over Max Of Cycle Channels ... +bool XCHMAIsSCOverMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 > nonOfShortCycleMax1 + // + ; + + // + return result; +} + +// +// Short Cycle Under Max Of Cycle Channels ... +bool XCHMAIsSCUnderMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 < nonOfShortCycleMax1 + // + ; + + // + return result; +} + +// +// Short Cycle Over Min Of Cycle Channels ... +bool XCHMAIsSCOverMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 > nonOfShortCycleMin1 + // + ; + + // + return result; +} + +// +// Short Cycle Under Min Of Cycle Channels ... +bool XCHMAIsSCUnderMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 < nonOfShortCycleMin1 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Over Max Of Cycle Channels ... +bool XCHMAIsSCCrossedOverMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMin2 = XCHMAGetCycleMinValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + double nonOfShortCycleMax2 = XCHMAGetCyclesMaxValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 > nonOfShortCycleMax1 && + shortCycleMin2 <= nonOfShortCycleMax2 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Under Max Of Cycle Channels ... +bool XCHMAIsSCCrossedUnderMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMax2 = XCHMAGetCycleMaxValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + double nonOfShortCycleMax2 = XCHMAGetCyclesMaxValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 < nonOfShortCycleMax1 && + shortCycleMax2 >= nonOfShortCycleMax2 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Over Min Of Cycle Channels ... +bool XCHMAIsSCCrossedOverMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMin2 = XCHMAGetCycleMinValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + double nonOfShortCycleMin2 = XCHMAGetCyclesMinValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 > nonOfShortCycleMin1 && + shortCycleMin2 <= nonOfShortCycleMin2 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Under Min Of Cycle Channels ... +bool XCHMAIsSCCrossedUnderMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMax2 = XCHMAGetCycleMaxValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + double nonOfShortCycleMin2 = XCHMAGetCyclesMinValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 < nonOfShortCycleMin1 && + shortCycleMax2 >= nonOfShortCycleMin2 + // + ; + + // + return result; +} + +// +// Long Cycle ... +// + +// +// Check LC is Peak ... +bool XCHMAIsLCPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xCHMALcSlowBuffer + // + ); + + // + return result; +} + +// +// Check LC is Vale ... +bool XCHMAIsLCVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xCHMALcSlowBuffer + // + ); + + // + return result; +} + +// +// Check LC Fast Crossed Over Slow ... +bool XCHMAIsLCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Over Slow ... +bool XCHMAIsLCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Crossed Under Slow ... +bool XCHMAIsLCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Under Slow ... +bool XCHMAIsLCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Get Trend Power ... +double XCHMAGetLCTrendPower( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + MathAbs(xCHMALcFastBuffer[bar_index] - xCHMALcSlowBuffer[bar_index]) + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsLCTrendsUp( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetLCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetLCTrendPower(i + 1); + double iTrend = XCHMAGetLCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsUpCount > trendsDownCount + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsLCTrendsDown( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetLCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetLCTrendPower(i + 1); + double iTrend = XCHMAGetLCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsDownCount > trendsUpCount + // + ; + + // + return result; +} + +// +// Medium Cycle ... +// + +// +// Check MC is Peak ... +bool XCHMAIsMCPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xCHMAMcSlowBuffer + // + ); + + // + return result; +} + +// +// Check MC is Vale ... +bool XCHMAIsMCVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xCHMAMcSlowBuffer + // + ); + + // + return result; +} + +// +// Check MC Fast Crossed Over Slow ... +bool XCHMAIsMCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Over Slow ... +bool XCHMAIsMCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Crossed Under Slow ... +bool XCHMAIsMCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Under Slow ... +bool XCHMAIsMCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Get Trend Power ... +double XCHMAGetMCTrendPower( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + MathAbs(xCHMAMcFastBuffer[bar_index] - xCHMAMcSlowBuffer[bar_index]) + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsMCTrendsUp( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetMCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetMCTrendPower(i + 1); + double iTrend = XCHMAGetMCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsUpCount > trendsDownCount + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsMCTrendsDown( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetMCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetMCTrendPower(i + 1); + double iTrend = XCHMAGetMCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsDownCount > trendsUpCount + // + ; + + // + return result; +} + +// +// Short Cycle ... +// + +// +// Check SC is Peak ... +bool XCHMAIsSCPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xCHMAScSlowBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XCHMAIsSCVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xCHMAScSlowBuffer + // + ); + + // + return result; +} + +// +// Check SC Fast Crossed Over Slow ... +bool XCHMAIsSCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Over Slow ... +bool XCHMAIsSCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Crossed Under Slow ... +bool XCHMAIsSCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Under Slow ... +bool XCHMAIsSCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Get SC Trend Power ... +double XCHMAGetSCTrendPower( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + MathAbs(xCHMAScFastBuffer[bar_index] - xCHMAScSlowBuffer[bar_index]) + // + ; + + // + return result; +} + +// +// Check SC Trends Up ... +bool XCHMAIsSCTrendsUp( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetSCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetSCTrendPower(i + 1); + double iTrend = XCHMAGetSCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsUpCount > trendsDownCount + // + ; + + // + return result; +} + +// +// Check SC Trends Down ... +bool XCHMAIsSCTrendsDown( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetSCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetSCTrendPower(i + 1); + double iTrend = XCHMAGetSCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsDownCount > trendsUpCount + // + ; + + // + return result; +} + +// +// Utility Functions ... +// + +// +// Check a Cycle is Over of Another ... +bool XCHMAIsCycleOverAnother( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES sourceCycle, // Specified Cycle ... + ENUM_XCHMA_CYCLES destCycle // Specified Cycle ... +) +{ + // + bool result = false; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceMinValue = XCHMAGetCycleMinValue(bar_index, sourceCycle); + double destMaxValue = XCHMAGetCycleMaxValue(bar_index, destCycle); + + // + result = + // + sourceMinValue > destMaxValue + // + ; + + // + return result; +} + +// +// Check a Cycle is Under of Another ... +bool XCHMAIsCycleUnderAnother( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES sourceCycle, // Specified Cycle ... + ENUM_XCHMA_CYCLES destCycle // Specified Cycle ... +) +{ + // + bool result = false; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceMaxValue = XCHMAGetCycleMaxValue(bar_index, sourceCycle); + double destMinValue = XCHMAGetCycleMinValue(bar_index, destCycle); + + // + result = + // + sourceMaxValue < destMinValue + // + ; + + // + return result; +} + +// +// Get Cycle Min Value ... +double XCHMAGetCycleMinValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + result = MathMin( + xCHMALcFastBuffer[bar_index], + xCHMALcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + result = MathMin( + xCHMAMcFastBuffer[bar_index], + xCHMAMcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_SHORT: + result = MathMin( + xCHMAScFastBuffer[bar_index], + xCHMAScSlowBuffer[bar_index]); + break; + } + + // + return result; +} + +// +// Get Cycles Min Value ... +double XCHMAGetCyclesMinValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES &cycle[] // Specified Cycles ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + // + bar_index <= 0 || + ArraySize(cycle) <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1) + // + ) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycle); i++) + { + // + ENUM_XCHMA_CYCLES iCycle = cycle[i]; + double iValue = XCHMAGetCycleMinValue( + bar_index, + iCycle); + + // + result = result == 0 || result > iValue ? iValue : result; + } + + // + return result; +} + +// +// Get Cycle Max Value ... +double XCHMAGetCycleMaxValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + result = MathMax( + xCHMALcFastBuffer[bar_index], + xCHMALcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + result = MathMax( + xCHMAMcFastBuffer[bar_index], + xCHMAMcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_SHORT: + result = MathMax( + xCHMAScFastBuffer[bar_index], + xCHMAScSlowBuffer[bar_index]); + break; + } + + // + return result; +} + +// +// Get Cycles Max Value ... +double XCHMAGetCyclesMaxValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES &cycle[] // Specified Cycles ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + // + bar_index <= 0 || + ArraySize(cycle) <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1) + // + ) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycle); i++) + { + // + ENUM_XCHMA_CYCLES iCycle = cycle[i]; + double iValue = XCHMAGetCycleMaxValue( + bar_index, + iCycle); + + // + result = result == 0 || result < iValue ? iValue : result; + } + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XCHMAIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xCHMALcFastBuffer) < size || + ArraySize(xCHMALcSlowBuffer) < size || + // + ArraySize(xCHMAMcFastBuffer) < size || + ArraySize(xCHMAMcSlowBuffer) < size || + // + ArraySize(xCHMAScFastBuffer) < size || + ArraySize(xCHMAScSlowBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Add Specified Object to it's correspond Buffer ... +void Add( + ENUM_XCHMA_CYCLES item, + ENUM_XCHMA_CYCLES &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// END XCHMA Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..19d3417 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 @@ -0,0 +1,358 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XFI Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XFI Oscillator"; + +// // +// input int xFILength = 18; // Market Length +// input ENUM_MA_METHOD xFIMethod = MODE_SMA; // MA Method +// input ENUM_APPLIED_VOLUME xFIAppliedTo = VOLUME_TICK; // Applied To + +// +// Configurations ... +int xFILength = 18; // Market Length +ENUM_MA_METHOD xFIMethod = MODE_SMA; // MA Method +ENUM_APPLIED_VOLUME xFIAppliedTo = VOLUME_TICK; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xFIHandler = INVALID_HANDLE; +double xFIBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XFIValidateInputs() +{ + // + bool result = false; + + // + result = xFILength > 2; + + // + if (!result) + { + // + LogMessage("XFI Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XFIInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XFI Handler ... + ArraySetAsSeries(xFIBuffer, true); + xFIHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xfi.oscillator", + // + // Inputs ... + xFILength, + xFIMethod, + xFIAppliedTo + // + ); + if (xFIHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XFI Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XFIReleaseHandlers() +{ + IndicatorRelease(xFIHandler); +} + +// +// Handle Reading Buffers ... +void XFIReadBuffers( + int xFIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XFI Signal ... + CopyBuffer( + xFIHandler, + 0, + 0, + xFIItemsPerTick, + xFIBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XFI Custom Functions ... +// + +// +// Check SC is Peak ... +bool XFIIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XFIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xFIBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XFIIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XFIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xFIBuffer + // + ); + + // + return result; +} + +// +// Detect XFI Crossed Over Zero ... +bool XFIIsCrossedOverZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] > 0 && + xFIBuffer[bar_index + 1] <= 0; + + // + return result; +} + +// +// Detect XFI Over Zero ... +bool XFIIsOverZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] > 0; + + // + return result; +} + +// +// Detect XFI Crossed Under Zero ... +bool XFIIsCrossedUnderZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] < 0 && + xFIBuffer[bar_index + 1] >= 0; + + // + return result; +} + +// +// Detect XFI Under Zero ... +bool XFIIsUnderZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] < 0; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XFIIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xFIBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XFI Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 0000000..e6a92f6 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 @@ -0,0 +1,668 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XLH 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XLH Indicator Buffer Lines ... +enum ENUM_X_XLH_BUFFER_LINES +{ + X_XLH_HH_LINE = 0, + X_XLH_LL_LINE = 1, + X_XLH_SIGNAL_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XLH Indicator"; + +// input int xLHLength = 72; // Length +// input ENUM_SERIESMODE xLHHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xLHLLMode = MODE_LOW; // Lowest Low Calculation Method + +// +// Configurations ... +int xLHLength = 72; // Length +ENUM_SERIESMODE xLHHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xLHLLMode = MODE_LOW; // Lowest Low Calculation Method + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +// +int xLHHandler = INVALID_HANDLE; + +// +double xLHHHBuffer[]; +double xLHLLBuffer[]; +double xLHSignalBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XLHValidateInputs() +{ + // + bool result = false; + + // + result = xLHLength >= 2; + + // + if (!result) + { + // + LogMessage("XLH Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XLHInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XLH Handler ... + ArraySetAsSeries(xLHHHBuffer, true); + ArraySetAsSeries(xLHLLBuffer, true); + ArraySetAsSeries(xLHSignalBuffer, true); + + // + xLHHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xlh.indicator", + // + // Inputs ... + xLHLength, + xLHHHMode, + xLHLLMode + // + ); + if (xLHHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XLH Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XLHReleaseHandlers() +{ + IndicatorRelease(xLHHandler); +} + +// +// Handle Reading Buffers ... +void XLHReadBuffers( + int xLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // HH Buffer ... + CopyBuffer( + xLHHandler, + X_XLH_HH_LINE, + 0, + xLHItemsPerTick, + xLHHHBuffer + // + ); + + // + // LL Buffer ... + CopyBuffer( + xLHHandler, + X_XLH_LL_LINE, + 0, + xLHItemsPerTick, + xLHLLBuffer + // + ); + + // + // Signal Buffer ... + CopyBuffer( + xLHHandler, + X_XLH_SIGNAL_LINE, + 0, + xLHItemsPerTick, + xLHSignalBuffer + // + ); +} + +// +// END Handler Funcions ... +// + +// +// START XLH Custom Functions ... +// + +// +// TODO: What we have to Implement ... +// - [] + +// +// Check Candle High is HH ... +bool XLHIsHighAttachedHH( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle = GetCandle(bar_index); + + // + result = + // + candle.high == xLHHHBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Candle Low is LL ... +bool XLHIsLowAttachedLL( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle = GetCandle(bar_index); + + // + result = + // + candle.low == xLHLLBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Price Jumping Up Signal ... +bool XLHIsPriceCrossedOverSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + XOHCL candle2 = GetCandle(bar_index + 1); + + // + result = + // + candle1.low > xLHSignalBuffer[bar_index] && + candle2.low < xLHSignalBuffer[bar_index + 1] + // + ; + + // + return result; +} + +// +// Check Price Over Signal ... +bool XLHIsPriceOverSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + + // + result = + // + candle1.low > xLHSignalBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Price Jumping Down Signal ... +bool XLHIsPriceCrossedUnderSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + XOHCL candle2 = GetCandle(bar_index + 1); + + // + result = + // + candle1.high < xLHSignalBuffer[bar_index] && + candle2.high > xLHSignalBuffer[bar_index + 1] + // + ; + + // + return result; +} + +// +// Check Price Down Signal ... +bool XLHIsPriceUnderSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + + // + result = + // + candle1.high < xLHSignalBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Price Ranging Signal ... +bool XLHIsPriceInSignalRange( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + + // + result = + // + candle1.high > xLHSignalBuffer[bar_index] && + candle1.low < xLHSignalBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check HH Increased ... +bool XLHIsHHIncreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xLHHHBuffer + // + ); + + // + return result; +} + +// +// Check HH Decreased ... +bool XLHIsHHDecreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xLHHHBuffer + // + ); + + // + return result; +} + +// +// Check LL Increased ... +bool XLHIsLLIncreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xLHLLBuffer + // + ); + + // + return result; +} + +// +// Check LL Decreased ... +bool XLHIsLLDecreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xLHLLBuffer + // + ); + + // + return result; +} + +// +// Check HH Same in Length ... +bool XLHIsHHSameInLength( + int bar_index, // Specified Index ... + int length = 5 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + double value1 = xLHHHBuffer[bar_index]; + + // + // Loop ... + result = true; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iValue = xLHHHBuffer[i]; + if (iValue != value1) + { + // + result = false; + + // + break; + } + } + + // + return result; +} + +// +// Check LL Same in Length ... +bool XLHIsLLSameInLength( + int bar_index, // Specified Index ... + int length = 5 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + double value1 = xLHLLBuffer[bar_index]; + + // + // Loop ... + result = true; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iValue = xLHLLBuffer[i]; + if (iValue != value1) + { + // + result = false; + + // + break; + } + } + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XLHIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xLHHHBuffer) < size || + ArraySize(xLHLLBuffer) < size || + ArraySize(xLHSignalBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XLH Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 0000000..f90f15b --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 @@ -0,0 +1,249 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XOBD 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XOBD Indicator"; + +// input int xOBDLength = 5; // Swing Length +// input uchar xOBDSwingHighArrowCode = 108; // Swing High Arrow Code +// input color xOBDSwingHighArrowColor = clrMagenta; // Swing High Arrow Color +// input uchar xOBDSwingLowArrowCode = 108; // Swing Low Arrow Code +// input color xOBDSwingLowArrowColor = clrAqua; // Swing Low Arrow Color + +// +// Configurations ... +int xOBDLength = 5; // Swing Length +uchar xOBDSwingHighArrowCode = 108; // Swing High Arrow Code +color xOBDSwingHighArrowColor = clrMagenta; // Swing High Arrow Color +uchar xOBDSwingLowArrowCode = 108; // Swing Low Arrow Code +color xOBDSwingLowArrowColor = clrAqua; // Swing Low Arrow Color + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +// +int xOBDHandler = INVALID_HANDLE; + +// +double xOBDBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XOBDValidateInputs() +{ + // + bool result = false; + + // + result = xOBDLength >= 2; + + // + if (!result) + { + // + LogMessage("XOBD Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XOBDInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XOBD Handler ... + ArraySetAsSeries(xOBDBuffer, true); + + // + xOBDHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xobd.indicator", + // + // Inputs ... + xOBDLength, + xOBDSwingHighArrowCode, + xOBDSwingHighArrowColor, + xOBDSwingLowArrowCode, + xOBDSwingLowArrowColor + // + ); + if (xOBDHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XOBD Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XOBDReleaseHandlers() +{ + IndicatorRelease(xOBDHandler); +} + +// +// Handle Reading Buffers ... +void XOBDReadBuffers( + int xOBDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // OBD Buffer ... + CopyBuffer( + xOBDHandler, + 0, + 0, + xOBDItemsPerTick, + xOBDBuffer + // + ); +} + +// +// END Handler Funcions ... +// + +// +// START XOBD Custom Functions ... +// + +// +// Check is Swing Low Occured or not ... +bool XOBDIsSwingLow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = xOBDBuffer[bar_index] == X_SWING_LOW; + + // + return result; +} + +// +// Check is Swing High Occured or not ... +bool XOBDIsSwingHigh( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = xOBDBuffer[bar_index] == X_SWING_HIGH; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XOBDIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xOBDBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XOBD Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..e6971b7 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 @@ -0,0 +1,433 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XRSI Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XRSI Oscillator Buffer Lines ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XRSI Oscillator"; + +// // +// input group "XRSI Market"; +// input int xRSILength = 18; // Market Length +// input ENUM_APPLIED_PRICE xRSIAppliedTo = PRICE_OPEN; // Applied To + +// // +// input group "XRSI Short Entry"; +// input double xRSIShortEntryValue = 70; // Short Entry Level +// input color xRSIShortEntryColor = clrRed; // Short Entry Level Color +// input ENUM_LINE_STYLE xRSIShortEntryLineStyle = STYLE_SOLID; // Short Entry Style + +// // +// input group "XRSI Short Exit"; +// input double xRSIShortExitValue = 40; // Short Exit Level +// input color xRSIShortExitColor = clrRed; // Short Exit Level Color +// input ENUM_LINE_STYLE xRSIShortExitLineStyle = STYLE_DOT; // Short Exit Style + +// // +// input group "XRSI Long Entry"; +// input double xRSILongEntryValue = 30; // Long Entry Level +// input color xRSILongEntryColor = clrRed; // Long Entry Level Color +// input ENUM_LINE_STYLE xRSILongEntryLineStyle = STYLE_SOLID; // Long Entry Style + +// // +// input group "XRSI Long Exit"; +// input double xRSILongExitValue = 60; // Long Exit Level +// input color xRSILongExitColor = clrRed; // Long Exit Level Color +// input ENUM_LINE_STYLE xRSILongExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// Configurations ... +int xRSILength = 18; // Market Length +ENUM_APPLIED_PRICE xRSIAppliedTo = PRICE_OPEN; // Applied To + +// +double xRSIShortEntryValue = 70; // Short Entry Level +color xRSIShortEntryColor = clrRed; // Short Entry Level Color +ENUM_LINE_STYLE xRSIShortEntryLineStyle = STYLE_SOLID; // Short Entry Style + +// +double xRSIShortExitValue = 40; // Short Exit Level +color xRSIShortExitColor = clrRed; // Short Exit Level Color +ENUM_LINE_STYLE xRSIShortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +double xRSILongEntryValue = 30; // Long Entry Level +color xRSILongEntryColor = clrRed; // Long Entry Level Color +ENUM_LINE_STYLE xRSILongEntryLineStyle = STYLE_SOLID; // Long Entry Style + +// +double xRSILongExitValue = 60; // Long Exit Level +color xRSILongExitColor = clrRed; // Long Exit Level Color +ENUM_LINE_STYLE xRSILongExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xRSIHandler = INVALID_HANDLE; +double xRSIBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XRSIValidateInputs() +{ + // + bool result = false; + + // + result = + xRSILongEntryValue < xRSILongExitValue && + xRSIShortEntryValue > xRSIShortExitValue && + xRSIShortEntryValue > xRSILongExitValue && + xRSIShortExitValue < xRSILongExitValue; + + // + if (!result) + { + // + LogMessage("XRSI Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XRSIInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XRSI Handler ... + ArraySetAsSeries(xRSIBuffer, true); + xRSIHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xrsi.oscillator", + // + // Inputs ... + // + // Market ... + "", + xRSILength, + xRSIAppliedTo, + // + // Short Entry ... + "", + xRSIShortEntryValue, + xRSIShortEntryColor, + xRSIShortEntryLineStyle, + // + // Short Exit ... + "", + xRSIShortExitValue, + xRSIShortExitColor, + xRSIShortExitLineStyle, + // + // Long Entry ... + "", + xRSILongEntryValue, + xRSILongEntryColor, + xRSILongEntryLineStyle, + // + // Long Exit ... + "", + xRSILongExitValue, + xRSILongExitColor, + xRSILongExitLineStyle + // + ); + if (xRSIHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XRSI Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XRSIReleaseHandlers() +{ + IndicatorRelease(xRSIHandler); +} + +// +// Handle Reading Buffers ... +void XRSIReadBuffers( + int xRSIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XRSI Signal ... + CopyBuffer( + xRSIHandler, + 0, + 0, + xRSIItemsPerTick, + xRSIBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XRSI Custom Functions ... +// + +// +// Check SC is Peak ... +bool XRSIIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xRSIBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XRSIIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xRSIBuffer + // + ); + + // + return result; +} + +// +// RSI Value GO Up from Long Entry ... +bool XRSIIsCrossedOverLongEntry( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] > xRSILongEntryValue && + xRSIBuffer[bar_index + 2] <= xRSILongEntryValue; + + // + return result; +} + +// +// RSI Value GO Up from Long Exit ... +bool XRSIIsCrossedOverLongExit( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] > xRSILongExitValue && + xRSIBuffer[bar_index + 2] <= xRSILongExitValue; + + // + return result; +} + +// +// RSI Value Go Down Short Entry ... +bool XRSIIsCrossedUnderShortEntry( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] < xRSIShortEntryValue && + xRSIBuffer[bar_index + 2] >= xRSIShortEntryValue; + + // + return result; +} + +// +// RSI Value Go Down Short Exit ... +bool XRSIIsCrossedUnderShortExit( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] < xRSIShortExitValue && + xRSIBuffer[bar_index + 2] >= xRSIShortExitValue; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XRSIIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xRSIBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XRSI Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..6286228 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 @@ -0,0 +1,931 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTD Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; + +// +// XTD Oscillator Buffer Lines ... +enum ENUM_X_XTD_BUFFER_LINES +{ + X_XTD_BULLISH_POWER_LINE = 0, + X_XTD_BEARISH_POWER_LINE = 1, + X_XTD_SIGNAL_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XTD Oscillator"; + +// input int xTDLength = 18; // Market Length +// input bool xTDDrawCrosses = false; // Draw Cross Arrows +// input uchar xTDBullishArrowCode = 228; // Cross Over Arrow Code +// input color xTDBullishArrowColor = clrAqua; // Cross Over Arrow Color +// input uchar xTDBearishArrowCode = 230; // Cross Under Arrow Code +// input color xTDBearishArrowColor = clrMagenta; // Cross Under Arrow Color + +// +// Configurations ... +int xTDLength = 18; // Market Length +bool xTDDrawCrosses = false; // Draw Cross Arrows +uchar xTDBullishArrowCode = 228; // Cross Over Arrow Code +color xTDBullishArrowColor = clrAqua; // Cross Over Arrow Color +uchar xTDBearishArrowCode = 230; // Cross Under Arrow Code +color xTDBearishArrowColor = clrMagenta; // Cross Under Arrow Color + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTDHandler = INVALID_HANDLE; +double xTDBullishBuffer[]; +double xTDBearishBuffer[]; +double xTDSignalBuffer[]; +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XTDValidateInputs() +{ + // + bool result = false; + + // + result = xTDLength >= 2; + + // + if (!result) + { + // + LogMessage("XTD Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XTDInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTD Handler ... + ArraySetAsSeries(xTDBullishBuffer, true); + ArraySetAsSeries(xTDBearishBuffer, true); + ArraySetAsSeries(xTDSignalBuffer, true); + xTDHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xtd.oscillator", + // + // Inputs ... + xTDLength, + xTDDrawCrosses, + xTDBullishArrowCode, + xTDBullishArrowColor, + xTDBearishArrowCode, + xTDBearishArrowColor); + if (xTDHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTD Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XTDReleaseHandlers() +{ + IndicatorRelease(xTDHandler); +} + +// +// Handle Reading Buffers ... +void XTDReadBuffers( + int xTDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XTD Bullish Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_BULLISH_POWER_LINE, + 0, + xTDItemsPerTick, + xTDBullishBuffer); + + // + // XTD Bullish Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_BEARISH_POWER_LINE, + 0, + xTDItemsPerTick, + xTDBearishBuffer); + + // + // XTD Signal Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_SIGNAL_LINE, + 0, + xTDItemsPerTick, + xTDSignalBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XTD Custom Functions ... +// + +// +// Check Signal Vale ... +bool XTDIsSignalVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTDSignalBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsSignalPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTDSignalBuffer + // + ); + + // + return result; +} + +// +// Check Signal Vale ... +bool XTDIsBullishVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTDBullishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsBullishPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTDBullishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Vale ... +bool XTDIsBearishVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTDBearishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsBearishPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTDBearishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... + +// +// Check Bullish Crossed Over Bearish ... +bool XTDIsBullCrossedOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Over Bearish ... +bool XTDIsBullOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Crossed Under Bearish ... +bool XTDIsBullCrossedUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Under Bearish ... +bool XTDIsBullUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Crossed Over Bearish ... +bool XTDIsSignalCrossedOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Over Bearish ... +bool XTDIsSignalOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Crossed Under Bearish ... +bool XTDIsSignalCrossedUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Under Bearish ... +bool XTDIsSignalUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTDIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + ArraySize(xTDBullishBuffer) < size || + ArraySize(xTDBullishBuffer) < size || + ArraySize(xTDSignalBuffer) < size) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Count Signal Crossed Over Bear ... +int XTDCountSignalCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedOverBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Signal Crossed Under Bear ... +int XTDCountSignalCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedUnderBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Bull Crossed Over Bear ... +int XTDCountBullCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedOverBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Bull Crossed Under Bear ... +int XTDCountBullCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedUnderBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Find Last Signal Crossed Over Bear ... +int XTDFindLastSignalCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedOverBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Signal Crossed Onder Bear ... +int XTDFindLastSignalCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedUnderBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Bull Crossed Over Bear ... +int XTDFindLastBullCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedOverBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Bull Crossed Under Bear ... +int XTDFindLastBullCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedUnderBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// END XTD Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 0000000..a871ed4 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 @@ -0,0 +1,598 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTM 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 1, + X_XTM_BEARISH = -1, + X_XTM_NEUTURAL = 0, +}; + +// +// XTM Indicator Buffer Lines ... +enum ENUM_X_XTM_BUFFER_LINES +{ + X_XTM_MA_LINE = 0, + X_XTM_MC_COLOR_LINE = 1, + X_XTM_STATE_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XTM Indicator"; + +// input int xTMMaPeriod = 18; // Period +// input int xTMMaShift = 0; // Shift +// input ENUM_MA_METHOD xTMMaMethod = MODE_EMA; // Method +// input ENUM_APPLIED_PRICE xTMMaAppliedTo = PRICE_OPEN; // Applied To + +// +// Configurations ... +int xTMMaPeriod = 18; // Period +int xTMMaShift = 0; // Shift +ENUM_MA_METHOD xTMMaMethod = MODE_EMA; // Method +ENUM_APPLIED_PRICE xTMMaAppliedTo = PRICE_OPEN; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTMHandler = INVALID_HANDLE; +double xTMMaBuffer[]; +double xTMStateBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XTMValidateInputs() +{ + // + bool result = false; + + // + result = xTMMaPeriod >= 2; + + // + if (!result) + { + // + LogMessage("XTM Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XTMInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTM Handler ... + ArraySetAsSeries(xTMMaBuffer, true); + ArraySetAsSeries(xTMStateBuffer, true); + xTMHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xtm.indicator", + // + // Inputs ... + xTMMaPeriod, + xTMMaShift, + xTMMaMethod, + xTMMaAppliedTo); + if (xTMHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTM Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XTMReleaseHandlers() +{ + IndicatorRelease(xTMHandler); +} + +// +// Handle Reading Buffers ... +void XTMReadBuffers( + int xTMItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // Ma Buffer ... + CopyBuffer( + xTMHandler, + X_XTM_MA_LINE, + 0, + xTMItemsPerTick, + xTMMaBuffer); + + // + // State Buffer ... + CopyBuffer( + xTMHandler, + X_XTM_STATE_LINE, + 0, + xTMItemsPerTick, + xTMStateBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XTM Custom Functions ... +// + +// +// Find Peak based On this Indicator ... +bool XTMIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTMMaBuffer + // + ); + + // + return result; +} + +// +// Find Vale based On this Indicator ... +bool XTMIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTMMaBuffer + // + ); + + // + return result; +} + +// +// Check TM Crossed Up ... +bool XTMIsStartBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BULLISH && + xTMStateBuffer[bar_index + 1] != X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Up After Neutural State ... +bool XTMIsStartBullishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BULLISH && + xTMStateBuffer[bar_index + 1] == X_XTM_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Up State ... +bool XTMIsBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State ... +bool XTMIsEndBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] != X_XTM_BULLISH && + xTMStateBuffer[bar_index + 1] == X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State By Neutural ... +bool XTMIsEndBullishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_NEUTURAL && + xTMStateBuffer[bar_index + 1] == X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down ... +bool XTMIsStartBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BEARISH && + xTMStateBuffer[bar_index + 1] != X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down After Neutural State ... +bool XTMIsStartBearishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BEARISH && + xTMStateBuffer[bar_index + 1] == X_XTM_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Down State ... +bool XTMIsBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State ... +bool XTMIsEndBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] != X_XTM_BEARISH && + xTMStateBuffer[bar_index + 1] == X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State By Neutural ... +bool XTMIsEndBearishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_NEUTURAL && + xTMStateBuffer[bar_index + 1] == X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM In Neutural State ... +bool XTMIsNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_NEUTURAL + // + ; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTMIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xTMMaBuffer) < size || + ArraySize(xTMStateBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XTM Custom Functions ... +// diff --git a/XEU5-0/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/XEU5-0/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..875eec0 --- /dev/null +++ b/XEU5-0/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 @@ -0,0 +1,1179 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTS Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// Methods to Calculate TimeFrames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// Buffer Lines ... +enum ENUM_X_XTS_BUFFER_LINES +{ + X_XTS_CURRENT_LINE = 0, + X_XTS_NEAREST_LINE = 1, + X_XTS_MEDIEST_LINE = 2, + X_XTS_FAREST_LINE = 3, +}; + +// +// Periods ... +enum ENUM_X_XTS_PERIODS +{ + // + // Current Period ... + X_XTS_PERIOD_CURRENT, + // + // Nearest Period ... + X_XTS_PERIOD_NEAREST, + // + // Mediest Period ... + X_XTS_PERIOD_MEDIEST, + // + // Farest Period ... + X_XTS_PERIOD_FAREST, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// // +// input group "XTS Oscillator"; + +// // +// input group "XTS Current Period"; +// input ENUM_APPLIED_PRICE xTSCurrentAppliedTo = PRICE_CLOSE; // Current Applied To +// // +// input group "XTS Nearest Period"; +// input ENUM_X_PERIOD_METHOD xTSNearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +// input ENUM_TIMEFRAMES xTSNearestPeriod = NULL; // Nearest Time Frame +// input ENUM_APPLIED_PRICE xTSNearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// // +// input group "XTS Mediest Period"; +// input ENUM_X_PERIOD_METHOD xTSMediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +// input ENUM_TIMEFRAMES xTSMediestPeriod = NULL; // Mediest Time Frame +// input ENUM_APPLIED_PRICE xTSMediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// // +// input group "XTS Farest Period"; +// input ENUM_X_PERIOD_METHOD xTSFarestMethod = X_PERIOD_AUTO; // How to Find Farest Period +// input ENUM_TIMEFRAMES xTSFarestPeriod = NULL; // Farest Time Frame +// input ENUM_APPLIED_PRICE xTSFarestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// Configurations ... +ENUM_APPLIED_PRICE xTSCurrentAppliedTo = PRICE_CLOSE; // Current Applied To +// +ENUM_X_PERIOD_METHOD xTSNearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +ENUM_TIMEFRAMES xTSNearestPeriod = NULL; // Nearest Time Frame +ENUM_APPLIED_PRICE xTSNearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// +ENUM_X_PERIOD_METHOD xTSMediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +ENUM_TIMEFRAMES xTSMediestPeriod = NULL; // Mediest Time Frame +ENUM_APPLIED_PRICE xTSMediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// +ENUM_X_PERIOD_METHOD xTSFarestMethod = X_PERIOD_AUTO; // How to Find Farest Period +ENUM_TIMEFRAMES xTSFarestPeriod = NULL; // Farest Time Frame +ENUM_APPLIED_PRICE xTSFarestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTSHandler = INVALID_HANDLE; +double xTSCurrentBuffer[]; +double xTSNearestBuffer[]; +double xTSMediestBuffer[]; +double xTSFarestBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XTSValidateInputs() +{ + // + bool result = false; + + // + result = true; + + // + if (!result) + { + // + LogMessage("XTS Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XTSInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTS Handler ... + ArraySetAsSeries(xTSCurrentBuffer, true); + ArraySetAsSeries(xTSNearestBuffer, true); + ArraySetAsSeries(xTSMediestBuffer, true); + ArraySetAsSeries(xTSFarestBuffer, true); + xTSHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xts.oscillator", + // + // Inputs ... + "", + xTSCurrentAppliedTo, + "", + xTSNearestMethod, + xTSNearestPeriod, + xTSNearestAppliedTo, + "", + xTSMediestMethod, + xTSMediestPeriod, + xTSMediestAppliedTo, + "", + xTSFarestMethod, + xTSFarestPeriod, + xTSFarestAppliedTo + // + ); + if (xTSHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTS Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XTSReleaseHandlers() +{ + IndicatorRelease(xTSHandler); +} + +// +// Handle Reading Buffers ... +void XTSReadBuffers( + int xTSItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XTS Current ... + CopyBuffer( + xTSHandler, + X_XTS_CURRENT_LINE, + 0, + xTSItemsPerTick, + xTSCurrentBuffer); + + // + // XTS Nearest ... + CopyBuffer( + xTSHandler, + X_XTS_NEAREST_LINE, + 0, + xTSItemsPerTick, + xTSNearestBuffer); + + // + // XTS Mediest ... + CopyBuffer( + xTSHandler, + X_XTS_MEDIEST_LINE, + 0, + xTSItemsPerTick, + xTSMediestBuffer); + + // + // XTS Farest ... + CopyBuffer( + xTSHandler, + X_XTS_FAREST_LINE, + 0, + xTSItemsPerTick, + xTSFarestBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XTS Custom Functions ... +// + +// +// Calculate Min Value ... +double XTSGetMinValue( + int bar_index // Specified Index ... +) +{ + // + ENUM_X_XTS_PERIODS periods[]; + XTSGetAllPeriodsEnum(periods); + + // + double result = XTSGetPeriodsMinValue( + periods, + bar_index); + + // + return result; +} + +// +// Calculate Max Value ... +double XTSGetMaxValue( + int bar_index // Specified Index ... +) +{ + // + ENUM_X_XTS_PERIODS periods[]; + XTSGetAllPeriodsEnum(periods); + + // + double result = XTSGetPeriodsMaxValue( + periods, + bar_index); + + // + return result; +} + +// +// Check if all Periods Values are Same ... +bool XTSIsAllSame( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + xTSCurrentBuffer[bar_index] == xTSNearestBuffer[bar_index] && + xTSNearestBuffer[bar_index] == xTSMediestBuffer[bar_index] && + xTSMediestBuffer[bar_index] == xTSFarestBuffer[bar_index]; + + // + return result; +} + +// +// Current ... + +// +// Check Current Buffer is Min Or Not ... +bool XTSIsCurrentMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double minValue = XTSGetMinValue(bar_index); + + // + result = + xTSCurrentBuffer[bar_index] == minValue; + + // + return result; +} + +// +// Check Current Buffer is Max Or Not ... +bool XTSIsCurrentMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double maxValue = XTSGetMaxValue(bar_index); + + // + result = + xTSCurrentBuffer[bar_index] == maxValue; + + // + return result; +} + +// +// Current VS Nearest ... + +// +// Check Current Crossed Over Nearest ... +bool XTSIsCurrentCrossedOverNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Check Current Over Nearest ... +bool XTSIsCurrentOverNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Check Current Crossed Under Nearest ... +bool XTSIsCurrentCrossedUnderNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Check Current Under Nearest ... +bool XTSIsCurrentUnderNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Current VS Mediest ... + +// +// Check Current Crossed Over Mediest ... +bool XTSIsCurrentCrossedOverMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Check Current Over Mediest ... +bool XTSIsCurrentOverMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Check Current Crossed Under Mediest ... +bool XTSIsCurrentCrossedUnderMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Check Current Under Mediest ... +bool XTSIsCurrentUnderMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Current VS Farest ... + +// +// Check Current Crossed Over Farest ... +bool XTSIsCurrentCrossedOverFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Check Current Over Farest ... +bool XTSIsCurrentOverFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Check Current Crossed Under Farest ... +bool XTSIsCurrentCrossedUnderFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Check Current Under Farest ... +bool XTSIsCurrentUnderFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Globally Custom Functions ... + +// +// Check a Period Crossed Over another one ... +bool XTSIsPeriodCrossedOverAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + double sourceValue1 = XTSGetPeriodValue( + source, + bar_index + 1); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + double destValue1 = XTSGetPeriodValue( + dest, + bar_index + 1); + + // + result = + sourceValue > destValue && + sourceValue1 <= destValue1; + + // + return result; +} + +// +// Check a Period Over another one ... +bool XTSIsPeriodOverAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + + // + result = + sourceValue > destValue; + + // + return result; +} + +// +// Check a Period Crossed Under another one ... +bool XTSIsPeriodCrossedUnderAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + double sourceValue1 = XTSGetPeriodValue( + source, + bar_index + 1); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + double destValue1 = XTSGetPeriodValue( + dest, + bar_index + 1); + + // + result = + sourceValue < destValue && + sourceValue1 >= destValue1; + + // + return result; +} + +// +// Check a Period Under another one ... +bool XTSIsPeriodUnderAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + + // + result = + sourceValue < destValue; + + // + return result; +} + +// +// Retrieve Specific Period's Value from Buffer for Specific Bar Index ... +double XTSGetPeriodValue( + ENUM_X_XTS_PERIODS period, // Specified Period to read it's Value ... + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + switch (period) + { + // + case X_XTS_PERIOD_CURRENT: + result = xTSCurrentBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_NEAREST: + result = xTSNearestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_MEDIEST: + result = xTSMediestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_FAREST: + result = xTSFarestBuffer[bar_index]; + break; + } + + // + return result; +} + +// +// Fill All Exists Periods ... +void XTSGetAllPeriodsEnum( + ENUM_X_XTS_PERIODS &result[] // Hold's Result ... +) +{ + // + CleanBuffer(result); + + // + Add( + X_XTS_PERIOD_CURRENT, + result); + + // + Add( + X_XTS_PERIOD_NEAREST, + result); + + // + Add( + X_XTS_PERIOD_MEDIEST, + result); + + // + Add( + X_XTS_PERIOD_FAREST, + result); +} + +// +// Fill All Exists Periods Except ... +void XTSGetAllPeriodsEnumExcept( + ENUM_X_XTS_PERIODS &result[], // Hold's Result ... + ENUM_X_XTS_PERIODS exception // Excepted Period ... +) +{ + // + CleanBuffer(result); + + // + ENUM_X_XTS_PERIODS allPeriods[]; + XTSGetAllPeriodsEnum(allPeriods); + int periodsCount = ArraySize(allPeriods); + if (periodsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = allPeriods[i]; + + // + if (iPeriod != exception) + { + Add( + iPeriod, + result); + } + } +} + +// +// Fill All Exists Periods Except ... +void XTSGetAllPeriodsEnumExcept( + ENUM_X_XTS_PERIODS &result[], // Hold's Result ... + ENUM_X_XTS_PERIODS &exceptions[] // Excepted Periods ... +) +{ + // + CleanBuffer(result); + + // + ENUM_X_XTS_PERIODS allPeriods[]; + XTSGetAllPeriodsEnum(allPeriods); + int periodsCount = ArraySize(allPeriods); + if (periodsCount <= 0) + { + return; + } + + // + int exceptionsCount = ArraySize(exceptions); + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = allPeriods[i]; + + // + bool canAddIPeriod = false; + if (exceptionsCount <= 0) + { + canAddIPeriod = true; + } + else + { + // + // Loop through Exceptions ... + for (int j = 0; j < exceptionsCount; j++) + { + // + ENUM_X_XTS_PERIODS jException = exceptions[j]; + + // + if (iPeriod == jException) + { + // + canAddIPeriod = false; + break; + } + + // + canAddIPeriod = true; + } + } + + // + if (canAddIPeriod) + { + // + Add( + iPeriod, + result); + } + } +} + +// +// Calculate Periods Min Value ... +double XTSGetPeriodsMinValue( + ENUM_X_XTS_PERIODS &periods[], // Specified Periods ... + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + int periodsCount = ArraySize(periods); + + // + // Validate Args ... + if ( + bar_index < 0 || + periodsCount <= 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = periods[i]; + + // + double iValue = 0; + + // + switch (iPeriod) + { + // + case X_XTS_PERIOD_CURRENT: + iValue = xTSCurrentBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_NEAREST: + iValue = xTSNearestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_MEDIEST: + iValue = xTSMediestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_FAREST: + iValue = xTSFarestBuffer[bar_index]; + break; + } + + // + // Compare iValue to result ... + result = + result == 0 || + result > iValue + ? iValue + : result; + } + + // + return result; +} + +// +// Calculate Periods Max Value ... +double XTSGetPeriodsMaxValue( + ENUM_X_XTS_PERIODS &periods[], // Specified Periods ... + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + int periodsCount = ArraySize(periods); + + // + // Validate Args ... + if ( + bar_index < 0 || + periodsCount <= 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = periods[i]; + + // + double iValue = 0; + + // + switch (iPeriod) + { + // + case X_XTS_PERIOD_CURRENT: + iValue = xTSCurrentBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_NEAREST: + iValue = xTSNearestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_MEDIEST: + iValue = xTSMediestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_FAREST: + iValue = xTSFarestBuffer[bar_index]; + break; + } + + // + // Compare iValue to result ... + result = + result == 0 || + result < iValue + ? iValue + : result; + } + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTSIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xTSCurrentBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +void Add( + ENUM_X_XTS_PERIODS item, // Specified Item ... + ENUM_X_XTS_PERIODS &buffer[] // Specified Buffer ... +) +{ + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; +} + +void CleanBuffer( + ENUM_X_XTS_PERIODS &buffer[] // Specified Buffer ... +) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +// END XTS Custom Functions ... +// diff --git a/XEU5-0/Indicators/.gitkeep b/XEU5-0/Indicators/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Indicators/x-saherelm.xama.indicator.mq5 b/XEU5-0/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 0000000..14d1ef7 --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xama.indicator.mq5 @@ -0,0 +1,353 @@ +/////////////////////////////////////////////////////// +// +// 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 int length = 18; // 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_CLOSE; // Applied To +// +// 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() +{ + // + string maBufferLabel = "XAMA " + "(" + (string)length + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // 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/XEU5-0/Indicators/x-saherelm.xchlh.oscillator.mq5 b/XEU5-0/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 0000000..5c74787 --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xchlh.oscillator.mq5 @@ -0,0 +1,753 @@ +////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel LH Oscillator +// --------------------------------------------------- +// Name: XCHLH +// Description: detecting HH and LL based on cycles ... +// +// +// 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 XCHLH Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHLH" + +// +// XCHLH Hot States ... +enum ENUM_X_XCHLH_HOT_STATES +{ + X_XCHLH_HOT_HH = 1, + X_XCHLH_NEUTURAL = 0, + X_XCHLH_HOT_LL = -1, +}; + +// +// Including Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotHHArrowCode = 234; // Hot HH Arrow Code +input color hotHHArrowColor = clrAqua; // Hot HH Arrow Color +input uchar hotLLArrowCode = 233; // Hot LL Arrow Code +input color hotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcLength = 28; // Length +input double lcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE lcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE lcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcHHColor = clrAqua; // Highest High Color +input color lcLLColor = clrFuchsia; // Lowest Low Color +input group "LC Drawings"; +input bool lcDrawHH = true; // Draw Highest High +input bool lcDrawLL = true; // Draw Lowest Low + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcLength = 14; // Length +input double mcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE mcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE mcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcHHColor = clrLime; // Highest High Color +input color mcLLColor = clrRed; // Lowest Low Color +input group "MC Drawings"; +input bool mcDrawHH = true; // Draw Highest High +input bool mcDrawLL = true; // Draw Lowest Low + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scLength = 7; // Length +input double scThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE scHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE scLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_DOT; // Draw Style +input color scHHColor = clrLightBlue; // Highest High Color +input color scLLColor = clrLightSalmon; // Lowest Low Color +input group "SC Drawings"; +input bool scDrawHH = true; // Draw Highest High +input bool scDrawLL = true; // Draw Lowest Low +// +// END Inputs ... +// + +// +// 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"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcHHBufferIndex 0 +#define lcLLBufferIndex 1 + +// +double lcHHBuffer[]; +double lcLLBuffer[]; + +// +// MC ... +#define mcHHBufferIndex 2 +#define mcLLBufferIndex 3 + +// +double mcHHBuffer[]; +double mcLLBuffer[]; + +// +// SC ... +#define scHHBufferIndex 4 +#define scLLBufferIndex 5 + +// +double scHHBuffer[]; +double scLLBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // 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 ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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(lcLength, mcLength); + maxLength = MathMax(maxLength, scLength); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = + lcLength >= 4 && + lcLength > mcLength && + lcLength > scLength; + bool isMCInputsValid = + mcLength >= 4 && + mcLength > scLength && + mcLength < lcLength; + bool isSCInputsValid = + scLength >= 4 && + scLength < mcLength && + scLength < lcLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// 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 // Current Candle Index ... +) +{ + // + // LC ... + LCCalculateBuffers(bar_index); + + // + // MC ... + MCCalculateBuffers(bar_index); + + // + // SC ... + SCCalculateBuffers(bar_index); + + // + // SIGNAL ... + SignalCalculateBuffers(bar_index); + + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC HH Buffer ... + string lcHHBufferLabel = ShortName + " LC HH (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcHHDrawType = lcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcHHBufferIndex, PLOT_LABEL, lcHHBufferLabel); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_COLOR, lcHHColor); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_TYPE, lcHHDrawType); + + // + // LC LL Buffer ... + string lcLLBufferLabel = ShortName + " LC LL (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcLLDrawType = lcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcLLBufferIndex, PLOT_LABEL, lcLLBufferLabel); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_COLOR, lcLLColor); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_TYPE, lcLLDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC HH Buffer ... + string mcHHBufferLabel = ShortName + " MC HH (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcHHDrawType = mcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcHHBufferIndex, PLOT_LABEL, mcHHBufferLabel); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_COLOR, mcHHColor); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_TYPE, mcHHDrawType); + + // + // MC LL Buffer ... + string mcLLBufferLabel = ShortName + " MC LL (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcLLDrawType = mcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcLLBufferIndex, PLOT_LABEL, mcLLBufferLabel); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_COLOR, mcLLColor); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_TYPE, mcLLDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC HH Buffer ... + string scHHBufferLabel = ShortName + " SC HH (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scHHDrawType = scDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scHHBufferIndex, PLOT_LABEL, scHHBufferLabel); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_COLOR, scHHColor); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_TYPE, scHHDrawType); + + // + // SC LL Buffer ... + string scLLBufferLabel = ShortName + " SC LL (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scLLDrawType = scDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scLLBufferIndex, PLOT_LABEL, scLLBufferLabel); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_COLOR, scLLColor); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_TYPE, scLLDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Calculations ... +void LCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = lcLength; + ENUM_SERIESMODE hhMode = lcHHMode; + ENUM_SERIESMODE llMode = lcLLMode; + double threshold = PipsToPrice(lcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + lcHHBuffer[bar_index] = hhValue; + lcLLBuffer[bar_index] = llValue; +} + +// +// MC Calculations ... +void MCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = mcLength; + ENUM_SERIESMODE hhMode = mcHHMode; + ENUM_SERIESMODE llMode = mcLLMode; + double threshold = PipsToPrice(mcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + mcHHBuffer[bar_index] = hhValue; + mcLLBuffer[bar_index] = llValue; +} + +// +// SC Calculations ... +void SCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = scLength; + ENUM_SERIESMODE hhMode = scHHMode; + ENUM_SERIESMODE llMode = scLLMode; + double threshold = PipsToPrice(scThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + scHHBuffer[bar_index] = hhValue; + scLLBuffer[bar_index] = llValue; +} + +// +// SIGNAL Calculations ... +void SignalCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC Values ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + double lcDelta = lcHH - lcLL; + double lcAvg = lcDelta / 2; + + // + // MC Values ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + double mcDelta = mcHH - mcLL; + double mcAvg = mcDelta / 2; + + // + // SC Values ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + double scDelta = scHH - scLL; + double scAvg = scDelta / 2; + + // + // Min Value ... + double minValue = MathMin( + scLL, mcLL); + minValue = MathMin( + lcLL, minValue); + + // + // Max Value ... + double maxValue = MathMin( + scHH, mcHH); + maxValue = MathMin( + lcHH, maxValue); +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + // + double lcHH1 = lcHHBuffer[bar_index + 1]; + double lcLL1 = lcLLBuffer[bar_index + 1]; + + // + // MC ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + // + double mcHH1 = mcHHBuffer[bar_index + 1]; + double mcLL1 = mcLLBuffer[bar_index + 1]; + + // + // SC ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + // + double scHH1 = scHHBuffer[bar_index + 1]; + double scLL1 = scLLBuffer[bar_index + 1]; + + // + bool isHotLLState = scLL == mcLL && mcLL == lcLL; + bool isHotLLState1 = scLL1 == mcLL1 && mcLL1 == lcLL1; + // + bool isHotHHState = scHH == mcHH && mcHH == lcHH; + bool isHotHHState1 = scHH1 == mcHH1 && mcHH1 == lcHH1; + + // + bool isHotLL = isHotLLState && !isHotLLState1; + bool isHotHH = isHotHHState && !isHotHHState1; + + // + double hotStateValue = X_XCHLH_NEUTURAL; + if (isHotHH) + { + hotStateValue = X_XCHLH_HOT_HH; + } + else if (isHotLL) + { + hotStateValue = X_XCHLH_HOT_LL; + } + + // + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotHHArea = hotStateValue == 1; + bool isHotLLArea = hotStateValue == -1; + if (isHotHHArea || isHotLLArea) + { + // + bool isHH = isHotHHArea; + + // + double price = isHH ? candle.high : candle.low; + ENUM_ARROW_ANCHOR anchor = isHH ? ANCHOR_BOTTOM : ANCHOR_TOP; + color clr = isHH ? hotHHArrowColor : hotLLArrowColor; + uchar arrowCode = isHH ? hotHHArrowCode : hotLLArrowCode; + string name = "HOT " + (isHH ? "HH" : "LL") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr, + STYLE_SOLID, + 1); + } + } +} +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xchma.oscillator.mq5 b/XEU5-0/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 0000000..12d6c69 --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xchma.oscillator.mq5 @@ -0,0 +1,1153 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel Moving Averages Oscillator +// ---------------------------------------------------------------- +// Name: XCHMA +// Description: trend detecting based on cycles ... +// +// +// 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 XCHMA Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHMA" + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotBullishArrowCode = 228; // Hot Bullish Arrow Code +input color hotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color +input uchar hotBearishArrowCode = 230; // Hot Bearish Arrow Code +input color hotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcFastLength = 20; // Fast Length +input int lcSlowLength = 50; // Slow Length +input ENUM_MA_METHOD lcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE lcAppliedTo = PRICE_CLOSE; // Applied To +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcFastColor = clrAqua; // Fast Color +input color lcSlowColor = clrFuchsia; // Slow Color +input group "LC Drawings"; +input bool lcDrawFast = true; // Draw Fast +input bool lcDrawSlow = true; // Draw Slow +input bool lcDrawCrosses = true; // Draw Cross Lines + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcFastLength = 10; // Fast Length +input int mcSlowLength = 30; // Slow Length +input ENUM_MA_METHOD mcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE mcAppliedTo = PRICE_CLOSE; // Applied To +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcFastColor = clrLime; // Fast Color +input color mcSlowColor = clrRed; // Slow Color +input group "MC Drawings"; +input bool mcDrawFast = true; // Draw Fast +input bool mcDrawSlow = true; // Draw Slow +input bool mcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scFastLength = 7; // Fast Length +input int scSlowLength = 14; // Slow Length +input ENUM_MA_METHOD scMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE scAppliedTo = PRICE_CLOSE; // Applied To +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_SOLID; // Draw Style +input color scFastColor = clrLightBlue; // Fast Color +input color scSlowColor = clrLightSalmon; // Slow Color +input group "SC Drawings"; +input bool scDrawFast = true; // Draw Fast +input bool scDrawSlow = true; // Draw Slow +input bool scDrawCrosses = false; // Draw Cross Lines +// +// END Inputs ... +// + +// +// 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" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcFastBufferIndex 0 +#define lcSlowBufferIndex 1 + +// +double lcFastBuffer[]; +double lcSlowBuffer[]; + +// +// MC ... +#define mcFastBufferIndex 2 +#define mcSlowBufferIndex 3 + +// +double mcFastBuffer[]; +double mcSlowBuffer[]; + +// +// SC ... +#define scFastBufferIndex 4 +#define scSlowBufferIndex 5 + +// +double scFastBuffer[]; +double scSlowBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// LC ... +int lcFastHandler = INVALID_HANDLE; +int lcSlowHandler = INVALID_HANDLE; + +// +// MC ... +int mcFastHandler = INVALID_HANDLE; +int mcSlowHandler = INVALID_HANDLE; + +// +// SC ... +int scFastHandler = INVALID_HANDLE; +int scSlowHandler = 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; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init All Required Handlers ... + if (!InitHandlers()) + { + 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 ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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(lcFastLength, lcSlowLength); + + // + // Get Retrieved Values from indicators ... + // + // LC ... + int lcFastCalculatedBars = BarsCalculated(lcFastHandler); + int lcSlowCalculatedBars = BarsCalculated(lcSlowHandler); + + // + // MC ... + int mcFastCalculatedBars = BarsCalculated(mcFastHandler); + int mcSlowCalculatedBars = BarsCalculated(mcSlowHandler); + + // + // SC ... + int scFastCalculatedBars = BarsCalculated(scFastHandler); + int scSlowCalculatedBars = BarsCalculated(scSlowHandler); + + // + // Check Calculated Bars ... + if ( + // + // LC ... + lcFastCalculatedBars < maxLength || + lcSlowCalculatedBars < maxLength || + // + // MC ... + mcFastCalculatedBars < maxLength || + mcSlowCalculatedBars < maxLength || + // + // SC ... + scFastCalculatedBars < maxLength || + scSlowCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Copy Buffers from indicators ... + // + // LC ... + int lcFastCopiedItems = CopyBuffer(lcFastHandler, 0, 0, limit + 1, lcFastBuffer); + int lcSlowCopiedItems = CopyBuffer(lcSlowHandler, 0, 0, limit + 1, lcSlowBuffer); + + // + // MC ... + int mcFastCopiedItems = CopyBuffer(mcFastHandler, 0, 0, limit + 1, mcFastBuffer); + int mcSlowCopiedItems = CopyBuffer(mcSlowHandler, 0, 0, limit + 1, mcSlowBuffer); + + // + // SC ... + int scFastCopiedItems = CopyBuffer(scFastHandler, 0, 0, limit + 1, scFastBuffer); + int scSlowCopiedItems = CopyBuffer(scSlowHandler, 0, 0, limit + 1, scSlowBuffer); + + // + // Check Copied Items Number ... + if ( + // + // LC ... + lcFastCopiedItems <= 0 || + lcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = lcFastLength >= 4 && lcSlowLength > lcFastLength; + bool isMCInputsValid = mcFastLength >= 4 && mcSlowLength > mcFastLength; + bool isSCInputsValid = scFastLength >= 4 && scSlowLength > scFastLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid && + lcFastLength > mcFastLength && + mcFastLength > scFastLength) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// Init Handlers ... +bool InitHandlers() +{ + // + bool result = false; + + // + // LC ... + result = LCInitHandlers(); + if (!result) + { + return result; + } + + // + // MC ... + result = MCInitHandlers(); + if (!result) + { + return result; + } + + // + // SC ... + result = SCInitHandlers(); + if (!result) + { + return result; + } + + // + 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 // Current Candle Index ... +) +{ + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC Fast Buffer ... + string lcFastBufferLabel = ShortName + " LC Fast (" + (string)lcFastLength + ")"; + ENUM_DRAW_TYPE lcFastDrawType = lcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcFastBuffer, true); + SetIndexBuffer(lcFastBufferIndex, lcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(lcFastBufferIndex, PLOT_LABEL, lcFastBufferLabel); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_COLOR, lcFastColor); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_BEGIN, lcFastLength); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_TYPE, lcFastDrawType); + + // + // LC Slow Buffer ... + string lcSlowBufferLabel = ShortName + " LC Slow (" + (string)lcSlowLength + ")"; + ENUM_DRAW_TYPE lcSlowDrawType = lcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcSlowBuffer, true); + SetIndexBuffer(lcSlowBufferIndex, lcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(lcSlowBufferIndex, PLOT_LABEL, lcSlowBufferLabel); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_COLOR, lcSlowColor); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_BEGIN, lcSlowLength); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_TYPE, lcSlowDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC Fast Buffer ... + string mcFastBufferLabel = ShortName + " MC Fast (" + (string)mcFastLength + ")"; + ENUM_DRAW_TYPE mcFastDrawType = mcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcFastBuffer, true); + SetIndexBuffer(mcFastBufferIndex, mcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(mcFastBufferIndex, PLOT_LABEL, mcFastBufferLabel); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_COLOR, mcFastColor); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_BEGIN, mcFastLength); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_TYPE, mcFastDrawType); + + // + // MC Slow Buffer ... + string mcSlowBufferLabel = ShortName + " MC Slow (" + (string)mcSlowLength + ")"; + ENUM_DRAW_TYPE mcSlowDrawType = mcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcSlowBuffer, true); + SetIndexBuffer(mcSlowBufferIndex, mcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(mcSlowBufferIndex, PLOT_LABEL, mcSlowBufferLabel); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_COLOR, mcSlowColor); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_BEGIN, mcSlowLength); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_TYPE, mcSlowDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC Fast Buffer ... + string scFastBufferLabel = ShortName + " SC Fast (" + (string)scFastLength + ")"; + ENUM_DRAW_TYPE scFastDrawType = scDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scFastBuffer, true); + SetIndexBuffer(scFastBufferIndex, scFastBuffer, INDICATOR_DATA); + PlotIndexSetString(scFastBufferIndex, PLOT_LABEL, scFastBufferLabel); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_COLOR, scFastColor); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_BEGIN, scFastLength); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_TYPE, scFastDrawType); + + // + // SC Slow Buffer ... + string scSlowBufferLabel = ShortName + " SC Slow (" + (string)scSlowLength + ")"; + ENUM_DRAW_TYPE scSlowDrawType = scDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scSlowBuffer, true); + SetIndexBuffer(scSlowBufferIndex, scSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(scSlowBufferIndex, PLOT_LABEL, scSlowBufferLabel); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_COLOR, scSlowColor); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_BEGIN, scSlowLength); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_TYPE, scSlowDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Init Handlers ... +bool LCInitHandlers() +{ + // + ResetLastError(); + + // + // LC Fast Handler ... + lcFastHandler = iMA( + _Symbol, + _Period, + lcFastLength, + 0, + lcMethod, + lcAppliedTo); + if (lcFastHandler == INVALID_HANDLE) + { + // + LogMessage("LC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // LC Slow Handler ... + lcSlowHandler = iMA( + _Symbol, + _Period, + lcSlowLength, + 0, + lcMethod, + lcAppliedTo); + if (lcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("LC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// MC Init Handlers ... +bool MCInitHandlers() +{ + // + ResetLastError(); + + // + // MC Fast Handler ... + mcFastHandler = iMA( + _Symbol, + _Period, + mcFastLength, + 0, + mcMethod, + mcAppliedTo); + if (mcFastHandler == INVALID_HANDLE) + { + // + LogMessage("MC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // MC Slow Handler ... + mcSlowHandler = iMA( + _Symbol, + _Period, + mcSlowLength, + 0, + mcMethod, + mcAppliedTo); + if (mcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("MC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// SC Init Handlers ... +bool SCInitHandlers() +{ + // + ResetLastError(); + + // + // SC Fast Handler ... + scFastHandler = iMA( + _Symbol, + _Period, + scFastLength, + 0, + scMethod, + scAppliedTo); + if (scFastHandler == INVALID_HANDLE) + { + // + LogMessage("SC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // SC Slow Handler ... + scSlowHandler = iMA( + _Symbol, + _Period, + scSlowLength, + 0, + scMethod, + scAppliedTo); + if (scSlowHandler == INVALID_HANDLE) + { + // + LogMessage("SC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// LC State ... +double GetLCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// MC State ... +double GetMCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// SC State ... +double GetSCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcFast = lcFastBuffer[bar_index]; + double lcSlow = lcSlowBuffer[bar_index]; + // + double lcFastPrev = lcFastBuffer[bar_index + 1]; + double lcSlowPrev = lcSlowBuffer[bar_index + 1]; + // + double lcState = GetLCState(bar_index); + + // + // MC ... + double mcFast = mcFastBuffer[bar_index]; + double mcSlow = mcSlowBuffer[bar_index]; + // + double mcFastPrev = mcFastBuffer[bar_index + 1]; + double mcSlowPrev = mcSlowBuffer[bar_index + 1]; + // + double mcState = GetMCState(bar_index); + + // + // SC ... + double scFast = scFastBuffer[bar_index]; + double scSlow = scSlowBuffer[bar_index]; + // + double scFastPrev = scFastBuffer[bar_index + 1]; + double scSlowPrev = scSlowBuffer[bar_index + 1]; + // + double scState = GetSCState(bar_index); + + // + // Detect HOT Bearish Area ... + bool isHotBearishArea = + lcFast < lcSlow && + mcFast < mcSlow && + scFast < scSlow; + // + bool isPrevHotBearishArea = + lcFastPrev < lcSlowPrev && + mcFastPrev < mcSlowPrev && + scFastPrev < scSlowPrev; + + // + // Detect HOT Bearish Area ... + bool isHotBullishArea = + lcFast > lcSlow && + mcFast > mcSlow && + scFast > scSlow; + // + bool isPrevHotBullishArea = + lcFastPrev > lcSlowPrev && + mcFastPrev > mcSlowPrev && + scFastPrev > scSlowPrev; + + // + // Generate HotState Value ... + double hotStateValue = + isHotBullishArea && !isPrevHotBullishArea + ? 1 + : isHotBearishArea && !isPrevHotBearishArea + ? -1 + : 0; + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotBullishArea = hotStateValue == 1; + bool isHotBearishArea = hotStateValue == -1; + if (isHotBullishArea || isHotBearishArea) + { + // + bool isBull = isHotBullishArea; + + // + double price = isBull ? candle.low : candle.high; + ENUM_ARROW_ANCHOR anchor = isBull ? ANCHOR_TOP : ANCHOR_BOTTOM; + color clr = isBull ? hotBullishArrowColor : hotBearishArrowColor; + uchar arrowCode = isBull ? hotBullishArrowCode : hotBearishArrowCode; + string name = "HOT " + (isBull ? "Bullish" : "Bearish") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); + } + } + + // + // Draw LC Crosses ... + if (lcDrawCrosses) + { + // + double lcStateValue = GetLCState(bar_index); + bool isLcFastCrossedOverSlow = lcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isLcFastCrossedUnderSlow = lcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isLcFastCrossedOverSlow || isLcFastCrossedUnderSlow) + { + // + bool isBull = isLcFastCrossedOverSlow; + + // + color clr = isBull ? lcFastColor : lcSlowColor; + string name = "LC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw MC Crosses ... + if (mcDrawCrosses) + { + // + double mcStateValue = GetMCState(bar_index); + bool isMcFastCrossedOverSlow = mcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isMcFastCrossedUnderSlow = mcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isMcFastCrossedOverSlow || isMcFastCrossedUnderSlow) + { + // + bool isBull = isMcFastCrossedOverSlow; + + // + color clr = isBull ? mcFastColor : mcSlowColor; + string name = "MC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw SC Crosses ... + if (scDrawCrosses) + { + // + double scStateValue = GetSCState(bar_index); + bool isScFastCrossedOverSlow = scStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isScFastCrossedUnderSlow = scStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isScFastCrossedOverSlow || isScFastCrossedUnderSlow) + { + // + bool isBull = isScFastCrossedOverSlow; + + // + color clr = isBull ? scFastColor : scSlowColor; + string name = "SC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } +} +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xfi.oscillator.mq5 b/XEU5-0/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 0000000..cfd393c --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xfi.oscillator.mq5 @@ -0,0 +1,317 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XFI Oscillator +// --------------------------------------------- +// Name: XFI +// Description: Price Momentum Power Detection +// 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 XFI Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XFI" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 18; // Length +input ENUM_MA_METHOD method = MODE_SMA; // MA Method +input ENUM_APPLIED_VOLUME appliedTo = VOLUME_TICK; // Applied To +// +// 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_separate_window + +// +#property indicator_buffers 2 +#property indicator_plots 1 + +// +// FI Buffer ... +#define fiBufferIndex 0 +#define fiColorBufferIndex 1 + +// +double fiBuffer[]; +double fiColorBuffer[]; + +// +#property indicator_label1 "XFI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int fiHandler = 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; + + // + fiHandler = iForce( + _Symbol, + _Period, + length, + method, + appliedTo); + if (fiHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing 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(fiHandler); +} + +// +// 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, length); + + // + // Check Calculated Bars ... + int fiCalculatedBars = BarsCalculated(fiHandler); + if (fiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFis = CopyBuffer(fiHandler, 0, 0, limit, fiBuffer); + if (copiedFis <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + 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() +{ + // + string fiBufferLabel = "XFI " + "(" + (string)length + ")"; + + // + // FI Buffer ... + ArraySetAsSeries(fiBuffer, true); + SetIndexBuffer(fiBufferIndex, fiBuffer, INDICATOR_DATA); + PlotIndexSetString(fiBufferIndex, PLOT_LABEL, fiBufferLabel); + + // + // FI Color Buffer ... + ArraySetAsSeries(fiColorBuffer, true); + SetIndexBuffer(fiColorBufferIndex, fiColorBuffer, 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 +) +{ + // + double iValue = fiBuffer[bar_index]; + + // + double iColorIndex = + iValue > 0 ? 0 : iValue < 0 ? 2 + : 1; + + // + // Set Buffer Color Index ... + fiColorBuffer[bar_index] = iColorIndex; +} +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xlh.indicator.mq5 b/XEU5-0/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 0000000..4dfc64e --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xlh.indicator.mq5 @@ -0,0 +1,346 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XLH Indicator +// --------------------------------------------- +// Name: XLH +// Description: Moving Average 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 XLH Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XLH" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 14; // Length +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method +// +// 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 3 + +// +// HH Buffer ... +#define hhBufferIndex 0 + +// +double hhBuffer[]; + +// +#property indicator_label1 "XLH HH" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// LL Buffer ... +#define llBufferIndex 1 + +// +double llBuffer[]; + +// +#property indicator_label2 "XLH LL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrFuchsia +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Signal Buffer ... +#define signalBufferIndex 2 + +// +double signalBuffer[]; + +// +#property indicator_label3 "XLH S" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // 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, length); + + // + 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 = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // HH Buffer ... + string hhBufferLabel = ShortName + " HH " + "(" + (string)length + ")"; + ArraySetAsSeries(hhBuffer, true); + SetIndexBuffer(hhBufferIndex, hhBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hhBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(hhBufferIndex, PLOT_LABEL, hhBufferLabel); + + // + // LL Buffer ... + string llBufferLabel = ShortName + " LL " + "(" + (string)length + ")"; + ArraySetAsSeries(llBuffer, true); + SetIndexBuffer(llBufferIndex, llBuffer, INDICATOR_DATA); + PlotIndexSetInteger(llBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(llBufferIndex, PLOT_LABEL, llBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + " S " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// 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 Threshold ... + // + // HH Buffer ... + int hhIndex = iHighest( + _Symbol, + _Period, + hhMode, + length, + bar_index); + double hhValue = GetAppliedPrice( + hhIndex, + hhMode); + + // + hhBuffer[bar_index] = hhValue; + + // + // LL Buffer ... + int llIndex = iLowest( + _Symbol, + _Period, + llMode, + length, + bar_index); + double llValue = GetAppliedPrice( + llIndex, + llMode); + + // + llBuffer[bar_index] = llValue; + + // + XOHCL c = GetCandle(bar_index); + double lhDiff = hhValue - llValue; + double signalValue = (lhDiff / 2); + + // + signalBuffer[bar_index] = (hhValue - signalValue); +} +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xobd.indicator.mq5 b/XEU5-0/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 0000000..4ac05cf --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xobd.indicator.mq5 @@ -0,0 +1,390 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Indicator +// ----------------------------------------------------- +// Name: XOBD +// Description: detect Order Blocks based on Swings ... +// +// +// 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 XOBD Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XOBD" +// +// END Constants ... +// + +// +// START Inputs ... +// +// +input int length = 5; // Swing Length + +// +input uchar swingHighArrowCode = 108; // Swing High Arrow Code +input color swingHighArrowColor = clrMagenta; // Swing High Arrow Color + +// +input uchar swingLowArrowCode = 108; // Swing Low Arrow Code +input color swingLowArrowColor = clrAqua; // Swing Low Arrow Color +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Include Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 1 +#property indicator_plots 0 + +// +#define swingBufferIndex 0 +double swingBuffer[]; +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // 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 ... + OnDeinitDrawLibrary(); +} + +// +// 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, length * 3); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + 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() +{ + // + ArraySetAsSeries(swingBuffer, true); + SetIndexBuffer(swingBufferIndex, swingBuffer, 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) +{ + // + // GetCandleSwing(bar_index); + ENUM_X_SWING_TYPE type = X_NO_SWING; + + // + // Try To Detect Order Blocks ... + bool isSwingLow = false; + bool isSwingHigh = false; + + // + // Reading Candles Data ... + XOHCL candles[]; + for (int i = bar_index; i < bar_index + ((length * 2) + 2); i++) + { + // + XOHCL iCandle = GetCandle( + _Symbol, + _Period, + i); + + // + Add( + iCandle, + candles); + } + + // + // Swing Low ... + isSwingLow = + // + candles[1].close > candles[2].close && + candles[2].close > candles[3].close && + // + candles[3].close < candles[4].close && + // + candles[5].close > candles[4].close && + candles[6].close > candles[5].close + // + ; + + // + if (isSwingLow) + { + type = X_SWING_LOW; + } + + // + if (!isSwingLow) + { + // + // Swing High ... + isSwingHigh = + // + candles[1].close < candles[2].close && + candles[2].close < candles[3].close && + // + candles[3].close > candles[4].close && + // + candles[5].close < candles[4].close && + candles[6].close < candles[5].close + // + ; + + // + if (isSwingHigh) + { + type = X_SWING_HIGH; + } + } + + // + switch (type) + { + // + // Swing High ... + case X_SWING_HIGH: + // + swingBuffer[bar_index] = type; + DrawSwingArrow(1, bar_index); + break; + + // + // Swinmg Low ... + case X_SWING_LOW: + // + swingBuffer[bar_index] = type; + DrawSwingArrow(0, bar_index); + break; + + // + // No Swing ... + default: + case X_NO_SWING: + // + swingBuffer[bar_index] = 0; + break; + } +} + +// +// Draw a Swing Arrow Shape ... +void DrawSwingArrow( + int type, // Swing Type: 0 - Low / 1 - High ... + int bar_index) +{ + // + bool isSwingHigh = type == 1; + XOHCL candle = GetCandle(bar_index + 3); + double arrowDistanceInPoint = 0; + + // + // Define Required Object Properties fro Draw an Arrow ... + datetime time = iTime(_Symbol, _Period, bar_index + 3); + double purePrice = isSwingHigh ? candle.high : candle.low; + color clr = isSwingHigh ? swingHighArrowColor : swingLowArrowColor; + ENUM_ARROW_ANCHOR anchor = isSwingHigh ? ANCHOR_BOTTOM : ANCHOR_TOP; + uchar arrowCode = uchar(isSwingHigh ? swingHighArrowCode : swingLowArrowCode); + double price = isSwingHigh ? purePrice + arrowDistanceInPoint : purePrice - arrowDistanceInPoint; + string name = "Swing " + (isSwingHigh ? "High" : "Low") + "_" + (string)time + "_" + (string)purePrice; + + // + // Draw desired Arrow ... + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); +} +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xrsi.oscillator.mq5 b/XEU5-0/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 0000000..5659e07 --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xrsi.oscillator.mq5 @@ -0,0 +1,397 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Oscillator +// ------------------------------------------------------ +// Name: XRSI +// Description: detect market conditions based on RSI ... +// +// +// 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 XRSI Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XRSI" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 14; // Market Length +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +input group "Short Entry"; +input double shortEntryValue = 70; // Short Entry Level +input color shortEntryColor = clrRed; // Short Entry Level Color +input ENUM_LINE_STYLE shortEntryLineStyle = STYLE_DOT; // Short Entry Style + +// +input group "Short Exit"; +input double shortExitValue = 40; // Short Exit Level +input color shortExitColor = clrRed; // Short Exit Level Color +input ENUM_LINE_STYLE shortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +input group "Long Entry"; +input double longEntryValue = 30; // Long Entry Level +input color longEntryColor = clrRed; // Long Entry Level Color +input ENUM_LINE_STYLE longEntryLineStyle = STYLE_DOT; // Long Entry Style + +// +input group "Long Exit"; +input double longExitValue = 60; // Long Exit Level +input color longExitColor = clrRed; // Long Exit Level Color +input ENUM_LINE_STYLE longExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// START Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_separate_window +#property indicator_buffers 2 +#property indicator_plots 1 + +// +#define rsiBufferIndex 0 +#define rsiColorBufferIndex 1 + +// +double rsiBuffer[]; +double rsiColorBuffer[]; + +// +#property indicator_label1 "XRSI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int rsiHandler = 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; + + // + rsiHandler = iRSI( + _Symbol, + _Period, + length, + appliedTo); + if (rsiHandler == INVALID_HANDLE) + { + 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(rsiHandler); +} + +// +// 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, length); + + // + int rsiCalculatedBars = BarsCalculated(rsiHandler); + if (rsiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + int rsiCopiedItems = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + if (rsiCopiedItems <= 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 = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RSI ... + string rsiBufferLabel = ShortName + " (" + (string)length + ")"; + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rsiBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(rsiBufferIndex, PLOT_LABEL, rsiBufferLabel); + + // + // RSI Color Buffer ... + ArraySetAsSeries(rsiColorBuffer, true); + SetIndexBuffer(rsiColorBufferIndex, rsiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set Indicator Levels here ... + // OB, ExitLong, ExitShort, OS ... + IndicatorSetInteger(INDICATOR_LEVELS, 4); + + // + // SHORTENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, shortEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, shortEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, shortEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 0, "Short Entry"); + + // + // LONGEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, longExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, longExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, shortExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 1, "Long Exit"); + + // + // SHORTEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, shortExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 2, shortExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 2, longEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 2, "Short Exit"); + + // + // LONGENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 3, longEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 3, longEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 3, longExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 3, "Long Entry"); + + // + // Set Maximum and Minimum for subwindow + IndicatorSetInteger(INDICATOR_DIGITS, 2); + IndicatorSetDouble(INDICATOR_MINIMUM, 0); + IndicatorSetDouble(INDICATOR_MAXIMUM, 100); +} + +// +// 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) +{ + // + double iValue = rsiBuffer[bar_index]; + + // + double iColorIndex = 0; + + // + if ( + iValue >= shortEntryValue || + iValue <= longEntryValue || + (iValue < longExitValue && + iValue > shortExitValue)) + { + iColorIndex = 0; + } + else if ( + iValue <= shortEntryValue && + iValue >= longExitValue) + { + iColorIndex = 2; + } + else if ( + iValue < shortExitValue && + iValue > longEntryValue) + { + iColorIndex = 1; + } + + // + rsiColorBuffer[bar_index] = iColorIndex; +} + +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xtd.oscillator.mq5 b/XEU5-0/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 0000000..5f46d18 --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xtd.oscillator.mq5 @@ -0,0 +1,465 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Trend Detector Oscillator +// -------------------------------------------------- +// Name: XTD +// Description: trend detecting in both sides ... +// +// +// 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 XTD Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTD" + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; +// +// END Constants ... +// + +// +// Include Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// START Inputs ... +// +input int length = 14; // Market Length +input bool drawCrosses = true; // Draw Cross Arrows + +// +// Bullish ... +input uchar bullishArrowCode = 228; // Cross Over Arrow Code +input color bullishArrowColor = clrAqua; // Cross Over Arrow Color + +// +// Bearish ... +input uchar bearishArrowCode = 230; // Cross Under Arrow Code +input color bearishArrowColor = clrMagenta; // Cross Under Arrow Color +// +// END Inputs ... +// + +// +// 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"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +#define bullishBufferIndex 0 +#define bearishBufferIndex 1 +#define signalBufferIndex 2 + +// +double bullishBuffer[]; +double bearishBuffer[]; +double signalBuffer[]; + +// +#property indicator_label1 "XBullPower" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#property indicator_label2 "XBearPower" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#property indicator_label3 "XSignal" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +int xtdBullishCandleCount = 0; +int xtdBearishCandleCount = 0; +// +// 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; + + // + // 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 ... + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); +} + +// +// 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, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i, close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 5) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish Buffer ... + string bullishBufferLabel = ShortName + "BullPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bullishBuffer, true); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bullishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bullishBufferIndex, PLOT_LABEL, bullishBufferLabel); + + // + // Bearish Buffer ... + string bearishBufferLabel = ShortName + "BearPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bearishBuffer, true); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bearishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bearishBufferIndex, PLOT_LABEL, bearishBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + "Signal " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// 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, + const double &close[]) +{ + // + // Reset Global Counters ... + xtdBullishCandleCount = 0; + xtdBearishCandleCount = 0; + + // + // Loop through Closes ... + for (int i = bar_index; i <= bar_index + length; i++) + { + for (int j = i + 1; j <= bar_index + length; j++) + { + // + if (close[i] > close[j]) + { + xtdBullishCandleCount++; + } + + // + if (close[i] < close[j]) + { + xtdBearishCandleCount++; + } + } + } + + // + // Bullish Power Buffer ... + bullishBuffer[bar_index] = MathAbs(xtdBullishCandleCount); + + // + // Bearish Power Buffer ... + bearishBuffer[bar_index] = MathAbs(xtdBearishCandleCount); + + // + // Signal Buffer ... + signalBuffer[bar_index] = bullishBuffer[bar_index] - bearishBuffer[bar_index]; + + // + // Check and Draw Crosses if it's Specified ... + if (drawCrosses) + { + DrawCrosses(bar_index); + } +} + +// +// +double GetState( + int bar_index // Specified Bar Index +) +{ + // + // Check Cross Points ... + // bullishCrossedOverBearish = 2; + // bullishOverBearish = 1; + // bullishCrossedUnderBearish = -2; + // bullishUnderBearish = -1; + // OtherWise = 0; + bool isBullishCrossedOverBearish = IsCrossOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishCrossedUnderBearish = IsCrossUnder( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishOverBearish = IsOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishUnderBearish = IsUnder( + bullishBuffer, + bearishBuffer, + bar_index); + + // + double result = X_XTD_NEUTURAL; + if (isBullishCrossedOverBearish) + { + result = X_XTD_BULLISH_CROSSED_OVER_BEARISH; + } + else if (isBullishCrossedUnderBearish) + { + result = X_XTD_BULLISH_CROSSED_UNDER_BEARISH; + } + else if (isBullishOverBearish) + { + result = X_XTD_BULLISH_OVER_BEARISH; + } + else if (isBullishUnderBearish) + { + result = X_XTD_BULLISH_UNDER_BEARISH; + } + else + { + result = X_XTD_NEUTURAL; + } + + // + return result; +} + +// +// Draw Crosses ... +void DrawCrosses( + int bar_index // the bars which required to draw cross arrow on it ... +) +{ + // + double stateValue = GetState(bar_index); + + // + bool isOver = stateValue == 2; + double low = iLow(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + + // + double price = isOver ? low : high; + datetime time = iTime(_Symbol, _Period, bar_index); + ENUM_ARROW_ANCHOR anchor = isOver ? ANCHOR_TOP : ANCHOR_BOTTOM; + uchar arrowCode = isOver ? bullishArrowCode : bearishArrowCode; + color arrowColor = isOver ? bullishArrowColor : bearishArrowColor; + string crossName = "Trend " + (isOver ? "Up" : "Down") + "_" + (string)time + "_" + (string)price; + + // + DrawArrow( + 0, + crossName, + 0, + time, + price, + arrowCode, + anchor, + arrowColor); +} +// +// END Functions ... +// diff --git a/XEU5-0/Indicators/x-saherelm.xtm.indicator.mq5 b/XEU5-0/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 0000000..eac88e0 --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xtm.indicator.mq5 @@ -0,0 +1,349 @@ +/////////////////////////////////////////////////////// +// +// 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 int maPeriod = 14; // Period +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Applied To +// +// 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() +{ + // + string maBufferLabel = "XTM " + "(" + (string)maPeriod + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // 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/XEU5-0/Indicators/x-saherelm.xts.oscillator.mq5 b/XEU5-0/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 0000000..46e9fbf --- /dev/null +++ b/XEU5-0/Indicators/x-saherelm.xts.oscillator.mq5 @@ -0,0 +1,558 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTS Oscillator +// --------------------------------------------- +// Name: XTS +// Description: Time Sections Oscillator ... +// +// +// 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 XTS Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XTS" + +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// XTS Oscillator States ... + +// +// END Constants ... +// + +// +// START Inputs ... +// +input group "Current Period"; +input ENUM_APPLIED_PRICE currentAppliedTo = PRICE_CLOSE; // Current Applied To +// +input group "Nearest Period"; +input ENUM_X_PERIOD_METHOD nearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +input ENUM_TIMEFRAMES nearestPeriod = NULL; // Nearest Time Frame +input ENUM_APPLIED_PRICE nearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// +input group "Mediest Period"; +input ENUM_X_PERIOD_METHOD mediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +input ENUM_TIMEFRAMES mediestPeriod = NULL; // Mediest Time Frame +input ENUM_APPLIED_PRICE mediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// +input group "Farest Period"; +input ENUM_X_PERIOD_METHOD farestMethod = X_PERIOD_AUTO; // How to Find Farest Period +input ENUM_TIMEFRAMES farestPeriod = NULL; // Farest Time Frame +input ENUM_APPLIED_PRICE farestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// 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" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// Current ... +#define currentBufferIndex 0 + +double currentBuffer[]; + +#property indicator_label1 "XTS C" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// Nearest ... +#define nearestBufferIndex 1 + +double nearestBuffer[]; + +#property indicator_label2 "XTS N" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrAqua +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// Mediest ... +#define mediestBufferIndex 2 + +double mediestBuffer[]; + +#property indicator_label3 "XTS M" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrLime +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// Farest ... +#define farestBufferIndex 3 + +double farestBuffer[]; + +#property indicator_label4 "XTS F" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLightBlue +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +ENUM_TIMEFRAMES mNearestPeriod = NULL; +ENUM_TIMEFRAMES mMediestPeriod = NULL; +ENUM_TIMEFRAMES mFarestPeriod = 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; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Oscillator ShortName ... + SetOscillatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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 = 30; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + int maxLength = 30; + + // + // Current ... + ArraySetAsSeries(currentBuffer, true); + SetIndexBuffer(currentBufferIndex, currentBuffer, INDICATOR_DATA); + PlotIndexSetInteger(currentBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Nearest ... + ArraySetAsSeries(nearestBuffer, true); + SetIndexBuffer(nearestBufferIndex, nearestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(nearestBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Mediest ... + ArraySetAsSeries(mediestBuffer, true); + SetIndexBuffer(mediestBufferIndex, mediestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mediestBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Farest ... + ArraySetAsSeries(farestBuffer, true); + SetIndexBuffer(farestBufferIndex, farestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(farestBufferIndex, PLOT_DRAW_BEGIN, maxLength); +} + +// +// Set Oscillator Short Name and also we can define Buffers Labels ... +void SetOscillatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Current ... + CalculateCurrent(bar_index); + + // + // Nearest ... + CalculateNearest(bar_index); + + // + // Mediest ... + CalculateMediest(bar_index); + + // + // Farest ... + CalculateFarest(bar_index); + + // + // Commenting ... + string comment = GenerateDescriptionComment(); + Comment(comment); +} + +// +// Current ... +void CalculateCurrent(int bar_index) +{ + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + _Period, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + currentAppliedTo); + + // + currentBuffer[bar_index] = value; +} + +// +// Nearest ... +void CalculateNearest(int bar_index) +{ + // + if (mNearestPeriod == NULL) + { + // + switch (nearestMethod) + { + // + case X_PERIOD_AUTO: + mNearestPeriod = GetNearestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mNearestPeriod = nearestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mNearestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + nearestAppliedTo); + + // + nearestBuffer[bar_index] = value; +} + +// +// Mediest ... +void CalculateMediest(int bar_index) +{ + // + if (mMediestPeriod == NULL) + { + // + switch (mediestMethod) + { + // + case X_PERIOD_AUTO: + mMediestPeriod = GetMediestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mMediestPeriod = mediestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mMediestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + mediestAppliedTo); + + // + mediestBuffer[bar_index] = value; +} + +// +// Farest ... +void CalculateFarest(int bar_index) +{ + // + if (mFarestPeriod == NULL) + { + // + switch (farestMethod) + { + // + case X_PERIOD_AUTO: + mFarestPeriod = GetFarestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mFarestPeriod = farestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mFarestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + farestAppliedTo); + + // + farestBuffer[bar_index] = value; +} + +// +// Generate Comment ... +string GenerateDescriptionComment() +{ + // + string result = ""; + + // + result += "Nearest : " + EnumToString(mNearestPeriod) + "\n"; + result += "Mediest : " + EnumToString(mMediestPeriod) + "\n"; + result += "Farest : " + EnumToString(mFarestPeriod) + "\n"; + + // + return result; +} +// +// END Functions ... +// diff --git a/XEU5-0/Libraries/.gitkeep b/XEU5-0/Libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Libraries/x-saherelm.alert.lib.mq5 b/XEU5-0/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 0000000..1079063 --- /dev/null +++ b/XEU5-0/Libraries/x-saherelm.alert.lib.mq5 @@ -0,0 +1,200 @@ +/////////////////////////////////////////////////////// +// +// 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); + } +} +void SendAlert( + XSignal &signal, // the Signal Object which requred to Alert + bool asExecuted = true // determines Alert Signal as Executed Signal or not +) +{ + // + // Prepare Message ... + string message = asExecuted ? ExecutedSignalToString(signal) : SignalToString(signal); + + // + // Do Alerting ... + SendAlert(message); +} +// +// END Provided Functions ... +// diff --git a/XEU5-0/Libraries/x-saherelm.common.lib.mq5 b/XEU5-0/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..290dde9 --- /dev/null +++ b/XEU5-0/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,4429 @@ +/////////////////////////////////////////////////////// +// +// 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; +} + +// +// 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_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetAsk() : GetBid(); + result = NormalizePrice(result); + + // + return result; +} +double GetEntry( + string symbol, // Specified Symbol + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetAsk(symbol) : GetBid(symbol); + result = NormalizePrice(result, symbol); + + // + return result; +} + +// +// Get Signal Exit ... +double GetExit( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetBid() : GetAsk(); + result = NormalizePrice(result); + + // + return result; +} +double GetExit( + string symbol, // Specified Symbol + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetBid(symbol) : GetAsk(symbol); + result = NormalizePrice(result, symbol); + + // + 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; +} + +// +// 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; +} + +// +// 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 HasStrongBody(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 = HasStrongBody(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 = HasStrongBody(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 = HasStrongBody(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; +} + +// +// 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; +} + +// +// 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; +} + +// +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; +} + +// +// Validate Struct ... +bool IsValid(XSignal &model, ulong magicNumber) +{ + // + bool result = false; + + // + // Validate Signal Type ... + result = model.type != X_SIGNAL_UNKNOWN; + if (!result) + { + return result; + } + + // + // Check Symbol ... + result = StringLen(model.symbol) == 0 ? true : model.symbol == _Symbol; + if (!result) + { + return result; + } + + // + // Check magic number ... + result = model.magicNumber <= 0 ? true : model.magicNumber == magicNumber; + if (!result) + { + return result; + } + + // + // Check Entry ... + result = model.entry > 0; + if (!result) + { + return result; + } + + // + // Check SL ... + result = model.sl == 0 ? true : model.type == X_SIGNAL_LONG ? model.sl < model.entry + : model.sl > model.entry; + if (!result) + { + return result; + } + + // + // Check TP ... + result = model.tp == 0 ? true : model.type == X_SIGNAL_LONG ? model.tp > model.entry + : model.tp < model.entry; + if (!result) + { + return result; + } + + // + // Check Volume ... + result = model.volume > 0; + if (!result) + { + return result; + } + + // + // Check Time ... + result = model.time > 0; + if (!result) + { + return result; + } + + // + return result; +} + +// +void CleanBuffer(int &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(ulong &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(double &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XSignal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XDeal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XOrder &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; +} +void Add( + XSignal &item, // item want to add + XSignal &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XDeal &item, // item want to add + XDeal &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XOrder &item, // item want to add + XOrder &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// 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; +} + +// +// Check a Signal is Long or not ... +bool IsLong(ENUM_X_SIGNAL_TYPE type) +{ + return type == X_SIGNAL_LONG; +} +bool IsLong(XSignal &signal) +{ + // + bool result = IsLong(signal.type); + + // + return result; +} + +// +// Check a Signal is Short or not ... +bool IsShort(ENUM_X_SIGNAL_TYPE type) +{ + return type == X_SIGNAL_SHORT; +} +bool IsShort(XSignal &signal) +{ + // + bool result = IsShort(signal.type); + + // + return result; +} + +// +// Retrieve a Signal Type String Value ... +string GetSignalType(ENUM_X_SIGNAL_TYPE type) +{ + // + string result = ""; + + // + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + result = type == X_SIGNAL_LONG ? "Long" : "Short"; + + // + return result; +} +string GetSignalType(XSignal &signal) +{ + // + string result = ""; + + // + result = GetSignalType(signal.type); + + // + return result; +} +ENUM_X_SIGNAL_TYPE GetSignalType(string typeStr) +{ + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + if (typeStr == GetSignalType(X_SIGNAL_LONG)) + { + result = X_SIGNAL_LONG; + } + else if (typeStr == GetSignalType(X_SIGNAL_SHORT)) + { + result = X_SIGNAL_SHORT; + } + + // + return result; +} + +// +// Retrieve Signal Execution String ... +string GetSignalExecutionError(int error) +{ + // + string result = ""; + + // + switch (error) + { + // + case X_TRADER_INVALID_SIGNAL_ERROR: + result = "Invalid Signal ..."; + break; + + // + case X_TRADER_NOT_ENOUGH_EQUITY_ERROR: + result = "Not Enough Equity for Trade ..."; + break; + + // + case X_TRADER_NOT_ENOUGH_BALANCE_ERROR: + result = "Not Enough Balance for Trade ..."; + break; + + // + case X_TRADER_NOT_ENOUGH_MARIGIN_ERROR: + result = "Not Enough Marigin For Trade ..."; + break; + + // + case X_TRADER_MAX_TRADES_REACHED_ERROR: + result = "Max Allowed Trade Reached ..."; + break; + + // + case X_TRADER_UNKNOWN_ERROR: + default: + result = "Unknown Issue ..."; + break; + } + + // + return result; +} + +// +// 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; +} + +// +// +// + +// +// 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 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; +} + +// +// END Provided Functions ... +// diff --git a/XEU5-0/Libraries/x-saherelm.draw.lib.mq5 b/XEU5-0/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ece98c8 --- /dev/null +++ b/XEU5-0/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2345 @@ +/////////////////////////////////////////////////////// +// +// 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(); +} + +// +void DrawSignalShape( + XSignal &signal, // Specify Signal to Draw + color longColor = clrAqua, // Long Signals Color + color shortColor = clrFuchsia, // Short Signal Color + color entryColor = clrGold // Signal Entry Price Color +) +{ + // + // Draw Signal Info : + // - Draw Entry Price Line; + // - Draw SL; + // - Draw TP; + // - Risk Free; + + // + bool isLong = signal.type == X_SIGNAL_LONG; + + // + color tpColor = longColor; + color slColor = shortColor; + + // + string name = "T(" + (string)signal.ticket + ")" + "_" + "TY(" + EnumToString(signal.type) + ")"; + + // + string tpName = "TP_" + name; + if (IsDrawExists(tpName)) + { + RemoveDraw(tpName); + } + + // + string slName = "SL_" + name; + if (IsDrawExists(slName)) + { + RemoveDraw(slName); + } + + // + string riskFreeName = "RF_" + name; + if (IsDrawExists(riskFreeName)) + { + RemoveDraw(riskFreeName); + } + + // + string entryName = "Entry_" + name; + if (IsDrawExists(entryName)) + { + RemoveDraw(entryName); + } + + // + string vlName = "Time_" + name; + if (IsDrawExists(vlName)) + { + RemoveDraw(vlName); + } + + // + int signalBarIndex = iBarShift( + signal.symbol, + _Period, + signal.time); + + // + datetime time1 = iTime( + signal.symbol, + _Period, + signalBarIndex + 1); + datetime time2 = iTime( + signal.symbol, + _Period, + signalBarIndex - 1); + + // + // Entry ... + bool isTrendLineDrawn = DrawTrendLine( + 0, + entryName, + 0, + time1, + signal.entry, + time2, + signal.entry, + entryColor); + + // + // TP ... + bool isTPDrawn = false; + if (signal.tp > 0) + { + // + isTPDrawn = DrawTrendLine( + 0, + tpName, + 0, + time1, + signal.tp, + time2, + signal.tp, + tpColor, + STYLE_SOLID, + 1, + false, + true); + } + + // + // RISKFREE ... + bool isRFDrawn = false; + if (signal.riskFreeStep > 0) + { + // + double firstStepPrice = isLong ? signal.entry + PipsToPrice(signal.riskFreeStep) + : signal.entry - PipsToPrice(signal.riskFreeStep); + + // + isRFDrawn = DrawTrendLine( + 0, + riskFreeName, + 0, + time1, + firstStepPrice, + time2, + firstStepPrice, + tpColor, + STYLE_DOT, + 1, + false, + true); + } + + // + // SL ... + bool isSLDrawn = false; + if (signal.sl > 0) + { + // + isSLDrawn = DrawTrendLine( + 0, + slName, + 0, + time1, + signal.sl, + time2, + signal.sl, + slColor, + STYLE_SOLID, + 1, + false, + true); + } + + // + // Draw a Vertical Line ... + bool isVerticalLineDrawn = DrawVerticalLine( + 0, + vlName, + 0, + signal.time, + slColor); +} + +// +// 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; +} + +// +// 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 sub_window = 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, sub_window, 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 back_clr = 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, back_clr); + + // + // 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 ... +// + +// +// END Regular Draws ... +// + +// +// START Chart Style Drawers ... +// +// +// Apply Styles On Chart ... +void ApplyChartStyle( + int chartId = -1, // chart's ID + ENUM_CHART_MODE mode = CHART_CANDLES, // chart's mode + bool showBidLine = true, // show bid line + bool showAskLine = true, // show ask line + bool showGrid = false, // show grids on chart + bool showVolumes = false, // show volumes + bool showTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool autoScroll = true, // chart autoscroll + bool quickNavigation = true, // chart quick navigation state + color foreGroundColor = clrWhite, // chart's foreground color + color backGroundColor = clrBlack, // chart's background color + color upColor = clrGreen, // Up Color + color downColor = clrRed, // Down Color + color bullishColor = clrGreen, // Bullish color + color bearishColor = clrRed, // Bearish color + color gridColor = clrGray, // grid color + color bidLineColor = clrGray, // bid line color + color askLineColor = clrRed, // ask line color + color lineColor = clrLime, // line mode and doji candlestick color + color stopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color volumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (chartId == -1) + { + chartId = 0; + } + + // + ChartSetInteger(chartId, CHART_MODE, mode); + ChartSetInteger(chartId, CHART_SHOW_BID_LINE, showBidLine); + ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, showAskLine); + ChartSetInteger(chartId, CHART_SHOW_GRID, showGrid); + ChartSetInteger(chartId, CHART_SHOW_VOLUMES, showVolumes); + ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, showTradeLevels); + ChartSetInteger(chartId, CHART_AUTOSCROLL, autoScroll); + ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, quickNavigation); + ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, foreGroundColor); + ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, backGroundColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_UP, upColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, downColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, bullishColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, bearishColor); + ChartSetInteger(chartId, CHART_COLOR_GRID, gridColor); + ChartSetInteger(chartId, CHART_COLOR_BID, bidLineColor); + ChartSetInteger(chartId, CHART_COLOR_ASK, askLineColor); + ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, stopColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, lineColor); + ChartSetInteger(chartId, CHART_COLOR_VOLUME, volumesColor); +} +// +// END Chart Style Drawers ... +// \ No newline at end of file diff --git a/XEU5-0/Libraries/x-saherelm.http.lib.mq5 b/XEU5-0/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 0000000..97f7ac0 --- /dev/null +++ b/XEU5-0/Libraries/x-saherelm.http.lib.mq5 @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Http Library +// ------------------------------------------ +// Name: XHttp +// Description: provide http communication +// 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 Model Definition ... +// +enum X_HTTP_METHOD +{ + X_HTTP_GET, + X_HTTP_POST +}; +// +// END Model Definition ... +// + +// +// START Inputs ... +// +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Initial Library if required ... +bool OnInInitHttpLibrary() +{ + return false; +} + +// +// DeInitial Library if required ... +void OnDeinitHttpLibrary() +{ +} + +// +// 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; +} + +// +// 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; + } + + // + result = WebRequest( + strMethod, + url, + headers, + timeout, + payload, + response, + responseHeaders + ); + + // + 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; +} +// +// END Provided Functions ... +// diff --git a/XEU5-0/Libraries/x-saherelm.log.lib.mq5 b/XEU5-0/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 0000000..70f1bda --- /dev/null +++ b/XEU5-0/Libraries/x-saherelm.log.lib.mq5 @@ -0,0 +1,261 @@ +/////////////////////////////////////////////////////// +// +// 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); +} + +// +// 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); +} + +// +// Convert a Signal to String Message ... +string SignalToString(const XSignal &signal) +{ + // + string result = "\n"; + + // + result += "Signal: " + "\n"; + result += "id: " + (string)signal.id + "\n"; + result += "symbol: " + signal.symbol + "\n"; + result += "type: " + EnumToString(signal.type) + "\n"; + result += "magicNumber: " + (string)signal.magicNumber + "\n"; + result += "ticket: " + (string)signal.ticket + "\n"; + result += "entry: " + (string)signal.entry + "\n"; + result += "tp: " + (string)signal.tp + "\n"; + result += "sl: " + (string)signal.sl + "\n"; + result += "riskFreeStep: " + (string)signal.riskFreeStep + "\n"; + result += "riskFreeRate: " + (string)signal.riskFreeRate + "\n"; + result += "profit: " + (string)signal.profit + "\n"; + result += "time: " + (string)signal.time + "\n"; + result += "volume: " + (string)signal.volume + "\n"; + result += "comment: " + signal.comment + "\n"; + + // + return result; +} + +// +// Convert an Executed Signal to String Message ... +string ExecutedSignalToString(const XSignal &signal) +{ + // + string result = ""; + + // + result += (signal.type == X_SIGNAL_LONG ? "Buy" : "Sell") + " Signal Executed provided on (" + signal.symbol + " _ " + EnumToString(_Period) + ") by this comment: " + signal.comment; + + // + return result; +} + +// +// Logging Signal ... +void LogSignal(const XSignal &signal) +{ + // + string message = SignalToString(signal); + + // + LogMessage(message); +} + +// +// Log Signal Execution ... +void LogExecutedSignal(const XSignal &signal) +{ + // + string message = ExecutedSignalToString(signal); + + // + LogMessage(message); +} + +// +// Convert a Deal to String ... +string DealToString(const XDeal &deal) +{ + // + string result = "\n"; + + // + result += "Deal:" + "\n"; + result += " " + "\n"; + result += "time: " + (string)deal.time + "\n"; + result += "ticket: " + (string)deal.ticket + "\n"; + result += "order: " + (string)deal.order + "\n"; + result += "positionId: " + (string)deal.positionId + "\n"; + result += "type: " + EnumToString(deal.type) + "\n"; + result += "entry: " + EnumToString(deal.entry) + "\n"; + result += "reason: " + EnumToString(deal.reason) + "\n"; + result += "symbol: " + deal.symbol + "\n"; + result += "price: " + (string)deal.price + "\n"; + result += "profit: " + (string)deal.profit + "\n"; + result += "swap: " + (string)deal.swap + "\n"; + result += "commission: " + (string)deal.commission + "\n"; + result += "volume: " + (string)deal.volume + "\n"; + result += "comment: " + deal.comment + "\n"; + + // + return result; +} + +// +// Log Specific Deal ... +void LogDeal(const XDeal &deal) +{ + // + string message = DealToString(deal); + + // + LogMessage(message); +} + +// +// Convert an Order to String ... +string OrderToString(const XOrder &order) +{ + // + string result = "\n"; + + // + result += "Order: " + "\n"; + result += "magic: " + (string)order.magic + "\n"; + result += "positionId: " + (string)order.positionId + "\n"; + result += "symbol: " + (string)order.symbol + "\n"; + result += "ticket: " + (string)order.ticket + "\n"; + result += "timeSetup: " + (string)order.timeSetup + "\n"; + result += "timeDone: " + (string)order.timeDone + "\n"; + result += "timeExpiration: " + (string)order.timeExpiration + "\n"; + result += "priceOpen: " + (string)order.priceOpen + "\n"; + result += "priceCurrent: " + (string)order.priceCurrent + "\n"; + result += "priceStopLimit: " + (string)order.priceStopLimit + "\n"; + result += "stopLoss: " + (string)order.stopLoss + "\n"; + result += "takeProfit: " + (string)order.takeProfit + "\n"; + result += "volumeInitial: " + (string)order.volumeInitial + "\n"; + result += "volumeCurrent: " + (string)order.volumeCurrent + "\n"; + result += "comment: " + order.comment + "\n"; + result += "type: " + EnumToString(order.type) + "\n"; + result += "state: " + EnumToString(order.state) + "\n"; + result += "typeFilling: " + EnumToString(order.typeFilling) + "\n"; + result += "typeTime: " + EnumToString(order.typeTime) + "\n"; + result += "reason: " + EnumToString(order.reason) + "\n"; + + // + return result; +} + +// +// Log Specific Order ... +void LogOrder(const XOrder &order) +{ + // + string message = OrderToString(order); + + // + LogMessage(message); +} + +// +// END Provided Functions ... +// diff --git a/XEU5-0/Libraries/x-saherelm.models.lib.mq5 b/XEU5-0/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 0000000..b98ae3e --- /dev/null +++ b/XEU5-0/Libraries/x-saherelm.models.lib.mq5 @@ -0,0 +1,438 @@ +/////////////////////////////////////////////////////// +// +// 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 +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + double high; + double open; + double close; + double low; +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +// XTrader Execution Signal Result ... +enum ENUM_EXECUTION_SIGNAL_RESULT +{ + // + X_TRADER_UNKNOWN_ERROR, + X_TRADER_SUCCEED_EXECUTION, + X_TRADER_INVALID_SIGNAL_ERROR, + X_TRADER_NOT_ENOUGH_EQUITY_ERROR, + X_TRADER_MAX_TRADES_REACHED_ERROR, + X_TRADER_NOT_ENOUGH_BALANCE_ERROR, + X_TRADER_NOT_ENOUGH_MARIGIN_ERROR + // +}; + +// +// Signal Types ... +enum ENUM_X_SIGNAL_TYPE +{ + X_SIGNAL_LONG, + X_SIGNAL_SHORT, + X_SIGNAL_UNKNOWN, +}; + +// +// Signal Structure ... +struct XSignal +{ + // + // Identifier ... + ulong id; + + // + // Which Symbol used for Signal ... + string symbol; + + // + // Which Type of operations ... + ENUM_X_SIGNAL_TYPE type; + + // + // Magic Number ... + ulong magicNumber; + + // + // Ticket ... + ulong ticket; + + // + // Entry/Open Price ... + double entry; + + // + // TP ... + double tp; + + // + // SL ... + double sl; + + // + // Make Risk Free Trade on this Value if provided ... + double riskFreeStep; + + // + // a Multiplier for determines how much trade volume exit on risk free time ... + double riskFreeRate; + + // + // Trade Profit ... + double profit; + + // + // Time of Operation ... + datetime time; + + // + // Volume ... + double volume; + + // + // Comment ... + string comment; +}; + +// +// Signal Additional Info ... +struct XProvidedSignal +{ + // + // Suggested TP ... + double tp; + + // + // Suggested SL ... + double sl; + + // + // Signallers ... + string signallers[]; +}; + +// +// Model Specific 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 Specific Order ... +struct XOrder +{ + // + // the ID of expert that placed the order ... + ulong magic; + + // + // the ID of position ... + ulong positionId; + + // + // the name of order symbol ... + string symbol; + + // + // the ticket of an order, previously selected for access ... + ulong ticket; + + // + // the time of order placement ... + datetime timeSetup; + + // + // the time of order execution or cancellation ... + datetime timeDone; + + // + // the order expiration time ... + datetime timeExpiration; + + // + // the order price ... + double priceOpen; + + // + // the current price by order symbol ... + double priceCurrent; + + // + // the price of a pending order ... + double priceStopLimit; + + // + // the order's Stop Loss ... + double stopLoss; + + // + // the order's Take Profit ... + double takeProfit; + + // + // the initial volume of order ... + double volumeInitial; + + // + // the unfilled volume of order ... + double volumeCurrent; + + // + // the order comment ... + string comment; + + // + // the order type ... + // -------------------- + // ORDER_TYPE_BUY => Market Buy order ... + // ORDER_TYPE_SELL => Market Sell order ... + // ORDER_TYPE_BUY_LIMIT => Buy Limit pending order ... + // ORDER_TYPE_SELL_LIMIT => Sell Limit pending order ... + // ORDER_TYPE_BUY_STOP => Buy Stop pending order ... + // ORDER_TYPE_SELL_STOP => Sell Stop pending order ... + // ORDER_TYPE_BUY_STOP_LIMIT => Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price ... + // ORDER_TYPE_SELL_STOP_LIMIT => Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price ... + // ORDER_TYPE_CLOSE_BY => Order to close a position by an opposite one ... + ENUM_ORDER_TYPE type; + + // + // the order state ... + // -------------------------- + // ORDER_STATE_STARTED => Order checked, but not yet accepted by broker ... + // ORDER_STATE_PLACED => Order accepted ... + // ORDER_STATE_CANCELED => Order canceled by client ... + // ORDER_STATE_PARTIAL => Order partially executed ... + // ORDER_STATE_FILLED => Order fully executed ... + // ORDER_STATE_REJECTED => Order rejected ... + // ORDER_STATE_EXPIRED => Order expired ... + // ORDER_STATE_REQUEST_ADD => Order is being registered (placing to the trading system) + // ORDER_STATE_REQUEST_MODIFY => Order is being modified (changing its parameters) ... + // ORDER_STATE_REQUEST_CANCEL => Order is being deleted (deleting from the trading system) ... + ENUM_ORDER_STATE state; + + // + // the order filling type ... + // ---------------------------- + // ORDER_FILLING_FOK => Fill or Kill + // An order can be executed in the specified volume only. + // If the necessary amount of a financial instrument is currently unavailable in the market, + // the order will not be executed. + // The desired volume can be made up of several available offers. + // The possibility of using FOK orders is determined at the trade server. + // ORDER_FILLING_IOC => Immediate or Cancel + // A trader agrees to execute a deal with the volume maximally available in the market within that indicated in the order. + // If the request cannot be filled completely, an order with the available volume will be executed, + // and the remaining volume will be canceled. + // The possibility of using IOC orders is determined at the trade server. + // ORDER_FILLING_BOC => Passive (Book or Cancel) + // The BoC order assumes that the order can only be placed in the Depth of Market and cannot be immediately executed. + // If the order can be executed immediately when placed, then it is canceled. + // In fact, the BOC policy guarantees that the price of the placed order will be worse than + // the current market. BoC orders are used to implement passive trading, + // so that the order is not executed immediately when placed and does not affect current liquidity. + // Only limit and stop limit orders are supported (ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT, ORDER_TYPE_SELL_STOP_LIMIT). + // ORDER_FILLING_RETURN => Return + // In case of partial filling, an order with remaining volume is not canceled but processed further. + // Return orders are not allowed in the Market Execution + // mode (market execution — SYMBOL_TRADE_EXECUTION_MARKET). + ENUM_ORDER_TYPE_FILLING typeFilling; + + // + // the type of order at the time of the expiration ... + // -------------------------------------------------------- + // ORDER_TIME_GTC => Good till cancel order ... + // ORDER_TIME_DAY => Good till current trade day order ... + // ORDER_TIME_SPECIFIED => Good till expired order ... + // ORDER_TIME_SPECIFIED_DAY => The order will be effective till 23:59:59 of the specified day. + // If this time is outside a trading session, the order expires in the nearest trading time ... + ENUM_ORDER_TYPE_TIME typeTime; + + // + // The reason for order placing ... + // -------------------------------------- + // ORDER_REASON_SL => The order was placed as a result of Stop Loss activation ... + // ORDER_REASON_TP => The order was placed as a result of Take Profit activation ... + // ORDER_REASON_SO => The order was placed as a result of the Stop Out event ... + // ORDER_REASON_WEB => The order was placed from a web platform ... + // ORDER_REASON_CLIENT => The order was placed from a desktop terminal ... + // ORDER_REASON_MOBILE => The order was placed from a mobile application ... + // ORDER_REASON_EXPERT => The order was placed from an MQL5-program, i.e. by an Expert Advisor or a script ... + ENUM_ORDER_REASON reason; +}; +// +// END Provided Functions ... +// diff --git a/XEU5-0/Providers/.gitkeep b/XEU5-0/Providers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 b/XEU5-0/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 new file mode 100644 index 0000000..b45d4fd --- /dev/null +++ b/XEU5-0/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 @@ -0,0 +1,9201 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XEU5 Signal Provider Indicators Library +// ---------------------------------------------------------------- +// +// 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 Define Enums ... +// + +// +enum ENUM_XEU5_SIGNAL_PROVIDERS +{ + // + // XSP Expert Support Mechanism ... + XSP, + // + // XTD ... + XTD, + // + // XTAM ... + XTAM, + // + // XSI ... + XSI, + // + // XSTFI ... + XSTFI, + // + // XOBDLH ... + XOBDLH, + // + // XCHMACC ... + XCHMACC, + // + // XCHMACMN ... + XCHMACMN, + // + // XCHMACMX ... + XCHMACMX, +}; + +// +// Represent Market Conditions ... +struct XEU5MarketConditions +{ + // + // XTM ... + bool isXTMPeak; + bool isXTMVale; + bool isXTMBullish; + bool isXTMBearish; + bool isXTMNeutural; + bool isXTMEndBullish; + bool isXTMEndBearish; + bool isXTMStartBullish; + bool isXTMStartBearish; + bool isXTMEndBullishByNeutural; + bool isXTMEndBearishByNeutural; + bool isXTMStartBullishAfterNeutural; + bool isXTMStartBearishAfterNeutural; + + // + // XAMA ... + bool isXAMAPeak; + bool isXAMAVale; + bool isXAMABullish; + bool isXAMABearish; + bool isXAMANeutural; + bool isXAMAEndBullish; + bool isXAMAEndBearish; + bool isXAMAStartBullish; + bool isXAMAStartBearish; + bool isXAMAEndBullishByNeutural; + bool isXAMAEndBearishByNeutural; + bool isXAMAStartBullishAfterNeutural; + bool isXAMAStartBearishAfterNeutural; + + // + // XLH ... + bool isXLHHHIncreased; + bool isXLHHHDecreased; + bool isXLHLLIncreased; + bool isXLHLLDecreased; + bool isXLHLowAttachedLL; + bool isXLHHighAttachedHH; + bool isXLHHHSameInLength; + bool isXLHLLSameInLength; + bool isXLHPriceOverSignal; + bool isXLHPriceUnderSignal; + bool isXLHPriceInSignalRange; + bool isXLHPriceCrossedOverSignal; + bool isXLHPriceCrossedUnderSignal; + + // + // XTD ... + bool isXTDSignalPeak; + bool isXTDSignalVale; + bool isXTDBullishPeak; + bool isXTDBullishVale; + bool isXTDBearishPeak; + bool isXTDBearishVale; + bool isXTDBullOverBear; + bool isXTDBullUnderBear; + bool isXTDSignalOverBear; + bool isXTDSignalUnderBear; + bool isXTDBullCrossedOverBear; + bool isXTDBullCrossedUnderBear; + bool isXTDSignalCrossedOverBear; + bool isXTDSignalCrossedUnderBear; + + // + // XFI ... + bool isXFIPeak; + bool isXFIVale; + bool isXFICrossedOverZero; + bool isXFIOverZero; + bool isXFICrossedUnderZero; + bool isXFIUnderZero; + + // + // XTS ... + bool isXTSAllSame; + bool isXTSCurrentMin; + bool isXTSCurrentMax; + bool isXTSCurrentOverFarest; + bool isXTSCurrentOverNearest; + bool isXTSCurrentOverMediest; + bool isXTSCurrentUnderFarest; + bool isXTSCurrentUnderNearest; + bool isXTSCurrentUnderMediest; + bool isXTSCurrentCrossedOverFarest; + bool isXTSCurrentCrossedOverNearest; + bool isXTSCurrentCrossedOverMediest; + bool isXTSCurrentCrossedUnderFarest; + bool isXTSCurrentCrossedUnderNearest; + bool isXTSCurrentCrossedUnderMediest; + + // + // XRSI ... + bool isXRSIPeak; + bool isXRSIVale; + bool isXRSICrossedOverLongExit; + bool isXRSICrossedOverLongEntry; + bool isXRSICrossedUnderShortExit; + bool isXRSICrossedUnderShortEntry; + + // + // XOBD ... + bool isXOBDSwingLow; + bool isXOBDSwingHigh; + + // + // XCHLH ... + // + bool isXCHLHSameHHs; + bool isXCHLHSameLLs; + // + bool isXCHLHSCMCHHSame; + bool isXCHLHSCMCLLSame; + // + bool isXCHLHSCLCHHSame; + bool isXCHLHSCLCLLSame; + // + bool isXCHLHMCLCHHSame; + bool isXCHLHMCLCLLSame; + // + bool isXCHLHMCOnTopOfLC; + bool isXCHLHMCInBottomOfLC; + + // + // XCHMA ... + // + bool isXCHMASCOverMax; + bool isXCHMASCOverMin; + bool isXCHMASCUnderMax; + bool isXCHMASCUnderMin; + // + bool isXCHMASCCrossedOverMax; + bool isXCHMASCCrossedUnderMax; + bool isXCHMASCCrossedOverMin; + bool isXCHMASCCrossedUnderMin; + // + bool isXCHMASCPeak; + bool isXCHMASCVale; + bool isXCHMASCTrendsUp; + bool isXCHMASCTrendsDown; + bool isXCHMASCFastOverSlow; + bool isXCHMASCFastUnderSlow; + bool isXCHMASCFastCrossedOverSlow; + bool isXCHMASCFastCrossedUnderSlow; + // + bool isXCHMAMCPeak; + bool isXCHMAMCVale; + bool isXCHMAMCTrendsUp; + bool isXCHMAMCTrendsDown; + bool isXCHMAMCFastOverSlow; + bool isXCHMAMCFastUnderSlow; + bool isXCHMAMCFastCrossedOverSlow; + bool isXCHMAMCFastCrossedUnderSlow; + // + bool isXCHMALCPeak; + bool isXCHMALCVale; + bool isXCHMALCTrendsUp; + bool isXCHMALCTrendsDown; + bool isXCHMALCFastOverSlow; + bool isXCHMALCFastUnderSlow; + bool isXCHMALCFastCrossedOverSlow; + bool isXCHMALCFastCrossedUnderSlow; +}; + +// +// END Define Enums ... +// + +// +// Include Provider Inputs ... +#include "x-saherelm.xeu5.provider.inputs.lib.mq5" + +// +// Signallers ... +input group "XEU5 Signallers"; + +// +// XTD ... +input group "XEU5 XTD Signaller"; +input bool xEU5XTDEnableSignaller = true; // Enable Signaller +// input bool xEU5XTDEnableTPSL = false; // Enable TP/SL +input bool xEU5XTDAllowLongSignals = true; // Enable Long Signals +input bool xEU5XTDAllowShortSignals = true; // Enable Short Signals + +// +// XTAM ... +input group "XEU5 XTAM Signaller"; +input bool xEU5XTAMEnableSignaller = true; // Enable Signaller +// input bool xEU5XTAMEnableTPSL = false; // Enable TP/SL +input bool xEU5XTAMAllowLongSignals = true; // Enable Long Signals +input bool xEU5XTAMAllowShortSignals = true; // Enable Short Signals + +// +// XSI ... +input group "XEU5 XSI Signaller"; +input bool xEU5XSIEnableSignaller = true; // Enable Signaller +// input bool xEU5SIXEnableTPSL = false; // Enable TP/SL +input bool xEU5XSIAllowLongSignals = true; // Enable Long Signals +input bool xEU5XSIAllowShortSignals = true; // Enable Short Signals + +// +// XSTFI ... +input group "XEU5 XSTFI Signaller"; +input bool xEU5XSTFIEnableSignaller = true; // Enable Signaller +// input bool xEU5XSTFIEnableTPSL = false; // Enable TP/SL +input bool xEU5XSTFIAllowLongSignals = true; // Enable Long Signals +input bool xEU5XSTFIAllowShortSignals = true; // Enable Short Signals + +// +// XOBDLH ... +input group "XEU5 XOBDLH Signaller"; +input bool xEU5XOBDLHEnableSignaller = true; // Enable Signaller +// input bool xEU5XOBDLHEnableTPSL = false; // Enable TP/SL +input bool xEU5XOBDLHAllowLongSignals = true; // Enable Long Signals +input bool xEU5XOBDLHAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACC ... +input group "XEU5 XCHMACC Signaller"; +input bool xEU5XCHMACCEnableSignaller = true; // Enable Signaller +// input bool xEU5XCHMACCEnableTPSL = false; // Enable TP/SL +input bool xEU5XCHMACCAllowLongSignals = true; // Enable Long Signals +input bool xEU5XCHMACCAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACMX ... +input group "XEU5 XCHMACMX Signaller"; +input bool xEU5XCHMACMXEnableSignaller = true; // Enable Signaller +// input bool xEU5XCHMACMXEnableTPSL = false; // Enable TP/SL +input bool xEU5XCHMACMXAllowLongSignals = true; // Enable Long Signals +input bool xEU5XCHMACMXAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACMN ... +input group "XEU5 XCHMACMN Signaller"; +input bool xEU5XCHMACMNEnableSignaller = true; // Enable Signaller +// input bool xEU5XCHMACMNEnableTPSL = false; // Enable TP/SL +input bool xEU5XCHMACMNAllowLongSignals = true; // Enable Long Signals +input bool xEU5XCHMACMNAllowShortSignals = true; // Enable Short Signals + +// +// Imports all Indicators Helper here ... +// input group "XEU5 Provider Indicators"; + +// +#include "../Helpers/x-saherelm.xtm.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xama.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xlh.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xts.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xobd.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5" + +// +bool xEU5IsTestMode = true; +int xEU5MaxLengthOfInputs = 0; +int xEU5CalculatedBars = 0; + +// +// Signaller Variables ... +// +// XTD ... +bool xEU5MXTDEnableSignaller = xEU5XTDEnableSignaller; +// bool xEU5MXTDEnableTPSL = xEU5XTDEnableTPSL; +bool xEU5MXTDAllowLongSignals = xEU5XTDAllowLongSignals; +bool xEU5MXTDAllowShortSignals = xEU5XTDAllowShortSignals; + +// +// XTAM ... +bool xEU5MXTAMEnableSignaller = xEU5XTAMEnableSignaller; +// bool xEU5MXTAMEnableTPSL = xEU5XTAMEnableTPSL; +bool xEU5MXTAMAllowLongSignals = xEU5XTAMAllowLongSignals; +bool xEU5MXTAMAllowShortSignals = xEU5XTAMAllowShortSignals; + +// +// XSI ... +bool xEU5MXSIEnableSignaller = xEU5XSIEnableSignaller; +// bool xEU5MSIXEnableTPSL = xEU5SIXEnableTPSL; +bool xEU5MXSIAllowLongSignals = xEU5XSIAllowLongSignals; +bool xEU5MXSIAllowShortSignals = xEU5XSIAllowShortSignals; + +// +// XSTFI ... +bool xEU5MXSTFIEnableSignaller = xEU5XSTFIEnableSignaller; +// bool xEU5MXSTFIEnableTPSL = xEU5XSTFIEnableTPSL; +bool xEU5MXSTFIAllowLongSignals = xEU5XSTFIAllowLongSignals; +bool xEU5MXSTFIAllowShortSignals = xEU5XSTFIAllowShortSignals; + +// +// XOBDLH ... +bool xEU5MXOBDLHEnableSignaller = xEU5XOBDLHEnableSignaller; +// bool xEU5MXOBDLHEnableTPSL = xEU5XOBDLHEnableTPSL; +bool xEU5MXOBDLHAllowLongSignals = xEU5XOBDLHAllowLongSignals; +bool xEU5MXOBDLHAllowShortSignals = xEU5XOBDLHAllowShortSignals; + +// +// XCHMACC ... +bool xEU5MXCHMACCEnableSignaller = xEU5XCHMACCEnableSignaller; +// bool xEU5MXCHMACCEnableTPSL = xEU5XCHMACCEnableTPSL; +bool xEU5MXCHMACCAllowLongSignals = xEU5XCHMACCAllowLongSignals; +bool xEU5MXCHMACCAllowShortSignals = xEU5XCHMACCAllowShortSignals; + +// +// XCHMAMX ... +bool xEU5MXCHMACMXEnableSignaller = xEU5XCHMACMXEnableSignaller; +// bool xEU5MXCHMACMXEnableTPSL = xEU5XCHMACMXEnableTPSL; +bool xEU5MXCHMACMXAllowLongSignals = xEU5XCHMACMXAllowLongSignals; +bool xEU5MXCHMACMXAllowShortSignals = xEU5XCHMACMXAllowShortSignals; + +// +// XCHMAMN ... +bool xEU5MXCHMACMNEnableSignaller = xEU5XCHMACMNEnableSignaller; +// bool xEU5MXCHMACMNEnableTPSL = xEU5XCHMACMNEnableTPSL; +bool xEU5MXCHMACMNAllowLongSignals = xEU5XCHMACMNAllowLongSignals; +bool xEU5MXCHMACMNAllowShortSignals = xEU5XCHMACMNAllowShortSignals; + +// +// Funded Next Resolve Guards ... +bool isXEU5OnFundedNext = true; + +// +// Here we Define some Global Market Variables to Analyse MArket Conditions +// using them at each time ... +XEU5MarketConditions xEU5Conditions = {}; + +// +// Validate Indicators Inputs ... +bool XEU5ValidateIndicatorsInputs() +{ + // + bool result = false; + + // + // XTM ... + result = XTMValidateInputs(); + if (!result) + { + return result; + } + + // + // XAMA ... + result = XAMAValidateInputs(); + if (!result) + { + return result; + } + + // + // XTD ... + result = XTDValidateInputs(); + if (!result) + { + return result; + } + + // + // XFI ... + result = XFIValidateInputs(); + if (!result) + { + return result; + } + + // + // XTS ... + result = XTSValidateInputs(); + if (!result) + { + return result; + } + + // + // XOBD ... + result = XOBDValidateInputs(); + if (!result) + { + return result; + } + + // + // XLH ... + result = XLHValidateInputs(); + if (!result) + { + return result; + } + + // + // XRSI ... + result = XRSIValidateInputs(); + if (!result) + { + return result; + } + + // + // XCHLH ... + result = XCHLHValidateInputs(); + if (!result) + { + return result; + } + + // + // XCHMA ... + result = XCHMAValidateInputs(); + if (!result) + { + return result; + } + + // + result = true; + + // + return result; +} + +// +// Init Indicators ... +bool XEU5InitIndicators() +{ + // + bool result = false; + + // + // Make it Enable when we need to Log Market Conditions ... + // xEU5IsTestMode = false; // IsRunningOnTestMode(); + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xEU5MaxLengthOfInputs = MathMax( + xTMMaPeriod, + xEU5NumberOfItemsPerTick); + + // + // XAMA ... + xEU5MaxLengthOfInputs = MathMax( + xAMALength, + xEU5NumberOfItemsPerTick); + xEU5MaxLengthOfInputs = MathMax( + xAMAFastEMA, + xEU5NumberOfItemsPerTick); + xEU5MaxLengthOfInputs = MathMax( + xAMASlowEMA, + xEU5NumberOfItemsPerTick); + + // + // XLH ... + xEU5MaxLengthOfInputs = MathMax( + xLHLength, + xEU5NumberOfItemsPerTick); + + // + // XTD ... + xEU5MaxLengthOfInputs = MathMax( + xTDLength, + xEU5MaxLengthOfInputs); + + // + // XFI ... + xEU5MaxLengthOfInputs = MathMax( + xFILength, + xEU5MaxLengthOfInputs); + + // + // XRSI ... + xEU5MaxLengthOfInputs = MathMax( + xRSILength, + xEU5MaxLengthOfInputs); + + // + // XOBD ... + xEU5MaxLengthOfInputs = MathMax( + xOBDLength, + xEU5MaxLengthOfInputs); + + // + // XCHLH ... + xEU5MaxLengthOfInputs = MathMax( + xCHLHLcLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHLHMcLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHLHScLength, + xEU5MaxLengthOfInputs); + + // + // XCHMA ... + xEU5MaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xEU5MaxLengthOfInputs); + + // + // Validate Indicators Inputs before Initialization ... + result = XEU5ValidateIndicatorsInputs(); + if (!result) + { + return result; + } + + // + // Validate Signallers ... + + // + // XTD ... + bool isXTDEnable = + xEU5XTDEnableSignaller && + (xEU5XTDAllowLongSignals || + xEU5XTDAllowShortSignals); + + // + // XTAM ... + bool isXTAMEnable = + xEU5XTAMEnableSignaller && + (xEU5XTAMAllowLongSignals || + xEU5XTAMAllowShortSignals); + + // + // XSI ... + bool isXSIEnable = + xEU5XSIEnableSignaller && + (xEU5XSIAllowLongSignals || + xEU5XSIAllowShortSignals); + + // + // XSTFI ... + bool isXSTFIEnable = + xEU5XSTFIEnableSignaller && + (xEU5XSTFIAllowLongSignals || + xEU5XSTFIAllowShortSignals); + + // + // XOBDLH ... + bool isXOBDLHEnable = + xEU5XOBDLHEnableSignaller && + (xEU5XOBDLHAllowLongSignals || + xEU5XOBDLHAllowShortSignals); + + // + // XCHMACC ... + bool isXCHMACCEnable = + xEU5XCHMACCEnableSignaller && + (xEU5XCHMACCAllowLongSignals || + xEU5XCHMACCAllowShortSignals); + + // + // XCHMACMX ... + bool isXCHMACMXEnable = + xEU5XCHMACMXEnableSignaller && + (xEU5XCHMACMXAllowLongSignals || + xEU5XCHMACMXAllowShortSignals); + + // + // XCHMACMN ... + bool isXCHMACMNEnable = + xEU5XCHMACMNEnableSignaller && + (xEU5XCHMACMNAllowLongSignals || + xEU5XCHMACMNAllowShortSignals); + + // + bool hasSignaller = + // + isXTDEnable || + isXTAMEnable || + isXSIEnable || + isXSTFIEnable || + isXOBDLHEnable || + isXCHMACCEnable || + isXCHMACMXEnable || + isXCHMACMNEnable + // + ; + result = hasSignaller; + if (!result) + { + // + LogMessage("XEU5 doesn't enable any Signaller ..."); + + // + return result; + } + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTM Init ... + result = XTMInitHandlers(); + if (!result) + { + return result; + } + + // + // XAMA Init ... + result = XAMAInitHandlers(); + if (!result) + { + return result; + } + + // + // XLH Init ... + result = XLHInitHandlers(); + if (!result) + { + return result; + } + + // + // XTD Init ... + result = XTDInitHandlers(); + if (!result) + { + return result; + } + + // + // XFI Init ... + result = XFIInitHandlers(); + if (!result) + { + return result; + } + + // + // XTS Init ... + result = XTSInitHandlers(); + if (!result) + { + return result; + } + + // + // XRSI Init ... + result = XRSIInitHandlers(); + if (!result) + { + return result; + } + + // + // XOBD Init ... + result = XOBDInitHandlers(); + if (!result) + { + return result; + } + + // + // XCLH Init ... + result = XCHLHInitHandlers(); + if (!result) + { + return result; + } + + // + // XCHMA Init ... + result = XCHMAInitHandlers(); + if (!result) + { + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XEU5ReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XAMAReleaseHandlers(); + XLHReleaseHandlers(); + XTDReleaseHandlers(); + XFIReleaseHandlers(); + XTSReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XEU5HandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xEU5CalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xEU5NumberOfItemsPerTick); + XAMAReadBuffers(xEU5NumberOfItemsPerTick); + XLHReadBuffers(xEU5NumberOfItemsPerTick); + XTDReadBuffers(xEU5NumberOfItemsPerTick); + XFIReadBuffers(xEU5NumberOfItemsPerTick); + XTSReadBuffers(xEU5NumberOfItemsPerTick); + XRSIReadBuffers(xEU5NumberOfItemsPerTick); + XOBDReadBuffers(xEU5NumberOfItemsPerTick); + XCHMAReadBuffers(xEU5NumberOfItemsPerTick); + XCHLHReadBuffers(xEU5NumberOfItemsPerTick); + + // + XEU5ReadConditions(); +} + +// +// +// START Combination Functions ... +// +// + +// +// Can Open Long Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Long Signals ... +bool XEU5CanOpenLongTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XEU5HasLongSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + XEU5ClearConditions(); + } + + // + return result; +} + +// +// Can Close Long Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Long Signals ... +bool XEU5CanCloseLongTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// Can Open Short Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Short Signals ... +bool XEU5CanOpenShortTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XEU5HasShortSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + XEU5ClearConditions(); + } + + // + return result; +} + +// +// Can Close Short Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Short Signals ... +bool XEU5CanCloseShortTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// Read All Globally Required Conditions ... +void XEU5ReadConditions() +{ + // + XEU5ClearConditions(); + + // + xEU5Conditions = XEU5GenerateMarketConditions(1); +} + +// +// Cleanup Conditions ... +void XEU5ClearConditions() +{ + // + XEU5MarketConditions mConditions = {}; + + // + xEU5Conditions = mConditions; +} + +// +// Generate Merket Conditions for Specified Bar Index ... +XEU5MarketConditions XEU5GenerateMarketConditions( + int bar_index = 1 // Specified Bar Index ... +) +{ + // + XEU5MarketConditions mConditions = {}; + + // + // XTM ... + mConditions.isXTMPeak = XTMIsPeak(bar_index); + mConditions.isXTMVale = XTMIsVale(bar_index); + mConditions.isXTMBullish = XTMIsBullish(bar_index); + mConditions.isXTMBearish = XTMIsBearish(bar_index); + mConditions.isXTMNeutural = XTMIsNeutural(bar_index); + mConditions.isXTMEndBullish = XTMIsEndBullish(bar_index); + mConditions.isXTMEndBearish = XTMIsEndBearish(bar_index); + mConditions.isXTMStartBullish = XTMIsStartBullish(bar_index); + mConditions.isXTMStartBearish = XTMIsStartBearish(bar_index); + mConditions.isXTMEndBullishByNeutural = XTMIsEndBullishByNeutural(bar_index); + mConditions.isXTMEndBearishByNeutural = XTMIsEndBearishByNeutural(bar_index); + mConditions.isXTMStartBullishAfterNeutural = XTMIsStartBullishAfterNeutural(bar_index); + mConditions.isXTMStartBearishAfterNeutural = XTMIsStartBearishAfterNeutural(bar_index); + + // + // XAMA ... + mConditions.isXAMAPeak = XAMAIsPeak(bar_index); + mConditions.isXAMAVale = XAMAIsVale(bar_index); + mConditions.isXAMABullish = XAMAIsBullish(bar_index); + mConditions.isXAMABearish = XAMAIsBearish(bar_index); + mConditions.isXAMANeutural = XAMAIsNeutural(bar_index); + mConditions.isXAMAEndBullish = XAMAIsEndBullish(bar_index); + mConditions.isXAMAEndBearish = XAMAIsEndBearish(bar_index); + mConditions.isXAMAStartBullish = XAMAIsStartBullish(bar_index); + mConditions.isXAMAStartBearish = XAMAIsStartBearish(bar_index); + mConditions.isXAMAEndBullishByNeutural = XAMAIsEndBullishByNeutural(bar_index); + mConditions.isXAMAEndBearishByNeutural = XAMAIsEndBearishByNeutural(bar_index); + mConditions.isXAMAStartBullishAfterNeutural = XAMAIsStartBullishAfterNeutural(bar_index); + mConditions.isXAMAStartBearishAfterNeutural = XAMAIsStartBearishAfterNeutural(bar_index); + + // + // XLH ... + mConditions.isXLHHHIncreased = XLHIsHHIncreased(bar_index); + mConditions.isXLHHHDecreased = XLHIsHHDecreased(bar_index); + mConditions.isXLHLLIncreased = XLHIsLLIncreased(bar_index); + mConditions.isXLHLLDecreased = XLHIsLLDecreased(bar_index); + mConditions.isXLHLowAttachedLL = XLHIsLowAttachedLL(bar_index); + mConditions.isXLHHighAttachedHH = XLHIsHighAttachedHH(bar_index); + mConditions.isXLHHHSameInLength = XLHIsHHSameInLength(bar_index); + mConditions.isXLHLLSameInLength = XLHIsLLSameInLength(bar_index); + mConditions.isXLHPriceOverSignal = XLHIsPriceOverSignal(bar_index); + mConditions.isXLHPriceUnderSignal = XLHIsPriceUnderSignal(bar_index); + mConditions.isXLHPriceInSignalRange = XLHIsPriceInSignalRange(bar_index); + mConditions.isXLHPriceCrossedOverSignal = XLHIsPriceCrossedOverSignal(bar_index); + mConditions.isXLHPriceCrossedUnderSignal = XLHIsPriceCrossedUnderSignal(bar_index); + + // + // XTD ... + mConditions.isXTDSignalPeak = XTDIsSignalPeak(bar_index); + mConditions.isXTDSignalVale = XTDIsSignalVale(bar_index); + mConditions.isXTDBullishPeak = XTDIsBullishPeak(bar_index); + mConditions.isXTDBullishVale = XTDIsBullishVale(bar_index); + mConditions.isXTDBearishPeak = XTDIsBearishPeak(bar_index); + mConditions.isXTDBearishVale = XTDIsBearishVale(bar_index); + mConditions.isXTDBullOverBear = XTDIsBullOverBear(bar_index); + mConditions.isXTDBullUnderBear = XTDIsBullUnderBear(bar_index); + mConditions.isXTDSignalOverBear = XTDIsSignalOverBear(bar_index); + mConditions.isXTDSignalUnderBear = XTDIsSignalUnderBear(bar_index); + mConditions.isXTDBullCrossedOverBear = XTDIsBullCrossedOverBear(bar_index); + mConditions.isXTDBullCrossedUnderBear = XTDIsBullCrossedUnderBear(bar_index); + mConditions.isXTDSignalCrossedOverBear = XTDIsSignalCrossedOverBear(bar_index); + mConditions.isXTDSignalCrossedUnderBear = XTDIsSignalCrossedUnderBear(bar_index); + + // + // XFI ... + mConditions.isXFIPeak = XFIIsPeak(bar_index); + mConditions.isXFIVale = XFIIsVale(bar_index); + mConditions.isXFIOverZero = XFIIsOverZero(bar_index); + mConditions.isXFIUnderZero = XFIIsUnderZero(bar_index); + mConditions.isXFICrossedOverZero = XFIIsCrossedOverZero(bar_index); + mConditions.isXFICrossedUnderZero = XFIIsCrossedUnderZero(bar_index); + + // + // XTS ... + mConditions.isXTSAllSame = XTSIsAllSame(bar_index); + mConditions.isXTSCurrentMin = XTSIsCurrentMin(bar_index); + mConditions.isXTSCurrentMax = XTSIsCurrentMax(bar_index); + mConditions.isXTSCurrentOverFarest = XTSIsCurrentOverFarest(bar_index); + mConditions.isXTSCurrentOverNearest = XTSIsCurrentOverNearest(bar_index); + mConditions.isXTSCurrentOverMediest = XTSIsCurrentOverMediest(bar_index); + mConditions.isXTSCurrentUnderFarest = XTSIsCurrentUnderFarest(bar_index); + mConditions.isXTSCurrentUnderNearest = XTSIsCurrentUnderNearest(bar_index); + mConditions.isXTSCurrentUnderMediest = XTSIsCurrentUnderMediest(bar_index); + mConditions.isXTSCurrentCrossedOverFarest = XTSIsCurrentCrossedOverFarest(bar_index); + mConditions.isXTSCurrentCrossedOverNearest = XTSIsCurrentCrossedOverNearest(bar_index); + mConditions.isXTSCurrentCrossedOverMediest = XTSIsCurrentCrossedOverMediest(bar_index); + mConditions.isXTSCurrentCrossedUnderFarest = XTSIsCurrentCrossedUnderFarest(bar_index); + mConditions.isXTSCurrentCrossedUnderNearest = XTSIsCurrentCrossedUnderNearest(bar_index); + mConditions.isXTSCurrentCrossedUnderMediest = XTSIsCurrentCrossedUnderMediest(bar_index); + + // + // XRSI ... + mConditions.isXRSIPeak = XRSIIsPeak(bar_index); + mConditions.isXRSIVale = XRSIIsVale(bar_index); + mConditions.isXRSICrossedOverLongExit = XRSIIsCrossedOverLongExit(bar_index); + mConditions.isXRSICrossedOverLongEntry = XRSIIsCrossedOverLongEntry(bar_index); + mConditions.isXRSICrossedUnderShortExit = XRSIIsCrossedUnderShortExit(bar_index); + mConditions.isXRSICrossedUnderShortEntry = XRSIIsCrossedUnderShortEntry(bar_index); + + // + // XOBD ... + mConditions.isXOBDSwingLow = XOBDIsSwingLow(bar_index); + mConditions.isXOBDSwingHigh = XOBDIsSwingHigh(bar_index); + + // + // XCHLH ... + // + mConditions.isXCHLHSameHHs = XCHLHIsSameHHs(bar_index); + mConditions.isXCHLHSameLLs = XCHLHIsSameLLs(bar_index); + // + mConditions.isXCHLHSCMCHHSame = XCHLHIsMCSCHasSameHH(bar_index); + mConditions.isXCHLHSCMCLLSame = XCHLHIsMCSCHasSameLL(bar_index); + // + mConditions.isXCHLHSCLCHHSame = XCHLHIsLCSCHasSameHH(bar_index); + mConditions.isXCHLHSCLCLLSame = XCHLHIsLCSCHasSameLL(bar_index); + // + mConditions.isXCHLHMCLCHHSame = XCHLHIsLCMCHasSameHH(bar_index); + mConditions.isXCHLHMCLCLLSame = XCHLHIsLCMCHasSameLL(bar_index); + // + mConditions.isXCHLHMCOnTopOfLC = XCHLHIsMCOnTopOfLC(bar_index); + mConditions.isXCHLHMCInBottomOfLC = XCHLHIsMCInBottomOfLC(bar_index); + + // + // XCHMA ... + // + mConditions.isXCHMASCOverMax = XCHMAIsSCOverMax(bar_index); + mConditions.isXCHMASCOverMin = XCHMAIsSCOverMin(bar_index); + mConditions.isXCHMASCUnderMax = XCHMAIsSCUnderMax(bar_index); + mConditions.isXCHMASCUnderMin = XCHMAIsSCUnderMin(bar_index); + // + mConditions.isXCHMASCCrossedOverMax = XCHMAIsSCCrossedOverMax(bar_index); + mConditions.isXCHMASCCrossedUnderMax = XCHMAIsSCCrossedUnderMax(bar_index); + mConditions.isXCHMASCCrossedOverMin = XCHMAIsSCCrossedOverMin(bar_index); + mConditions.isXCHMASCCrossedUnderMin = XCHMAIsSCCrossedUnderMin(bar_index); + // + mConditions.isXCHMASCPeak = XCHMAIsSCPeak(bar_index); + mConditions.isXCHMASCVale = XCHMAIsSCVale(bar_index); + mConditions.isXCHMASCTrendsUp = XCHMAIsSCTrendsUp(bar_index); + mConditions.isXCHMASCTrendsDown = XCHMAIsSCTrendsDown(bar_index); + mConditions.isXCHMASCFastOverSlow = XCHMAIsSCFastOverSlow(bar_index); + mConditions.isXCHMASCFastUnderSlow = XCHMAIsSCFastUnderSlow(bar_index); + mConditions.isXCHMASCFastCrossedOverSlow = XCHMAIsSCFastCrossedOverSlow(bar_index); + mConditions.isXCHMASCFastCrossedUnderSlow = XCHMAIsSCFastCrossedUnderSlow(bar_index); + // + mConditions.isXCHMAMCPeak = XCHMAIsMCPeak(bar_index); + mConditions.isXCHMAMCVale = XCHMAIsMCVale(bar_index); + mConditions.isXCHMAMCTrendsUp = XCHMAIsMCTrendsUp(bar_index); + mConditions.isXCHMAMCTrendsDown = XCHMAIsMCTrendsDown(bar_index); + mConditions.isXCHMAMCFastOverSlow = XCHMAIsMCFastOverSlow(bar_index); + mConditions.isXCHMAMCFastUnderSlow = XCHMAIsMCFastUnderSlow(bar_index); + mConditions.isXCHMAMCFastCrossedOverSlow = XCHMAIsMCFastCrossedOverSlow(bar_index); + mConditions.isXCHMAMCFastCrossedUnderSlow = XCHMAIsMCFastCrossedUnderSlow(bar_index); + // + mConditions.isXCHMALCPeak = XCHMAIsLCPeak(bar_index); + mConditions.isXCHMALCVale = XCHMAIsLCVale(bar_index); + mConditions.isXCHMALCTrendsUp = XCHMAIsLCTrendsUp(bar_index); + mConditions.isXCHMALCTrendsDown = XCHMAIsLCTrendsDown(bar_index); + mConditions.isXCHMALCFastOverSlow = XCHMAIsLCFastOverSlow(bar_index); + mConditions.isXCHMALCFastUnderSlow = XCHMAIsLCFastUnderSlow(bar_index); + mConditions.isXCHMALCFastCrossedOverSlow = XCHMAIsLCFastCrossedOverSlow(bar_index); + mConditions.isXCHMALCFastCrossedUnderSlow = XCHMAIsLCFastCrossedUnderSlow(bar_index); + + // + return mConditions; +} + +// +// Check Market Conditions by Combination of Power of All tools for LONGs ... +bool XEU5HasLongSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XEU5XTDHasLongSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XEU5XTAMHasLongSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XEU5XSIHasLongSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XEU5XSTFIHasLongSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XEU5XOBDLHHasLongSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XEU5XCHMACCHasLongSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMACMNHasSignal = XEU5XCHMACMNHasLongSignal(); + if (isXCHMACMNHasSignal) + { + // + Add( + EnumToString(XCHMACMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMACMXHasSignal = XEU5XCHMACMXHasLongSignal(); + if (isXCHMACMXHasSignal) + { + // + Add( + EnumToString(XCHMACMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXSTFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMACMNHasSignal + // + || + // + isXCHMACMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xEU5IsTestMode) + { + // + string message = XEU5GetConditionsString(xEU5Conditions, "\n"); + + // + LogMessage( + "Long Signal Provided by: \n" + + info.signallers[ArraySize(info.signallers) - 1] + "\n" + + "Pusher: " + (string)ArraySize(info.signallers) + "\n" + + "Market Conditions: " + message); + } + } + + // + return result; +} + +// +// Check Market Conditions by Combination of Power of All tools for SHORTs ... +bool XEU5HasShortSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XEU5XTDHasShortSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XEU5XTAMHasShortSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XEU5XSIHasShortSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XEU5XSTFIHasShortSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XEU5XOBDLHHasShortSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XEU5XCHMACCHasShortSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMACMNHasSignal = XEU5XCHMACMNHasShortSignal(); + if (isXCHMACMNHasSignal) + { + // + Add( + EnumToString(XCHMACMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMACMXHasSignal = XEU5XCHMACMXHasShortSignal(); + if (isXCHMACMXHasSignal) + { + // + Add( + EnumToString(XCHMACMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXSTFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMACMNHasSignal + // + || + // + isXCHMACMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xEU5IsTestMode) + { + // + string message = XEU5GetConditionsString(xEU5Conditions, "\n"); + + // + LogMessage( + "Short Signal Provided by: \n" + + info.signallers[ArraySize(info.signallers) - 1] + "\n" + + "Pusher: " + (string)ArraySize(info.signallers) + "\n" + + "Market Conditions: " + message); + } + } + + // + return result; +} + +// +// +// END Combination Signaling ... +// +// + +// +// START Signal Providers ... +// + +// +// Disbale All Signallers Longs ... +void XEU5DisableLongSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + xEU5MXTDAllowLongSignals = false; + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + xEU5MXTAMAllowLongSignals = false; + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + xEU5MXSIAllowLongSignals = false; + } + + // + // XSTFI ... + if (xEU5MXSTFIEnableSignaller) + { + xEU5MXSTFIAllowLongSignals = false; + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + xEU5MXOBDLHAllowLongSignals = false; + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + xEU5MXCHMACCAllowLongSignals = false; + } + + // + // XCHMAMX ... + if (xEU5MXCHMACMXEnableSignaller) + { + xEU5MXCHMACMXAllowLongSignals = false; + } + + // + // XCHMAMN ... + if (xEU5MXCHMACMNEnableSignaller) + { + xEU5MXCHMACMNAllowLongSignals = false; + } +} + +// +// Enable All Signallers Longs ... +// Only if they are Configured as Enable at Settings ... +void XEU5EnableLongSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + xEU5MXTDAllowLongSignals = + xEU5XTDAllowLongSignals + ? true + : xEU5MXTDAllowLongSignals; + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + xEU5MXTAMAllowLongSignals = + xEU5XTAMAllowLongSignals + ? true + : xEU5MXTAMAllowLongSignals; + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + xEU5MXSIAllowLongSignals = + xEU5XSIAllowLongSignals + ? true + : xEU5MXSIAllowLongSignals; + } + + // + // XSTFI ... + if (xEU5MXSTFIEnableSignaller) + { + xEU5MXSTFIAllowLongSignals = + xEU5XSTFIAllowLongSignals + ? true + : xEU5MXSTFIAllowLongSignals; + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + xEU5MXOBDLHAllowLongSignals = + xEU5XOBDLHAllowLongSignals + ? true + : xEU5MXOBDLHAllowLongSignals; + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + xEU5MXCHMACCAllowLongSignals = + xEU5XCHMACCAllowLongSignals + ? true + : xEU5MXCHMACCAllowLongSignals; + } + + // + // XCHMAMX ... + if (xEU5MXCHMACMXEnableSignaller) + { + xEU5MXCHMACMXAllowLongSignals = + xEU5XCHMACMXAllowLongSignals + ? true + : xEU5MXCHMACMXAllowLongSignals; + } + + // + // XCHMAMN ... + if (xEU5MXCHMACMNEnableSignaller) + { + xEU5MXCHMACMNAllowLongSignals = + xEU5XCHMACMNAllowLongSignals + ? true + : xEU5MXCHMACMNAllowLongSignals; + } +} + +// +// Disable All Signallers Shorts ... +void XEUDisableShortSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + xEU5MXTDAllowShortSignals = false; + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + xEU5MXTAMAllowShortSignals = false; + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + xEU5MXSIAllowShortSignals = false; + } + + // + // XSTFI ... + if (xEU5MXSTFIEnableSignaller) + { + xEU5MXSTFIAllowShortSignals = false; + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + xEU5MXOBDLHAllowShortSignals = false; + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + xEU5MXCHMACCAllowShortSignals = false; + } + + // + // XCHMAMX ... + if (xEU5MXCHMACMXEnableSignaller) + { + xEU5MXCHMACMXAllowShortSignals = false; + } + + // + // XCHMAMN ... + if (xEU5MXCHMACMNEnableSignaller) + { + xEU5MXCHMACMNAllowShortSignals = false; + } +} + +// +// Enable All Signallers Shorts ... +// Only if they are Configured as Enable at Settings ... +void XEUEnableShortSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + xEU5MXTDAllowShortSignals = + xEU5XTDAllowShortSignals + ? true + : xEU5MXTDAllowShortSignals; + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + xEU5MXTAMAllowShortSignals = + xEU5XTAMAllowShortSignals + ? true + : xEU5MXTAMAllowShortSignals; + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + xEU5MXSIAllowShortSignals = + xEU5XSIAllowShortSignals + ? true + : xEU5MXSIAllowShortSignals; + } + + // + // XSTFI ... + if (xEU5MXSTFIEnableSignaller) + { + xEU5MXSTFIAllowShortSignals = + xEU5XSTFIAllowShortSignals + ? true + : xEU5MXSTFIAllowShortSignals; + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + xEU5MXOBDLHAllowShortSignals = + xEU5XOBDLHAllowShortSignals + ? true + : xEU5MXOBDLHAllowShortSignals; + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + xEU5MXCHMACCAllowShortSignals = + xEU5XCHMACCAllowShortSignals + ? true + : xEU5MXCHMACCAllowShortSignals; + } + + // + // XCHMAMX ... + if (xEU5MXCHMACMXEnableSignaller) + { + xEU5MXCHMACMXAllowShortSignals = + xEU5XCHMACMXAllowShortSignals + ? true + : xEU5MXCHMACMXAllowShortSignals; + } + + // + // XCHMAMN ... + if (xEU5MXCHMACMNEnableSignaller) + { + xEU5MXCHMACMNAllowShortSignals = + xEU5XCHMACMNAllowShortSignals + ? true + : xEU5MXCHMACMNAllowShortSignals; + } +} + +// +// XTD Long Signal Checking ... +bool XEU5XTDHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTDEnableSignaller || + !xEU5MXTDAllowLongSignals) + { + return result; + } + + // + result = + // + xEU5Conditions.isXTDSignalCrossedOverBear && + // + !xEU5Conditions.isXLHHighAttachedHH && + !xEU5Conditions.isXLHPriceInSignalRange && + // + !xEU5Conditions.isXCHMAMCPeak && + !xEU5Conditions.isXCHMALCPeak && + !xEU5Conditions.isXCHMAMCFastUnderSlow && + !xEU5Conditions.isXCHMALCFastUnderSlow && + !xEU5Conditions.isXCHMAMCFastCrossedUnderSlow && + !xEU5Conditions.isXCHMALCFastCrossedUnderSlow + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXLHPriceOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBearishVale && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXTDSignalCrossedOverBear && + xEU5Conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXTDSignalCrossedOverBear && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XTD Short Signal Checking ... +bool XEU5XTDHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTDEnableSignaller || + !xEU5MXTDAllowShortSignals) + { + return result; + } + + // + result = + // + xEU5Conditions.isXTDSignalCrossedUnderBear + // + && + // + !xEU5Conditions.isXLHLowAttachedLL && + !xEU5Conditions.isXLHPriceInSignalRange && + // + !xEU5Conditions.isXCHMAMCVale && + !xEU5Conditions.isXCHMALCVale && + !xEU5Conditions.isXCHMAMCFastOverSlow && + !xEU5Conditions.isXCHMALCFastOverSlow && + !xEU5Conditions.isXCHMAMCFastCrossedOverSlow && + !xEU5Conditions.isXCHMALCFastCrossedOverSlow + // + && + // + !( + // + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin + // + ) + // + && + !( + // + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalCrossedUnderBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBearish && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXTDSignalCrossedUnderBear && + xEU5Conditions.isXLHPriceCrossedUnderSignal && + xEU5Conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XTAM Long Signal Checking ... +bool XEU5XTAMHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTAMEnableSignaller || + !xEU5MXTAMAllowLongSignals) + { + return result; + } + + // + result = + // + xAMAMaBuffer[1] > xTMMaBuffer[1] && + xAMAMaBuffer[2] > xTMMaBuffer[2] + // + && + // + xEU5Conditions.isXAMABullish + // + && + // + xEU5Conditions.isXTMBullish + // + && + // + xEU5Conditions.isXLHLLSameInLength + // + && + // + xEU5Conditions.isXFIOverZero + // + && + // + xEU5Conditions.isXTSCurrentMax + // + && + // + xEU5Conditions.isXTSCurrentOverFarest + // + && + // + xEU5Conditions.isXCHMASCUnderMax + // + && + // + !xEU5Conditions.isXOBDSwingLow + // + && + // + !xEU5Conditions.isXTDSignalCrossedUnderBear + // + && + // + !( + // + ( + // + ( + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow) + // + && + // + ( + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow) + + ) + // + || + // + ( + // + ( + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow) + // + && + // + ( + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow) + // + && + // + ( + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + ) + // + ) + // + && + // + ( + // + ( + xEU5Conditions.isXCHMASCFastOverSlow + ? !xEU5Conditions.isXCHMASCTrendsDown + : true) + // + || + // + ( + xEU5Conditions.isXCHMAMCFastOverSlow + ? !xEU5Conditions.isXCHMAMCTrendsDown + : true) + // + || + // + ( + xEU5Conditions.isXCHMALCFastOverSlow + ? !xEU5Conditions.isXCHMALCTrendsDown + : true) + // + ) + // + && + // + ( + // + (xEU5Conditions.isXLHHHSameInLength || + xEU5Conditions.isXLHLLSameInLength) + ? !( + xEU5Conditions.isXLHPriceInSignalRange || + xEU5Conditions.isXLHPriceUnderSignal) + : true + // + ) + // + && + // + ( + // + xEU5Conditions.isXTSCurrentMax || + xEU5Conditions.isXFICrossedOverZero || + (xEU5Conditions.isXTSCurrentOverNearest || + xEU5Conditions.isXTSCurrentCrossedOverNearest) || + (xEU5Conditions.isXTSCurrentOverMediest || + xEU5Conditions.isXTSCurrentCrossedOverMediest) + ? (!xEU5Conditions.isXLHPriceOverSignal && + !xEU5Conditions.isXLHPriceUnderSignal && + !xEU5Conditions.isXLHPriceInSignalRange && + !xEU5Conditions.isXLHPriceCrossedOverSignal && + !xEU5Conditions.isXLHPriceCrossedUnderSignal + ? !( + ( + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + ( + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXLHLLSameInLength) + // + ) + : true) && + (xEU5Conditions.isXLHPriceInSignalRange + ? !xEU5Conditions.isXLHHighAttachedHH + : true) && + (xEU5Conditions.isXLHPriceUnderSignal + ? !(xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXLHLLSameInLength) + : true) && + ((xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) + ? !( + // + ( + ( + xEU5Conditions.isXLHLLDecreased || + xEU5Conditions.isXLHHHDecreased || + xEU5Conditions.isXLHHHSameInLength || + xEU5Conditions.isXLHHighAttachedHH) && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + ( + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + ( + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXRSICrossedUnderShortEntry && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + ) + : true) + : true + // + ) + // + && + // + ( + // + xEU5Conditions.isXLHLLSameInLength && + (xEU5Conditions.isXTSCurrentOverNearest || + xEU5Conditions.isXTSCurrentOverMediest) + ? !(xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) + : true + // + ) + // + && + // + // False Positives ... + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTSCurrentMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTMStartBullish && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXAMAStartBullish && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedUnderMax + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTSCurrentMax && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXLHLLSameInLength && + ( + // + xEU5Conditions.isXLHHHIncreased || + xEU5Conditions.isXLHHighAttachedHH + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMASCFastCrossedOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXTSCurrentOverFarest && + xEU5Conditions.isXTSCurrentOverMediest + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTDBearishVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTSCurrentMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXFICrossedOverZero && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXTSCurrentOverNearest && + xEU5Conditions.isXTSCurrentOverMediest && + xEU5Conditions.isXTDSignalCrossedOverBear && + xEU5Conditions.isXTSCurrentCrossedOverNearest && + xEU5Conditions.isXTSCurrentCrossedOverMediest + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTSCurrentMax && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXFICrossedOverZero && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXTDBullCrossedOverBear && + xEU5Conditions.isXLHPriceCrossedOverSignal && + xEU5Conditions.isXCHMAMCFastCrossedOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXRSICrossedOverLongExit + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXTDBullCrossedUnderBear) + // + || + // + ((xEU5Conditions.isXCHMASCFastUnderSlow || + xEU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + ((xEU5Conditions.isXCHMAMCVale && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow)) && + (xEU5Conditions.isXCHMALCVale && + (xEU5Conditions.isXCHMALCFastUnderSlow || + xEU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + || + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalUnderBear) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + ) + // + && + // + // Funded ... + !( + // + (xEU5Conditions.isXCHMALCPeak && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXLHPriceOverSignal && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XTAM Short Signal Checking ... +bool XEU5XTAMHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTAMEnableSignaller || + !xEU5MXTAMAllowShortSignals) + { + return result; + } + + // + result = + // + xAMAMaBuffer[1] < xTMMaBuffer[1] && + xAMAMaBuffer[2] < xTMMaBuffer[2] + // + && + // + xEU5Conditions.isXAMABearish + // + && + // + xEU5Conditions.isXTMBearish + // + && + // + xEU5Conditions.isXFIUnderZero + // + && + // + xEU5Conditions.isXTSCurrentMin + // + && + // + xEU5Conditions.isXTSCurrentUnderFarest + // + && + // + !xEU5Conditions.isXOBDSwingHigh + // + && + // + !( + // + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale + // + ) + // + && + // + ( + // + ((xEU5Conditions.isXTSCurrentUnderNearest || + xEU5Conditions.isXTSCurrentCrossedUnderNearest) || + (xEU5Conditions.isXTSCurrentUnderMediest || + xEU5Conditions.isXTSCurrentCrossedUnderMediest)) + ? ( + // + ( + // + (xEU5Conditions.isXLHPriceUnderSignal || + xEU5Conditions.isXLHPriceInSignalRange || + xEU5Conditions.isXLHPriceCrossedUnderSignal) + ? !( + (xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXLHLLDecreased && + (xEU5Conditions.isXCHLHSCMCLLSame || + xEU5Conditions.isXCHLHMCLCHHSame)) + // + || + // + (xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXLHHHIncreased) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSCMCHHSame) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHLHSameLLs || + xEU5Conditions.isXLHLowAttachedLL || + xEU5Conditions.isXLHHHSameInLength) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + // + xEU5Conditions.isXLHHHSameInLength + // + || + // + (xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + (xEU5Conditions.isXLHHHDecreased || + xEU5Conditions.isXCHMALCPeak)) + // + || + // + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + (xEU5Conditions.isXCHMALCPeak || + xEU5Conditions.isXCHMASCFastOverSlow)) + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXTDBullCrossedUnderBear) + // + || + // + (xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + ) + // + ) + // + ) + : (xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) + ? ( + !( + xEU5Conditions.isXCHLHSameHHs + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSCMCHHSame) + // + || + // + (xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXLHLLIncreased) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + (xEU5Conditions.isXLHHHSameInLength + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCFastOverSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + ( + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + ) + // + ) + // + || + // + ( + xEU5Conditions.isXLHLLSameInLength && + ( + // + (xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + )) + // + ) + // + ) + : ( + !xEU5Conditions.isXLHPriceOverSignal && + !xEU5Conditions.isXLHPriceUnderSignal && + !xEU5Conditions.isXLHPriceInSignalRange && + !xEU5Conditions.isXLHPriceCrossedOverSignal && + !xEU5Conditions.isXLHPriceCrossedUnderSignal) + ? !( + // + (xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + (xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow) + // + ) + : true) + // + ) + : true + // + ) + // + && + // + ( + // + ( + (xEU5Conditions.isXTDBullOverBear || + (xEU5Conditions.isXTDBullUnderBear || + xEU5Conditions.isXTDBullCrossedUnderBear)) && + (xEU5Conditions.isXTDSignalUnderBear || + xEU5Conditions.isXTDSignalCrossedUnderBear)) + ? !( + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXAMAVale) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXLHHHSameInLength) + // + || + // + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHPriceCrossedUnderSignal) + // + ) + : true + // + ) + // + && + // + ( + // + (xEU5Conditions.isXLHPriceUnderSignal || + xEU5Conditions.isXLHPriceCrossedUnderSignal) + ? !( + // + (xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXCHLHSameHHs) + // + || + // + ( + xEU5Conditions.isXLHHHSameInLength && + ( + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + (xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXLHLowAttachedLL) + // + || + // + (xEU5Conditions.isXCHMALCVale && + ( + // + xEU5Conditions.isXCHMAMCVale + // + || + // + xEU5Conditions.isXCHMASCFastOverSlow + // + ) + // + ) + // + || + // + xEU5Conditions.isXCHLHSameLLs + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXRSICrossedOverLongExit && + xEU5Conditions.isXLHPriceCrossedUnderSignal) + // + ) + : xEU5Conditions.isXLHPriceInSignalRange + ? ( + // + ( + xEU5Conditions.isXLHHHSameInLength + ? !( + // + xEU5Conditions.isXCHLHSameLLs + // + || + // + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXTDSignalVale || + xEU5Conditions.isXLHLLSameInLength) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + // Funded ... + ( + // + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCPeak) + // + || + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + : true + // + ) + // + ) + : (xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) + ? !( + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + ( + // + xEU5Conditions.isXLHLLSameInLength + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + ) + // + ) + // + ) + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHPriceInSignalRange && + xEU5Conditions.isXTSCurrentCrossedUnderFarest + // + ) + // + && + // + // False Positives ... + !( + ((xEU5Conditions.isXTSCurrentUnderNearest || + xEU5Conditions.isXTSCurrentCrossedUnderNearest) + // + || + // + (xEU5Conditions.isXTSCurrentUnderMediest || + xEU5Conditions.isXTSCurrentCrossedUnderMediest) + // + ) + // + ? (xEU5Conditions.isXLHPriceInSignalRange + ? ( + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + xEU5Conditions.isXFICrossedUnderZero + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXLHHHDecreased || + // + ( + // + xEU5Conditions.isXCHMAMCFastOverSlow || + // + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + || + // + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + (xEU5Conditions.isXTMBearish && + xEU5Conditions.isXAMABearish && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalCrossedUnderBear) + // + ) + // + || + // + (xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXTSCurrentCrossedUnderFarest && + xEU5Conditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + ) + // + ) + // + : (xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) + ? ( + // + (xEU5Conditions.isXLHHHSameInLength && + // + ( + // + xEU5Conditions.isXTMVale + // + || + // + xEU5Conditions.isXTDSignalCrossedUnderBear + // + || + // + (xEU5Conditions.isXCHLHMCLCHHSame && + (xEU5Conditions.isXCHMAMCPeak || + xEU5Conditions.isXCHMAMCFastOverSlow)) + // + || + // + (xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale) + // + || + // + (xEU5Conditions.isXCHMASCVale && + (xEU5Conditions.isXCHMALCVale || + xEU5Conditions.isXCHMASCFastOverSlow)) + // + || + // + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXLHLLIncreased) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + || + // + (!xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsDown && + !xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedUnderMax) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHHDecreased) + // + || + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + || + // + (xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + ) + // + : (xEU5Conditions.isXLHPriceUnderSignal || + xEU5Conditions.isXLHPriceCrossedUnderSignal) + ? ( + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + xEU5Conditions.isXCHLHSCMCHHSame + // + || + // + xEU5Conditions.isXCHMAMCFastOverSlow + // + || + // + xEU5Conditions.isXRSICrossedUnderShortExit + // + || + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale) + // + || + // + (xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + ((xEU5Conditions.isXCHMALCPeak || + xEU5Conditions.isXCHMAMCVale) && + xEU5Conditions.isXCHMALCFastOverSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHSCMCLLSame) + // + ) + // + // XLH Price False ... + : + // + // Funed ... + ( + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + ( + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXLHHHSameInLength) + // + || + // + ( + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + // Just Current XTS Min and Farest ... + : (xEU5Conditions.isXLHPriceInSignalRange + ? ( + // + (xEU5Conditions.isXLHHHSameInLength && + ( + // + xEU5Conditions.isXCHMASCFastOverSlow + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + (xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalCrossedUnderBear && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + : (xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) + ? ( + // + ( + xEU5Conditions.isXLHLLSameInLength && + ( + // + xEU5Conditions.isXCHLHMCLCLLSame + // + || + // + xEU5Conditions.isXFICrossedUnderZero + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + )) + // + ) + // + : ( + xEU5Conditions.isXLHPriceUnderSignal || + xEU5Conditions.isXLHPriceCrossedUnderSignal) + ? ( + // + ( + // + (xEU5Conditions.isXLHHHSameInLength && + ( + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + || + // + (xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXFICrossedUnderZero) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + (xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHLHMCOnTopOfLC) + // + || + // + ((xEU5Conditions.isXCHMALCPeak || + xEU5Conditions.isXCHMAMCVale) && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXTDBullOverBear) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + ) + // + ) + // + || + // + ( + (xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + ( + // + xEU5Conditions.isXLHHHDecreased + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale) + // + || + // + (xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXLHLowAttachedLL) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + ) + // + ) + // + // XLH Price Falses ... + : ( + // + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHSCMCHHSame) + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + ((xEU5Conditions.isXTMBearish || + xEU5Conditions.isXTMStartBearish) && + (xEU5Conditions.isXAMABearish || + xEU5Conditions.isXAMAStartBearish) && + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) && + xEU5Conditions.isXLHLLIncreased && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XSI Long Signal Checking ... +bool XEU5XSIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXSIEnableSignaller || + !xEU5MXSIAllowLongSignals) + { + return result; + } + + // + result = + // + xEU5Conditions.isXRSICrossedOverLongEntry && + xRSIBuffer[3] < xRSILongEntryValue + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMASCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCUnderMin + ? !( + // + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMASCFastUnderSlow + // + ) && + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCVale || + xEU5Conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMAMCFastOverSlow + ? !xEU5Conditions.isXCHMAMCTrendsDown + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCPeak + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCUnderMin + ? !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXTDBearishVale && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength + // + ) + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXTMEndBearishByNeutural + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHSCLCLLSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXLHPriceInSignalRange && + xEU5Conditions.isXCHMASCFastCrossedOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHSCLCLLSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMASCFastCrossedOverSlow + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XSI Short Signal Checking ... +bool XEU5XSIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXSIEnableSignaller || + !xEU5MXSIAllowShortSignals) + { + return result; + } + + // + result = + // + xEU5Conditions.isXRSICrossedUnderShortEntry && + xRSIBuffer[3] > xRSIShortEntryValue && + !xEU5Conditions.isXOBDSwingHigh + // + && + // + !( + // + ( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak + // + ) + // + || + // + ( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak + // + ) + // + || + // + ( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCPeak + // + ) + // + || + // + ( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXTDSignalCrossedOverBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXCHMASCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXTDSignalOverBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHSCLCHHSame && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXLHPriceInSignalRange + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBearish && + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHSCLCHHSame && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXLHPriceInSignalRange && + xEU5Conditions.isXLHPriceCrossedUnderSignal && + xEU5Conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXTDSignalCrossedOverBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXLHPriceCrossedUnderSignal && + xEU5Conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + && + // + !( + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXTDBullCrossedUnderBear && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMABullish && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear) || + (xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal) || + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + (xEU5Conditions.isXTSCurrentMax && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XSTFI Long Signal Checking ... +bool XEU5XSTFIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXSTFIEnableSignaller || + !xEU5MXSTFIAllowLongSignals) + { + return result; + } + + // + result = + // + // Base Condition ... + XTSGetMinValue(1) == xTSFarestBuffer[1] && + (xEU5Conditions.isXTSCurrentOverFarest || + xEU5Conditions.isXTSCurrentCrossedOverFarest) && + (xTSCurrentBuffer[1] < xTSNearestBuffer[1] || + xTSCurrentBuffer[1] < xTSMediestBuffer[1]) && + !(xEU5Conditions.isXTSCurrentUnderNearest || + xEU5Conditions.isXTSCurrentCrossedUnderNearest) + // + && + // + // Check Market MA's ... + ( + // + ( + // + ( + // + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + && + // + ( + // + !(xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + && + // + !(xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + && + // + !(xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + ) + // + // End of Check MA's ... + ) + // + && + // + // Check XTS ... + ( + // + !( + // + (xEU5Conditions.isXTSCurrentUnderNearest && + xEU5Conditions.isXTSCurrentCrossedUnderNearest) + // + || + // + (xEU5Conditions.isXTSCurrentUnderMediest && + xEU5Conditions.isXTSCurrentCrossedUnderMediest) + // + ) + // + // End Of Check XTS ... + ) + // + && + // + // Check XLH ... + ( + // + // Based On Price ... + !( + // + // Signal Range ... + ( + // + xEU5Conditions.isXLHPriceInSignalRange && + ( + // + ((xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + ( + // + xEU5Conditions.isXCHMALCPeak + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + (xEU5Conditions.isXTMStartBearish && + xEU5Conditions.isXAMAStartBearish && + xEU5Conditions.isXFICrossedOverZero) + // + || + // + (((xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow) || + xEU5Conditions.isXCHMALCPeak) && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastOverSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + // + ( + // + ((xEU5Conditions.isXCHMASCTrendsDown && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) && + (xEU5Conditions.isXCHMAMCTrendsDown && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow))) + // + || + // + (xEU5Conditions.isXAMABullish && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXOBDSwingHigh && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + ( + // + ((xEU5Conditions.isXCHMASCPeak || + xEU5Conditions.isXCHMAMCPeak) && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXFICrossedOverZero && + xEU5Conditions.isXTDSignalCrossedOverBear) + // + || + // + (xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXLHHHSameInLength) + // + || + // + (xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXTDBearishVale) + // + )) + // + ) + // + || + // + // Under Signal ... + ( + // + (xEU5Conditions.isXLHPriceUnderSignal || + xEU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + (xEU5Conditions.isXLHHHSameInLength && + ( + // + ((xEU5Conditions.isXCHMAMCVale || + xEU5Conditions.isXCHMAMCPeak || + xEU5Conditions.isXFICrossedUnderZero) && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural) + // + || + // + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + ( + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + // Funded ... + ( + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXTSCurrentOverFarest && + xEU5Conditions.isXTSCurrentUnderMediest) + // + || + // + (xEU5Conditions.isXCHMASCTrendsDown && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + ( + // + ((xEU5Conditions.isXCHMASCPeak || + xEU5Conditions.isXTDBearishVale || + xEU5Conditions.isXCHLHMCLCHHSame || + (xEU5Conditions.isXTMBearish && + xEU5Conditions.isXAMABearish) || + (xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow)) && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHLHMCLCHHSame && + (xEU5Conditions.isXFICrossedOverZero || + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXCHMAMCTrendsDown))) + // + || + // + (xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Over Signal ... + ( + // + (xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + ((xEU5Conditions.isXCHMASCPeak || + xEU5Conditions.isXCHMAMCPeak) && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXLHHHDecreased) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Price Nothing ... + ( + // + ( + !xEU5Conditions.isXLHPriceOverSignal && + !xEU5Conditions.isXLHPriceUnderSignal && + !xEU5Conditions.isXLHPriceInSignalRange && + !xEU5Conditions.isXLHPriceCrossedOverSignal && + !xEU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + (xEU5Conditions.isXLHHHSameInLength && + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + ) + // + ) + // + ) + // + // End Based On Price Check ... + ) + // + // End Of Check XLH ... + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XSTFI Short Signal Checking ... +bool XEU5XSTFIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXSTFIEnableSignaller || + !xEU5MXSTFIAllowShortSignals) + { + return result; + } + + // + result = + // + // Base Conditions ... + XTSGetMaxValue(1) == xTSFarestBuffer[1] && + (xEU5Conditions.isXTSCurrentUnderFarest || + xEU5Conditions.isXTSCurrentCrossedUnderFarest) && + (xTSCurrentBuffer[1] > xTSNearestBuffer[1] || + xTSCurrentBuffer[1] > xTSMediestBuffer[1]) && + !(xEU5Conditions.isXTSCurrentOverNearest || + xEU5Conditions.isXTSCurrentCrossedOverNearest) + // + && + // + // XOBD Check ... + !xEU5Conditions.isXOBDSwingHigh + // + && + // + // XCHMA Check ... + ( + // + !(xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + && + // + !(xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin) + // + && + // + !(xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + ) + // + && + // + // XLH Prices ... + ( + // + !( + // + // Signal Range ... + (xEU5Conditions.isXLHPriceInSignalRange && + // + ( + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural) + // + || + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXAMAVale && + xEU5Conditions.isXTMEndBearish) + // + || + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMAEndBullish && + xEU5Conditions.isXLHLLDecreased) + // + || + // + (xEU5Conditions.isXCHMASCTrendsUp && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCVale) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHLHMCLCLLSame) + // + || + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + ((xEU5Conditions.isXTMBullish || + xEU5Conditions.isXTMStartBullish) && + (xEU5Conditions.isXAMABullish || + xEU5Conditions.isXAMAStartBullish)) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + // + ( + // + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXAMAVale) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMABullish) + // + || + // + (xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXTDBearishVale) + // + || + // + // Funded ... + ( + // + ( + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXAMAEndBearish && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXFICrossedUnderZero) + // + || + // + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCTrendsUp && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHLLIncreased) + // + || + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + xEU5Conditions.isXCHMAMCPeak + // + || + // + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xEU5Conditions.isXAMABullish && + xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTMEndBearish) + // + || + // + ((xEU5Conditions.isXCHMAMCPeak || + xEU5Conditions.isXCHMAMCVale) && + (xEU5Conditions.isXCHMALCPeak || + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow))) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + ((xEU5Conditions.isXTMStartBullish && + xEU5Conditions.isXAMAEndBearish) || + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) || + (xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXTSCurrentOverMediest && + xEU5Conditions.isXTSCurrentUnderFarest && + xEU5Conditions.isXTSCurrentUnderNearest))) + // + || + // + // Funded ... + ( + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMABearish && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + || + ( + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + // + ( + // + xEU5Conditions.isXCHMALCPeak + // + || + // + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMAEndBearish && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHSCMCHHSame) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) && + ( + // + xEU5Conditions.isXCHMALCPeak + // + ) + // + ) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXTDBullCrossedOverBear) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSameLLs) + // + ) + // + ) + // + ) + // + || + // + // Under Signal ... + ((xEU5Conditions.isXLHPriceUnderSignal || + xEU5Conditions.isXLHPriceCrossedUnderSignal) && + // + ( + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + // + (xEU5Conditions.isXTMBearish && + xEU5Conditions.isXAMABearish) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXTDBearishVale) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + (xEU5Conditions.isXCHMALCVale || + xEU5Conditions.isXAMAVale || + xEU5Conditions.isXTMBullish || + xEU5Conditions.isXCHLHSCMCLLSame || + xEU5Conditions.isXFICrossedOverZero)) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXFICrossedUnderZero) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXCHMALCPeak || + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + // + ( + // + (xEU5Conditions.isXCHMASCVale && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastOverSlow)) + // + || + // + (xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXAMAVale) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXCHLHSCMCLLSame && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXLHLLIncreased) + // + || + // + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHMCLCHHSame && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + // + ( + // + xEU5Conditions.isXTDBearishVale + // + || + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + ((xEU5Conditions.isXTMVale || + xEU5Conditions.isXLHLLDecreased) && + xEU5Conditions.isXAMAVale) + // + || + ((xEU5Conditions.isXCHMASCVale || + xEU5Conditions.isXCHMALCVale) && + xEU5Conditions.isXCHMAMCVale) + // + || + // + (xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + ((xEU5Conditions.isXCHMALCPeak || + xEU5Conditions.isXFICrossedUnderZero || + xEU5Conditions.isXCHMAMCFastOverSlow) && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXFICrossedUnderZero) + // + ) + // + ) + // + || + // + ( + // + (xEU5Conditions.isXCHLHSCMCHHSame && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHMAMCTrendsDown) + // + || + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) + // + || + // + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXAMAVale && + xEU5Conditions.isXLHLowAttachedLL) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xEU5Conditions.isXAMANeutural && + (xEU5Conditions.isXTMBullish || + xEU5Conditions.isXTMStartBullish)) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHLHSameLLs) + // + || + // + (xEU5Conditions.isXLHHHDecreased && + (xEU5Conditions.isXLHLLDecreased || + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural))) + // + || + // + (xEU5Conditions.isXTMBearish && + xEU5Conditions.isXAMABearish && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHMAMCFastUnderSlow) + // + || + // + ((xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow) && + ( + // + xEU5Conditions.isXCHMAMCVale + // + || + // + xEU5Conditions.isXCHMALCVale + // + || + // + xEU5Conditions.isXCHLHSameLLs + // + || + // + xEU5Conditions.isXFICrossedOverZero + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMABullish) + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXCHMASCVale || + xEU5Conditions.isXLHLowAttachedLL) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXAMAStartBullish && + xEU5Conditions.isXRSICrossedOverLongEntry) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHSCMCLLSame && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXAMAEndBearish && + xEU5Conditions.isXCHLHSCMCLLSame && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + || + // + // Over Signal ... + ((xEU5Conditions.isXLHPriceOverSignal || + xEU5Conditions.isXLHPriceCrossedOverSignal) && + // + ( + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + // + ((xEU5Conditions.isXCHMAMCVale || + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXCHMASCVale) || + (xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXLHPriceCrossedOverSignal)) && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale) + // + || + // + (xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHLHMCLCLLSame) + // + || + // + (xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCFastOverSlow) + // + || + // + (xEU5Conditions.isXAMABullish && + xEU5Conditions.isXCHLHSCMCHHSame) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) || + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + // Funded ... + ( + // + (xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXLHLLIncreased) + // + ) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + // + ( + // + (xEU5Conditions.isXTMVale && + xEU5Conditions.isXAMAVale) + // + || + // + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMAMCPeak || + xEU5Conditions.isXAMANeutural || + xEU5Conditions.isXCHMALCVale || + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + (xEU5Conditions.isXTMStartBullish && + xEU5Conditions.isXAMAStartBullish) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCCrossedOverMax) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xEU5Conditions.isXCHMALCVale && + (xEU5Conditions.isXCHMAMCVale || + xEU5Conditions.isXCHMASCFastOverSlow || + (xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXCHLHSCMCLLSame))) + // + || + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMABullish) + // + || + // + (xEU5Conditions.isXCHLHSCMCLLSame || + xEU5Conditions.isXFICrossedUnderZero) + // + || + // + (xEU5Conditions.isXOBDSwingLow && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (((xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural) || + (xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMALCVale)) && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + // Funded ... + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXLHLLIncreased) + // + || + // + (xEU5Conditions.isXCHMALCVale && + (xEU5Conditions.isXCHMAMCTrendsDown && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + ( + // + ((xEU5Conditions.isXCHMASCVale || + xEU5Conditions.isXCHMAMCPeak) && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMANeutural) + // + || + // + (xEU5Conditions.isXTMEndBullish && + xEU5Conditions.isXAMAEndBullish) + // + || + // + (xEU5Conditions.isXTMStartBullish && + xEU5Conditions.isXAMAStartBullish) + // + || + // + (xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXAMAEndBearish) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXAMANeutural) + // + || + // + ((xEU5Conditions.isXCHMAMCPeak || + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + ( + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMABullish && + xEU5Conditions.isXLHHighAttachedHH) + // + || + // + ((xEU5Conditions.isXCHMAMCPeak || + xEU5Conditions.isXCHMASCTrendsUp || + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) && + (xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + ((xEU5Conditions.isXCHMALCPeak || + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXTMEndBullish && + xEU5Conditions.isXAMAEndBullish && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXFICrossedUnderZero) + // + ) + // + ) + // + ) + // + || + // + // Price Empty Condition ... + ((!xEU5Conditions.isXLHPriceOverSignal && + !xEU5Conditions.isXLHPriceInSignalRange && + !xEU5Conditions.isXLHPriceUnderSignal && + !xEU5Conditions.isXLHPriceCrossedUnderSignal && + !xEU5Conditions.isXLHPriceCrossedOverSignal) && + // + ( + // + (xEU5Conditions.isXLHHHSameInLength && + // + ( + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXAMANeutural && + (xEU5Conditions.isXTMEndBearish || + xEU5Conditions.isXTMNeutural) && + xEU5Conditions.isXLHLLIncreased) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXAMAEndBearish) + // + || + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + // Funded ... + ( + // + (xEU5Conditions.isXCHMALCPeak && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + || + // + (xEU5Conditions.isXLHLLSameInLength && + // + ( + // + (xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak) + // + || + // + (xEU5Conditions.isXAMAEndBearish && + xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXTMStartBullish) + // + || + // + ((xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + ((xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMABullish) + // + || + // + (xEU5Conditions.isXCHMAMCPeak && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXCHLHMCLCHHSame) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ); + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XOBDLH Long Signal Checking ... +bool XEU5XOBDLHHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXOBDLHEnableSignaller || + !xEU5MXOBDLHAllowLongSignals) + { + return result; + } + + // + double entry = GetEntry(X_SIGNAL_LONG); + XEU5MarketConditions conditions2 = XEU5GenerateMarketConditions(2); + + // + result = + // + conditions2.isXOBDSwingLow && + conditions2.isXLHLowAttachedLL && + xLHLLBuffer[1] >= xLHLLBuffer[2] && + // + ( + // + xEU5Conditions.isXLHPriceUnderSignal + ? entry < xLHSignalBuffer[1] + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCFastUnderSlow + ? !( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCUnderMin + ? !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale + // + ) + : true + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + ? !xEU5Conditions.isXCHMASCTrendsUp + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXLHLLDecreased && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXTDBullCrossedOverBear + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XOBDLH Short Signal Checking ... +bool XEU5XOBDLHHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXOBDLHEnableSignaller || + !xEU5MXOBDLHAllowShortSignals) + { + return result; + } + + // + double entry = GetEntry(X_SIGNAL_SHORT); + XEU5MarketConditions conditions2 = XEU5GenerateMarketConditions(2); + + // + result = + // + conditions2.isXOBDSwingHigh && + conditions2.isXLHHighAttachedHH && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + ( + // + ( + // + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) || + ( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastCrossedOverSlow + // + ) + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceInSignalRange && + xEU5Conditions.isXCHMASCCrossedUnderMax + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMStartBullish && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHPriceOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXTDSignalOverBear && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + // Funded ... + !( + // + (xEU5Conditions.isXTMBullish && + xEU5Conditions.isXAMABullish && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXTDSignalOverBear) + // + || + // + (xEU5Conditions.isXTSCurrentMax && + (xEU5Conditions.isXTSCurrentOverFarest || + xEU5Conditions.isXTSCurrentCrossedOverFarest) && + (xEU5Conditions.isXTSCurrentOverNearest || + xEU5Conditions.isXTSCurrentCrossedOverNearest) && + (xEU5Conditions.isXTSCurrentOverMediest || + xEU5Conditions.isXTSCurrentCrossedOverMediest)) + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal) + // + || + // + (xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCUnderMax) + // + || + // + ((xEU5Conditions.isXCHMASCFastOverSlow || + xEU5Conditions.isXCHMASCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XCHMACC Long Signal Checking ... +bool XEU5XCHMACCHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACCEnableSignaller || + !xEU5MXCHMACCAllowLongSignals) + { + return result; + } + + // + // Required Data ... + double entry = GetEntry(X_SIGNAL_LONG); + double nearHH = GetHighestHigh(3, 1); + double nearLL = GetLowestLow(3, 1); + + // + bool isSharpChanged = IsSharpIncreasedChanged( + 5, + 1, + xTMMaBuffer); + + // + bool isCandleSharpChanged = IsSharpIncreasedChanged( + 5, + 1, + PRICE_CLOSE); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + double xCHMANonSCMax3 = XCHMAGetCyclesMaxValue(3, cycles); + double xCHMANonSCMin3 = XCHMAGetCyclesMinValue(3, cycles); + + // + result = + // + xCHMAScFastBuffer[1] > xCHMAScSlowBuffer[1] && + xCHMAMcFastBuffer[1] > xCHMAMcSlowBuffer[1] && + xCHMALcFastBuffer[1] > xCHMALcSlowBuffer[1] && + // + xCHMAScFastBuffer[2] > xCHMAScSlowBuffer[2] && + xCHMAMcFastBuffer[2] > xCHMAMcSlowBuffer[2] && + xCHMALcFastBuffer[2] > xCHMALcSlowBuffer[2] && + // + !( + // + xCHMAScFastBuffer[3] > xCHMAScSlowBuffer[3] && + xCHMAMcFastBuffer[3] > xCHMAMcSlowBuffer[3] && + xCHMALcFastBuffer[3] > xCHMALcSlowBuffer[3] + // + ) + // + && + // + ( + // + XCHMAIsSCFastCrossedOverSlow(2) + ? XCHMAGetSCTrendPower(1) <= (XCHMAGetSCTrendPower(2) * 2) + : true + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCOverMax + ? XCHMAGetSCTrendPower(2) <= (xCHMANonSCMax2 - xCHMANonSCMin2) + : true + // + ) + // + && + // + !xEU5Conditions.isXCHMAMCTrendsDown + // + && + // + ( + // + xEU5Conditions.isXCHMASCCrossedOverMax || xEU5Conditions.isXLHPriceOverSignal + ? !isCandleSharpChanged + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak + // + ) + // + && + // + ( + // + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength + ? entry < nearHH + : true + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCFastOverSlow + ? !xEU5Conditions.isXCHMASCTrendsDown + : true) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XCHMACC Short Signal Checking ... +bool XEU5XCHMACCHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACCEnableSignaller || + !xEU5MXCHMACCAllowShortSignals) + { + return result; + } + + // + result = + // + xCHMAScFastBuffer[1] < xCHMAScSlowBuffer[1] && + xCHMAMcFastBuffer[1] < xCHMAMcSlowBuffer[1] && + xCHMALcFastBuffer[1] < xCHMALcSlowBuffer[1] && + // + xCHMAScFastBuffer[2] < xCHMAScSlowBuffer[2] && + xCHMAMcFastBuffer[2] < xCHMAMcSlowBuffer[2] && + xCHMALcFastBuffer[2] < xCHMALcSlowBuffer[2] && + // + !( + // + xCHMAScFastBuffer[3] < xCHMAScSlowBuffer[3] && + xCHMAMcFastBuffer[3] < xCHMAMcSlowBuffer[3] && + xCHMALcFastBuffer[3] < xCHMALcSlowBuffer[3] + // + ) + // + && + // + !( + // + ( + // + !xEU5Conditions.isXCHMASCTrendsUp && + !xEU5Conditions.isXCHMASCTrendsDown + // + ) + // + || + // + ( + // + !xEU5Conditions.isXCHMAMCTrendsUp && + !xEU5Conditions.isXCHMAMCTrendsDown + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameLLs && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXLHPriceUnderSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXCHMALCFastUnderSlow && + ( + // + !xEU5Conditions.isXCHMALCTrendsUp && + !xEU5Conditions.isXCHMALCTrendsDown + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceInSignalRange + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXTMStartBullishAfterNeutural + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXTMEndBullishByNeutural && + xEU5Conditions.isXTDSignalCrossedUnderBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHHIncreased && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceInSignalRange + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXTMEndBearishByNeutural + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDSignalVale && + xEU5Conditions.isXTDBullishVale && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedUnderMin + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXTMEndBearishByNeutural + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXTDBullCrossedUnderBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXTMStartBullishAfterNeutural + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBearish && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceInSignalRange && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBearish && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCUnderMin && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + (xEU5Conditions.isXTMEndBearish && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceUnderSignal) + // + ) + // + && + // + // Funded ... + !( + // + (xEU5Conditions.isXTMVale && + (xEU5Conditions.isXTMBearish || + xEU5Conditions.isXTMStartBearish) && + xEU5Conditions.isXAMAVale && + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHPriceUnderSignal) + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXFIOverZero && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXTDBullOverBear) + // + || + // + (xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XCHMACMN Long Signal Checking ... +bool XEU5XCHMACMNHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACMNEnableSignaller || + !xEU5MXCHMACMNAllowLongSignals) + { + return result; + } + + // + // Required Data ... + double entry = GetEntry(X_SIGNAL_LONG); + double nearHH = GetHighestHigh(3, 1); + double nearLL = GetLowestLow(3, 1); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + result = + // + xEU5Conditions.isXCHMASCCrossedOverMin && + xCHMAScFastBuffer[2] < xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMin2 && + // + ( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax + ? !( + // + XCHMAGetCycleMaxValue(1, X_XCHMA_CYCLE_MEDIUM) < XCHMAGetCycleMaxValue(1, X_XCHMA_CYCLE_LONG) && + XCHMAGetCycleMinValue(1, X_XCHMA_CYCLE_MEDIUM) > XCHMAGetCycleMinValue(1, X_XCHMA_CYCLE_LONG) + // + ) + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHighAttachedHH + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + ? !xEU5Conditions.isXLHPriceInSignalRange + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHPriceOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXRSICrossedOverLongExit + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDBearishVale && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMASCFastCrossedOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceOverSignal && + xEU5Conditions.isXCHMASCCrossedOverMin && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCCrossedOverMin && + xEU5Conditions.isXLHPriceCrossedOverSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + (xEU5Conditions.isXCHLHMCLCHHSame || + xEU5Conditions.isXCHLHMCLCLLSame) && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedOverMin && + xEU5Conditions.isXCHMASCFastCrossedOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal && + (xEU5Conditions.isXCHMAMCVale && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow)) && + (xEU5Conditions.isXCHMALCVale && + (xEU5Conditions.isXCHMALCFastUnderSlow || + xEU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + && + // + // Funded ... + !( + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXTSCurrentMax && + xEU5Conditions.isXAMAEndBearish && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHPriceUnderSignal) + // + || + // + (xEU5Conditions.isXCHMAMCVale && + (xEU5Conditions.isXCHMASCFastUnderSlow || + xEU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + ( + // + xEU5Conditions.isXOBDSwingLow + // + || + // + (xEU5Conditions.isXTMNeutural && + xEU5Conditions.isXAMANeutural && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXTDBullCrossedOverBear) + // + || + // + (xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHPriceInSignalRange) + // + || + // + ((xEU5Conditions.isXCHMASCFastUnderSlow || + xEU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xEU5Conditions.isXCHMAMCFastUnderSlow || + xEU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XCHMACMN Short Signal Checking ... +bool XEU5XCHMACMNHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACMNEnableSignaller || + !xEU5MXCHMACMNAllowShortSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + double xCHMANonSCMin3 = XCHMAGetCyclesMinValue(3, cycles); + + // + result = + // + xEU5Conditions.isXCHMASCCrossedUnderMin && + xCHMAScFastBuffer[2] > xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] > xCHMANonSCMin2 + // + && + // + !( + // + ( + // + xEU5Conditions.isXCHMASCFastCrossedOverSlow || + ( + // + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow + // + ) + // + ) && + ( + // + xEU5Conditions.isXCHMAMCFastCrossedOverSlow || + ( + // + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + ) && + ( + // + xEU5Conditions.isXCHMALCFastCrossedOverSlow || + ( + // + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXCHMALCVale + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXCHMALCFastUnderSlow && + // + ( + // + ( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow + // + ) || + ( + // + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBearish && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXTDBullCrossedUnderBear + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceInSignalRange + // + ) + // + && + // + !( + // + ( + // + xEU5Conditions.isXCHMASCVale || + xEU5Conditions.isXCHMAMCVale + // + ) + // + && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXTDSignalUnderBear && + ( + // + ( + // + xEU5Conditions.isXTMVale && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength + // + ) || + ( + // + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMALCVale && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + // Funded ... + !( + // + (xEU5Conditions.isXAMAVale && + xEU5Conditions.isXCHMAMCVale && + xEU5Conditions.isXTDBullOverBear) + // + || + // + ((xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength) && + (xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XCHMACMX Long Signal Checking ... +bool XEU5XCHMACMXHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACMXEnableSignaller || + !xEU5MXCHMACMXAllowLongSignals) + { + return result; + } + + // + // Required Data ... + double entry = GetEntry(X_SIGNAL_LONG); + double nearHH = GetHighestHigh(3, 1); + double nearLL = GetLowestLow(3, 1); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + result = + // + xEU5Conditions.isXCHMASCCrossedOverMax && + xCHMAScFastBuffer[2] < xCHMANonSCMax2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMax2 && + MathAbs(xCHMANonSCMax2 - xCHMAScFastBuffer[2]) > MathAbs(xCHMAScFastBuffer[2] - xCHMAScSlowBuffer[2]) && + MathAbs(xCHMANonSCMax2 - xCHMAScSlowBuffer[2]) > MathAbs(xCHMAScFastBuffer[2] - xCHMAScSlowBuffer[2]) + // + && + // + !( + // + xEU5Conditions.isXLHPriceInSignalRange && + xEU5Conditions.isXLHHighAttachedHH + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + ( + // + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCOnTopOfLC && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXLHLLSameInLength + ? entry < nearHH + : true + // + ) + // + && + // + !( + // + xEU5Conditions.isXTMBullish && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXLHHighAttachedHH && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedOverMax && + xEU5Conditions.isXTDSignalCrossedOverBear + // + ) && + // + !( + // + (xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXLHHHDecreased && + xEU5Conditions.isXCHMASCOverMax && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedOverMax && + xEU5Conditions.isXLHPriceCrossedOverSignal) + // + || + // + (xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceOverSignal) + // + || + // + (xEU5Conditions.isXCHMASCPeak && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// XCHMACMX Short Signal Checking ... +bool XEU5XCHMACMXHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACMXEnableSignaller || + !xEU5MXCHMACMXAllowShortSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax3 = XCHMAGetCyclesMaxValue(3, cycles); + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + result = + // + xEU5Conditions.isXCHMASCCrossedUnderMax && + xCHMAScFastBuffer[2] > xCHMANonSCMax2 && + xCHMAScSlowBuffer[2] > xCHMANonSCMax2 + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMALCPeak + // + ) + // + && + // + !( + // + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXLHPriceInSignalRange && + // + ( + // + ( + // + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) || + ( + // + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXTDSignalUnderBear + // + ) + // + ) + // + ) + // + && + // + !( + // + ( + // + xEU5Conditions.isXCHMASCFastCrossedOverSlow || + ( + // + xEU5Conditions.isXCHMASCTrendsUp && + xEU5Conditions.isXCHMASCFastOverSlow + // + ) + // + ) && + ( + // + xEU5Conditions.isXCHMAMCFastCrossedOverSlow || + ( + // + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow + // + ) + // + ) && + ( + // + xEU5Conditions.isXCHMALCFastCrossedOverSlow || + ( + // + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + ) + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMin + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHLHSCMCLLSame && + xEU5Conditions.isXCHLHMCLCHHSame && + xEU5Conditions.isXLHLowAttachedLL + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHLHSameHHs && + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHMAMCTrendsUp && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXLHPriceInSignalRange + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXLHLLIncreased && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHPriceUnderSignal && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMAMCPeak && + xEU5Conditions.isXCHLHSCMCHHSame && + xEU5Conditions.isXCHLHMCLCLLSame && + xEU5Conditions.isXTDBullUnderBear && + xEU5Conditions.isXLHLLSameInLength && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMAMCFastUnderSlow && + xEU5Conditions.isXCHMALCFastUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXCHMALCTrendsUp && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMASCFastOverSlow && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCCrossedUnderMax && + xEU5Conditions.isXLHPriceCrossedUnderSignal + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCCrossedUnderMax && + xEU5Conditions.isXTDSignalCrossedUnderBear && + xEU5Conditions.isXCHMASCFastCrossedUnderSlow + // + ) + // + && + // + !( + // + xEU5Conditions.isXCHMALCPeak && + xEU5Conditions.isXCHMASCOverMin && + xEU5Conditions.isXTDBullOverBear && + xEU5Conditions.isXCHMASCUnderMax && + xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXCHMASCTrendsDown && + xEU5Conditions.isXCHMAMCTrendsDown && + xEU5Conditions.isXCHMALCTrendsDown && + xEU5Conditions.isXTDSignalUnderBear && + xEU5Conditions.isXCHMAMCFastOverSlow && + xEU5Conditions.isXCHMALCFastOverSlow && + xEU5Conditions.isXCHMASCFastUnderSlow && + xEU5Conditions.isXCHMASCCrossedUnderMax + // + ) + // + && + // + !( + // + (xEU5Conditions.isXLHLowAttachedLL && + xEU5Conditions.isXLHHHSameInLength && + xEU5Conditions.isXLHPriceUnderSignal && + (xEU5Conditions.isXCHMAMCFastOverSlow || + xEU5Conditions.isXCHMAMCFastCrossedOverSlow) && + (xEU5Conditions.isXCHMALCFastOverSlow || + xEU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ; + + // + // Funded Next ... + if (isXEU5OnFundedNext && result) + { + // + result = + // + true + // + ; + } + + // + return result; +} + +// +// END Signal Providers ... +// + +// +// START Utilities ... +// + +// +// Converts Market Conditions to Specific String Representation ... +string XEU5GetConditionsString( + XEU5MarketConditions &condition, // Specify Conditiond + string separator = ",", // Specify Separator + bool ignoreFalses = true // Ignore False Conditions +) +{ + // + XEU5MarketConditions mConditions = {}; + + // + mConditions = condition; + + // + string result = "\n"; + + // + // XOBD ... + result += + "| XOBD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXOBDSwingLow)) + { + result += "isXOBDSwingLow: " + (string)mConditions.isXOBDSwingLow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXOBDSwingHigh)) + { + result += "isXOBDSwingHigh: " + (string)mConditions.isXOBDSwingHigh + separator; + } + + // + // Separator ... + result += separator; + + // + // XTM ... + result += + "| XTM |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMPeak)) + { + result += "isXTMPeak: " + (string)mConditions.isXTMPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMVale)) + { + result += "isXTMVale: " + (string)mConditions.isXTMVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBullish)) + { + result += "isXTMStartBullish: " + (string)mConditions.isXTMStartBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBullishAfterNeutural)) + { + result += "isXTMStartBullishAfterNeutural: " + (string)mConditions.isXTMStartBullishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMBullish)) + { + result += "isXTMBullish: " + (string)mConditions.isXTMBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBullish)) + { + result += "isXTMEndBullish: " + (string)mConditions.isXTMEndBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBullishByNeutural)) + { + result += "isXTMEndBullishByNeutural: " + (string)mConditions.isXTMEndBullishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBearish)) + { + result += "isXTMStartBearish: " + (string)mConditions.isXTMStartBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBearishAfterNeutural)) + { + result += "isXTMStartBearishAfterNeutural: " + (string)mConditions.isXTMStartBearishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMBearish)) + { + result += "isXTMBearish: " + (string)mConditions.isXTMBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBearish)) + { + result += "isXTMEndBearish: " + (string)mConditions.isXTMEndBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBearishByNeutural)) + { + result += "isXTMEndBearishByNeutural: " + (string)mConditions.isXTMEndBearishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMNeutural)) + { + result += "isXTMNeutural: " + (string)mConditions.isXTMNeutural + separator; + } + + // + // Separator ... + result += separator; + + // + // XAMA ... + result += + "| XAMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAPeak)) + { + result += "isXAMAPeak: " + (string)mConditions.isXAMAPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAVale)) + { + result += "isXAMAVale: " + (string)mConditions.isXAMAVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBullish)) + { + result += "isXAMAStartBullish: " + (string)mConditions.isXAMAStartBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBullishAfterNeutural)) + { + result += "isXAMAStartBullishAfterNeutural: " + (string)mConditions.isXAMAStartBullishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMABullish)) + { + result += "isXAMABullish: " + (string)mConditions.isXAMABullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBullish)) + { + result += "isXAMAEndBullish: " + (string)mConditions.isXAMAEndBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBullishByNeutural)) + { + result += "isXAMAEndBullishByNeutural: " + (string)mConditions.isXAMAEndBullishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBearish)) + { + result += "isXAMAStartBearish: " + (string)mConditions.isXAMAStartBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBearishAfterNeutural)) + { + result += "isXAMAStartBearishAfterNeutural: " + (string)mConditions.isXAMAStartBearishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMABearish)) + { + result += "isXAMABearish: " + (string)mConditions.isXAMABearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBearish)) + { + result += "isXAMAEndBearish: " + (string)mConditions.isXAMAEndBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBearishByNeutural)) + { + result += "isXAMAEndBearishByNeutural: " + (string)mConditions.isXAMAEndBearishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMANeutural)) + { + result += "isXAMANeutural: " + (string)mConditions.isXAMANeutural + separator; + } + + // + // Separator ... + result += separator; + + // + // XTD ... + result += + "| XTD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalPeak)) + { + result += "isXTDSignalPeak: " + (string)mConditions.isXTDSignalPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalVale)) + { + result += "isXTDSignalVale: " + (string)mConditions.isXTDSignalVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullishPeak)) + { + result += "isXTDBullishPeak: " + (string)mConditions.isXTDBullishPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullishVale)) + { + result += "isXTDBullishVale: " + (string)mConditions.isXTDBullishVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBearishPeak)) + { + result += "isXTDBearishPeak: " + (string)mConditions.isXTDBearishPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBearishVale)) + { + result += "isXTDBearishVale: " + (string)mConditions.isXTDBearishVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullOverBear)) + { + result += "isXTDBullOverBear: " + (string)mConditions.isXTDBullOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullUnderBear)) + { + result += "isXTDBullUnderBear: " + (string)mConditions.isXTDBullUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalOverBear)) + { + result += "isXTDSignalOverBear: " + (string)mConditions.isXTDSignalOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalUnderBear)) + { + result += "isXTDSignalUnderBear: " + (string)mConditions.isXTDSignalUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullCrossedOverBear)) + { + result += "isXTDBullCrossedOverBear: " + (string)mConditions.isXTDBullCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullCrossedUnderBear)) + { + result += "isXTDBullCrossedUnderBear: " + (string)mConditions.isXTDBullCrossedUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalCrossedOverBear)) + { + result += "isXTDSignalCrossedOverBear: " + (string)mConditions.isXTDSignalCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalCrossedUnderBear)) + { + result += "isXTDSignalCrossedUnderBear: " + (string)mConditions.isXTDSignalCrossedUnderBear + separator; + } + + // + // Separator ... + result += separator; + + // + // XFI ... + result += + "| XFI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIPeak)) + { + result += "isXFIPeak: " + (string)mConditions.isXFIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIVale)) + { + result += "isXFIVale: " + (string)mConditions.isXFIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIOverZero)) + { + result += "isXFIOverZero: " + (string)mConditions.isXFIOverZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIUnderZero)) + { + result += "isXFIUnderZero: " + (string)mConditions.isXFIUnderZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFICrossedOverZero)) + { + result += "isXFICrossedOverZero: " + (string)mConditions.isXFICrossedOverZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFICrossedUnderZero)) + { + result += "isXFICrossedUnderZero: " + (string)mConditions.isXFICrossedUnderZero + separator; + } + + // + // Separator ... + result += separator; + + // + // XTS ... + result += + "| XTS |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSAllSame)) + { + result += "isXTSAllSame: " + (string)mConditions.isXTSAllSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentMin)) + { + result += "isXTSCurrentMin: " + (string)mConditions.isXTSCurrentMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentMax)) + { + result += "isXTSCurrentMax: " + (string)mConditions.isXTSCurrentMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverFarest)) + { + result += "isXTSCurrentOverFarest: " + (string)mConditions.isXTSCurrentOverFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverNearest)) + { + result += "isXTSCurrentOverNearest: " + (string)mConditions.isXTSCurrentOverNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverMediest)) + { + result += "isXTSCurrentOverMediest: " + (string)mConditions.isXTSCurrentOverMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderFarest)) + { + result += "isXTSCurrentUnderFarest: " + (string)mConditions.isXTSCurrentUnderFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderNearest)) + { + result += "isXTSCurrentUnderNearest: " + (string)mConditions.isXTSCurrentUnderNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderMediest)) + { + result += "isXTSCurrentUnderMediest: " + (string)mConditions.isXTSCurrentUnderMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverFarest)) + { + result += "isXTSCurrentCrossedOverFarest: " + (string)mConditions.isXTSCurrentCrossedOverFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverNearest)) + { + result += "isXTSCurrentCrossedOverNearest: " + (string)mConditions.isXTSCurrentCrossedOverNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverMediest)) + { + result += "isXTSCurrentCrossedOverMediest: " + (string)mConditions.isXTSCurrentCrossedOverMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderFarest)) + { + result += "isXTSCurrentCrossedUnderFarest: " + (string)mConditions.isXTSCurrentCrossedUnderFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderNearest)) + { + result += "isXTSCurrentCrossedUnderNearest: " + (string)mConditions.isXTSCurrentCrossedUnderNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderMediest)) + { + result += "isXTSCurrentCrossedUnderMediest: " + (string)mConditions.isXTSCurrentCrossedUnderMediest + separator; + } + + // + // Separator ... + result += separator; + + // + // XLH ... + result += + "| XLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHIncreased)) + { + result += "isXLHHHIncreased: " + (string)mConditions.isXLHHHIncreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHDecreased)) + { + result += "isXLHHHDecreased: " + (string)mConditions.isXLHHHDecreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLIncreased)) + { + result += "isXLHLLIncreased: " + (string)mConditions.isXLHLLIncreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLDecreased)) + { + result += "isXLHLLDecreased: " + (string)mConditions.isXLHLLDecreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHighAttachedHH)) + { + result += "isXLHHighAttachedHH: " + (string)mConditions.isXLHHighAttachedHH + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLowAttachedLL)) + { + result += "isXLHLowAttachedLL: " + (string)mConditions.isXLHLowAttachedLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHSameInLength)) + { + result += "isXLHHHSameInLength: " + (string)mConditions.isXLHHHSameInLength + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLSameInLength)) + { + result += "isXLHLLSameInLength: " + (string)mConditions.isXLHLLSameInLength + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceCrossedOverSignal)) + { + result += "isXLHPriceCrossedOverSignal: " + (string)mConditions.isXLHPriceCrossedOverSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceOverSignal)) + { + result += "isXLHPriceOverSignal: " + (string)mConditions.isXLHPriceOverSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceCrossedUnderSignal)) + { + result += "isXLHPriceCrossedUnderSignal: " + (string)mConditions.isXLHPriceCrossedUnderSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceUnderSignal)) + { + result += "isXLHPriceUnderSignal: " + (string)mConditions.isXLHPriceUnderSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceInSignalRange)) + { + result += "isXLHPriceInSignalRange: " + (string)mConditions.isXLHPriceInSignalRange + separator; + } + + // + // Separator ... + result += separator; + + // + // XRSI ... + result += + "| XRSI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSIPeak)) + { + result += "isXRSIPeak: " + (string)mConditions.isXRSIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSIVale)) + { + result += "isXRSIVale: " + (string)mConditions.isXRSIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedOverLongExit)) + { + result += "isXRSICrossedOverLongExit: " + (string)mConditions.isXRSICrossedOverLongExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedOverLongEntry)) + { + result += "isXRSICrossedOverLongEntry: " + (string)mConditions.isXRSICrossedOverLongEntry + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedUnderShortExit)) + { + result += "isXRSICrossedUnderShortExit: " + (string)mConditions.isXRSICrossedUnderShortExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedUnderShortEntry)) + { + result += "isXRSICrossedUnderShortEntry: " + (string)mConditions.isXRSICrossedUnderShortEntry + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHLH ... + result += + "| XCHLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSameHHs)) + { + result += "isXCHLHSameHHs: " + (string)mConditions.isXCHLHSameHHs + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSameLLs)) + { + result += "isXCHLHSameLLs: " + (string)mConditions.isXCHLHSameLLs + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCMCHHSame)) + { + result += "isXCHLHSCMCHHSame: " + (string)mConditions.isXCHLHSCMCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCMCLLSame)) + { + result += "isXCHLHSCMCLLSame: " + (string)mConditions.isXCHLHSCMCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCLCHHSame)) + { + result += "isXCHLHSCLCHHSame: " + (string)mConditions.isXCHLHSCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCLCLLSame)) + { + result += "isXCHLHSCLCLLSame: " + (string)mConditions.isXCHLHSCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCLCHHSame)) + { + result += "isXCHLHMCLCHHSame: " + (string)mConditions.isXCHLHMCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCLCLLSame)) + { + result += "isXCHLHMCLCLLSame: " + (string)mConditions.isXCHLHMCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCOnTopOfLC)) + { + result += "isXCHLHMCOnTopOfLC: " + (string)mConditions.isXCHLHMCOnTopOfLC + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCInBottomOfLC)) + { + result += "isXCHLHMCInBottomOfLC: " + (string)mConditions.isXCHLHMCInBottomOfLC + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHMA ... + result += + "| XCHMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCOverMax)) + { + result += "isXCHMASCOverMax: " + (string)mConditions.isXCHMASCOverMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCOverMin)) + { + result += "isXCHMASCOverMin: " + (string)mConditions.isXCHMASCOverMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCUnderMax)) + { + result += "isXCHMASCUnderMax: " + (string)mConditions.isXCHMASCUnderMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCUnderMin)) + { + result += "isXCHMASCUnderMin: " + (string)mConditions.isXCHMASCUnderMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedOverMax)) + { + result += "isXCHMASCCrossedOverMax: " + (string)mConditions.isXCHMASCCrossedOverMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedUnderMax)) + { + result += "isXCHMASCCrossedUnderMax: " + (string)mConditions.isXCHMASCCrossedUnderMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedOverMin)) + { + result += "isXCHMASCCrossedOverMin: " + (string)mConditions.isXCHMASCCrossedOverMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedUnderMin)) + { + result += "isXCHMASCCrossedUnderMin: " + (string)mConditions.isXCHMASCCrossedUnderMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCPeak)) + { + result += "isXCHMASCPeak: " + (string)mConditions.isXCHMASCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCVale)) + { + result += "isXCHMASCVale: " + (string)mConditions.isXCHMASCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCTrendsUp)) + { + result += "isXCHMASCTrendsUp: " + (string)mConditions.isXCHMASCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCTrendsDown)) + { + result += "isXCHMASCTrendsDown: " + (string)mConditions.isXCHMASCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastOverSlow)) + { + result += "isXCHMASCFastOverSlow: " + (string)mConditions.isXCHMASCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastUnderSlow)) + { + result += "isXCHMASCFastUnderSlow: " + (string)mConditions.isXCHMASCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastCrossedOverSlow)) + { + result += "isXCHMASCFastCrossedOverSlow: " + (string)mConditions.isXCHMASCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastCrossedUnderSlow)) + { + result += "isXCHMASCFastCrossedUnderSlow: " + (string)mConditions.isXCHMASCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCPeak)) + { + result += "isXCHMAMCPeak: " + (string)mConditions.isXCHMAMCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCVale)) + { + result += "isXCHMAMCVale: " + (string)mConditions.isXCHMAMCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCTrendsUp)) + { + result += "isXCHMAMCTrendsUp: " + (string)mConditions.isXCHMAMCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCTrendsDown)) + { + result += "isXCHMAMCTrendsDown: " + (string)mConditions.isXCHMAMCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastOverSlow)) + { + result += "isXCHMAMCFastOverSlow: " + (string)mConditions.isXCHMAMCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastUnderSlow)) + { + result += "isXCHMAMCFastUnderSlow: " + (string)mConditions.isXCHMAMCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastCrossedOverSlow)) + { + result += "isXCHMAMCFastCrossedOverSlow: " + (string)mConditions.isXCHMAMCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastCrossedUnderSlow)) + { + result += "isXCHMAMCFastCrossedUnderSlow: " + (string)mConditions.isXCHMAMCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCPeak)) + { + result += "isXCHMALCPeak: " + (string)mConditions.isXCHMALCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCVale)) + { + result += "isXCHMALCVale: " + (string)mConditions.isXCHMALCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCTrendsUp)) + { + result += "isXCHMALCTrendsUp: " + (string)mConditions.isXCHMALCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCTrendsDown)) + { + result += "isXCHMALCTrendsDown: " + (string)mConditions.isXCHMALCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastOverSlow)) + { + result += "isXCHMALCFastOverSlow: " + (string)mConditions.isXCHMALCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastUnderSlow)) + { + result += "isXCHMALCFastUnderSlow: " + (string)mConditions.isXCHMALCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastCrossedOverSlow)) + { + result += "isXCHMALCFastCrossedOverSlow: " + (string)mConditions.isXCHMALCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastCrossedUnderSlow)) + { + result += "isXCHMALCFastCrossedUnderSlow: " + (string)mConditions.isXCHMALCFastCrossedUnderSlow + separator; + } + + // + // Separator ... + result += separator; + + // + return result; +} + +void Add( + ENUM_XEU5_SIGNAL_PROVIDERS item, + ENUM_XEU5_SIGNAL_PROVIDERS &items[]) +{ + // + ArrayResize( + items, + ArraySize(items) + 1); + + // + items[ArraySize(items) - 1] = item; +} +// +// START Utilities ... +// \ No newline at end of file diff --git a/XEU5-0/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 b/XEU5-0/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 new file mode 100644 index 0000000..b873b64 --- /dev/null +++ b/XEU5-0/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 @@ -0,0 +1,321 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XEU5 Signal Provider Library Inputs +// ----------------------------------------------------------- +// +// 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 Logger ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Classes ... +#include "../Classes/x-saherelm.class.lib.mq5" + +// +// START Definitions ... +// + +// +// Cross Signals Methods ... +enum ENUM_XEU5_CROSS_SIGNAL_METHOD +{ + // + // Do Nothing and Ignore them ... + XEU5_CROSS_SIGNAL_DO_NOTHING, + // + // Accept all Cross Signals and Act Usually ... + XEU5_CROSS_SIGNAL_REGULAR, + // + // Accept all Cross Signals and for Directional Act Usually and for Indirectional Ac Important ... + XEU5_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT, + // + // Accept all Cross Signals and for Directional Act Important and for Indirectional Ac Usually ... + XEU5_CROSS_SIGNAL_DIRECTION_IMPORTANT_INDIRECTION_REGULAR, + // + // Accept Only Indirectional Signals and Act Usually ... + XEU5_CROSS_SIGNAL_INDIRECTION_REGULAR, + // + // Accept Only Directional Signals and Act Usually ... + XEU5_CROSS_SIGNAL_DIRECTION_REGULAR, + // + // Accept Only Indirectional Signals and Act Important ... + XEU5_CROSS_SIGNAL_INDIRECTION_IMPORTANT, + // + // Accept Only Directional Signals and Act Important ... + XEU5_CROSS_SIGNAL_DIRECTION_IMPORTANT, +}; + +// +// END Definitions ... +// + +// +input group "XEU5 Provider"; + +// +// Commonly Used Configurations ... +input group "XEU5 Common"; +// +// Provider ... +input bool xEU5EnableProvider = true; // Enable Provider +input int xEU5NumberOfItemsPerTick = 30; // Number Of items Readed In Each Tick +// +// Alerts ... +input bool xEU5EnableAlerts = true; // Enable Events Alert +input bool xEU5EnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xEU5EnableDailyAlerts = false; // Send Alert on each new Day +input bool xEU5EnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xEU5EnableMonthlyAlerts = true; // Send Alert on each new Month +// +// Reports ... +input bool xEU5EnableDailyReports = false; // Send Report on each new Day +input bool xEU5EnableWeeklyReports = false; // Send Report on each new Week +input bool xEU5EnableMonthlyReports = true; // Send Report on each new Month + +// +// Trader and Expert Specific Configurations ... +input group "XEU5 Trader"; +input int xEU5MagicNumber = 16940561; // Trader MagicNumber +input int xEU5Slippage = 10; // Trader Slippage + +// +// Trades Management Configurations ... +input group "XEU5 Trade Management"; +input bool xEU5AllowLongTrades = true; // Allow Long Trades +input bool xEU5AllowShortTrades = true; // Allow Short Trades + +// +// Risk Management Configurations ... +input group "XEU5 Risk Management"; +// +input bool xEU5UseVirtualTPSl = true; // Use Virtual TP SL +// +// Trade Count ... +input int xEU5MaxAllowedTrades = 4; // Max Allowed Trades at Same Time +input ENUM_XEU5_CROSS_SIGNAL_METHOD xEU5CrossSignalsMethod = XEU5_CROSS_SIGNAL_REGULAR; // Handle Cross Signals Method +// +// Max Allowed Trade Age ... +input int xEU5MaxAllowedTradeAge = 0; // Detect Long Time Trades +input ENUM_X_GUARD_ACTIONS xEU5OldTradesAction = X_GUARD_DO_NOTHING; // What to do with Old Trades +// +// Trade Volume Specific Configurations ... +input double xEU5StaticVolumeFactor = 0.00002; // Static Volume baesd on Balance +input ENUM_STATIC_VOLUME_METHODS xEU5StaticVolumeMethod = X_STATIC_VOLUME_BASED_ON_DEPOSIT; // How to Calculate Static Volume +input double xEU5VolumeMultiplier = 2.0; // Volume Increase Multiplier +input double xEU5ApplyVolumeMultiplierFactor = 0.002; // Apply Volume Multiplier Rate based on Balance +input double xEU5MaxSupportedVolumePerTradeFactor = 0.00008; // Max Supported Volume Per Trade Factor based on Balance +input double xEU5IncreasedMaxSupportedVolumeRate = 0.3; // Increase Max Supported Volume based on Balance +// +// Trade Profits ... +input double xEU5MinRewardInPips = 15; // Minimum Reward Per Trade in Pips +input double xEU5RiskFreeStepInPips = 4; // Make Trades Risk Free Steps in Pips +input double xEU5RiskFreeRate = 0.75; // Volume Multiplier for Risk Free Trades +// +// Guard Riskable Money and Profits ... +input double xEU5CriticalDrawDownFactor = 0.25; // Critical Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xEU5CriticalGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5; // Specify Guard Action on Critical Drawdown +input double xEU5MaxAllowedDrawDownFactor = 0.4; // Max Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xEU5MaxAllowedGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10; // Specify Guard Action on Max Allowed Drawdown +input int xEU5GuardStopoutFiredAfterTouches = 5; // Guard Stopout all Trades if Max Allowed Drawdown touched +// +// TODO: Complete this ... +// input ENUM_X_GUARD_SUPPORT_METHODS xEU5GuardSupportMethod = X_SUPPORT_DO_NOTHING; // How to Supprt Open Trades + +// +// Account Conditions for Trading ... +input double xEU5BalanceFactorForOpenTrades = 0.5; // Minimum Balance for Open Trades +input double xEU5FreeMarginFactorForOpenTrades = 0.8; // Minimum Free Margin for Open Trades + +// +// Validate Inputs before Initialization ... +bool XEU5ValidateInputs() +{ + // + bool result = false; + + // + // Implement Other Verifications ... + + // + // Check Trading Availability ... + bool isTradeAvailable = xEU5AllowLongTrades || xEU5AllowShortTrades; + if (!isTradeAvailable) + { + LogMessage("XEU5 => Warning: Trading disabled ..."); + } + + // + // Chekc Number of reading items per tick ... + result = xEU5NumberOfItemsPerTick >= 5; + if (!result) + { + // + LogMessage("XEU5 invalid Number of items Reading Per Tick ..."); + + // + return result; + } + + // + // Check Max Allowed Trades Count ... + result = isTradeAvailable && xEU5MaxAllowedTrades >= 1; + if (!result) + { + // + LogMessage("XEU5 Number of Trades not valid ..."); + + // + return result; + } + + // + // Check Free Margin ... + result = + isTradeAvailable && + xEU5FreeMarginFactorForOpenTrades > 0 && + xEU5FreeMarginFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XEU5 Invalid Free Margin ..."); + + // + return result; + } + + // + // Check min Balance for Open Trades ... + result = + isTradeAvailable && + xEU5BalanceFactorForOpenTrades > 0 && + xEU5BalanceFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XEU5 Invalid Min Balance for Open Trades ..."); + + // + return result; + } + + // + // Check Min Reward Per Trade ... + result = xEU5MinRewardInPips > 0; + if (!result) + { + // + LogMessage("XEU5 Invalid Min Reward Per Trade ..."); + + // + return result; + } + + // + // Check Trades Volume ... + result = xEU5StaticVolumeFactor > 0; + if (!result) + { + // + LogMessage("XEU5 Invalid Static Volume ..."); + + // + return result; + } + + // + // Check Volume Multiplier ... + result = xEU5VolumeMultiplier >= 0; + if (!result) + { + // + LogMessage("XEU5 Invalid Volume Multiplier ..."); + + // + return result; + } + + // + result = + xEU5CriticalDrawDownFactor == 0 || (xEU5CriticalDrawDownFactor > 0 && + xEU5CriticalDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XEU5 Invalid Critical DrawDown Factor ..."); + + // + return result; + } + + // + result = + xEU5MaxAllowedDrawDownFactor == 0 || (xEU5MaxAllowedDrawDownFactor > 0 && + xEU5MaxAllowedDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XEU5 Invalid Max Allowed DrawDown Factor ..."); + + // + return result; + } + + // + // Check Guard Actions ... + // + result = + xEU5CriticalDrawDownFactor > 0 && + xEU5CriticalDrawDownFactor < 1 && + xEU5MaxAllowedDrawDownFactor > 0 && + xEU5MaxAllowedDrawDownFactor < 1; + if (!result) + { + // + LogMessage("XEU5 For Critical Drawdown, you have to Specify Max Drawdown also ..."); + + // + return result; + } + + // + result = xEU5CriticalDrawDownFactor > 0 && xEU5CriticalDrawDownFactor < xEU5MaxAllowedDrawDownFactor; + if (!result) + { + // + LogMessage("XEU5 Critical Drawdown must Smaller than Max Drawdown ..."); + + // + return result; + } + + // + if (xEU5CriticalDrawDownFactor > 0 && xEU5CriticalGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XEU5 IMPORTANT you Specified Critical Drawdown, but there is no any Guard Action ..."); + } + + // + if (xEU5MaxAllowedDrawDownFactor > 0 && xEU5MaxAllowedGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XEU5 IMPORTANT you Specified Max Allowed Drawdown, but there is no any Guard Action ..."); + } + + // + result = true; + + // + return result; +} \ No newline at end of file diff --git a/XEU5-0/Providers/x-saherelm.xeu5.provider.lib.mq5 b/XEU5-0/Providers/x-saherelm.xeu5.provider.lib.mq5 new file mode 100644 index 0000000..4366410 --- /dev/null +++ b/XEU5-0/Providers/x-saherelm.xeu5.provider.lib.mq5 @@ -0,0 +1,1370 @@ +//////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XEU5 Signal Provider Library +// -------------------------------------------------------- +// Name: XEU5SignalProvider +// Description: XEU5 based 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 + +#define XEU5ProviderName "XEU5" + +// +// START Inputs ... +// + +#include "x-saherelm.xeu5.provider.inputs.lib.mq5"; + +// +// END Inputs ... +// + +// +// 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 Class Libraries ... +#include "../Classes/x-saherelm.class.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +XCGuard *xEU5Guard; +XCTrade *xEU5Trader; +XCReporter *xEU5Reporter; +XCCollector *xEU5Collector; +XCAccountInfo *xEU5AccountInfo; +XCVolumeManager *xEU5VolumeManager; + +// +#include "x-saherelm.xeu5.provider.indicators.lib.mq5" + +// +// Controlling Variables ... +bool xEU5MEnableProvider = false; +bool xEU5MAllowLongTrades = false; +bool xEU5MAllowShortTrades = false; + +// +double xEU5Deposit = 0; +double xEU5Balance = 0; +double xEU5MinReward = 0; +double xEU5FreeMargin = 0; +double xEU5BalanceForOpenTrades = 0; +double xEU5FreeMarginForOpenTrades = 0; + +// +// Guard ... +double xEU5CriticalDrawDown = 0; +double xEU5MaxAllowedDrawDown = 0; + +// +double xEU5MaxDrawUp = 0; +double xEU5MaxDrawDown = 0; + +// +int NOT_ENOUGH_MONEY_ERROR = 4756; +const string XEU5_SUPPORT_ID = "SP"; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// Initial Library if required ... +bool XEU5InitSignalProviderLibrary() +{ + // + bool result = false; + + // + if (!xEU5EnableProvider) + { + return result; + } + + // + // Controlling Variables ... + xEU5MEnableProvider = xEU5EnableProvider; + xEU5MAllowLongTrades = xEU5AllowLongTrades; + xEU5MAllowShortTrades = xEU5AllowShortTrades; + + // + // Validate Inputs ... + result = XEU5ValidateInputs(); + if (!result) + { + return result; + } + + // + // Init Indicators ... + result = XEU5InitIndicators(); + if (!result) + { + return result; + } + + // + xEU5Reporter = new XCReporter(); + xEU5Collector = new XCCollector(); + xEU5AccountInfo = new XCAccountInfo(); + + // + // Calculate Account Deposit ... + xEU5Deposit = xEU5AccountInfo.GetInitialBalance(); + + // + // Prepare Min Reward ... + if (xEU5MinRewardInPips > 0) + { + xEU5MinReward = PipsToPrice(xEU5MinRewardInPips); + } + + // + // Calculate Min Balance for Trades ... + if (xEU5BalanceFactorForOpenTrades > 0) + { + xEU5BalanceForOpenTrades = xEU5BalanceFactorForOpenTrades * xEU5Deposit; + } + + // + // Claculate Min Free Marging for Trades ... + if (xEU5FreeMarginFactorForOpenTrades > 0) + { + xEU5FreeMarginForOpenTrades = xEU5FreeMarginFactorForOpenTrades * xEU5Deposit; + } + + // + // Calculate Init Time Critical DrawDown Value ... + if (xEU5CriticalDrawDownFactor > 0) + { + xEU5CriticalDrawDown = xEU5CriticalDrawDownFactor * xEU5Deposit; + } + + // + // Calculate Init Time Max Allowed DrawDown Value ... + if (xEU5MaxAllowedDrawDownFactor > 0) + { + xEU5MaxAllowedDrawDown = xEU5MaxAllowedDrawDownFactor * xEU5Deposit; + } + + // + // Instant Volume Manager ... + xEU5VolumeManager = new XCVolumeManager( + xEU5StaticVolumeFactor, + xEU5StaticVolumeMethod, + xEU5VolumeMultiplier, + xEU5ApplyVolumeMultiplierFactor, + xEU5MaxSupportedVolumePerTradeFactor, + xEU5IncreasedMaxSupportedVolumeRate); + + // + // Make XCTrader instance ... + xEU5Trader = new XCTrade( + XEU5ProviderName, + _Symbol, + xEU5Slippage, + xEU5MagicNumber, + xEU5UseVirtualTPSl, + xEU5MaxAllowedTrades, + xEU5FreeMarginForOpenTrades, + xEU5BalanceForOpenTrades); + + // + // Instantiate Account Guard ... + xEU5Guard = new XCGuard( + // + // Old Trades ... + xEU5MaxAllowedTradeAge, + xEU5OldTradesAction, + // + // Critical DrawDown ... + xEU5CriticalDrawDownFactor, + xEU5CriticalGuardAction, + // + // Max Allowed DrawDown ... + xEU5MaxAllowedDrawDownFactor, + xEU5MaxAllowedGuardAction, + xEU5GuardStopoutFiredAfterTouches, + // + // xEU5GuardSupportMethod + X_SUPPORT_DO_NOTHING + // + ); + + // + // Reset Calculations Buffers and Variables ... + XEU5ResetCollectors(); + + // + XEU5UpdateReports(); + + // + result = true; + + // + // Logging State ... + XEU5IssueInitializationSucceedAlert(); + + // + return result; +} + +// +// DeInitial Library if required ... +void XEU5DeinitSignalProviderLibrary(const int reason) +{ + // + // Release Handlers ... + XEU5ReleaseIndicators(); + + // + // Logging State ... + XEU5IssueDeinitializationSucceedAlert(); +} + +// +// this is a Globally Function which do all of +// checkings and positions handling ... +void XEU5SignalProviderHandleTick() +{ + // + // Check Provider is Enable or Not ... + if (!xEU5MEnableProvider) + { + return; + } + + // + XEU5SignalProviderDoControlState(); + + // + // Reading Indicator Buffers ... + XEU5HandleReadingBuffers(); + if (xEU5CalculatedBars < xEU5MaxLengthOfInputs) + { + return; + } + + // + // Handle Open Trades ... + XEU5HandleOpenTrades(); + + // + // Handle Close Trades ... + XEU5HandleCloseTrades(); + + // + // DrawDown and DrawUp ... + XEU5HandleCalculateDrawDownUp(); +} + +// +// Do Control Checks here ... +void XEU5SignalProviderDoControlState() +{ + // + // Update account Balance ... + xEU5Balance = xEU5AccountInfo.GetBalance(); + xEU5FreeMargin = xEU5AccountInfo.GetFreeMargin(); + + // + // Check Provider is Enable or Not ... + if (!xEU5MEnableProvider) + { + return; + } + + // + // Protect Account by Guarding Maximum Drawdown ... + // TODO: add Guard Result here ... + string guardMessage = ""; + XGuardHandlerResult guardHandlerResult; + bool isGuarded = xEU5Guard.Guard( + guardHandlerResult, + guardMessage, + xEU5Trader, + _Period); + if (isGuarded) + { + // + // Criticals ... + int criticalsCount = ArraySize(guardHandlerResult.criticals); + if (criticalsCount > 0) + { + // + for (int i = 0; i < criticalsCount; i++) + { + // + XSignal iSignal = guardHandlerResult.criticals[i]; + + // + XEU5OnGuard( + iSignal, + X_GUARDED_CRITICAL, + guardMessage); + } + } + + // + // Maxes ... + int maxesCount = ArraySize(guardHandlerResult.maxes); + if (maxesCount > 0) + { + // + for (int i = 0; i < maxesCount; i++) + { + // + XSignal iSignal = guardHandlerResult.maxes[i]; + + // + XEU5OnGuard( + iSignal, + X_GUARDED_MAX, + guardMessage, + guardHandlerResult.isStopOut); + } + } + + // + // Olds ... + int oldsCount = ArraySize(guardHandlerResult.olds); + if (oldsCount > 0) + { + // + for (int i = 0; i < oldsCount; i++) + { + // + XSignal iSignal = guardHandlerResult.olds[i]; + + // + XEU5OnGuard( + iSignal, + X_GUARDED_OLD, + guardMessage); + } + } + } + + // + // Signal Protection ... + XSignal protectSupports[]; + bool isSupported = xEU5Guard.ProtectSignals( + protectSupports, + xEU5Trader); + if (isSupported) + { + // + LogMessage("Guard do Support Trdae ..."); + } + + // + // Handling Signals ... + XTraderHandlerResult signalHandlerResult; + xEU5Trader.HandleSignals( + signalHandlerResult, + false // Ignore Risk Free Trdaes + ); + + // + // Handle Sl Reports ... + int handledSLsCount = ArraySize(signalHandlerResult.sl); + if (handledSLsCount > 0) + { + // + for (int i = 0; i < handledSLsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.sl[i]; + XEU5OnSL(iSignal); + } + } + + // + // Handle TP Reports ... + int handledTPsCount = ArraySize(signalHandlerResult.tp); + if (handledTPsCount > 0) + { + // + for (int i = 0; i < handledTPsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.tp[i]; + XEU5OnTP(iSignal); + } + } + + // + // Handle RFs as TP Reports ... + int handledRFsCount = ArraySize(signalHandlerResult.rf); + if (handledRFsCount > 0) + { + // + for (int i = 0; i < handledRFsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.rf[i]; + XEU5OnRF(iSignal); + } + } +} + +// +// Handle Trades when OnTrade Event Hnadler Calls ... +void XEU5SignalProviderHandleTrade() +{ + // + // Check Provider Enabled ... + if (!xEU5MEnableProvider) + { + return; + } + + // + // Handle OnTrade Event ... + XOnTradeHandlerResult result = {}; + xEU5Trader.HandleOnTradeEvent( + result); + + // + // Detected TP or SL ... + if (result.hasNewDeal) + { + // + XDeal last = xEU5Trader.GetLastDeal(); + + // + if (last.reason == DEAL_REASON_SL) + { + xEU5Reporter.AddTradeSLInReports(); + } + else if (last.reason == DEAL_REASON_TP) + { + xEU5Reporter.AddTradeTPInReports(); + } + } +} + +// +// Handle Open Trades ... +void XEU5HandleOpenTrades() +{ + // + // Check Can Trade ... + bool canTrade = xEU5MAllowLongTrades || xEU5MAllowShortTrades; + if (!canTrade) + { + return; + } + + // + // Check Max Open Trades ... + int openSignals = xEU5Trader.Count(); + bool canOpenPositions = openSignals < xEU5MaxAllowedTrades; + if (!canOpenPositions) + { + return; + } + + // + // Check Signals Exists ... + XProvidedSignal longSignalInfo; + XProvidedSignal shortSignalInfo; + bool hasLongSignal = XEU5CanOpenLongTrade(longSignalInfo); + bool hasShortSignal = XEU5CanOpenShortTrade(shortSignalInfo); + if (!hasLongSignal && !hasShortSignal) + { + return; + } + + // + // Update Reports ... + XEU5UpdateReports(); + + // + // Open Long Trades ... + if ( + // + hasLongSignal && + xEU5MAllowLongTrades) + { + // + bool isOpened = XEU5OpenLongPosition(longSignalInfo); + } + + // + // Open Short Trades ... + if ( + // + hasShortSignal && + xEU5MAllowShortTrades) + { + // + bool isOpened = XEU5OpenShortPosition(shortSignalInfo); + } +} + +// +// Handle Close Trades ... +void XEU5HandleCloseTrades() +{ + // + // Force Close Long Trades ... + bool isClosedLongTrades = false; + bool canCloseLongTrades = XEU5CanCloseLongTrade(); + if (xEU5MAllowLongTrades && canCloseLongTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; + + // + XSignal closed[]; + xEU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedLongTrades = closedTradesCount > 0; + if (isClosedLongTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XEU5OnFC(iSignal); + } + } + } + + // + // Force Close Short Trades ... + bool isClosedShortTrades = false; + bool canCloseShortTrades = XEU5CanCloseShortTrade(); + if (xEU5MAllowShortTrades && canCloseShortTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; + + // + XSignal closed[]; + xEU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedShortTrades = closedTradesCount > 0; + if (isClosedShortTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XEU5OnFC(iSignal); + } + } + } +} + +// +// Open Long Position ... +bool XEU5OpenLongPosition( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // Calculate Required Data for Position ... + double entry = GetEntry(_Symbol, X_SIGNAL_LONG); + double sl = info.sl > 0 ? info.sl : 0; + // entry - (200 * _Point); + // info.sl > 0 ? info.sl : 0; + double tp = info.tp > 0 ? info.tp : entry + xEU5MinReward; + double riskFreeRate = xEU5RiskFreeRate; + double riskFreeStep = xEU5RiskFreeStepInPips; + double volume = XEU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xEU5Trader.GenerateSignal( + X_SIGNAL_LONG, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xEU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xEU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XEU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xEU5CrossSignalsMethod != XEU5_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal( + signal, + false, // Ignore Number of Trades ... + true // Check Account Conditions ... + ); + result = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (result) + { + // + // Update Reports ... + string providers[]; + ArrayCopy( + providers, + info.signallers + ); + + // + XSignal tSignal = xEU5Trader.GetSignal(signal.ticket); + + // + XEU5OnSignal( + tSignal, + providers); + } + else + { + XEU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Open Short Position ... +bool XEU5OpenShortPosition( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // Calculate Required Data for Position ... + double entry = GetEntry(_Symbol, X_SIGNAL_SHORT); + double sl = info.sl > 0 ? info.sl : 0; + // entry + (200 * _Point); + // info.sl > 0 ? info.sl : 0; + double tp = info.tp > 0 ? info.tp : entry - xEU5MinReward; + double riskFreeRate = xEU5RiskFreeRate; + double riskFreeStep = xEU5RiskFreeStepInPips; + double volume = XEU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xEU5Trader.GenerateSignal( + X_SIGNAL_SHORT, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xEU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xEU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XEU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xEU5CrossSignalsMethod != XEU5_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal( + signal, + false, // Ignore Number of Trades ... + true // Check Account Conditions ... + ); + result = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (result) + { + string providers[]; + ArrayCopy( + providers, + info.signallers + ); + + // + XSignal tSignal = xEU5Trader.GetSignal(signal.ticket); + + // + XEU5OnSignal( + tSignal, + providers); + } + else + { + XEU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Apply Cross Signal Actions ... +void XEU5HnadleCrossSignal( + XSignal &signal // Specified Signal ... +) +{ + // + // Check Cross Signal Handling Enabled ... + if (xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DO_NOTHING) + { + return; + } + + // + // First We have to Change Cross Signals Comment ... + string comment = xEU5Trader.GenerateSignalComment( + signal, + true); + + // + signal.comment = comment; + + // + // If Every thing is Regular, prevent any changes here ... + if (xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_REGULAR) + { + return; + } + + // + // Retrieve Max in Drawdown Signal ... + XSignal maxInDDSignal = xEU5Trader.GetMaxInDrawdownSignal(); + + // + // Validate Signal ... + bool isValidSignal = + maxInDDSignal.ticket > 0 && + maxInDDSignal.symbol == signal.symbol && + IsValid(maxInDDSignal, xEU5MagicNumber); + if (!isValidSignal) + { + return; + } + + // + double volume = signal.volume; + bool isDirectional = maxInDDSignal.type == signal.type; + + // + // Prevent any changes on Regular Conditions ... + bool isRegular = + isDirectional + ? ( + // + xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_REGULAR || + xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT + // + ) + : ( + // + xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_INDIRECTION_REGULAR || + xEU5CrossSignalsMethod == XEU5_CROSS_SIGNAL_DIRECTION_IMPORTANT_INDIRECTION_REGULAR + // + ); + if (isRegular) + { + return; + } + + // + // Important Act needs to Multiply volume by 2 ... + volume *= 2; + + // + // Set Volume of signal ... + signal.volume = volume; +} + +// +// Calculate Usefull data ... +void XEU5HandleCalculateDrawDownUp() +{ + // + XSignal signals[]; + xEU5Trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + double profit = 0; + double volume = 0; + XCollector collector = {}; + double maxAllowedVolume = xEU5VolumeManager.GetMaxAllowedVolume(); + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + profit += iSignal.profit; + + // + volume = + volume == 0 || + volume < iSignal.volume + ? iSignal.volume + : volume; + } + + // + if (profit < 0) + { + // + xEU5MaxDrawDown = + xEU5MaxDrawDown == 0 || + xEU5MaxDrawDown > MathAbs(profit) + ? MathAbs(profit) + : xEU5MaxDrawDown; + + // + // Update Buffers ... + datetime time = iTime(_Symbol, _Period, 0); + + // + // Calculate Max Allowed Drawdown ... + // + collector.time = time; + collector.volume = volume; + collector.maxDrawDown = xEU5MaxDrawDown; + collector.maxAllowedVolume = maxAllowedVolume; + collector.minBalanceForOpenTrade = xEU5Trader.GetMinBalanceForOpenTrades(); + } + else + { + // + xEU5MaxDrawUp = + xEU5MaxDrawUp == 0 || + xEU5MaxDrawUp < profit + ? profit + : xEU5MaxDrawUp; + } + + // + // Update Collector ... + xEU5Collector.Add(collector); + + // + // Update Reports ... + xEU5Reporter.UpdateMaxDrawUpInReports(xEU5MaxDrawUp); + xEU5Reporter.UpdateMaxDrawDownInReports(xEU5MaxDrawDown); + xEU5Reporter.UpdateMaxSameTimeTradesInReports(signalsCount); +} + +// +// START Event Handlers ... +// + +// +// Runs When a Signal Successfully Executed ... +void XEU5OnSignal( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + // Issue Propper Alert ... + XEU5IssueSignalExecutionAlert( + signal, + providers); + + // + // Add Signal To Supports on Guard ... + xEU5Guard.AddSupport(signal); + + // + // Update Reports ... + xEU5Reporter.AddSignalToReports( + signal, + providers); +} + +// +// Runs when a Position Got Take Profit ... +void XEU5OnTP( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueTPAlert(signal); + + // + // Remove Signal From Guard Protector ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeTPInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Got Stop Loss ... +void XEU5OnSL( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueSLAlert(signal); + + // + // Remove Signal From Guard Protector ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Risk Free ... +void XEU5OnRF( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueRFAlert(signal); + + // + // Remove Signal From Guard Protector ... + // since RiskFree Signals has SL ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Force Closed ... +void XEU5OnFC( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueFCAlert(signal); + + // + // Remove Signal From Guard Protector ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Guarded ... +void XEU5OnGuard( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason, // Reason of Guard Applied + string message, // Guard Returned Message + bool isStopOut = false // Specified StopOut Fired or not +) +{ + // + // Chekc StopOut ... + if (isStopOut) + { + // + LogMessage(message); + + // + xEU5MEnableProvider = false; + } + + // + // Issue Propper Alert ... + XEU5IssueGuardAlert(signal, reason, isStopOut); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// END Event Handlers ... +// + +// +// END Provided Functions ... +// + +// +// START Private Functions ... +// + +// +// START Volume Baseed Functions ... +// + +// +// Calculating Volume for Tradings ... +double XEU5CalculateVolume( + double forceMultiplier = 0 // some times we get more than one signal at the same time, here we increase volume using this ... +) +{ + // + // Check Open Trades ... + int openSignals = xEU5Trader.Count(); + + // + double result = xEU5VolumeManager.CalculateVolume( + openSignals, + _Symbol); + + // + result *= forceMultiplier; + + // + // Normalize Volume ... + result = NormalizeVolume(result, _Symbol, 2); + + // + return result; +} + +// +// END Volume Baseed Functions ... +// + +// +// START Report/Collect and Guard Functions ... +// + +// +// Update Report Info ... +void XEU5UpdateReports() +{ + // + double staticVolume = xEU5VolumeManager.GetStaticVolume(); + string staticVolumeCalculationMethod = EnumToString(xEU5StaticVolumeMethod); + double maxAllowedVolume = xEU5VolumeManager.GetMaxAllowedVolume(); + double volumeIncreaseMultiplier = xEU5VolumeManager.GetVolumeMultiplier(); + double balanceGowingToApplyMultiplier = xEU5VolumeManager.GetIncreaseMultiplierBalance(); + + double balanceGrowingToIncreaseMaxAllowedVolume = xEU5VolumeManager.GetIncreaseMaxAllowedVolumeBalance(); + + // + // Update Reports Volume Info ... + xEU5Reporter.UpdateReportsVolumeInfo( + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Calculate Max Allowed Drawdown ... + double minBalanceForTradeBasedOnBalance = xEU5Trader.GetMinBalanceForOpenTrades(); + xEU5Reporter.UpdateMinBalanceForOpenTradesInReports(minBalanceForTradeBasedOnBalance); +} + +// +// Reset XEU5 Info Buffers ... +void XEU5ResetCollectors() +{ + // + // Reset Calculations Buffers and Variables ... + xEU5MaxDrawUp = 0; + xEU5MaxDrawDown = 0; + + // + xEU5Trader.Reset(); + xEU5Reporter.Reset(); + xEU5Collector.Reset(); + xEU5VolumeManager.ResetForceVolumeMultiplier(); +} + +// +// END Report/Collect and Guard Functions ... +// + +// +// START Alert Functions ... +// + +// +// Send Alert ... +void XEU5IssueAlert(string message) +{ + // + // Validate Args ... + if (StringLen(message) <= 0) + { + return; + } + + // + if (xEU5EnableAlerts) + { + SendAlert(message); + } + else + { + LogMessage(message); + } +} + +// +// Send Take Profit Alert on Specific Signal ... +void XEU5IssueTPAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalTPComment(signal); + + // + XEU5IssueAlert(message); +} + +// +// Send Stop Loss Alert on Specific Signal ... +void XEU5IssueSLAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalSLComment(signal); + + // + XEU5IssueAlert(message); +} + +// +// Send Force Close Alert on Specific Signal ... +void XEU5IssueFCAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalForceCloseComment(signal); + + // + XEU5IssueAlert(message); +} + +// +// Send Risk Free Alert on Specific Signal ... +void XEU5IssueRFAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalRFComment(signal, 0); + + // + XEU5IssueAlert(message); +} + +// +// Send Guard Alert on Specific Signal ... +void XEU5IssueGuardAlert( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason, // Specified Guard Reason + bool isStopOut = false // Specified StopOut Fired or not +) +{ + // + string message = ""; + + // + message = xEU5Guard.GenerateGuardedSignalComment( + signal, + reason); + + // + XEU5IssueAlert(message); +} + +// +// Send Initialization Succeed Alert ... +void XEU5IssueInitializationSucceedAlert() +{ + // + string message = "Initializion of (" + XEU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; + XEU5IssueAlert(message); +} + +// +// Send De Initialization Succeed Alert ... +void XEU5IssueDeinitializationSucceedAlert() +{ + // + string message = "De Initializion of (" + XEU5ProviderName + " Provider" + ") Succeeded ..."; + XEU5IssueAlert(message); +} + +// +// Send Signal Successfully Execution Alert ... +void XEU5IssueSignalExecutionAlert( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + string message = xEU5Trader.ToString(signal); + + // + string providersMsg = ToString(providers); + if (StringLen(providersMsg) > 0) + { + message += ", Providers: " + providersMsg; + } + + // + XEU5IssueAlert(message); +} + +// +// Send Signal Execution Alert ... +void XEU5IssueSignalExecutionError(int error) +{ + // + string message = GetSignalExecutionError(error); + if (StringLen(message) == 0) + { + return; + } + + // + XEU5IssueAlert(message); +} + +// +// END Alert Functions ... +// + +// +// END Private Functions ... +// diff --git a/XEU5-0/Settings/.gitkeep b/XEU5-0/Settings/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Templates/.gitkeep b/XEU5-0/Templates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5-0/Templates/FundedNext.XEU5.Guarded.Signals.txt b/XEU5-0/Templates/FundedNext.XEU5.Guarded.Signals.txt new file mode 100644 index 0000000..79c473c --- /dev/null +++ b/XEU5-0/Templates/FundedNext.XEU5.Guarded.Signals.txt @@ -0,0 +1,548 @@ +2020.02.06 20:35:00 XEU5EA > Long Signal Provided by: +2020.02.06 20:35:00 XTAM +2020.02.06 20:35:00 Pusher: 1 +2020.02.06 20:35:00 Market Conditions: +2020.02.06 20:35:00 | XOBD | +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XTM | +2020.02.06 20:35:00 isXTMBullish: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XAMA | +2020.02.06 20:35:00 isXAMABullish: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XTD | +2020.02.06 20:35:00 isXTDBullOverBear: true +2020.02.06 20:35:00 isXTDSignalOverBear: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XFI | +2020.02.06 20:35:00 isXFIOverZero: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XTS | +2020.02.06 20:35:00 isXTSCurrentMax: true +2020.02.06 20:35:00 isXTSCurrentOverFarest: true +2020.02.06 20:35:00 isXTSCurrentOverMediest: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XLH | +2020.02.06 20:35:00 isXLHLLSameInLength: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XRSI | +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XCHLH | +2020.02.06 20:35:00 isXCHLHMCLCLLSame: true +2020.02.06 20:35:00 isXCHLHMCOnTopOfLC: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 | XCHMA | +2020.02.06 20:35:00 isXCHMASCOverMin: true +2020.02.06 20:35:00 isXCHMASCUnderMax: true +2020.02.06 20:35:00 isXCHMASCUnderMin: true +2020.02.06 20:35:00 isXCHMASCTrendsUp: true +2020.02.06 20:35:00 isXCHMASCFastOverSlow: true +2020.02.06 20:35:00 isXCHMAMCVale: true +2020.02.06 20:35:00 isXCHMAMCTrendsDown: true +2020.02.06 20:35:00 isXCHMAMCFastUnderSlow: true +2020.02.06 20:35:00 isXCHMALCVale: true +2020.02.06 20:35:00 isXCHMALCTrendsUp: true +2020.02.06 20:35:00 isXCHMALCFastUnderSlow: true +2020.02.06 20:35:00 +2020.02.06 20:35:00 +2020.02.06 20:35:00 market buy 1.04 EURUSD tp: 1.10013 (1.09810 / 1.09813 / 1.09810) +2020.02.06 20:35:00 deal #785 buy 1.04 EURUSD at 1.09813 done (based on order #785) +2020.02.06 20:35:00 deal performed [#785 buy 1.04 EURUSD at 1.09813] +2020.02.06 20:35:00 order performed buy 1.04 at 1.09813 [#785 buy 1.04 EURUSD at 1.09813] +2020.02.06 20:35:00 XEU5EA > T(785)_TY(Long)_TP(1.10013)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2020.04.29 02:05:00 XEU5EA > Short Signal Provided by: +2020.04.29 02:05:00 XSI +2020.04.29 02:05:00 Pusher: 1 +2020.04.29 02:05:00 Market Conditions: +2020.04.29 02:05:00 | XOBD | +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XTM | +2020.04.29 02:05:00 isXTMBullish: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XAMA | +2020.04.29 02:05:00 isXAMABullish: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XTD | +2020.04.29 02:05:00 isXTDBullOverBear: true +2020.04.29 02:05:00 isXTDSignalOverBear: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XFI | +2020.04.29 02:05:00 isXFIOverZero: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XTS | +2020.04.29 02:05:00 isXTSCurrentMax: true +2020.04.29 02:05:00 isXTSCurrentOverFarest: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XLH | +2020.04.29 02:05:00 isXLHLLSameInLength: true +2020.04.29 02:05:00 isXLHPriceOverSignal: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XRSI | +2020.04.29 02:05:00 isXRSICrossedUnderShortEntry: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XCHLH | +2020.04.29 02:05:00 isXCHLHSCMCHHSame: true +2020.04.29 02:05:00 isXCHLHMCOnTopOfLC: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 | XCHMA | +2020.04.29 02:05:00 isXCHMASCOverMax: true +2020.04.29 02:05:00 isXCHMASCOverMin: true +2020.04.29 02:05:00 isXCHMASCCrossedOverMax: true +2020.04.29 02:05:00 isXCHMASCPeak: true +2020.04.29 02:05:00 isXCHMASCTrendsUp: true +2020.04.29 02:05:00 isXCHMASCFastOverSlow: true +2020.04.29 02:05:00 isXCHMAMCTrendsDown: true +2020.04.29 02:05:00 isXCHMAMCFastUnderSlow: true +2020.04.29 02:05:00 isXCHMALCPeak: true +2020.04.29 02:05:00 isXCHMALCTrendsUp: true +2020.04.29 02:05:00 isXCHMALCFastOverSlow: true +2020.04.29 02:05:00 +2020.04.29 02:05:00 +2020.04.29 02:05:00 market sell 1.14 EURUSD tp: 1.08201 (1.08401 / 1.08451 / 1.08401) +2020.04.29 02:05:00 deal #975 sell 1.14 EURUSD at 1.08401 done (based on order #975) +2020.04.29 02:05:00 deal performed [#975 sell 1.14 EURUSD at 1.08401] +2020.04.29 02:05:00 order performed sell 1.14 at 1.08401 [#975 sell 1.14 EURUSD at 1.08401] +2020.04.29 02:05:00 XEU5EA > T(975)_TY(Short)_TP(1.08201)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XSI + + +2020.05.25 21:10:00 XEU5EA > Short Signal Provided by: +2020.05.25 21:10:00 XTAM +2020.05.25 21:10:00 Pusher: 1 +2020.05.25 21:10:00 Market Conditions: +2020.05.25 21:10:00 | XOBD | +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XTM | +2020.05.25 21:10:00 isXTMBearish: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XAMA | +2020.05.25 21:10:00 isXAMABearish: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XTD | +2020.05.25 21:10:00 isXTDSignalUnderBear: true +2020.05.25 21:10:00 isXTDBullCrossedUnderBear: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XFI | +2020.05.25 21:10:00 isXFIUnderZero: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XTS | +2020.05.25 21:10:00 isXTSCurrentMin: true +2020.05.25 21:10:00 isXTSCurrentUnderFarest: true +2020.05.25 21:10:00 isXTSCurrentUnderNearest: true +2020.05.25 21:10:00 isXTSCurrentUnderMediest: true +2020.05.25 21:10:00 isXTSCurrentCrossedUnderNearest: true +2020.05.25 21:10:00 isXTSCurrentCrossedUnderMediest: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XLH | +2020.05.25 21:10:00 isXLHHHSameInLength: true +2020.05.25 21:10:00 isXLHPriceCrossedOverSignal: true +2020.05.25 21:10:00 isXLHPriceOverSignal: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XRSI | +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XCHLH | +2020.05.25 21:10:00 isXCHLHMCOnTopOfLC: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 | XCHMA | +2020.05.25 21:10:00 isXCHMASCOverMin: true +2020.05.25 21:10:00 isXCHMASCUnderMax: true +2020.05.25 21:10:00 isXCHMASCTrendsUp: true +2020.05.25 21:10:00 isXCHMASCFastUnderSlow: true +2020.05.25 21:10:00 isXCHMAMCFastOverSlow: true +2020.05.25 21:10:00 isXCHMALCVale: true +2020.05.25 21:10:00 isXCHMALCTrendsDown: true +2020.05.25 21:10:00 isXCHMALCFastUnderSlow: true +2020.05.25 21:10:00 +2020.05.25 21:10:00 +2020.05.25 21:10:00 market sell 1.05 EURUSD tp: 1.08760 (1.08960 / 1.08966 / 1.08960) +2020.05.25 21:10:00 deal #1036 sell 1.05 EURUSD at 1.08960 done (based on order #1036) +2020.05.25 21:10:00 deal performed [#1036 sell 1.05 EURUSD at 1.08960] +2020.05.25 21:10:00 order performed sell 1.05 at 1.08960 [#1036 sell 1.05 EURUSD at 1.08960] +2020.05.25 21:10:00 XEU5EA > T(1036)_TY(Short)_TP(1.0876)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2020.07.10 19:15:00 XEU5EA > Short Signal Provided by: +2020.07.10 19:15:00 XTAM +2020.07.10 19:15:00 Pusher: 1 +2020.07.10 19:15:00 Market Conditions: +2020.07.10 19:15:00 | XOBD | +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XTM | +2020.07.10 19:15:00 isXTMStartBearish: true +2020.07.10 19:15:00 isXTMStartBearishAfterNeutural: true +2020.07.10 19:15:00 isXTMBearish: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XAMA | +2020.07.10 19:15:00 isXAMAStartBearish: true +2020.07.10 19:15:00 isXAMAStartBearishAfterNeutural: true +2020.07.10 19:15:00 isXAMABearish: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XTD | +2020.07.10 19:15:00 isXTDBullOverBear: true +2020.07.10 19:15:00 isXTDSignalOverBear: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XFI | +2020.07.10 19:15:00 isXFIUnderZero: true +2020.07.10 19:15:00 isXFICrossedUnderZero: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XTS | +2020.07.10 19:15:00 isXTSCurrentMin: true +2020.07.10 19:15:00 isXTSCurrentUnderFarest: true +2020.07.10 19:15:00 isXTSCurrentUnderNearest: true +2020.07.10 19:15:00 isXTSCurrentUnderMediest: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XLH | +2020.07.10 19:15:00 isXLHHHSameInLength: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XRSI | +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XCHLH | +2020.07.10 19:15:00 isXCHLHMCLCHHSame: true +2020.07.10 19:15:00 isXCHLHMCOnTopOfLC: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 | XCHMA | +2020.07.10 19:15:00 isXCHMASCOverMax: true +2020.07.10 19:15:00 isXCHMASCOverMin: true +2020.07.10 19:15:00 isXCHMASCUnderMax: true +2020.07.10 19:15:00 isXCHMASCTrendsDown: true +2020.07.10 19:15:00 isXCHMASCFastOverSlow: true +2020.07.10 19:15:00 isXCHMAMCPeak: true +2020.07.10 19:15:00 isXCHMAMCTrendsDown: true +2020.07.10 19:15:00 isXCHMAMCFastOverSlow: true +2020.07.10 19:15:00 isXCHMALCPeak: true +2020.07.10 19:15:00 isXCHMALCTrendsDown: true +2020.07.10 19:15:00 isXCHMALCFastUnderSlow: true +2020.07.10 19:15:00 +2020.07.10 19:15:00 +2020.07.10 19:15:00 market sell 0.22 EURUSD tp: 1.12803 (1.13003 / 1.13007 / 1.13003) +2020.07.10 19:15:00 deal #1174 sell 0.22 EURUSD at 1.13003 done (based on order #1174) +2020.07.10 19:15:00 deal performed [#1174 sell 0.22 EURUSD at 1.13003] +2020.07.10 19:15:00 order performed sell 0.22 at 1.13003 [#1174 sell 0.22 EURUSD at 1.13003] +2020.07.10 19:15:00 XEU5EA > T(1174)_TY(Short)_TP(1.12803)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2020.09.28 02:05:00 XEU5EA > Short Signal Provided by: +2020.09.28 02:05:00 XTAM +2020.09.28 02:05:00 Pusher: 1 +2020.09.28 02:05:00 Market Conditions: +2020.09.28 02:05:00 | XOBD | +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XTM | +2020.09.28 02:05:00 isXTMBearish: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XAMA | +2020.09.28 02:05:00 isXAMABearish: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XTD | +2020.09.28 02:05:00 isXTDBullUnderBear: true +2020.09.28 02:05:00 isXTDSignalUnderBear: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XFI | +2020.09.28 02:05:00 isXFIUnderZero: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XTS | +2020.09.28 02:05:00 isXTSCurrentMin: true +2020.09.28 02:05:00 isXTSCurrentUnderFarest: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XLH | +2020.09.28 02:05:00 isXLHHHSameInLength: true +2020.09.28 02:05:00 isXLHPriceUnderSignal: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XRSI | +2020.09.28 02:05:00 isXRSICrossedUnderShortExit: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XCHLH | +2020.09.28 02:05:00 isXCHLHSCMCLLSame: true +2020.09.28 02:05:00 isXCHLHMCOnTopOfLC: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 | XCHMA | +2020.09.28 02:05:00 isXCHMASCUnderMax: true +2020.09.28 02:05:00 isXCHMASCUnderMin: true +2020.09.28 02:05:00 isXCHMASCVale: true +2020.09.28 02:05:00 isXCHMASCTrendsUp: true +2020.09.28 02:05:00 isXCHMASCFastUnderSlow: true +2020.09.28 02:05:00 isXCHMAMCTrendsUp: true +2020.09.28 02:05:00 isXCHMAMCFastUnderSlow: true +2020.09.28 02:05:00 isXCHMALCVale: true +2020.09.28 02:05:00 isXCHMALCTrendsDown: true +2020.09.28 02:05:00 isXCHMALCFastUnderSlow: true +2020.09.28 02:05:00 +2020.09.28 02:05:00 +2020.09.28 02:05:00 market sell 0.36 EURUSD tp: 1.15989 (1.16189 / 1.16191 / 1.16189) +2020.09.28 02:05:00 deal #1364 sell 0.36 EURUSD at 1.16189 done (based on order #1364) +2020.09.28 02:05:00 deal performed [#1364 sell 0.36 EURUSD at 1.16189] +2020.09.28 02:05:00 order performed sell 0.36 at 1.16189 [#1364 sell 0.36 EURUSD at 1.16189] +2020.09.28 02:05:00 XEU5EA > T(1364)_TY(Short)_TP(1.15989)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2021.03.04 05:20:00 XEU5EA > Long Signal Provided by: +2021.03.04 05:20:00 XTAM +2021.03.04 05:20:00 Pusher: 1 +2021.03.04 05:20:00 Market Conditions: +2021.03.04 05:20:00 | XOBD | +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XTM | +2021.03.04 05:20:00 isXTMStartBullish: true +2021.03.04 05:20:00 isXTMStartBullishAfterNeutural: true +2021.03.04 05:20:00 isXTMBullish: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XAMA | +2021.03.04 05:20:00 isXAMAStartBullish: true +2021.03.04 05:20:00 isXAMAStartBullishAfterNeutural: true +2021.03.04 05:20:00 isXAMABullish: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XTD | +2021.03.04 05:20:00 isXTDBearishVale: true +2021.03.04 05:20:00 isXTDBullOverBear: true +2021.03.04 05:20:00 isXTDSignalOverBear: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XFI | +2021.03.04 05:20:00 isXFIOverZero: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XTS | +2021.03.04 05:20:00 isXTSCurrentMax: true +2021.03.04 05:20:00 isXTSCurrentOverFarest: true +2021.03.04 05:20:00 isXTSCurrentOverMediest: true +2021.03.04 05:20:00 isXTSCurrentCrossedOverMediest: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XLH | +2021.03.04 05:20:00 isXLHLLSameInLength: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XRSI | +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XCHLH | +2021.03.04 05:20:00 isXCHLHMCOnTopOfLC: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 | XCHMA | +2021.03.04 05:20:00 isXCHMASCUnderMax: true +2021.03.04 05:20:00 isXCHMASCUnderMin: true +2021.03.04 05:20:00 isXCHMASCTrendsUp: true +2021.03.04 05:20:00 isXCHMASCFastOverSlow: true +2021.03.04 05:20:00 isXCHMAMCVale: true +2021.03.04 05:20:00 isXCHMAMCTrendsDown: true +2021.03.04 05:20:00 isXCHMAMCFastUnderSlow: true +2021.03.04 05:20:00 isXCHMALCVale: true +2021.03.04 05:20:00 isXCHMALCTrendsUp: true +2021.03.04 05:20:00 isXCHMALCFastUnderSlow: true +2021.03.04 05:20:00 +2021.03.04 05:20:00 +2021.03.04 05:20:00 market buy 0.4 EURUSD tp: 1.20764 (1.20563 / 1.20564 / 1.20563) +2021.03.04 05:20:00 deal #1558 buy 0.4 EURUSD at 1.20564 done (based on order #1558) +2021.03.04 05:20:00 deal performed [#1558 buy 0.4 EURUSD at 1.20564] +2021.03.04 05:20:00 order performed buy 0.4 at 1.20564 [#1558 buy 0.4 EURUSD at 1.20564] +2021.03.04 05:20:00 XEU5EA > T(1558)_TY(Long)_TP(1.20764)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2021.05.17 07:40:00 XEU5EA > Short Signal Provided by: +2021.05.17 07:40:00 XOBDLH +2021.05.17 07:40:00 Pusher: 1 +2021.05.17 07:40:00 Market Conditions: +2021.05.17 07:40:00 | XOBD | +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XTM | +2021.05.17 07:40:00 isXTMBullish: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XAMA | +2021.05.17 07:40:00 isXAMABullish: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XTD | +2021.05.17 07:40:00 isXTDBullOverBear: true +2021.05.17 07:40:00 isXTDSignalOverBear: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XFI | +2021.05.17 07:40:00 isXFIOverZero: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XTS | +2021.05.17 07:40:00 isXTSCurrentMax: true +2021.05.17 07:40:00 isXTSCurrentOverFarest: true +2021.05.17 07:40:00 isXTSCurrentOverNearest: true +2021.05.17 07:40:00 isXTSCurrentOverMediest: true +2021.05.17 07:40:00 isXTSCurrentCrossedOverNearest: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XLH | +2021.05.17 07:40:00 isXLHHighAttachedHH: true +2021.05.17 07:40:00 isXLHLLSameInLength: true +2021.05.17 07:40:00 isXLHPriceOverSignal: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XRSI | +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XCHLH | +2021.05.17 07:40:00 isXCHLHSCMCHHSame: true +2021.05.17 07:40:00 isXCHLHMCOnTopOfLC: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 | XCHMA | +2021.05.17 07:40:00 isXCHMASCOverMax: true +2021.05.17 07:40:00 isXCHMASCOverMin: true +2021.05.17 07:40:00 isXCHMASCUnderMax: true +2021.05.17 07:40:00 isXCHMASCTrendsUp: true +2021.05.17 07:40:00 isXCHMASCFastOverSlow: true +2021.05.17 07:40:00 isXCHMAMCTrendsDown: true +2021.05.17 07:40:00 isXCHMAMCFastUnderSlow: true +2021.05.17 07:40:00 isXCHMALCPeak: true +2021.05.17 07:40:00 isXCHMALCTrendsDown: true +2021.05.17 07:40:00 isXCHMALCFastOverSlow: true +2021.05.17 07:40:00 +2021.05.17 07:40:00 +2021.05.17 07:40:00 market sell 0.16 EURUSD tp: 1.21210 (1.21410 / 1.21460 / 1.21410) +2021.05.17 07:40:00 deal #1701 sell 0.16 EURUSD at 1.21410 done (based on order #1701) +2021.05.17 07:40:00 deal performed [#1701 sell 0.16 EURUSD at 1.21410] +2021.05.17 07:40:00 order performed sell 0.16 at 1.21410 [#1701 sell 0.16 EURUSD at 1.21410] +2021.05.17 07:40:00 XEU5EA > T(1701)_TY(Short)_TP(1.2121)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XOBDLH + + +2021.05.17 22:05:00 XEU5EA > Short Signal Provided by: +2021.05.17 22:05:00 XTAM +2021.05.17 22:05:00 Pusher: 1 +2021.05.17 22:05:00 Market Conditions: +2021.05.17 22:05:00 | XOBD | +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XTM | +2021.05.17 22:05:00 isXTMVale: true +2021.05.17 22:05:00 isXTMBearish: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XAMA | +2021.05.17 22:05:00 isXAMABearish: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XTD | +2021.05.17 22:05:00 isXTDBullUnderBear: true +2021.05.17 22:05:00 isXTDSignalUnderBear: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XFI | +2021.05.17 22:05:00 isXFIUnderZero: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XTS | +2021.05.17 22:05:00 isXTSCurrentMin: true +2021.05.17 22:05:00 isXTSCurrentUnderFarest: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XLH | +2021.05.17 22:05:00 isXLHHHSameInLength: true +2021.05.17 22:05:00 isXLHPriceInSignalRange: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XRSI | +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XCHLH | +2021.05.17 22:05:00 isXCHLHMCOnTopOfLC: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 | XCHMA | +2021.05.17 22:05:00 isXCHMASCOverMin: true +2021.05.17 22:05:00 isXCHMASCUnderMax: true +2021.05.17 22:05:00 isXCHMASCCrossedUnderMax: true +2021.05.17 22:05:00 isXCHMASCVale: true +2021.05.17 22:05:00 isXCHMASCTrendsUp: true +2021.05.17 22:05:00 isXCHMASCFastUnderSlow: true +2021.05.17 22:05:00 isXCHMAMCTrendsDown: true +2021.05.17 22:05:00 isXCHMAMCFastOverSlow: true +2021.05.17 22:05:00 isXCHMALCPeak: true +2021.05.17 22:05:00 isXCHMALCTrendsDown: true +2021.05.17 22:05:00 isXCHMALCFastOverSlow: true +2021.05.17 22:05:00 +2021.05.17 22:05:00 +2021.05.17 22:05:00 market sell 0.16 EURUSD tp: 1.21306 (1.21506 / 1.21533 / 1.21506) +2021.05.17 22:05:00 deal #1706 sell 0.16 EURUSD at 1.21506 done (based on order #1706) +2021.05.17 22:05:00 deal performed [#1706 sell 0.16 EURUSD at 1.21506] +2021.05.17 22:05:00 order performed sell 0.16 at 1.21506 [#1706 sell 0.16 EURUSD at 1.21506] +2021.05.17 22:05:00 XEU5EA > T(1706)_TY(Short)_TP(1.21306)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2021.08.16 23:10:00 XEU5EA > Long Signal Provided by: +2021.08.16 23:10:00 XTAM +2021.08.16 23:10:00 Pusher: 1 +2021.08.16 23:10:00 Market Conditions: +2021.08.16 23:10:00 | XOBD | +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XTM | +2021.08.16 23:10:00 isXTMBullish: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XAMA | +2021.08.16 23:10:00 isXAMABullish: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XTD | +2021.08.16 23:10:00 isXTDBullOverBear: true +2021.08.16 23:10:00 isXTDSignalCrossedOverBear: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XFI | +2021.08.16 23:10:00 isXFIOverZero: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XTS | +2021.08.16 23:10:00 isXTSCurrentMax: true +2021.08.16 23:10:00 isXTSCurrentOverFarest: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XLH | +2021.08.16 23:10:00 isXLHLLSameInLength: true +2021.08.16 23:10:00 isXLHPriceOverSignal: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XRSI | +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XCHLH | +2021.08.16 23:10:00 isXCHLHMCOnTopOfLC: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 | XCHMA | +2021.08.16 23:10:00 isXCHMASCOverMin: true +2021.08.16 23:10:00 isXCHMASCUnderMax: true +2021.08.16 23:10:00 isXCHMASCTrendsUp: true +2021.08.16 23:10:00 isXCHMASCFastOverSlow: true +2021.08.16 23:10:00 isXCHMAMCVale: true +2021.08.16 23:10:00 isXCHMAMCTrendsDown: true +2021.08.16 23:10:00 isXCHMAMCFastUnderSlow: true +2021.08.16 23:10:00 isXCHMALCPeak: true +2021.08.16 23:10:00 isXCHMALCTrendsDown: true +2021.08.16 23:10:00 isXCHMALCFastOverSlow: true +2021.08.16 23:10:00 +2021.08.16 23:10:00 +2021.08.16 23:10:00 market buy 0.42 EURUSD tp: 1.17985 (1.17780 / 1.17785 / 1.17780) +2021.08.16 23:10:00 deal #1924 buy 0.42 EURUSD at 1.17785 done (based on order #1924) +2021.08.16 23:10:00 deal performed [#1924 buy 0.42 EURUSD at 1.17785] +2021.08.16 23:10:00 order performed buy 0.42 at 1.17785 [#1924 buy 0.42 EURUSD at 1.17785] +2021.08.16 23:10:00 XEU5EA > T(1924)_TY(Long)_TP(1.17985)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XTAM + + +2023.06.08 02:05:00 XEU5EA > Short Signal Provided by: +2023.06.08 02:05:00 XCHMACC +2023.06.08 02:05:00 Pusher: 1 +2023.06.08 02:05:00 Market Conditions: +2023.06.08 02:05:00 | XOBD | +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XTM | +2023.06.08 02:05:00 isXTMNeutural: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XAMA | +2023.06.08 02:05:00 isXAMANeutural: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XTD | +2023.06.08 02:05:00 isXTDBullOverBear: true +2023.06.08 02:05:00 isXTDSignalUnderBear: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XFI | +2023.06.08 02:05:00 isXFIOverZero: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XTS | +2023.06.08 02:05:00 isXTSCurrentMax: true +2023.06.08 02:05:00 isXTSCurrentOverFarest: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XLH | +2023.06.08 02:05:00 isXLHHHSameInLength: true +2023.06.08 02:05:00 isXLHLLSameInLength: true +2023.06.08 02:05:00 isXLHPriceOverSignal: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XRSI | +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XCHLH | +2023.06.08 02:05:00 isXCHLHMCOnTopOfLC: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 | XCHMA | +2023.06.08 02:05:00 isXCHMASCUnderMax: true +2023.06.08 02:05:00 isXCHMASCUnderMin: true +2023.06.08 02:05:00 isXCHMASCTrendsUp: true +2023.06.08 02:05:00 isXCHMASCFastUnderSlow: true +2023.06.08 02:05:00 isXCHMAMCTrendsDown: true +2023.06.08 02:05:00 isXCHMAMCFastUnderSlow: true +2023.06.08 02:05:00 isXCHMALCTrendsDown: true +2023.06.08 02:05:00 isXCHMALCFastUnderSlow: true +2023.06.08 02:05:00 +2023.06.08 02:05:00 +2023.06.08 02:05:00 market sell 5.21 EURUSD tp: 1.06802 (1.07002 / 1.07003 / 1.07002) +2023.06.08 02:05:00 deal #3489 sell 5.21 EURUSD at 1.07002 done (based on order #3489) +2023.06.08 02:05:00 deal performed [#3489 sell 5.21 EURUSD at 1.07002] +2023.06.08 02:05:00 order performed sell 5.21 at 1.07002 [#3489 sell 5.21 EURUSD at 1.07002] +2023.06.08 02:05:00 XEU5EA > T(3489)_TY(Short)_TP(1.06802)_SL(0.0)_RFS(6.0)_RFR(0.6), Providers: XCHMACC diff --git a/XEU5/Classes/.gitkeep b/XEU5/Classes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Classes/x-saherelm.class.lib.mq5 b/XEU5/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 0000000..68f4847 --- /dev/null +++ b/XEU5/Classes/x-saherelm.class.lib.mq5 @@ -0,0 +1,10316 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XClass +// Description: provides all classes for use ... +// +// +// 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 +#include +#include +#include +#include +#include +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.alert.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Constant Definitions ... +// + +static uchar _md5_PADDING[64] = + { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define _md5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define _md5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define _md5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define _md5_I(x, y, z) ((y) ^ ((x) | (~z))) +#define _md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define _md5_FF(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_F((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define _md5_GG(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_G((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define _md5_HH(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_H((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define _md5_II(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_I((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +#define _md5_INIT_STATE_0 0x67452301 +#define _md5_INIT_STATE_1 0xefcdab89 +#define _md5_INIT_STATE_2 0x98badcfe +#define _md5_INIT_STATE_3 0x10325476 + +#define _md5_S11 7 +#define _md5_S12 12 +#define _md5_S13 17 +#define _md5_S14 22 + +#define _md5_S21 5 +#define _md5_S22 9 +#define _md5_S23 14 +#define _md5_S24 20 + +#define _md5_S31 4 +#define _md5_S32 11 +#define _md5_S33 16 +#define _md5_S34 23 + +#define _md5_S41 6 +#define _md5_S42 10 +#define _md5_S43 15 +#define _md5_S44 21 + +// +// END Constant Definitions ... +// + +// +// START Model Definitions ... +// + +// +string X_SIGNAL_TP = "TP"; +string X_SIGNAL_SL = "SL"; +string X_SIGNAL_TYPE = "TY"; +string X_SIGNAL_TICKET = "T"; +string X_SIGNAL_RISKFREE_STEP = "RFS"; +string X_SIGNAL_RISKFREE_RATE = "RFR"; + +// +// Model Signal Handler Result on XCTrade Class ... +struct XTraderHandlerResult +{ + // + // List Of Closed On SL Signals ... + XSignal sl[]; + + // + // List Of Closed On TP Signals ... + XSignal tp[]; + + // + // List Of Risk Free Signals ... + XSignal rf[]; +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerResult +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; +}; + +// +// Model Guard Action Applied Signals ... +struct XGuardHandlerResult +{ + // + // Critical Guard ... + XSignal criticals[]; + + // + // Max Guard ... + XSignal maxes[]; + + // + // Old ... + XSignal olds[]; + + // + // Determines Stopout Action Cals or not ... + bool isStopOut; +}; + +// +// Define Volume States ... +struct XVolumeInfo +{ + // + // Current Available Static Volume ... + double staticVolume; + + // + // Static Volume Calculation Method ... + string staticVolumeCalculationMethod; + + // + // Current Maximum Appliable Volume ... + double maxAllowedVolume; + + // + // Static Volume Increase Multiplier ... + double volumeIncreaseMultiplier; + + // + // Multiply Volume Based On Balance Growing ... + double balanceGowingToApplyMultiplier; + + // + // Where to Increase MaxAllowed Volume ... + double balanceGrowingToIncreaseMaxAllowedVolume; +}; + +// +// Model a Simple Provider Status ... +struct XSignallerInfo +{ + // + // Provider Name ... + string name; + + // + // Number of Longs ... + int longs; + + // + // Number of Shorts ... + int shorts; +}; + +// +// Model Some of Usefull Signals and Market Data ... +struct XSummaryInfo +{ + // + // Define Max Signal Volume ... + double maxSignalVolume; + + // + // Max DrawDown ... + double maxDrawDown; + + // + // Max DrawUp ... + double maxDrawUp; + + // + // Max Number of Same Time Signals ... + int maxSameTimeSignals; + + // + // Number of Long Trades ... + int longSignals; + + // + // Number of Short Trades ... + int shortSignals; + + // + // Number of TPs Attached ... + int numberOfTPs; + + // + // Number of SLs Attached ... + int numberOfSLs; +}; + +// +// Model Account info ... +struct XAccountInfo +{ + // + // User Account ... + string user; + + // + // Name of Client ... + string name; + + // + // Trade Server Name ... + string server; + + // + // Broker Name ... + string broker; + + // + // Account Trade Mode ... + ENUM_ACCOUNT_TRADE_MODE mode; + + // + // Account Leverage ... + long leverage; + + // + // Currency ... + string currency; + + // + // Deposit ... + double deposit; + + // + // Balance ... + double balance; + + // + // Min Balance for Open Trades ... + double minBalanceForOpenTrades; +}; + +// +// this is a Model Which holds Reports for Specific Time Periods ... +struct XReport +{ + // + datetime start; + + // + datetime end; + + // + XAccountInfo accountInfo; + + // + XVolumeInfo volumeInfo; + + // + XSignallerInfo signallersInfo[]; + + // + XSummaryInfo summaryInfo; +}; + +// +// an Enumeration Object which determines Report Type ... +enum ENUM_XREPORT_TYPES +{ + // + // Main Report ... + XREPORT_MAIN, + // + // Daily Report ... + XREPORT_DAILY, + // + // Weekly Report ... + XREPORT_WEEKLY, + // + // Monthly Report ... + XREPORT_MONTHLY, +}; + +// +// a Signal Protection Structure ... +struct XProtectedSignal +{ + // + ulong ticket; + + // + datetime time[]; + + // + double profit[]; +}; + +// +// Represent Collector State Based on Time ... +struct XCollector +{ + // + // time in checking ... + datetime time; + + // + // Signal Volume ... + double volume; + + // + // Max DrawDown in Check Time ... + double maxDrawDown; + + // + // Max Allowed Volume in Check Time ... + double maxAllowedVolume; + + // + // Minimum required Balance for Opening Trades at Check Time ... + double minBalanceForOpenTrade; +}; + +// +// Cross Signals Methods ... +enum ENUM_X_CROSS_SIGNAL_METHOD +{ + // + // Do Nothing and Ignore them ... + X_CROSS_SIGNAL_DO_NOTHING, + // + // Accept all Cross Signals and Act Usually ... + X_CROSS_SIGNAL_REGULAR, + // + // Accept all Cross Signals and for Directional Act Usually and for Indirectional Ac Important ... + X_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT, + // + // Accept all Cross Signals and for Directional Act Important and for Indirectional Ac Usually ... + X_CROSS_SIGNAL_DIRECTION_IMPORTANT_INDIRECTION_REGULAR, + // + // Accept Only Indirectional Signals and Act Usually ... + X_CROSS_SIGNAL_INDIRECTION_REGULAR, + // + // Accept Only Directional Signals and Act Usually ... + X_CROSS_SIGNAL_DIRECTION_REGULAR, + // + // Accept Only Indirectional Signals and Act Important ... + X_CROSS_SIGNAL_INDIRECTION_IMPORTANT, + // + // Accept Only Directional Signals and Act Important ... + X_CROSS_SIGNAL_DIRECTION_IMPORTANT, +}; + +// +// the Action which Guard Handler Can Done when Attacked ... +enum ENUM_X_GUARD_ACTIONS +{ + // + // Do Nothing ... + X_GUARD_DO_NOTHING, + // + // Close All Open Positions ... + X_GUARD_CLOSE_ALL, + // + // Close Max In Drawdown Position ... + X_GUARD_CLOSE_MAX_IN_DD, + // + // Partial Close Max In Drawdown Position by 1% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1, + // + // Partial Close Max In Drawdown Position by 2% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_2, + // + // Partial Close Max In Drawdown Position by 3% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_3, + // + // Partial Close Max In Drawdown Position by 5% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5, + // + // Partial Close Max In Drawdown Position by 10% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10, + // + // Partial Close Max In Drawdown Position by 15% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_15, + // + // Partial Close Max In Drawdown Position by 20% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_20, + // + // Partial Close Max In Drawdown Position by 25% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25, + // + // Partial Close Max In Drawdown Position by 30% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30, + // + // Partial Close Max In Drawdown Position by 40% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40, + // + // Partial Close Max In Drawdown Position by 50% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50, + // + // Partial Close Max In Drawdown Position by 60% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60, + // + // Partial Close Max In Drawdown Position by 70% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_70, + // + // Partial Close Max In Drawdown Position by 75% of Volume ... + X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75, +}; + +// +// Guard Reason ... +enum ENUM_X_GUARD_REASONS +{ + // + // Critical ... + X_GUARDED_CRITICAL, + // + // Max ... + X_GUARDED_MAX, + // + // Old ... + X_GUARDED_OLD +}; + +// +// All Suuported Support Positions Guard ... +enum ENUM_X_GUARD_SUPPORT_METHODS +{ + // + // Ignore Supporting ... + X_SUPPORT_DO_NOTHING, + // + // Full Both Side Support ... + X_SUPPORT_FULL, + // + // Indirectional Supports On Drawing Down ... + X_SUPPORT_IN_DRAWDOWN_INDIRECTIONAL, + // + // Directional Supports On Drawing Up ... + X_SUPPORT_IN_DRAWUP_DIRECTIONAL, +}; + +// +// END Model Definitions ... +// + +// +// START Overrides ... +// + +// +// XBase Class ... +class XCBase +{ + // + // Public ... +public: + // + // Protected ... +protected: + // + void AddItemToBuffer( + double item, // Specified Item + double &buffer[] // Specified Buffer + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; + } + void AddItemToBuffer( + datetime item, // Specified Item + datetime &buffer[] // Specified Buffer + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; + } + void AddItemToBuffer( + XSignal &item, + XSignal &buffer[]) + { + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + } + void AddItemToBuffer( + XCollector &item, // Specified Item + XCollector &buffer[] // Specified Buffer + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; + } + void AddItemToBuffer( + XSignallerInfo &item, + XSignallerInfo &buffer[]) + { + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + } + void AddItemToBuffer( + XProtectedSignal &item, // Item ... + XProtectedSignal &buffer[] // Buffer ... + ) + { + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + buffer[bufferSize] = item; + } + + // + void CleanBuffer(double &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XDeal &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XOrder &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XSignal &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XCollector &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XSignallerInfo &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + void CleanBuffer(XProtectedSignal &buffer[]) + { + // + ArrayFree(buffer); + ArrayResize(buffer, 0); + } + + // + void CopyBuffer( + const XSignallerInfo &source[], // Source Buffer ... + XSignallerInfo &dest[] // Dest Buffer ... + ) + { + // + CleanBuffer(dest); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < sourceCount; i++) + { + // + XSignallerInfo iInfo = source[i]; + + // + AddItemToBuffer( + iInfo, + dest); + } + } + void CopyBuffer( + XProtectedSignal &source[], // Source Buffer to Copy + XProtectedSignal &dest[] // Fill this buffer using source + ) + { + // + CleanBuffer(dest); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + XProtectedSignal iItem = source[i]; + + // + AddItemToBuffer( + iItem, + dest); + } + } + + // + // Private ... +private: +}; + +// +// XCTrade Base Class ... +class XSCTrade : 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 ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +// XCMD5 a library for Hashing ... +class XCMD5 : public XCBase +{ + // + // Public Provides ... +public: + // + // Protected Provides ... + + // + // Constructor ... + XCMD5(void) {} + + // + // Deconstructor ... + ~XCMD5(void) {} + + // + // Hash Specified Char Array ... + string Hash( + uchar &source[], // Specify Char Array to Hash + int length = 0 // Specify Length of Char Array which required to hash + ) + { + // + string result = ""; + + // + int sourceCount = ArraySize(source); + + // + // Validate Args ... + if ( + sourceCount <= 0 || + (sourceCount > 0 && length > sourceCount)) + { + return result; + } + + // + // Normalize Args ... + if (length == 0) + { + length = sourceCount; + } + + // + // Init MD5 ... + MD5Init(); + + // + // Update Buffer ... + MD5Update(source, length); + + // + // Calculate Result ... + result = MD5Final(); + + // + return result; + } + + // + // Hash Specified String ... + string Hash( + string source // Specified String + ) + { + // + string result = ""; + + // + // Converts String to Char Array ... + uchar bytes[]; + StringToCharArray( + source, + bytes, + 0, + StringLen(source)); + + // + result = Hash( + bytes, + ArraySize(bytes)); + + // + return result; + } + +protected: + // + // Private Provides ... +private: + // + uint m_lMD5[4]; + uint m_nCount[2]; + uchar m_lpszBuffer[64]; + + // + // Convert Byte to DWord ... + void ByteToDWord(int &out[], uint &in[], uint len) + { + // + uint i = 0; + uint j = 0; + + // + for (; j < len; i++, j += 4) + { + out[i] = (int)in[j] | (int)in[j + 1] << 8 | (int)in[j + 2] << 16 | (int)in[j + 3] << 24; + } + } + + // + // Convert DWord to Byte ... + void DWordToByte(uchar &out[], int &in[], uint len) + { + // + uint i = 0; + uint j = 0; + + // + for (; j < len; i++, j += 4) + { + // + out[j] = (uchar)(in[i] & 0xff); + out[j + 1] = (uchar)((in[i] >> 8) & 0xff); + out[j + 2] = (uchar)((in[i] >> 16) & 0xff); + out[j + 3] = (uchar)((in[i] >> 24) & 0xff); + } + } + + // + // Init MD5 Array ... + void MD5Init() + { + // + ArrayInitialize(m_lpszBuffer, 64); + + // + m_nCount[0] = m_nCount[1] = 0; + m_lMD5[0] = _md5_INIT_STATE_0; + m_lMD5[1] = _md5_INIT_STATE_1; + m_lMD5[2] = _md5_INIT_STATE_2; + m_lMD5[3] = _md5_INIT_STATE_3; + } + + // + // Update MD5 ... + void MD5Update(uchar &inBuf[], uint inLen) + { + // + int i, ii; + int mdi; + + // + uint in[16]; + int i0 = 0; + + // + mdi = (int)((m_nCount[0] >> 3) & 0x3F); + + // + if ((m_nCount[0] + ((uint)inLen << 3)) < m_nCount[0]) + { + m_nCount[1]++; + } + + // + m_nCount[0] += ((uint)inLen << 3); + m_nCount[1] += ((uint)inLen >> 29); + + // + while ((inLen--) > 0) + { + // + m_lpszBuffer[mdi++] = inBuf[i0++]; + if (mdi == 0x40) + { + // + for (i = 0, ii = 0; i < 16; i++, ii += 4) + { + in[i] = (((uint)m_lpszBuffer[ii + 3]) << 24) | (((uint)m_lpszBuffer[ii + 2]) << 16) | (((uint)m_lpszBuffer[ii + 1]) << 8) | ((uint)m_lpszBuffer[ii]); + } + + // + Transform(m_lMD5, in); + + // + mdi = 0; + } + } + } + + // + // Finalize an MD5 Expression ... + string MD5Final() + { + // + uchar bits[8]; + int nIndex; + uint nPadLen; + const int nMD5Size = 16; + uchar lpszMD5[16]; + string temp; + string out = ""; + int i; + + // + DWordToByte(bits, m_nCount, 8); + nIndex = (int)((m_nCount[0] >> 3) & 0x3f); + nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex); + MD5Update(_md5_PADDING, nPadLen); + MD5Update(bits, 8); + DWordToByte(lpszMD5, m_lMD5, nMD5Size); + + // + for (i = 0; i < nMD5Size; i++) + { + // + if (lpszMD5[i] == 0) + { + temp = "00"; + } + else if (lpszMD5[i] <= 15) + { + temp = StringFormat("0%x", lpszMD5[i]); + } + else + { + temp = StringFormat("%x", lpszMD5[i]); + } + + // + out += temp; + } + + // + lpszMD5[0] = '\0'; + + // + return (out); + } + + // + // Transform Buffers ... + void Transform(uint &buf[], uint &in[]) + { + // + uint a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + // + _md5_FF(a, b, c, d, in[0], _md5_S11, 0xD76AA478); + _md5_FF(d, a, b, c, in[1], _md5_S12, 0xE8C7B756); + _md5_FF(c, d, a, b, in[2], _md5_S13, 0x242070DB); + _md5_FF(b, c, d, a, in[3], _md5_S14, 0xC1BDCEEE); + _md5_FF(a, b, c, d, in[4], _md5_S11, 0xF57C0FAF); + _md5_FF(d, a, b, c, in[5], _md5_S12, 0x4787C62A); + _md5_FF(c, d, a, b, in[6], _md5_S13, 0xA8304613); + _md5_FF(b, c, d, a, in[7], _md5_S14, 0xFD469501); + _md5_FF(a, b, c, d, in[8], _md5_S11, 0x698098D8); + _md5_FF(d, a, b, c, in[9], _md5_S12, 0x8B44F7AF); + _md5_FF(c, d, a, b, in[10], _md5_S13, 0xFFFF5BB1); + _md5_FF(b, c, d, a, in[11], _md5_S14, 0x895CD7BE); + _md5_FF(a, b, c, d, in[12], _md5_S11, 0x6B901122); + _md5_FF(d, a, b, c, in[13], _md5_S12, 0xFD987193); + _md5_FF(c, d, a, b, in[14], _md5_S13, 0xA679438E); + _md5_FF(b, c, d, a, in[15], _md5_S14, 0x49B40821); + + // + _md5_GG(a, b, c, d, in[1], _md5_S21, 0xF61E2562); + _md5_GG(d, a, b, c, in[6], _md5_S22, 0xC040B340); + _md5_GG(c, d, a, b, in[11], _md5_S23, 0x265E5A51); + _md5_GG(b, c, d, a, in[0], _md5_S24, 0xE9B6C7AA); + _md5_GG(a, b, c, d, in[5], _md5_S21, 0xD62F105D); + _md5_GG(d, a, b, c, in[10], _md5_S22, 0x02441453); + _md5_GG(c, d, a, b, in[15], _md5_S23, 0xD8A1E681); + _md5_GG(b, c, d, a, in[4], _md5_S24, 0xE7D3FBC8); + _md5_GG(a, b, c, d, in[9], _md5_S21, 0x21E1CDE6); + _md5_GG(d, a, b, c, in[14], _md5_S22, 0xC33707D6); + _md5_GG(c, d, a, b, in[3], _md5_S23, 0xF4D50D87); + _md5_GG(b, c, d, a, in[8], _md5_S24, 0x455A14ED); + _md5_GG(a, b, c, d, in[13], _md5_S21, 0xA9E3E905); + _md5_GG(d, a, b, c, in[2], _md5_S22, 0xFCEFA3F8); + _md5_GG(c, d, a, b, in[7], _md5_S23, 0x676F02D9); + _md5_GG(b, c, d, a, in[12], _md5_S24, 0x8D2A4C8A); + + // + _md5_HH(a, b, c, d, in[5], _md5_S31, 0xFFFA3942); + _md5_HH(d, a, b, c, in[8], _md5_S32, 0x8771F681); + _md5_HH(c, d, a, b, in[11], _md5_S33, 0x6D9D6122); + _md5_HH(b, c, d, a, in[14], _md5_S34, 0xFDE5380C); + _md5_HH(a, b, c, d, in[1], _md5_S31, 0xA4BEEA44); + _md5_HH(d, a, b, c, in[4], _md5_S32, 0x4BDECFA9); + _md5_HH(c, d, a, b, in[7], _md5_S33, 0xF6BB4B60); + _md5_HH(b, c, d, a, in[10], _md5_S34, 0xBEBFBC70); + _md5_HH(a, b, c, d, in[13], _md5_S31, 0x289B7EC6); + _md5_HH(d, a, b, c, in[0], _md5_S32, 0xEAA127FA); + _md5_HH(c, d, a, b, in[3], _md5_S33, 0xD4EF3085); + _md5_HH(b, c, d, a, in[6], _md5_S34, 0x04881D05); + _md5_HH(a, b, c, d, in[9], _md5_S31, 0xD9D4D039); + _md5_HH(d, a, b, c, in[12], _md5_S32, 0xE6DB99E5); + _md5_HH(c, d, a, b, in[15], _md5_S33, 0x1FA27CF8); + _md5_HH(b, c, d, a, in[2], _md5_S34, 0xC4AC5665); + + // + _md5_II(a, b, c, d, in[0], _md5_S41, 0xF4292244); + _md5_II(d, a, b, c, in[7], _md5_S42, 0x432AFF97); + _md5_II(c, d, a, b, in[14], _md5_S43, 0xAB9423A7); + _md5_II(b, c, d, a, in[5], _md5_S44, 0xFC93A039); + _md5_II(a, b, c, d, in[12], _md5_S41, 0x655B59C3); + _md5_II(d, a, b, c, in[3], _md5_S42, 0x8F0CCC92); + _md5_II(c, d, a, b, in[10], _md5_S43, 0xFFEFF47D); + _md5_II(b, c, d, a, in[1], _md5_S44, 0x85845DD1); + _md5_II(a, b, c, d, in[8], _md5_S41, 0x6FA87E4F); + _md5_II(d, a, b, c, in[15], _md5_S42, 0xFE2CE6E0); + _md5_II(c, d, a, b, in[6], _md5_S43, 0xA3014314); + _md5_II(b, c, d, a, in[13], _md5_S44, 0x4E0811A1); + _md5_II(a, b, c, d, in[4], _md5_S41, 0xF7537E82); + _md5_II(d, a, b, c, in[11], _md5_S42, 0xBD3AF235); + _md5_II(c, d, a, b, in[2], _md5_S43, 0x2AD7D2BB); + _md5_II(b, c, d, a, in[9], _md5_S44, 0xEB86D391); + + // + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; + } +}; + +// +// XSaherElm Account Info Class ... +class XCAccountInfo : public XCBase +{ + // + // Public properties ... +public: + // + // Constructro ... + void XCAccountInfo() + { + // + mAccountInfo = new CAccountInfo(); + + // + mInitialBalance = mAccountInfo.Balance(); + } + + // + // Deconstructor ... + void ~XCAccountInfo() + { + // + mInitialBalance = 0; + } + + // + // 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 Initial Deposit Balance ... + double GetInitialBalance() + { + return mInitialBalance; + } + + // + // 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; + } + + // + // Protected properties ... +protected: + // + // Private properties ... +private: + // + // Initial Account Balance ... + double mInitialBalance; + + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// XSaherElm Report Info Class ... +class XCReporter : public XCBase +{ + // + // Public Provided ... +public: + // + // Constructro ... + void XCReporter() + { + // + mAccountInfo = new XCAccountInfo(); + + // + Reset(); + } + + // + // Deconstructor ... + void ~XCReporter() + { + } + + // + // Reset Specific Report ... + void Reset( + ENUM_XREPORT_TYPES type // Specify Report Type + ) + { + CleanReport(type); + } + + // + // Reset All Reports ... + void Reset() + { + // + CleanReport(XREPORT_MAIN); + CleanReport(XREPORT_MONTHLY); + CleanReport(XREPORT_WEEKLY); + CleanReport(XREPORT_DAILY); + } + + // + // Update Volume Info ... + void UpdateReportVolumeInfo( + ENUM_XREPORT_TYPES type, // Specified Report Type + // + double staticVolume, // Current Available Static Volume + string staticVolumeCalculationMethod, // Static Volume Calculation Method + double maxAllowedVolume, // Current Maximum Appliable Volume + double volumeIncreaseMultiplier, // Static Volume Increase Multiplier + double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing + double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume + ) + { + // + // Filling Account Info ... + FillReportAccountInfo(type); + + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + // + FillingVolumeInfo( + mMainReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + // + FillingVolumeInfo( + mMonthlyReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + // + FillingVolumeInfo( + mWeeklyReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + + // + // Daily ... + case XREPORT_DAILY: + // + FillingVolumeInfo( + mDailyReport, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + break; + } + } + + // + // Update Volume Info on All Reports ... + void UpdateReportsVolumeInfo( + double staticVolume, // Current Available Static Volume + string staticVolumeCalculationMethod, // Static Volume Calculation Method + double maxAllowedVolume, // Current Maximum Appliable Volume + double volumeIncreaseMultiplier, // Static Volume Increase Multiplier + double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing + double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume + ) + { + // + // Main ... + UpdateReportVolumeInfo( + XREPORT_MAIN, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Monthly ... + UpdateReportVolumeInfo( + XREPORT_MONTHLY, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Weekly ... + UpdateReportVolumeInfo( + XREPORT_WEEKLY, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Daily ... + UpdateReportVolumeInfo( + XREPORT_DAILY, + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + } + + // + // Add Specific Signal to Report ... + void AddSignalToReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + const XSignal &signal, // Specified Signal + const string &providers[] // Specified Signal Providers + ) + { + // + // + // Filling Account Info ... + FillReportAccountInfo(type); + + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + AddSignalToReport( + mMainReport, + signal, + providers); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + AddSignalToReport( + mMonthlyReport, + signal, + providers); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + AddSignalToReport( + mWeeklyReport, + signal, + providers); + break; + + // + // Daily ... + case XREPORT_DAILY: + AddSignalToReport( + mDailyReport, + signal, + providers); + break; + } + } + + // + // Add Specific Signal to All Reports ... + void AddSignalToReports( + const XSignal &signal, // Specified Signal + const string &providers[] // Specified Signal Providers + ) + { + // + // Main ... + AddSignalToReport( + XREPORT_MAIN, + signal, + providers); + + // + // Monthly ... + AddSignalToReport( + XREPORT_MONTHLY, + signal, + providers); + + // + // Weekly ... + AddSignalToReport( + XREPORT_WEEKLY, + signal, + providers); + + // + // Daily ... + AddSignalToReport( + XREPORT_DAILY, + signal, + providers); + } + + // + // Report a TP for Specific Report ... + void AddTradeTPInReport( + ENUM_XREPORT_TYPES type // Specified Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + AddTradeTPInReport(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + AddTradeTPInReport(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + AddTradeTPInReport(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + AddTradeTPInReport(mDailyReport); + break; + } + } + + // + // Report a TP for All Reports ... + void AddTradeTPInReports() + { + // + // Main ... + AddTradeTPInReport(XREPORT_MAIN); + + // + // Monthly ... + AddTradeTPInReport(XREPORT_MONTHLY); + + // + // Weekly ... + AddTradeTPInReport(XREPORT_WEEKLY); + + // + // Daily ... + AddTradeTPInReport(XREPORT_DAILY); + } + + // + // Report a SL for Specific Report ... + void AddTradeSLInReport( + ENUM_XREPORT_TYPES type // Specified Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + AddTradeSLInReport(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + AddTradeSLInReport(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + AddTradeSLInReport(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + AddTradeSLInReport(mDailyReport); + break; + } + } + + // + // Report a SL for All Reports ... + void AddTradeSLInReports() + { + // + // Main ... + AddTradeSLInReport(XREPORT_MAIN); + + // + // Monthly ... + AddTradeSLInReport(XREPORT_MONTHLY); + + // + // Weekly ... + AddTradeSLInReport(XREPORT_WEEKLY); + + // + // Daily ... + AddTradeSLInReport(XREPORT_DAILY); + } + + // + // Update Number of Same Time Trades in Specific Report ... + void UpdateMaxSameTimeTradesInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + int value // number of same time trades + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMaxSameTimeTradesInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMaxSameTimeTradesInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMaxSameTimeTradesInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMaxSameTimeTradesInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Number of Same Time Trades in All Report ... + void UpdateMaxSameTimeTradesInReports( + int value // number of same time trades + ) + { + // + // Main ... + UpdateMaxSameTimeTradesInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMaxSameTimeTradesInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMaxSameTimeTradesInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMaxSameTimeTradesInReport( + XREPORT_DAILY, + value); + } + + // + // Update Max DrawDown in Specific Report ... + void UpdateMaxDrawDownInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + double value // draw down value + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMaxDrawDownInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMaxDrawDownInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMaxDrawDownInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMaxDrawDownInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Max DrawDown in All Report ... + void UpdateMaxDrawDownInReports( + double value // draw down value + ) + { + // + // Main ... + UpdateMaxDrawDownInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMaxDrawDownInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMaxDrawDownInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMaxDrawDownInReport( + XREPORT_DAILY, + value); + } + + // + // Update Max DrawUp in Specific Report ... + void UpdateMaxDrawUpInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + double value // draw up value + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMaxDrawUpInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMaxDrawUpInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMaxDrawUpInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMaxDrawUpInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Max DrawUp in All Report ... + void UpdateMaxDrawUpInReports( + double value // draw up value + ) + { + // + // Main ... + UpdateMaxDrawUpInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMaxDrawUpInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMaxDrawUpInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMaxDrawUpInReport( + XREPORT_DAILY, + value); + } + + // + // Update Min Balance for Open Trades in Specific Report ... + void UpdateMinBalanceForOpenTradesInReport( + ENUM_XREPORT_TYPES type, // Specified Report Type + double value // min balance for open trades + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + UpdateMinBalanceForOpenTradesInReport( + mMainReport, + value); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + UpdateMinBalanceForOpenTradesInReport( + mMonthlyReport, + value); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + UpdateMinBalanceForOpenTradesInReport( + mWeeklyReport, + value); + break; + + // + // Daily ... + case XREPORT_DAILY: + UpdateMinBalanceForOpenTradesInReport( + mDailyReport, + value); + break; + } + } + + // + // Update Min Balance for Open Trades in All Report ... + void UpdateMinBalanceForOpenTradesInReports( + double value // min balance for open trades + ) + { + // + // Main ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_MAIN, + value); + + // + // Monthly ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_MONTHLY, + value); + + // + // Weekly ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_WEEKLY, + value); + + // + // Daily ... + UpdateMinBalanceForOpenTradesInReport( + XREPORT_DAILY, + value); + } + + // + // Gnerate Specific Type Of Report String Representation ... + string GenerateReportString( + ENUM_XREPORT_TYPES type, // Specified Report Type + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + result = GenerateReportString( + mMainReport, + separator); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + result = GenerateReportString( + mMonthlyReport, + separator); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + result = GenerateReportString( + mWeeklyReport, + separator); + break; + + // + // Daily ... + case XREPORT_DAILY: + result = GenerateReportString( + mDailyReport, + separator); + break; + } + + // + return result; + } + + // + // Protected Provided ... +protected: + // + // Private Provided ... +private: + // + // Account Info Instance ... + XCAccountInfo mAccountInfo; + + // + // Main Report ... + XReport mMainReport; + + // + // Monthly Report ... + XReport mMonthlyReport; + + // + // Weekly Report ... + XReport mWeeklyReport; + + // + // Daily Report ... + XReport mDailyReport; + + // + // Clean Specific Report ... + void CleanReport( + XReport &report // Specified Report + ) + { + // + datetime time = TimeCurrent(); + + // + // Reset Times ... + report.start = time; + report.end = -1; + + // + // Reset Account Info ... + FillReportAccountInfo(report); + + // + // Reset Summary Info ... + report.summaryInfo.maxDrawUp = 0; + report.summaryInfo.maxDrawDown = 0; + report.summaryInfo.longSignals = 0; + report.summaryInfo.numberOfTPs = 0; + report.summaryInfo.numberOfSLs = 0; + report.summaryInfo.shortSignals = 0; + report.summaryInfo.maxSignalVolume = 0; + report.summaryInfo.maxSameTimeSignals = 0; + + // + // Reset Volume Info ... + report.volumeInfo.staticVolume = 0; + report.volumeInfo.maxAllowedVolume = 0; + report.volumeInfo.volumeIncreaseMultiplier = 0; + report.volumeInfo.balanceGowingToApplyMultiplier = 0; + report.volumeInfo.staticVolumeCalculationMethod = NULL; + report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = 0; + + // + // Reset Signallers Info ... + CleanBuffer(report.signallersInfo); + } + void CleanReport( + ENUM_XREPORT_TYPES type // Specify Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + CleanReport(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + CleanReport(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + CleanReport(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + CleanReport(mDailyReport); + break; + } + } + + // + // Update Specific Reports End Time ... + void FillReportEndTime( + XReport &report // Specified Report + ) + { + // + datetime time = TimeCurrent(); + report.end = time; + } + + // + // Filleing Report Account Info ... + void FillReportAccountInfo( + XReport &report // Specified Report + ) + { + // + FillReportEndTime(report); + + // + report.accountInfo.user = (string)mAccountInfo.GetUserAccount(); + report.accountInfo.name = mAccountInfo.GetName(); + report.accountInfo.server = mAccountInfo.GetServerName(); + report.accountInfo.broker = mAccountInfo.GetCompany(); + report.accountInfo.mode = mAccountInfo.GetTradeMode(); + report.accountInfo.leverage = mAccountInfo.GetLeverage(); + report.accountInfo.currency = mAccountInfo.GetCurrency(); + report.accountInfo.deposit = mAccountInfo.GetInitialBalance(); + report.accountInfo.balance = mAccountInfo.GetBalance(); + } + void FillReportAccountInfo( + ENUM_XREPORT_TYPES type // Specify Report Type + ) + { + // + switch (type) + { + // + // Main ... + case XREPORT_MAIN: + FillReportAccountInfo(mMainReport); + break; + + // + // Monthly ... + case XREPORT_MONTHLY: + FillReportAccountInfo(mMonthlyReport); + break; + + // + // Weekly ... + case XREPORT_WEEKLY: + FillReportAccountInfo(mWeeklyReport); + break; + + // + // Daily ... + case XREPORT_DAILY: + FillReportAccountInfo(mDailyReport); + break; + } + } + + // + // Filling Volume Info ... + void FillingVolumeInfo( + XReport &report, // Specified Report + // + double staticVolume, // Current Available Static Volume + string staticVolumeCalculationMethod, // Static Volume Calculation Method + double maxAllowedVolume, // Current Maximum Appliable Volume + double volumeIncreaseMultiplier, // Static Volume Increase Multiplier + double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing + double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume + ) + { + // + FillReportEndTime(report); + + // + report.volumeInfo.staticVolume = staticVolume; + report.volumeInfo.maxAllowedVolume = maxAllowedVolume; + report.volumeInfo.volumeIncreaseMultiplier = volumeIncreaseMultiplier; + report.volumeInfo.staticVolumeCalculationMethod = staticVolumeCalculationMethod; + report.volumeInfo.balanceGowingToApplyMultiplier = balanceGowingToApplyMultiplier; + report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = balanceGrowingToIncreaseMaxAllowedVolume; + } + + // + // Add Signal to Report ... + void AddSignalToReport( + XReport &report, // Specified Report + const XSignal &signal, // Specified Signal + const string &providers[] // Specified Signal Providers + ) + { + // + FillReportEndTime(report); + + // + double volume = signal.volume; + bool isLong = signal.type == X_SIGNAL_LONG; + + // + // Update Longs and Shorts ... + if (isLong) + { + report.summaryInfo.longSignals++; + } + else + { + report.summaryInfo.shortSignals++; + } + + // + // Chack Max Volume ... + if (volume > report.summaryInfo.maxSignalVolume) + { + report.summaryInfo.maxSignalVolume = volume; + } + + // + // Update Signallers Info ... + for (int i = 0; i < ArraySize(providers); i++) + { + // + string iProvider = providers[i]; + + // + AddOrUpdateSignaller( + report, + iProvider, + signal); + } + } + + // + // Add or Update Signaller Info of Specific Report ... + void AddOrUpdateSignaller( + XReport &report, // Specified Report + const string provider, // Signal Provider name + const XSignal &signal // Specified Signal + ) + { + // + int providerIdx = -1; + int signallersInfoCount = 0; + bool isLong = signal.type == X_SIGNAL_LONG; + + // + // Prepare New One Provider ... + XSignallerInfo info = {}; + info.name = provider; + if (isLong) + { + info.longs = 1; + } + else + { + info.shorts = 1; + } + + // + // Find Provider idx if Exists ... + providerIdx = FindProviderInSignallersInfo( + provider, + report.signallersInfo); + + // + // Check IDX ... + if (providerIdx > -1) + { + // + // Update Exists ... + if (isLong) + { + report.signallersInfo[providerIdx].longs++; + } + else + { + report.signallersInfo[providerIdx].shorts++; + } + } + else + { + // + // Add New One ... + AddItemToBuffer( + info, + report.signallersInfo); + } + } + + // + // Add TP in Report ... + void AddTradeTPInReport( + XReport &report // Specified Report + ) + { + // + FillReportEndTime(report); + + // + report.summaryInfo.numberOfTPs++; + } + + // + // Add SL in Report ... + void AddTradeSLInReport( + XReport &report // Specified Report + ) + { + // + FillReportEndTime(report); + + // + report.summaryInfo.numberOfSLs++; + } + + // + // Update Number of Same Time Trades in Report ... + void UpdateMaxSameTimeTradesInReport( + XReport &report, // Specified Report + int value // number of same time trades + ) + { + // + // Validate Args ... + if (value <= report.summaryInfo.maxSameTimeSignals) + { + return; + } + + // + FillReportEndTime(report); + + // + report.summaryInfo.maxSameTimeSignals = value; + } + + // + // Update Number of Same Time Trades in Report ... + void UpdateMaxDrawUpInReport( + XReport &report, // Specified Report + double value // draw up value + ) + { + // + // Validate Args ... + if (value <= report.summaryInfo.maxDrawUp) + { + return; + } + + // + FillReportEndTime(report); + + // + report.summaryInfo.maxDrawUp = value; + } + + // + // Update Number of Same Time Trades in Report ... + void UpdateMaxDrawDownInReport( + XReport &report, // Specified Report + double value // draw down value + ) + { + // + // Validate Args ... + if (value <= report.summaryInfo.maxDrawDown) + { + return; + } + + // + FillReportEndTime(report); + + // + report.summaryInfo.maxDrawDown = value; + } + + // + // Update Min Balance for Open Trades Value in Report ... + void UpdateMinBalanceForOpenTradesInReport( + XReport &report, // Specified Report + double value // min balance for open trades + ) + { + // + // Validate Arg ... + if (value <= 0) + { + return; + } + + // + FillReportEndTime(report); + + // + report.accountInfo.minBalanceForOpenTrades = value; + } + + // + // Generate Specific Report String Representation ... + string GenerateReportString( + XReport &report, // Specified Report + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Start and End Date ... + result += "Start: " + (string)report.start + separator; + result += "End: " + (string)report.end + separator; + + // + // Account Info ... + string accountStr = GenerateAccountInfoReportString(report.accountInfo); + result += "Account: " + separator + accountStr + separator; + + // + // Summary Info ... + string summaryStr = GenerateSummaryInfoReportString(report.summaryInfo); + result += "Summary: " + separator + summaryStr + separator; + + // + // Volume Info ... + string volumeStr = GenerateVolumeInfoReportString(report.volumeInfo); + result += "Volume: " + separator + volumeStr + separator; + + // + // Signallers Info ... + string signallersStr = GenerateSignallersInfoReportString(report.signallersInfo); + result += "Signallers: " + separator + signallersStr + separator; + + // + return result; + } + + // + // Generate Account info String Representation ... + string GenerateAccountInfoReportString( + XAccountInfo &info, // Specified Account Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Generate Report ... + result += "user: " + info.user + separator; + result += "name: " + info.name + separator; + result += "server: " + info.server + separator; + result += "broker: " + info.broker + separator; + result += "mode: " + EnumToString(info.mode) + separator; + result += "leverage: " + (string)info.leverage + separator; + result += "currency: " + info.currency + separator; + result += "deposit: " + (string)info.deposit + separator; + result += "balance: " + (string)info.balance + separator; + result += "minBalanceForTrading: " + (string)info.minBalanceForOpenTrades + separator; + + // + return result; + } + + // + // Generate Summary info String Representation ... + string GenerateSummaryInfoReportString( + XSummaryInfo &info, // Specified Summary Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Generate Report ... + result += "longSignals: " + (string)info.longSignals + separator; + result += "shortSignals: " + (string)info.shortSignals + separator; + result += "numberOfTps: " + (string)info.numberOfTPs + separator; + result += "numberOfSLs: " + (string)info.numberOfSLs + separator; + result += "maxDrawUp: " + (string)info.maxDrawUp + separator; + result += "maxDrawDown: " + (string)info.maxDrawDown + separator; + result += "maxSignalVolume: " + (string)info.maxSignalVolume + separator; + result += "maxSameTimeSignals: " + (string)info.maxSameTimeSignals + separator; + + // + return result; + } + + // + // Generate Volume info String Representation ... + string GenerateVolumeInfoReportString( + XVolumeInfo &info, // Specified Volume Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Generate Report ... + result += "staticVolume: " + (string)info.staticVolume + separator; + result += "staticVolumeCalculationMethod: " + info.staticVolumeCalculationMethod + separator; + result += "maxAllowedVolume: " + (string)info.maxAllowedVolume + separator; + result += "volumeIncreaseMultiplier: " + (string)info.volumeIncreaseMultiplier + separator; + result += "balanceGowingToApplyMultiplier: " + (string)info.balanceGowingToApplyMultiplier + separator; + result += "balanceGrowingToIncreaseMaxAllowedVolume: " + (string)info.balanceGrowingToIncreaseMaxAllowedVolume + separator; + + // + return result; + } + + // + // Generate Signallers info String Representation ... + string GenerateSignallersInfoReportString( + XSignallerInfo &infos[], // Specified Signallers Info + string separator = "\n" // Separator + ) + { + // + string result = ""; + + // + // Validate Signallers Array Size ... + int signallersCount = ArraySize(infos); + if (signallersCount <= 0) + { + // + result += "EMPTY" + separator; + return result; + } + + // + // Generate Report ... + for (int i = 0; i < signallersCount; i++) + { + // + XSignallerInfo iSignaller = infos[i]; + + // + result += "name: " + iSignaller.name + separator; + result += "longs: " + (string)iSignaller.longs + separator; + result += "shorts: " + (string)iSignaller.shorts + separator; + + // + if (i < signallersCount - 1) + { + result += separator; + } + } + // + return result; + } + + // + // Find a Provider Index in SignallersInfo ... + int FindProviderInSignallersInfo( + string provider, // Specified Provider Name ... + XSignallerInfo &infoBuffer[] // Specified XSignallerInfo Buffer ... + ) + { + // + int result = -1; + + // + int bufferSize = ArraySize(infoBuffer); + if (bufferSize <= 0) + { + return result; + } + + // + // Loop through buffer to find provider index ... + for (int i = 0; i < bufferSize; i++) + { + // + XSignallerInfo iInfo = infoBuffer[i]; + + // + if (iInfo.name != provider) + { + continue; + } + + // + result = i; + } + + // + return result; + } +}; + +// +// a Class For Collectiong Info ... +class XCCollector : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCCollector() + { + Reset(); + } + + // + // Deconstructor ... + ~XCCollector() {} + + // + // Reset All Collectors ... + void Reset() + { + Clean(); + } + + // + // Count Data ... + int Count() + { + // + int result = 0; + + // + result = ArraySize(mTimes); + + // + return result; + } + + // + // TODO: Implement Business Logic here ... + + // + // Add Specific item to Collection ... + bool Add( + XCollector &item // Specified Info + ) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid( + item, + false); + if (!result) + { + return result; + } + + // + // Add Items Values to Buffers ... + // + AddItemToBuffer( + item.time, + mTimes); + + // + AddItemToBuffer( + item.volume, + mVolumes); + + // + AddItemToBuffer( + item.maxDrawDown, + mMaxDrawDowns); + + // + AddItemToBuffer( + item.maxAllowedVolume, + mMaxAllowedVolumes); + + // + AddItemToBuffer( + item.minBalanceForOpenTrade, + mMinBalanceForTradePrices); + + // + return result; + } + + // + // Retrieve Specific Item ... + bool Get( + XCollector &item, // Hold's Result + int index = 0 // Specified Index to Retrieve + ) + { + // + bool result = false; + + // + result = IsValidIndex(index); + if (!result) + { + return result; + } + + // + // Filling Item ... + item.time = mTimes[index]; + item.volume = mVolumes[index]; + item.maxDrawDown = mMaxDrawDowns[index]; + item.maxAllowedVolume = mMaxAllowedVolumes[index]; + item.minBalanceForOpenTrade = mMinBalanceForTradePrices[index]; + + // + return result; + } + XCollector Get( + int index = 0 // Specified Index to Retrieve + ) + { + // + XCollector result = {}; + + // + bool isValidIndex = IsValidIndex(index); + if (!isValidIndex) + { + return result; + } + + // + // Filling Item ... + result.time = mTimes[index]; + result.volume = mVolumes[index]; + result.maxDrawDown = mMaxDrawDowns[index]; + result.maxAllowedVolume = mMaxAllowedVolumes[index]; + result.minBalanceForOpenTrade = mMinBalanceForTradePrices[index]; + + // + return result; + } + bool Get( + XCollector &item, // Hold's Result + datetime time // Specified Index to Retrieve + ) + { + // + bool result = false; + + // + if (time <= 0) + { + return result; + } + + // + int timesCount = ArraySize(mTimes); + result = timesCount > 0; + if (!result) + { + return result; + } + + // + int index = -1; + for (int i = 0; i < timesCount; i++) + { + // + datetime iTime = mTimes[i]; + + // + if (iTime == time) + { + // + index = i; + break; + } + } + + // + result = index >= 0; + if (!result) + { + return result; + } + + // + result = Get( + item, + index); + + // + return result; + } + XCollector Get( + datetime time // Specified Index to Retrieve + ) + { + // + XCollector result = {}; + + // + if (time <= 0) + { + return result; + } + + // + int timesCount = ArraySize(mTimes); + if (timesCount <= 0) + { + return result; + } + + // + int index = -1; + for (int i = 0; i < timesCount; i++) + { + // + datetime iTime = mTimes[i]; + + // + if (iTime == time) + { + // + index = i; + break; + } + } + + // + if (index <= -1) + { + return result; + } + + // + result = Get( + index); + + // + return result; + } + + // + // Retrieve All ... + void GetAll( + XCollector &result[], // Hold's Result + bool reversal = false // Extract Direction + ) + { + // + CleanBuffer(result); + + // + int timesCount = ArraySize(mTimes); + if (timesCount <= 0) + { + return; + } + + // + if (!reversal) + { + // + for (int i = 0; i < timesCount; i++) + { + // + XCollector iCollector = Get(i); + + // + AddItemToBuffer( + iCollector, + result); + } + } + else + { + // + for (int i = timesCount - 1; i >= 0; i--) + { + // + XCollector iCollector = Get(i); + + // + AddItemToBuffer( + iCollector, + result); + } + } + } + + // + // Extract History ... + void Extract( + XCollector &result[], // Hold's Result + int start, // Start Index + int end // End Index + ) + { + // + CleanBuffer(result); + + // + // Validate Args ... + if ( + end < 0 || + start < 0 || + (start == 0 && end == 0) || + MathAbs(start - end == 0)) + { + return; + } + + // + // Validate Start and End Index ... + bool isValidEnd = IsValidIndex(end); + bool isValidStart = IsValidIndex(start); + if (!isValidEnd || !isValidStart) + { + return; + } + + // + bool direction = end > start; + if (direction) + { + // + for (int i = start; i < end - 1; i++) + { + // + XCollector iCollect = Get(i); + + // + AddItemToBuffer( + iCollect, + result); + } + } + else + { + // + for (int i = end - 1; i >= start; i--) + { + // + XCollector iCollect = Get(i); + + // + AddItemToBuffer( + iCollect, + result); + } + } + } + + // + // Validate an Item ... + bool IsValid( + XCollector &item, // Specified Info + bool ignoreTime = true // Ignore Times Checking ... + ) + { + // + bool result = false; + + // + // Check Each Items contains Correct Value ... + // + result = item.volume >= 0; + if (!result) + { + return result; + } + + // + result = item.maxDrawDown >= 0; + if (!result) + { + return result; + } + + // + result = item.maxAllowedVolume >= 0; + if (!result) + { + return result; + } + + // + result = item.minBalanceForOpenTrade >= 0; + if (!result) + { + return result; + } + + // + // Check Time has Proper Value ... + result = item.time > 0; + if (!result) + { + return result; + } + + // + // Check time bigger than last Time ... + int timesCount = ArraySize(mTimes); + if ( + !ignoreTime && + timesCount >= 0) + { + // + // Retrieve Last Added Times ... + datetime lastTime; + result = GetLastItem(lastTime, mTimes); + if (!result) + { + return result; + } + + // + // Compare Last Time by current Time ... + result = item.time > lastTime; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Generate Logging String Representation ... + string GenerateString( + XCollector &item, // Specified Info + string separator = "\n" // Separator Character + ) + { + // + string result = ""; + + // + result += "time: " + (string)item.time + separator; + result += "volume: " + (string)item.volume + separator; + result += "maxDrawDown: " + (string)item.maxDrawDown + separator; + result += "maxAllowedVolume: " + (string)item.maxAllowedVolume + separator; + result += "minBalanceForOpenTrade: " + (string)item.minBalanceForOpenTrade + separator; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Max Draw Up touched till now ... + double mMaxDrawUp; + + // + // Max Draw Down touched till now ... + double mMaxDrawDown; + + // + // Last Time for Checks ... + datetime mTimes[]; + + // + // Volume at the Check Time ... + double mVolumes[]; + + // + // DrawDown for each Check ... + double mMaxDrawDowns[]; + + // + // Max Allowed Volume for each check ... + double mMaxAllowedVolumes[]; + + // + // Min Balance for Open Trades for Each Check ... + double mMinBalanceForTradePrices[]; + + // + // Reset ... + void Clean() + { + // + mMaxDrawUp = 0; + mMaxDrawDown = 0; + + // + CleanBuffer(mTimes); + CleanBuffer(mVolumes); + CleanBuffer(mMaxDrawDowns); + CleanBuffer(mMaxAllowedVolumes); + CleanBuffer(mMinBalanceForTradePrices); + } + + // + // Validate Index ... + bool IsValidIndex( + int index // Specified Index + ) + { + // + bool result = false; + + // + int bufferSize = ArraySize(mTimes); + if (bufferSize <= 0) + { + return result; + } + + // + result = index <= bufferSize - 1; + + // + return result; + } +}; + +// +// a Class for Managing Volumes ... +class XCVolumeManager : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCVolumeManager( + double staticVolumeRate, // Static Volume Calculation Mutiplier + ENUM_STATIC_VOLUME_METHODS volumeMethod = X_STATIC_VOLUME_BASED_ON_DEPOSIT, // How to Calculate Static Volume + double volumeMultiplier = 0, // Volume Multiplier + double volumeMultiplierAppliedRate = 0, // Apply Volume Multiplier when Balance Increased by this rate + double maxAllowedVolume = 0, // Max Allowed Volume + double increaseMaxAllowedVolumeRate = 0 // Increase Max Allowed Volumes when Balance Increased by this rate + ) + { + // + mAccountInfo = new XCAccountInfo(); + + // + ResetForceVolumeMultiplier(); + + // + mVolumeMethod = volumeMethod; + mStaticVoluemRate = staticVolumeRate; + mVolumeMultiplier = volumeMultiplier; + mMaxAllowedVolume = maxAllowedVolume; + mVolumeMultiplierAppliedRate = volumeMultiplierAppliedRate; + mIncreaseMaxAllowedVolumeRate = increaseMaxAllowedVolumeRate; + } + + // + // Deconstructor ... + ~XCVolumeManager(void) {} + + // + // Check Volume Multiplier ... + bool CanUseVolumeMultiplier() + { + // + bool result = false; + + // + result = + mVolumeMultiplier > 0 && + mVolumeMultiplierAppliedRate > 0; + + // + return result; + } + + // + // Check Max Volume ... + bool CanUseMaxVolume() + { + // + bool result = false; + + // + result = + mMaxAllowedVolume > 0; + + // + return result; + } + + // + // Calculate Volume for Position ... + double CalculateVolume( + int numberOfOpenPositions = 0, // Number Of Open Signals + string symbol = NULL // Specify Symbol + ) + { + // + double result = 0; + + // + // Normalize Symbol ... + if (StringLen(symbol) == 0) + { + symbol = _Symbol; + } + + // + // Static Volume ... + result = GetStaticVolume(); + + // + double multiplier = GetVolumeMultiplier(); + result *= multiplier; + + // + // Check Max Allowed Volume Exists ... + double maxAllowedVolume = GetMaxAllowedVolume(); + if (maxAllowedVolume > 0) + { + // + result = + result > maxAllowedVolume + ? maxAllowedVolume + : result; + } + + // + // Check Number of Open Positions ... + if (numberOfOpenPositions >= 0) + { + // + // Decrease Volume ... + result /= (1 + numberOfOpenPositions); + } + + // + // Apply Force Volume Multiplier ... + result *= mForceVolumeMultiplier; + + // + // Retrieve Symbol Volume Info ... + result = NormalizeVolume(result, symbol, 2); + + // + return result; + } + + // + // Calculate Volume Multiplier ... + double GetVolumeMultiplier() + { + // + double result = 1; + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + bool canUseVolumeMultiplier = CanUseVolumeMultiplier(); + if ( + balance < deposit || + !canUseVolumeMultiplier) + { + return result; + } + + // + // Apply Multiplier to Volume ... + double baseGrowBalance = deposit * mVolumeMultiplierAppliedRate; + double balanceGrows = balance - deposit; + if (balanceGrows < baseGrowBalance) + { + return result; + } + + // + double applyMultiplierTimes = balanceGrows / baseGrowBalance; + double roundedApplyMultiplierTimes = MathRound(applyMultiplierTimes); + + // + if (applyMultiplierTimes < roundedApplyMultiplierTimes) + { + applyMultiplierTimes -= (1 - (roundedApplyMultiplierTimes - applyMultiplierTimes)); + } + + // + // Calculate result ... + result = applyMultiplierTimes * mVolumeMultiplier; + + // + return result; + } + + // + // Retrieve Required Balance Grows for Increase Max Allowed Volume ... + double GetIncreaseMaxAllowedVolumeBalance() + { + // + double result = 0; + + // + if ( + mMaxAllowedVolume <= 0 || + mIncreaseMaxAllowedVolumeRate <= 0) + { + return result; + } + + // + result = mAccountInfo.GetInitialBalance() * mIncreaseMaxAllowedVolumeRate; + + // + return result; + } + + // + // Calculate Max Allowed Volume ... + double GetMaxAllowedVolume() + { + // + double result = 0; + + // + // Validate Args ... + result = + mMaxAllowedVolume <= 0 + ? 0 + : mMaxAllowedVolume; + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + bool canUseMaxAllowedVolume = CanUseMaxVolume(); + if ( + balance <= deposit || + !canUseMaxAllowedVolume || + mIncreaseMaxAllowedVolumeRate <= 0) + { + // + return result; + } + + // + // Apply Multiplier to Volume ... + double baseGrowBalance = GetIncreaseMaxAllowedVolumeBalance(); + double balanceGrows = balance - deposit; + if (balanceGrows < baseGrowBalance) + { + return result; + } + + // + double applyMultiplierTimes = balanceGrows / baseGrowBalance; + double roundedApplyMultiplierTimes = MathRound(applyMultiplierTimes); + + // + if (applyMultiplierTimes < roundedApplyMultiplierTimes) + { + applyMultiplierTimes -= (1 - (roundedApplyMultiplierTimes - applyMultiplierTimes)); + } + + // + result *= applyMultiplierTimes; + + // + return result; + } + + // + // Get Static Volume ... + double GetStaticVolume() + { + // + double result = 0; + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + + // + switch (mVolumeMethod) + { + // + case X_STATIC_VOLUME_BASED_ON_DEPOSIT: + result = mStaticVoluemRate * deposit; + break; + + // + case X_STATIC_VOLUME_BASED_ON_BALANCE: + result = mStaticVoluemRate * balance; + break; + } + + // + return result; + } + + // + // Reset Froce Volume Multiplier ... + void ResetForceVolumeMultiplier() + { + mForceVolumeMultiplier = 1; + } + + // + // Retrieve Current Force Volume Multiplier ... + double GetCurrentForceVolumeMultiplier() + { + return mForceVolumeMultiplier; + } + + // + // Retrieve Next Increase Multiplier Price ... + double GetIncreaseMultiplierBalance() + { + return mAccountInfo.GetInitialBalance() * mVolumeMultiplierAppliedRate; + } + + // + // Change Force Volume Multiplier ... + void ChangeForceVolumeMultiplier( + double rate // Change rate + ) + { + // + // Normalize rate ... + if (rate <= 1) + { + rate = 1; + } + + // + mForceVolumeMultiplier = rate; + } + + // + // Increase Force Volume Multiplier ... + void IncreaseForceVolumeMultiplier() + { + mForceVolumeMultiplier += 0.5; + } + + // + // Decrease Force Volume Multiplier ... + void DecreaseForceVolumeMultiplier() + { + // + if (mForceVolumeMultiplier <= 1) + { + return; + } + + // + mForceVolumeMultiplier -= 0.5; + } + + // + // Generate Current State Log String ... + string GenerateStateString( + string separator = "\n" // Log Separator ... + ) + { + // + string result = ""; + + // + // Normallize Separator ... + if (StringLen(separator) == 0) + { + separator = "\n"; + } + + // + result += "ForceVolumeMultiplier: " + (string)mForceVolumeMultiplier + separator; + // + result += "StaticVoluemRate: " + (string)mStaticVoluemRate + separator; + result += "StaticVoluem: " + (string)GetStaticVolume() + separator; + result += "VolumeMethod: " + EnumToString(mVolumeMethod) + separator; + // + result += "VolumeMultiplier: " + (string)mVolumeMultiplier + separator; + result += "VolumeMultiplierAppliedRate: " + (string)mVolumeMultiplierAppliedRate + separator; + // + result += "MaxAllowedVolume: " + (string)mMaxAllowedVolume + separator; + result += "IncreaseMaxAllowedVolumeRate: " + (string)mIncreaseMaxAllowedVolumeRate + separator; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // an Instance of Account Info for reading Balance and Deposit and etc ... + XCAccountInfo mAccountInfo; + + // + // Force Volume Rate Multiplier ... + double mForceVolumeMultiplier; + + // + // Static Volume Calculation Mutiplier ... + double mStaticVoluemRate; + + // + // How to Calculate Static Volume ... + ENUM_STATIC_VOLUME_METHODS mVolumeMethod; + + // + // Volume Multiplier ... + double mVolumeMultiplier; + + // + // Apply Volume Multiplier when Balance Increased by this rate ... + double mVolumeMultiplierAppliedRate; + + // + // Max Allowed Volume + double mMaxAllowedVolume; + + // + // Increase Max Allowed Volumes when Balance Increased by this rate + double mIncreaseMaxAllowedVolumeRate; +}; + +// +// a Class For Managing Signals Additional Data ... +class XCSignalManager : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCSignalManager(void) + { + CleanData(); + } + + // + // Deconstructor ... + ~XCSignalManager(void) {} + + // + void Reset() + { + CleanData(); + } + + // + // Retrieve All Signals ... + void GetAll( + XSignal &result[] // Hold's Result + ) + { + // + CleanBuffer(result); + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + AddItemToBuffer( + iSignal, + result); + } + } + + // + // Count Items ... + int Count() + { + return ArraySize(mSignals); + } + + // + // Retrieve Specific Signal by Ticket ... + XSignal Get( + ulong ticket // Signals Ticket ... + ) + { + // + XSignal result = {}; + + // + // Check Exists ... + bool isExists = IsExists(ticket); + if (!isExists) + { + return result; + } + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket == ticket) + { + // + result = iSignal; + break; + } + } + + // + return result; + } + + // + // Check Signal Exists or not ... + bool IsExists( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket == ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + bool IsExists( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket == signal.ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + + // + // Add Signal ... + bool Add( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Validate Args ... + if (signal.ticket <= 0) + { + return result; + } + + // + // Chekc Signal Exists ... + bool isExists = IsExists(signal); + if (isExists) + { + return result; + } + + // + AddItemToBuffer( + signal, + mSignals); + result = true; + + // + return result; + } + + // + // Update Specific Buffer ... + bool Update( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Validate Args ... + if (signal.ticket <= 0) + { + return result; + } + + // + // Chekc Signal Exists ... + bool isExists = IsExists(signal); + if (!isExists) + { + return result; + } + + // + // Remove Signal ... + Remove(signal); + + // + // Add new One ... + AddItemToBuffer( + signal, + mSignals); + + // + result = true; + + // + return result; + } + + // + // Remove Signal ... + bool Remove( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + // Check Signal Exists ... + bool isExists = IsExists(ticket); + if (!isExists) + { + return result; + } + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + XSignal signals[]; + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket != ticket) + { + AddItemToBuffer( + iSignal, + signals); + } + } + + // + // Now we have to Clean All Signals and Replace them by signals[] buffer ... + UpdateData(signals); + + // + result = true; + return result; + } + bool Remove( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Check Signal Exists ... + bool isExists = IsExists(signal); + if (!isExists) + { + return result; + } + + // + int signalsCount = ArraySize(mSignals); + if (signalsCount <= 0) + { + return result; + } + + // + XSignal signals[]; + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = mSignals[i]; + + // + if (iSignal.ticket != signal.ticket) + { + AddItemToBuffer( + iSignal, + signals); + } + } + + // + // Now we have to Clean All Signals and Replace them by signals[] buffer ... + UpdateData(signals); + + // + result = true; + return result; + } + + // + // Add Or Update ... + bool AddOrUpdate( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + // Validate Args ... + if (signal.ticket <= 0) + { + return result; + } + + // + // Chekc Signal Exists ... + bool isExists = IsExists(signal); + if (!isExists) + { + result = Add(signal); + } + else + { + result = Update(signal); + } + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Holds Signals ... + XSignal mSignals[]; + + // + // Clean All Exists Data ... + void CleanData() + { + CleanBuffer(mSignals); + } + + // + // Update Data ... + void UpdateData( + XSignal &source[] // a Buffer which needs to Replace ... + ) + { + // + CleanData(); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + XSignal iSignal = source[i]; + + // + AddItemToBuffer( + iSignal, + mSignals); + } + } +}; + +// +// XSaherElm Trade Class ... +class XCTrade : public XCBase +{ + // + // all public features ... +public: + // + // Constructor ... + void XCTrade( + string tag, // Specify a Tag for Trader instance + string symbol, // Specify Trader Symbol + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + bool useVirtualTPSL, // Use Virtual TP SL + int maxAllowedTrades, // Specify Max Allowed Trades + double minBallanceForOpenTrades, // Specify Minimum Balance for Open Trades + double minAllowedFreeMarginForOpenTrades, // Specify Minimum Free Marging for Open Trades + bool useSignalProtector = true // Specify Use Signal Protector or not + ) + { + // + mTag = tag; + mSymbol = symbol; + mSlippage = slippage; + mMagicNumber = magicNumber; + mUseVirtualTPSL = useVirtualTPSL; + mMaxAllowedTrades = maxAllowedTrades; + mMinBallanceForOpenTrades = minBallanceForOpenTrades; + mMinAllowedFreeMarginForOpenTrades = minAllowedFreeMarginForOpenTrades; + + // + mTrader = new XSCTrade(); + + // + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + mSignalManager = new XCSignalManager(); + + // + Reset(); + } + + // + // Deconstructor ... + void ~XCTrade() + { + } + + // + // START Configuring Class Functions ... + // + + // + // Reset all Variables ... + void Reset() + { + // + mSignalManager.Reset(); + + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + } + + // + // END Configuring Class Functions ... + // + + // + // START Count ... + // + + // + // Count Open Positions ... + int Count() + { + // + int result = 0; + + // + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + result++; + } + + // + return result; + } + + // + // Count Longs ... + int CountLongs() + { + int result = CountByType(X_SIGNAL_LONG); + return result; + } + + // + // Count Shorts ... + int CountShorts() + { + int result = CountByType(X_SIGNAL_SHORT); + return result; + } + + // + // Count Specific Type Of Positions ... + int CountByType(ENUM_POSITION_TYPE type) + { + // + int result = 0; + + // + int total = PositionsTotal(); + for (int i = 0; i < total; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + if (mPositionInfo.PositionType() != type) + { + continue; + } + + // + result++; + } + + // + return result; + } + + // + // Count By Type ... + int CountByType(ENUM_X_SIGNAL_TYPE type) + { + // + // Validate Args ... + ENUM_POSITION_TYPE mType = POSITION_TYPE_BUY; + if (type == X_SIGNAL_LONG) + { + mType = POSITION_TYPE_BUY; + } + else if (type == X_SIGNAL_SHORT) + { + mType = POSITION_TYPE_SELL; + } + + // + int result = CountByType(mType); + return result; + } + + // + // END Count ... + // + + // + // START Retrieve ... + // + + // + // Retrieve Specified Position by it's Ticket ... + XSignal GetSignal( + ulong ticket // Specified Ticket + ) + { + // + XSignal result = {}; + + // + result = PositionToSignal(ticket); + + // + return result; + } + + // + // Get Last Signal ... + XSignal GetLastSignal() + { + // + XSignal result = {}; + + // + XSignal signals[]; + GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + result = signals[0]; + + // + return result; + } + + // + // Retrieve Last Executed Signal ... + bool GetLastSignal(XSignal &signal) + { + // + bool result = false; + + // + XSignal signals[]; + GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + signal = signals[0]; + result = true; + + // + return result; + } + + // + // Retrieve All Positions ... + void GetSignals( + XSignal &result[] // Holds Result ... + ) + { + // + CleanBuffer(result); + + // + int totalPositions = PositionsTotal(); + for (int i = 0; i < totalPositions; i++) + { + // + if (!mPositionInfo.SelectByIndex(i)) + { + continue; + } + + // + if (mPositionInfo.Magic() != mMagicNumber) + { + continue; + } + + // + if (mPositionInfo.Symbol() != mSymbol) + { + continue; + } + + // + // Position to Signal ... + XSignal signal = PositionToSignal(i); + Add( + signal, + result); + } + } + + // + // Retrieve Type Specific Signals ... + void GetSignals( + XSignal &result[], // Holds Result ... + ENUM_X_SIGNAL_TYPE type // Specified Sginal Type ... + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals(signals); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = signalsCount - 1; i >= 0; i--) + { + // + XSignal iSignal = signals[i]; + + // + if (type == X_SIGNAL_UNKNOWN) + { + Add( + iSignal, + result); + } + else if (iSignal.type == type) + { + Add( + iSignal, + result); + } + } + } + + // + // Filter Signals By Searching Comments ... + void FilterSignals( + XSignal &result[], // Holds Result ... + const string query, // Search in Comment Qeury ... + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specified Sginal Type ... + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + + // + // Validate Args ... + if ( + StringLen(query) <= 0 || + signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + int queryPos = StringFind( + iSignal.comment, + query); + bool isContains = queryPos > -1; + if (!isContains) + { + continue; + } + + // + Add( + iSignal, + result); + } + } + + // + // Get All Trades Which Candle Passed after Open ... + void GetOldSignals( + XSignal &result[], // Holds Result + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + // Normalize Period ... + if (period == NULL) + { + period = _Period; + } + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Current Time Frame Candle Index ... + int currentBarIndex = 0; + + // + // Loop through Positions ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + // Retrieve Trade Open Bar Index based on Current Period ... + int tradeOpenBarIndex = iBarShift( + mSymbol, + period, + iSignal.time); + + // + // Calculate Trade Life ... + int diff = MathAbs(currentBarIndex - tradeOpenBarIndex); + + // + bool isPassed = diff >= life; + if (isPassed) + { + // + Add( + iSignal, + result); + } + } + } + + // + // Get In Profit Signals ... + void GetInProfitSignals( + XSignal &result[], // Holds Result + double minProfit = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isPassed = minProfit <= 0 && iSignal.profit > 0 + ? true + : iSignal.profit >= minProfit; + if (isPassed) + { + Add( + iSignal, + result); + } + } + } + + // + // Get In Drawdown Signals ... + void GetInDrawdownSignals( + XSignal &result[], // Holds Result + double maxDrawDown = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isPassed = maxDrawDown <= 0 && iSignal.profit < 0 + ? true + : iSignal.profit >= (-1 * maxDrawDown); + if (isPassed) + { + Add( + iSignal, + result); + } + } + } + + // + // Retrieve Max In Draw Down Trade ... + XSignal GetMaxInDrawdownSignal( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + XSignal result = {}; + + // + XSignal signals[]; + GetInDrawdownSignals( + signals, + 0, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + result = + (result.ticket <= 0 && + result.profit == 0) || + result.profit > iSignal.profit + ? iSignal + : result; + } + + // + return result; + } + + // + // Calculate Profits Of all Open Signals ... + double GetSignalsProfit( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + double result = 0; + + // + XSignal signals[]; + GetSignals(signals, type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + result += iSignal.profit; + } + + // + return result; + } + + // + // END Retrieve ... + // + + // + // START Signal Execution Actions ... + // + + // + // Execute a Signal in Market ... + ENUM_EXECUTION_SIGNAL_RESULT ExecuteSignal( + XSignal &signal, // Specified Signal + bool ignoreNumberOfTraes = false, // Ignore Number of Trades + bool checkAccountConditions = true // Check Account Balance, Equity and Free Margin for Signal Execution + ) + { + // + ENUM_EXECUTION_SIGNAL_RESULT result = X_TRADER_UNKNOWN_ERROR; + + // + // Validate Signal ... + bool isValid = IsValidSignal(signal); + if (!isValid) + { + // + result = X_TRADER_INVALID_SIGNAL_ERROR; + return result; + } + + // + // Check Account Equity ... + bool isEquityPassed = !checkAccountConditions + ? true + : IsEquityReadyForTrade(); + if (!isEquityPassed) + { + // + result = X_TRADER_NOT_ENOUGH_EQUITY_ERROR; + return result; + } + + // + // Check Account Balance ... + bool isBalancePassed = !checkAccountConditions + ? true + : IsBalanceReadyForTrade(); + if (!isBalancePassed) + { + // + result = X_TRADER_NOT_ENOUGH_BALANCE_ERROR; + return result; + } + + // + // Check Account FreeMargin ... + bool isFreeMarginPassed = !checkAccountConditions + ? true + : IsFreeMarginReadyForTrade(); + if (!isFreeMarginPassed) + { + // + result = X_TRADER_NOT_ENOUGH_MARIGIN_ERROR; + return result; + } + + // + // Check Number of Open Trades ... + int openTradesCount = Count(); + bool isTradeCountPassed = ignoreNumberOfTraes + ? true + : openTradesCount < mMaxAllowedTrades; + if (!isTradeCountPassed) + { + // + result = X_TRADER_MAX_TRADES_REACHED_ERROR; + return result; + } + + // + bool isExecuted = + signal.type == X_SIGNAL_LONG + ? Buy( + signal.volume, + signal.entry, + mUseVirtualTPSL + ? 0 + : signal.sl, + mUseVirtualTPSL + ? 0 + : signal.tp, + signal.comment) + : signal.type == X_SIGNAL_SHORT + ? Sell( + signal.volume, + signal.entry, + mUseVirtualTPSL + ? 0 + : signal.sl, + mUseVirtualTPSL + ? 0 + : signal.tp, + signal.comment) + : false; + if (isExecuted) + { + // + ulong ticket = PositionGetTicket(PositionsTotal() - 1); + + // + signal.id = ticket; + signal.ticket = ticket; + + // + AddOrUpdateSignalInfo(signal); + + // + result = X_TRADER_SUCCEED_EXECUTION; + } + + // + return result; + } + + // + // This Function, Handling Following Works on Open Positions: + // - Close On SL if Reached ... + // - Close On TP if Reached ... + // - Make Risk Free Trades ... + bool HandleSignals( + XTraderHandlerResult &handlerResult, // Holds Result + bool ignoreRiskFree = false // Ignore Risk Free Trdaes + ) + { + // + bool result = false; + + // + // Cleanup Result ... + CleanBuffer(handlerResult.sl); + CleanBuffer(handlerResult.tp); + CleanBuffer(handlerResult.rf); + + // + // Reading Open Positions ... + XSignal signals[]; + GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + double deviation = mSlippage * GetPoints(mSymbol); + + // + // Loop ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isLong = iSignal.type == X_SIGNAL_LONG; + double entry = GetEntry(iSignal.symbol, iSignal.type); + double exit = GetExit(iSignal.symbol, iSignal.type); + double spread = GetSpread(iSignal.symbol); + double appliedTPPrice = + iSignal.tp > 0 + ? isLong + ? iSignal.tp - deviation + : iSignal.tp + deviation + : 0; + double appliedSLPrice = + iSignal.sl > 0 + ? isLong + ? iSignal.sl + deviation + : iSignal.sl - deviation + : 0; + + // + double usedPrice = exit; + + // + bool isSLTouched = + isLong + ? usedPrice <= appliedSLPrice + : usedPrice >= appliedSLPrice; + + // + bool isTPTouched = + isLong + ? usedPrice >= appliedTPPrice + : usedPrice <= appliedTPPrice; + + // + // Handle SL ... + if ( + // + iSignal.sl > 0 + // + && + // + isSLTouched + // + && + // + mUseVirtualTPSL) + { + // + string comment = GenerateSignalSLComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + AddItemToBuffer( + iSignal, + handlerResult.sl); + } + } + + // + // Handle TP ... + if ( + // + iSignal.tp > 0 + // + && + // + isTPTouched + // + && + // + mUseVirtualTPSL) + { + // + string comment = GenerateSignalTPComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + AddItemToBuffer( + iSignal, + handlerResult.tp); + } + } + + // + // Handle Risk Free ... + if ( + // + !ignoreRiskFree + // + && + // + iSignal.riskFreeStep > 0 + // + && + // + iSignal.riskFreeRate > 0 + // + ) + { + // + // Make Signals Risk Free Only if Signal In Profit ... + if (iSignal.profit <= 0) + { + continue; + } + + // + // Base Price is ENTRY, then Last Level, in each level SL is Last Level ... + // + // Calculate Risk Free Level/Multiplier ... + double level = 0; + double roundedLevel = 0; + double rStepPrice = PipsToPrice(iSignal.riskFreeStep); + double rBasePrice = + iSignal.sl > 0 && + iSignal.sl > iSignal.entry + ? iSignal.sl + : iSignal.entry; + + // + double exit = GetExit(iSignal.type); + + // + // Check Base Price for Signal reached with Exit Price ... + bool isExitPriceReachedBasePrice = + isLong + ? exit > rBasePrice + : exit < rBasePrice; + if (!isExitPriceReachedBasePrice) + { + continue; + } + + // + // Calculate Risk Free Step Multiplier ... + level = MathAbs(exit - rBasePrice) / rStepPrice; + + // + // Check Level Must Bigger than 1 ... + if (level < 1) + { + continue; + } + + // + // Normalize Level ... + roundedLevel = MathRound(level); + if (level < roundedLevel) + { + level -= (1 - (roundedLevel - level)); + } + else if (level > roundedLevel) + { + level -= (level - roundedLevel); + } + + // + // Generate Comment ... + string comment = GenerateSignalRFComment(iSignal, (int)level); + + // + // Calculate SL ... + double slDistance = spread; + double sl = + isLong + ? exit - slDistance + : exit + slDistance; + + // + // Increase TP One Level if Exists ... + double tp = iSignal.tp; + if (iSignal.tp > 0 && (isLong + ? iSignal.tp < rBasePrice + rStepPrice + : iSignal.tp > rBasePrice - rStepPrice)) + { + // + tp = + isLong + ? iSignal.tp + rStepPrice + : iSignal.tp - rStepPrice; + } + + // + double rVolume = NormalizeVolume((iSignal.volume * iSignal.riskFreeRate), iSignal.symbol); + + // + // Update Signal Volume ... + double volume = iSignal.volume - rVolume; + + // + bool isClosedPartial = + ClosePartial( + iSignal.ticket, + rVolume, + comment); + if (isClosedPartial) + { + // + bool isModified = true; + if (!mUseVirtualTPSL) + { + // + isModified = Modify( + iSignal.ticket, + sl, + tp, + comment); + } + + // + if (isModified) + { + // + // Try to Update Signal ... + XSignal s = mSignalManager.Get(iSignal.ticket); + + // + // Apply Changes on Signal ... + s.sl = sl; + s.tp = tp; + s.volume = volume; + + // + // Update Signal ... + bool isUpdated = false; + bool isRemoved = false; + if (volume == 0) + { + isRemoved = mSignalManager.Remove(s); + } + else if (volume > 0) + { + isUpdated = mSignalManager.AddOrUpdate(s); + } + if ( + isUpdated || + isRemoved) + { + // + AddItemToBuffer( + s, + handlerResult.rf); + } + } + } + else + { + mSignalManager.Remove(iSignal.ticket); + } + } + } + + // + result = + ArraySize(handlerResult.tp) > 0 || + ArraySize(handlerResult.sl) > 0 || + ArraySize(handlerResult.rf) > 0; + + // + return result; + } + + // + // Close All Trades ... + void CloseSignals( + XSignal &result[], // Holds Result + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalForceCloseComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // Close Pyramid Signals ... + void CloseInPyramidSignals( + XSignal &result[], // Holds Result + double pyramid = 0, // Close Pyramid Profit + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetSignals( + signals, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + double profit = 0; + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + profit += iSignal.profit; + } + + // + // Normalize Pyramid ... + if (pyramid < 0) + { + pyramid = 0; + } + + // + if (profit > pyramid) + { + CloseSignals(result); + } + } + + // + // Close All Trades Which Candle Passed after Open ... + void CloseOldSignals( + XSignal &result[], // Holds Result + int life, // Max Candle Passed after Trades Open + ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetOldSignals( + signals, + life, + period, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalAgeComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // Close In Profit Signals ... + void CloseInProfitSignals( + XSignal &result[], // Holds Result + double minProfit = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetInProfitSignals( + signals, + minProfit, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalProfitComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // Close In Drawdown Signals ... + void CloseInDrawdownSignals( + XSignal &result[], // Holds Result + double maxDrawDown = 0, // Minimum Profit To Close Trades + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + GetInDrawdownSignals( + signals, + maxDrawDown, + type); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + string comment = GenerateSignalProfitComment(iSignal); + + // + bool isClosed = Close( + iSignal.ticket, + comment); + if (isClosed) + { + Add( + iSignal, + result); + } + } + } + + // + // END Signal Execution Actions ... + // + + // + // START Actions ... + // + + // + // Force Open a Buy/Long Position ... + bool Buy( + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + const string comment = "" // comment + ) + { + // + bool result = false; + + // + result = mTrader.Buy( + volume, + mSymbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + 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; + + // + result = mTrader.BuyLimit( + volume, + price, + mSymbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + 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; + + // + result = mTrader.BuyStop( + volume, + price, + mSymbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Force Open a Sell/Short Position ... + bool Sell( + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + const string comment = "" // comment + ) + { + // + bool result = false; + + // + result = mTrader.Sell( + volume, + mSymbol, + price, + sl, + tp, + comment); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + 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; + + // + result = mTrader.SellLimit( + volume, + price, + mSymbol, + sl, + tp, + typeTime, + expiration, + comment); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + 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; + + // + result = mTrader.SellStop( + volume, + price, + mSymbol, + 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 + const string comment = "" // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + if (tp <= 0 && sl <= 0) + { + result = false; + return result; + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment); + if (result) + { + // + if (mSignalManager.IsExists(ticket)) + { + // + XSignal signal = GetSignal(ticket); + + // + mSignalManager.Update(signal); + } + } + + // + 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); + if (result) + { + // + if (mSignalManager.IsExists(ticket)) + { + mSignalManager.Remove(ticket); + } + } + + // + return result; + } + + // + // 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); + if (result) + { + // + if (mSignalManager.IsExists(ticket)) + { + // + XSignal signal = GetSignal(ticket); + + // + mSignalManager.Update(signal); + } + } + + // + return result; + } + + // + // END Actions ... + // + + // + // START Account Related ... + // + + // + // Retrieve Minimum Balance For Open Trades ... + double GetMinBalanceForOpenTrades() + { + // + double result = mMinBallanceForOpenTrades; + + // + double balance = mAccountInfo.GetBalance(); + double deposit = mAccountInfo.GetInitialBalance(); + if (balance > deposit) + { + // + double rate = mMinBallanceForOpenTrades / deposit; + + // + double ratedBalance = balance * rate; + + // + result = MathMax(mMinBallanceForOpenTrades, ratedBalance); + } + + // + return result; + } + + // + // Check Account Has Minimum Balance For Trade ... + bool IsBalanceReadyForTrade() + { + // + bool result = false; + + // + double minBalance = GetMinBalanceForOpenTrades(); + result = mAccountInfo.GetBalance() >= minBalance; + + // + return result; + } + + // + // Check Free Margin Has Enough For Trade ... + bool IsFreeMarginReadyForTrade() + { + // + bool result = false; + + // + double freeMargin = mAccountInfo.GetFreeMargin(); + + // + result = freeMargin >= mMinAllowedFreeMarginForOpenTrades; + + // + return result; + } + + // + // Check Equity Has Enough For Trade ... + bool IsEquityReadyForTrade() + { + // + bool result = false; + + // + double equity = mAccountInfo.GetEquity(); + + // + result = equity >= mMinAllowedFreeMarginForOpenTrades; + + // + return result; + } + + // + // END Account Related ... + // + + // + // START Signal Related ... + // + + // + // Validate Signal ... + bool IsValidSignal( + XSignal &signal // Specified Signal for Execution + ) + { + // + bool result = false; + + // + // Validate Signal Type ... + result = signal.type != X_SIGNAL_UNKNOWN; + if (!result) + { + return result; + } + + // + // Check Symbol ... + result = StringLen(signal.symbol) == 0 ? true : signal.symbol == mSymbol; + if (!result) + { + return result; + } + + // + // Check magic number ... + result = signal.magicNumber <= 0 ? true : signal.magicNumber == mMagicNumber; + if (!result) + { + return result; + } + + // + // Check Entry ... + result = signal.entry > 0; + if (!result) + { + return result; + } + + // // + // // Check SL ... + // // For Fix RiskFree Issues Ignore this ... + // result = signal.sl == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.sl < signal.entry + // : signal.sl > signal.entry; + // if (!result) + // { + // return result; + // } + + // + // Check TP ... + result = signal.tp == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.tp > signal.entry + : signal.tp < signal.entry; + if (!result) + { + return result; + } + + // + // Check Volume ... + result = signal.volume > 0; + if (!result) + { + return result; + } + + // + // Check Time ... + result = signal.time > 0; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Get Signal InDirection (Reversal) Type ... + ENUM_X_SIGNAL_TYPE GetSignalIndirectionType( + XSignal &signal // Specified Signal + ) + { + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + switch (signal.type) + { + // + case X_SIGNAL_LONG: + result = X_SIGNAL_SHORT; + break; + + // + case X_SIGNAL_SHORT: + result = X_SIGNAL_LONG; + break; + } + + // + return result; + } + + // + // Get Signal InDirection (Reversal) Type ... + ENUM_X_SIGNAL_TYPE GetIndirectionSignalType( + ENUM_X_SIGNAL_TYPE type // Specified Type + ) + { + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + switch (type) + { + // + case X_SIGNAL_LONG: + result = X_SIGNAL_SHORT; + break; + + // + case X_SIGNAL_SHORT: + result = X_SIGNAL_LONG; + break; + } + + // + return result; + } + + // + // Calculate SignalAge ... + int GetSignalAge( + datetime time // Signal Execution Time + ) + { + // + int result = 0; + + // + // Validate Arg ... + if (time <= 0) + { + return result; + } + + // + int sIndex = iBarShift( + mSymbol, + _Period, + time); + + // + datetime cTime = iTime( + mSymbol, + _Period, + 0); + int cIndex = iBarShift( + mSymbol, + _Period, + cTime); + + // + result = MathAbs(cIndex - sIndex); + + // + return result; + } + int GetSignalAge( + datetime time, // Signal Execution Time + ENUM_TIMEFRAMES period // Specify Time Frame + ) + { + // + int result = 0; + + // + // Validate Arg ... + if (time <= 0) + { + return result; + } + + // + int sIndex = iBarShift( + mSymbol, + period, + time); + + // + datetime cTime = iTime( + mSymbol, + period, + 0); + int cIndex = iBarShift( + mSymbol, + _Period, + cTime); + + // + result = MathAbs(cIndex - sIndex); + + // + return result; + } + int GetSignalAge( + XSignal &signal // Specified Signal + ) + { + // + int result = 0; + + // + // Validate Arg ... + if ( + signal.time <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalAge(signal.time); + + // + return result; + } + int GetSignalAge( + XSignal &signal, // Specify Signal + ENUM_TIMEFRAMES period // Specify Time Frame + ) + { + // + int result = 0; + + // + // Validate Arg ... + if ( + signal.time <= 0 || + !IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GetSignalAge( + signal.time, + period); + + // + return result; + } + + // + // Prepare a Signall ... + XSignal GenerateSignal( + ENUM_X_SIGNAL_TYPE type, // Signal Type + double tp = 0, // Take Profit + double sl = 0, // Stop Loss + double volume = 0, // Volume + double riskFreeStep = 0, // Risk Free Step Price + double riskFreeRate = 0 // Risk Free Rate + ) + { + // + XSignal result = {}; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + // Check Signal Type ... + bool isLong = type == X_SIGNAL_LONG; + + // + // Retrieve entry Price ... + double entry = GetEntry(mSymbol, type); + double spread = GetSpread(mSymbol); + + // + result.tp = tp; + result.sl = sl; + result.type = type; + result.entry = entry; + result.symbol = mSymbol; + result.magicNumber = mMagicNumber; + result.riskFreeStep = riskFreeStep; + result.riskFreeRate = riskFreeRate; + result.time = iTime(mSymbol, _Period, 0); + result.volume = NormalizeVolume(volume, mSymbol); + + // + // Since we Use signal instance to Generate Comment, this must be at the end ... + result.comment = GenerateSignalComment(result); + + // + return result; + } + + // + // Convert a Signal to String Representation ... + string ToString( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + if (!IsValid(signal, mMagicNumber) || signal.ticket <= 0) + { + return result; + } + + // + // TICKET ... + // it is very importants since they hold position info ... + result += X_SIGNAL_TICKET + "(" + (string)signal.ticket + ")"; + + // + // TYPE ... + string typeStr = GetSignalType(signal.type); + result += "_" + X_SIGNAL_TYPE + "(" + typeStr + ")"; + + // + // TP ... + result += "_" + X_SIGNAL_TP + "(" + (string)signal.tp + ")"; + + // + // SL ... + result += "_" + X_SIGNAL_SL + "(" + (string)signal.sl + ")"; + + // + // RFS ... + result += "_" + X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.riskFreeStep + ")"; + + // + // RFR ... + result += "_" + X_SIGNAL_RISKFREE_RATE + "(" + (string)signal.riskFreeRate + ")"; + + // + return result; + } + + // + // Generate Comments for Specific Signal ... + string GenerateSignalComment( + ENUM_X_SIGNAL_TYPE type, // Specify Kind Signal Type + double volume, // Signal Volume + bool isCrossSignal = false // Specify Signal Cross + ) + { + // + string result = ""; + + // + string typeStr = GetSignalType(type); + if ( + volume <= 0 || + StringLen(typeStr) == 0) + { + return result; + } + + // + volume = NormalizeVolume(volume, mSymbol); + + // + result = mTag + (!isCrossSignal ? "" : "_Cross_") + "_" + typeStr; + + // + return result; + } + string GenerateSignalComment( + XSignal &signal, // Specified Signal + bool isCrossSignal = false // Specify Signal Cross + ) + { + // + string result = GenerateSignalComment( + signal.type, + signal.volume, + isCrossSignal + // + ); + + // + return result; + } + + // + // Generate Signal RF TP Comment ... + string GenerateSignalRFComment( + XSignal &signal, // Specified Signal + int level // Which Step of RFS + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + double exit = NormalizePrice(GetExit(signal.symbol, signal.type), signal.symbol); + + // + string prefix = X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.ticket + ")"; + // + result = + // + level > 0 + ? prefix + "_" + (string)level + ": " + (string)exit + : prefix + ": " + (string)exit; + // + ; + + // + return result; + } + + // + // Generate Signal TP Comment ... + string GenerateSignalTPComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + double exit = NormalizePrice(GetExit(signal.symbol, signal.type), signal.symbol); + + // + result = + // + X_SIGNAL_TP + "(" + (string)signal.ticket + "): " + (string)exit; + // + ; + + // + return result; + } + + // + // Generate Signal SL Comment ... + string GenerateSignalSLComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + double exit = NormalizePrice(GetExit(signal.symbol, signal.type), signal.symbol); + + // + result = + // + X_SIGNAL_SL + "(" + (string)signal.ticket + "): " + (string)exit; + // + ; + + // + return result; + } + + // + // Generate Signal Profit Comment ... + string GenerateSignalProfitComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + result = + // + "Profit(" + (string)signal.ticket + "): " + (string)signal.profit; + // + ; + + // + return result; + } + + // + // Generate Signal Force Close Comment ... + string GenerateSignalForceCloseComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + result = + // + "FC(" + (string)signal.ticket + "): " + (string)signal.profit; + // + ; + + // + return result; + } + + // + // Generate Signal Age Comment ... + string GenerateSignalAgeComment( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Signal and it's Ticket ... + if (!IsValidSignal(signal) || signal.ticket <= 0) + { + return result; + } + + // + int age = GetSignalAge(signal); + + // + result = + // + "(" + (string)signal.ticket + ") A: " + (string)age + ", P:" + (string)signal.profit; + // + ; + + // + return result; + } + + // + // Generate a Signal Object name for Draw Events On Chart ... + string GenerateSignalObjectName( + ulong ticket // Specify Ticket + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + // TICKET ... + // it is very importants since they hold position info ... + result += "T(" + (string)ticket + ")"; + + // + return result; + } + string GenerateSignalObjectName( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + // Validate Arg ... + if (!IsValid(signal, mMagicNumber)) + { + return result; + } + + // + result = GenerateSignalObjectName(signal.ticket); + + // + return result; + } + + // + // Genrate a Signal Event Object Name ... + string GenerateSignalEventObjectName( + ulong ticket // Specify Ticket + ) + { + // + string result = ""; + + // + result = GenerateSignalObjectName(ticket) + "_Event"; + + // + return result; + } + string GenerateSignalEventObjectName( + XSignal &signal // Specified Signal + ) + { + // + string result = ""; + + // + result = GenerateSignalEventObjectName(signal.ticket); + + // + return result; + } + + // + // END Signal Related ... + // + + // + // START Deals ... + // + + // + // Count Deals ... + int DealsCount( + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + int result = 0; + + // + XDeal deals[]; + GetDeals( + deals, + start, + end); + result = ArraySize(deals); + + // + return result; + } + + // + // Retrieve All Deals ... + void GetDeals( + XDeal &result[], // Hold's Result + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + CleanBuffer(result); + + // + // Select History if Start and End date provided ... + if (start > -1) + { + // + // Normalize End date ... + if (end == -1) + { + end = TimeCurrent(); + } + + // + bool isSelect = HistorySelect(start, end); + if (!isSelect) + { + return; + } + } + + // + int total = HistoryDealsTotal(); + if (total <= 0) + { + return; + } + + // + // Loop ... + for (int i = total - 1; i >= 0; i--) + { + // + // Select by Index ... + bool isSelect = mDealInfo.SelectByIndex(i); + if (!isSelect) + { + continue; + } + + // + // Check Magic ... + ulong magic = mDealInfo.Magic(); + bool isMagicSame = magic == mMagicNumber; + if (!isMagicSame) + { + continue; + } + + // + // Check Symbol ... + string symbol = mDealInfo.Symbol(); + bool isSymbolSame = symbol == mSymbol; + if (!isSymbolSame) + { + continue; + } + + // + XDeal deal = ToXDealByIndex(i); + + // + Add( + deal, + result); + } + } + + // + // Retrieve Last Deal ... + XDeal GetLastDeal() + { + // + XDeal result = {}; + + // + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount <= 0) + { + return result; + } + + // + result = deals[0]; + + // + return result; + } + + // + // END Deals ... + // + + // + // START Orders ... + // + + // + // Count Orders ... + int OrdersCount( + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + int result = 0; + + // + XOrder orders[]; + GetOrders( + orders, + start, + end); + result = ArraySize(orders); + + // + return result; + } + + // + // Retrieve Orders ... + void GetOrders( + XOrder &result[], // Hold's Result + datetime start = -1, // Start Date + datetime end = -1 // End Date + ) + { + // + CleanBuffer(result); + + // + // Select History if Start and End date provided ... + if (start > -1) + { + // + // Normalize End date ... + if (end == -1) + { + end = TimeCurrent(); + } + + // + bool isSelect = HistorySelect(start, end); + if (!isSelect) + { + return; + } + } + + // + int total = HistoryOrdersTotal(); + if (total <= 0) + { + return; + } + + // + // Loop ... + for (int i = total - 1; i >= 0; i--) + { + // + // Select by Index ... + bool isSelect = mOrderInfo.SelectByIndex(i); + if (!isSelect) + { + continue; + } + + // + // Check Magic ... + ulong magic = mOrderInfo.Magic(); + bool isMagicSame = magic == mMagicNumber; + if (!isMagicSame) + { + continue; + } + + // + // Check Symbol ... + string symbol = mOrderInfo.Symbol(); + bool isSymbolSame = symbol == mSymbol; + if (!isSymbolSame) + { + continue; + } + + // + XOrder order = ToXOrderByIndex(i); + + // + Add( + order, + result); + } + } + + // + // Retrieve Last Order ... + XOrder GetLastOrder() + { + // + XOrder result = {}; + + // + XOrder orders[]; + GetOrders(orders); + int ordersCount = ArraySize(orders); + if (ordersCount <= 0) + { + return result; + } + + // + result = orders[0]; + + // + return result; + } + + // + // END Orders ... + // + + // + // START OnTrade Handlers ... + // + + // + // Handle OnTrade Event ... + void HandleOnTradeEvent( + XOnTradeHandlerResult &result // Hold's Result + ) + { + // + if (mScanStarted) + { + ProcessOnTradeContext(result); + } + else + { + InitOnTradeContext(); + } + } + + // + // END OnTrade Handlers ... + // + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + // all protected features ... +protected: + // + // all private features ... +private: + // + // Specified Unique Tag ... + string mTag; + + // + // which Symbol ... + string mSymbol; + + // + // using deviation, it must be in Point ... + int mSlippage; + + // + // using magic number ... + ulong mMagicNumber; + + // + // Detect Using Virtual TP or SL ... + bool mUseVirtualTPSL; + + // + // Specify Max Allowed Trades + int mMaxAllowedTrades; + + // + // Minimum Free Marging for Open Trades + double mMinAllowedFreeMarginForOpenTrades; + + // + // Minimum Balance for Open Trades + double mMinBallanceForOpenTrades; + + // + // using CTrade instance ... + XSCTrade mTrader; + + // + // Deals Info ... + CDealInfo mDealInfo; + + // + // Order Info ... + COrderInfo mOrderInfo; + + // + // An Instance Of XCAccount Info for Handling Account Related Actions ... + XCAccountInfo mAccountInfo; + + // + // using PositionInfo instance ... + CPositionInfo mPositionInfo; + + // + // Signal Manager ... + XCSignalManager mSignalManager; + + // + // START OnTrade Handlers ... + // + + // + 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( + XOnTradeHandlerResult &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) + { + // + LogMessage("Failed to Load OnTrade Context History ..."); + + // + 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(); + + // + // load history ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + // + LogMessage("Failed to Load OnTrade Context History ..."); + + // + return; + } + + // + // get the current value ... + mOrdersCount = OrdersTotal(); + mPositionsCount = PositionsTotal(); + mDealsCount = HistoryDealsTotal(); + mHistoryOrdersCount = HistoryOrdersTotal(); + + // + mScanStarted = true; + } + + // + // END OnTrade Handlers ... + // + + // + // START Signal Private ... + // + + // + // Add Or Update Signal ... + void AddOrUpdateSignalInfo( + XSignal &signal // Specified Signal + ) + { + // + bool isExists = mSignalManager.IsExists(signal); + if (isExists) + { + mSignalManager.Remove(signal.ticket); + } + + // + bool isAddOrUpdated = mSignalManager.AddOrUpdate(signal); + if (isAddOrUpdated) + { + // + color longColor = clrAqua; + color shortColor = clrFuchsia; + + // + DrawSignalShape( + signal, + longColor, + shortColor); + } + } + + // + // Retrieve Signal String From Chart Event ... + XSignal RetrieveSignal( + ulong ticket // Specify Position Ticket + ) + { + // + XSignal result = {}; + + // + if (ticket <= 0) + { + return result; + } + + // + result = mSignalManager.Get(ticket); + + // + return result; + } + void RetrieveSignal( + XSignal &signal // Specified Signal + ) + { + + // + XSignal tSignal = mSignalManager.Get(signal.ticket); + + // + // Fill signal by tSignal Data ... + // since tese properties may change in signal manipulation times ... + signal.tp = tSignal.tp; + signal.sl = tSignal.sl; + signal.riskFreeStep = tSignal.riskFreeStep; + signal.riskFreeRate = tSignal.riskFreeRate; + } + + // + // Convert Position to Signal by Index ... + XSignal PositionToSignal(int index) + { + // + XSignal result = {}; + + // + if (!mPositionInfo.SelectByIndex(index)) + { + return result; + } + + // + ulong ticket = mPositionInfo.Ticket(); + result = PositionToSignal(ticket); + + // + return result; + } + + // + // Position To Signal by Ticket ... + XSignal PositionToSignal(ulong ticket) + { + // + XSignal result = {}; + + // + if (!mPositionInfo.SelectByTicket(ticket)) + { + return result; + } + + // + bool isExists = mSignalManager.IsExists(ticket); + if (isExists) + { + result = RetrieveSignal(ticket); + } + + // + // Ticket ... + result.ticket = mPositionInfo.Ticket(); + + // + // ID ... + result.id = mPositionInfo.Identifier(); + + // + // Symbol ... + result.symbol = mPositionInfo.Symbol(); + + // + // Type ... + ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)mPositionInfo.PositionType(); + ENUM_X_SIGNAL_TYPE type = pType == POSITION_TYPE_BUY ? X_SIGNAL_LONG : X_SIGNAL_SHORT; + result.type = type; + + // + // MagicNumber ... + result.magicNumber = mPositionInfo.Magic(); + + // + // Entry/Open Price ... + result.entry = mPositionInfo.PriceOpen(); + + // + // Take Profit ... + result.tp = result.tp <= 0 && mPositionInfo.TakeProfit() > 0 + ? mPositionInfo.TakeProfit() + : result.tp; + + // + // Stop Loss ... + result.sl = result.sl <= 0 && mPositionInfo.StopLoss() > 0 + ? mPositionInfo.StopLoss() + : result.sl; + + // + // Profit ... + result.profit = mPositionInfo.Profit(); + + // + // Time ... + result.time = mPositionInfo.Time(); + + // + // Volume ... + result.volume = mPositionInfo.Volume(); + + // + // Comment ... + result.comment = mPositionInfo.Comment(); + + // + return result; + } + + // + // Converts a Deal to XDeal by Index ... + XDeal ToXDealByIndex(int index) + { + // + XDeal result = {}; + + // + bool isSelect = mDealInfo.SelectByIndex(index); + if (!isSelect) + { + return result; + } + + // + // Read Deal Ticket ... + ulong ticket = mDealInfo.Ticket(); + result = ToXDealByTicket(ticket); + + // + return result; + } + + // + // Converts a Deal to XDeal by Ticket ... + XDeal ToXDealByTicket(ulong ticket) + { + // + XDeal result = {}; + + // + mDealInfo.Ticket(ticket); + + // + result.time = mDealInfo.Time(); + result.swap = mDealInfo.Swap(); + result.magic = mDealInfo.Magic(); + result.order = mDealInfo.Order(); + result.entry = mDealInfo.Entry(); + result.price = mDealInfo.Price(); + result.ticket = mDealInfo.Ticket(); + result.symbol = mDealInfo.Symbol(); + result.type = mDealInfo.DealType(); + result.profit = mDealInfo.Profit(); + result.volume = mDealInfo.Volume(); + result.comment = mDealInfo.Comment(); + result.positionId = mDealInfo.PositionId(); + result.commission = mDealInfo.Commission(); + result.reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + return result; + } + + // + // Convert an Order to XOrder by Index ... + XOrder ToXOrderByIndex(int index) + { + // + XOrder result = {}; + + // + bool isSelect = mOrderInfo.SelectByIndex(index); + if (!isSelect) + { + return result; + } + + // + ulong ticket = mOrderInfo.Ticket(); + result = ToXOrderByTicket(ticket); + + // + return result; + } + + // + // Convert an Order to XOrder by Ticket ... + XOrder ToXOrderByTicket(ulong ticket) + { + // + XOrder result = {}; + + // + bool isSelect = mOrderInfo.Select(ticket); + if (!isSelect) + { + return result; + } + + // + result.state = mOrderInfo.State(); + result.magic = mOrderInfo.Magic(); + result.ticket = mOrderInfo.Ticket(); + result.symbol = mOrderInfo.Symbol(); + result.type = mOrderInfo.OrderType(); + result.comment = mOrderInfo.Comment(); + result.stopLoss = mOrderInfo.StopLoss(); + result.typeTime = mOrderInfo.TypeTime(); + result.timeDone = mOrderInfo.TimeDone(); + result.timeSetup = mOrderInfo.TimeSetup(); + result.positionId = mOrderInfo.PositionId(); + result.priceOpen = mOrderInfo.PriceOpen(); + result.takeProfit = mOrderInfo.TakeProfit(); + result.typeFilling = mOrderInfo.TypeFilling(); + result.priceCurrent = mOrderInfo.PriceCurrent(); + result.volumeInitial = mOrderInfo.VolumeInitial(); + result.volumeCurrent = mOrderInfo.VolumeCurrent(); + result.timeExpiration = mOrderInfo.TimeExpiration(); + result.priceStopLimit = mOrderInfo.PriceStopLimit(); + result.reason = (ENUM_ORDER_REASON)HistoryOrderGetInteger( + ticket, + ORDER_REASON); + + // + return result; + } + // + // END Signal Private ... + // +}; + +// +// a Class For Guard Account ... +class XCGuard : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCGuard( + int oldAge, // Age for Old Trades + ENUM_X_GUARD_ACTIONS oldGuardAction, // Guard Action for Too Old State + double criticalFactor, // Critical DrawDown Factor based On Balance + ENUM_X_GUARD_ACTIONS criticalAction, // Guard Action for Critical State + double maxFactor, // Max DrawDown Factor based on Balance + ENUM_X_GUARD_ACTIONS maxAction, // Guard Action for Max State + int GuardStopoutFiredAfterTouches, // Guard Stopout if Max State touched + ENUM_X_GUARD_SUPPORT_METHODS supportMethod // How to Support Signals + ) + { + // + mSupportPrefix = "SPT"; + mDirectional = "SPD"; + mInDirectional = "SPIND"; + + // + mOldAge = oldAge; + mOldGuardAction = oldGuardAction; + + // + mMaxFactor = maxFactor; + mMaxAction = maxAction; + mCriticalFactor = criticalFactor; + mCriticalAction = criticalAction; + mGuardStopoutFiredAfterTouches = GuardStopoutFiredAfterTouches; + + // + mSupportMethod = supportMethod; + + // + mAccountInfo = new XCAccountInfo(); + + // + double deposit = mAccountInfo.GetInitialBalance(); + + // + if ( + maxFactor > 0 && + maxFactor < 1) + { + mMaxValue = maxFactor * deposit; + } + + // + if ( + criticalFactor > 0 && + criticalFactor < 1) + { + mCriticalValue = criticalFactor * deposit; + } + + // + Reset(); + ResetMaxDrawDownTouches(); + } + + // + // Deconstructor ... + ~XCGuard() {} + + // + // Reset List ... + void Reset() + { + // + CleanBuffer(mGuardedSignals); + CleanBuffer(mSupportedSignals); + } + + // + // Reset Consecutive Max DrawDown Touches ... + void ResetMaxDrawDownTouches() + { + mOccuredconsecutiveMaxDraDownTouches = 0; + } + + // + // Calculate and Retrieve Critical DrawDown Value ... + double GetCriticalValue() + { + // + double result = mCriticalValue; + if (mCriticalFactor <= 0) + { + return result; + } + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + + // + if (balance > deposit) + { + // + double balanceBasedCriticalDrawDown = mCriticalFactor * balance; + + // + result = MathMax( + mCriticalValue, + balanceBasedCriticalDrawDown); + } + + // + return result; + } + + // + // Calculate and Retrieve Max Allowed DrawDown Value ... + double GetMaxValue() + { + // + double result = mMaxValue; + if (mMaxValue <= 0) + { + return result; + } + + // + double deposit = mAccountInfo.GetInitialBalance(); + double balance = mAccountInfo.GetBalance(); + + // + if (balance > deposit) + { + // + double balanceBasedMaxAllwedDrawDown = mMaxFactor * balance; + + // + result = MathMax( + mMaxValue, + balanceBasedMaxAllwedDrawDown); + } + + // + return result; + } + + // + // Guard Account Protection ... + bool Guard( + XGuardHandlerResult &guardResult, // Hold's Message + string &message, // Hold's Message + XCTrade &trader, // Specified Trader + ENUM_TIMEFRAMES period = NULL // Specified Time Frame for Detecting Signal Ages + ) + { + // + message = ""; + + // + // Clean Result of Guard ... + CleanBuffer(guardResult.olds); + CleanBuffer(guardResult.maxes); + CleanBuffer(guardResult.criticals); + + // + bool result = false; + + // + // So Important is to Guard DrawDowns ... + result = GuardDrawDown( + guardResult, + message, + trader); + if (result) + { + return result; + } + + // + // Then we have to Guard Old Trades ... + result = GuardOlds( + guardResult, + message, + trader); + + // + return result; + } + + // + // Handle Guard Old Trades ... + bool GuardOlds( + XGuardHandlerResult &guardResult, // Hold's Message + string &message, // Hold's Message + XCTrade &trader, // Specified Trader + ENUM_TIMEFRAMES period = NULL // Specified Time Frame for Detecting Signal Ages + ) + { + // + // Cleanup Message ... + message = ""; + + // + // Clean Result of Guard ... + CleanBuffer(guardResult.olds); + + // + bool result = false; + + // + // Validate Args ... + if ( + mOldAge <= 0 || + mOldGuardAction == X_GUARD_DO_NOTHING) + { + return result; + } + + // + // Normalize Args ... + if (period == NULL) + { + period = _Period; + } + + // + // Retrieve Old Trades ... + XSignal oldSignals[]; + trader.GetOldSignals( + oldSignals, + mOldAge, + period); + int oldSignalsCount = ArraySize(oldSignals); + if (oldSignalsCount <= 0) + { + return result; + } + + // + result = DoGuardAction( + guardResult, + message, + trader, + mOldGuardAction, + X_GUARDED_OLD, // Specify Guard Reason + period // Specified Running Time Frame for Signal Age Calculations + ); + + // + return result; + } + + // + // Hnadle Guard DrawDown ... + bool GuardDrawDown( + XGuardHandlerResult &guardResult, // Hold's Message + string &message, // Hold's Message + XCTrade &trader // Specified Trader + ) + { + // + message = ""; + + // + // Clean Result of Guard ... + CleanBuffer(guardResult.maxes); + CleanBuffer(guardResult.criticals); + + // + bool result = false; + + // + // Check State for Guard ... + bool isCriticalGuardEnabled = mCriticalFactor > 0; + bool isMaxGuardEnabled = mMaxFactor > 0; + bool isGuardEnabled = + isMaxGuardEnabled; + + // + if (!isGuardEnabled) + { + return result; + } + + // + double maxValue = GetMaxValue(); + double criticalValue = GetCriticalValue(); + + // + double profitSums = trader.GetSignalsProfit(); + + // + bool isMaxReached = + profitSums < 0 && + isMaxGuardEnabled && + MathAbs(profitSums) >= maxValue; + bool isCriticalReached = + profitSums < 0 && + isCriticalGuardEnabled && + MathAbs(profitSums) >= criticalValue; + + // + if (!isMaxReached && !isCriticalReached) + { + // + // Reset Consecutive Max DrawDown Touches ... + ResetMaxDrawDownTouches(); + + // + return result; + } + + // + // Check For Critical Guard ... + if (isCriticalReached && !isMaxReached) + { + // + result = DoGuardAction( + guardResult, + message, + trader, + mCriticalAction, + X_GUARDED_CRITICAL); + } + else if (isMaxReached) + { + // + result = DoGuardAction( + guardResult, + message, + trader, + mMaxAction, + X_GUARDED_MAX); + + // + // Handle Guard StopOut Action ... + mOccuredconsecutiveMaxDraDownTouches++; + if ( + mMaxAction != X_GUARD_DO_NOTHING && + mMaxAction != X_GUARD_CLOSE_ALL && + mGuardStopoutFiredAfterTouches > 0 && + mOccuredconsecutiveMaxDraDownTouches >= mGuardStopoutFiredAfterTouches) + { + // + XSignal closed[]; + trader.CloseSignals(closed); + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + // + XSignal iSignal = closed[i]; + + // + AddItemToBuffer( + iSignal, + guardResult.maxes); + } + + // + message = "Guard StopOut Action Closed (" + (string)closedCount + ") Signals and Release Account ..."; + + // + guardResult.isStopOut = true; + + // + result = true; + } + } + } + + // + return result; + } + + // + // Do Signal Protections and apply Support ... + bool ProtectSignals( + XSignal &mResult[], // Hold's Result + XCTrade &trader, // Specified Trader + int numberOfItemsCheck = 30 // Number of Items to check + ) + { + // + bool result = false; + + // + CleanBuffer(mResult); + + // + // Check Supports Enabled ... + result = IsSupportEnabled(); + if (!result) + { + return result; + } + + // + // Update Supports ... + XSignal signals[]; + trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount > 0) + { + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isExists = IsSupportExists(iSignal.ticket); + if (isExists) + { + UpdateSupport(iSignal); + } + } + } + + // + // Count Supporteds ... + XProtectedSignal supporteds[]; + GetAllSupports(supporteds); + int supportedCount = ArraySize(supporteds); + result = supportedCount > 0; + if (!result) + { + return result; + } + + // + // Loop through ... + for (int i = 0; i < supportedCount; i++) + { + // + XProtectedSignal iP = supporteds[i]; + + // + bool canDoDirectional = CanDoDirectionalSupport( + trader, + iP.ticket, + numberOfItemsCheck); + bool canDoInDirectional = CanDoInDirectionalSupport( + trader, + iP.ticket, + numberOfItemsCheck); + + // + if ( + !canDoDirectional && + !canDoInDirectional) + { + continue; + } + + // + // Do Directional ... + if (canDoDirectional) + { + // + // Generate Propper Signal ... + XSignal sdSignal = GenerateDirectionalSupportSignal( + iP.ticket, + trader); + + // + ENUM_EXECUTION_SIGNAL_RESULT executionResult = trader.ExecuteSignal( + sdSignal, + true, + false); + bool isExecuted = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (isExecuted) + { + // + XSignal eSignal = trader.GetSignal(sdSignal.ticket); + + // + AddItemToBuffer( + eSignal, + mResult); + } + } + // + // Do Indirectional ... + else if (canDoInDirectional) + { + // + // Generate Propper Signal ... + XSignal sindSignal = GenerateDirectionalSupportSignal( + iP.ticket, + trader); + + // + ENUM_EXECUTION_SIGNAL_RESULT executionResult = trader.ExecuteSignal( + sindSignal, + true, + false); + bool isExecuted = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (isExecuted) + { + // + XSignal eSignal = trader.GetSignal(sindSignal.ticket); + + // + AddItemToBuffer( + eSignal, + mResult); + } + } + } + + // + result = ArraySize(mResult) > 0; + + // + return result; + } + + // + // Validate State ... + bool Validate() + { + // + bool result = false; + + // + result = + mMaxFactor > 0 && + (mCriticalFactor > 0 + ? mCriticalFactor < mMaxFactor + : true); + + // + return result; + } + + // + // START Guarded Signals Functions ... + // + + // + // Add new Protecte Signal ... + bool Add( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsExists(signal.ticket); + if (isExists) + { + return result; + } + + // + XProtectedSignal item; + + // + datetime time = TimeCurrent(); + + // + item.ticket = signal.ticket; + + // + AddItemToBuffer( + time, + item.time); + + // + AddItemToBuffer( + signal.profit, + item.profit); + + // + AddItemToBuffer( + item, + mGuardedSignals); + + // + return result; + } + + // + // Get All ... + void GetAll( + XProtectedSignal &result[] // Hold's Result + ) + { + // + CopyBuffer( + mGuardedSignals, + result); + } + + // + // Get ... + XProtectedSignal Get( + ulong ticket // Specified Signal Ticket + ) + { + // + XProtectedSignal result; + + // + bool isExists = IsExists(ticket); + if (!isExists) + { + return result; + } + + // + int protectedCounts = ArraySize(mGuardedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mGuardedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = iProtected; + break; + } + } + + // + return result; + } + + // + // Remove ... + bool Remove( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + result = IsExists(ticket); + if (!result) + { + return result; + } + + // + int protectedCounts = ArraySize(mGuardedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + XProtectedSignal cleared[]; + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mGuardedSignals[i]; + + // + if (iProtected.ticket != ticket) + { + AddItemToBuffer( + iProtected, + cleared); + } + } + + // + // Update Source by Cleared ... + CopyBuffer( + cleared, + mGuardedSignals); + + // + result = true; + + // + return result; + } + + // + // Update ... + bool Update( + ulong ticket, // Specified Signal Ticket + datetime time, // Specified Last Checked time + double profit // Specified Signal Profit + // XProtectedSignal &item // Specified which object to Update + ) + { + // + bool result = false; + + // + int protectedCounts = ArraySize(mGuardedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + result = IsExists(ticket); + if (!result) + { + return result; + } + + // + // Retrieve Struct ... + XProtectedSignal item = Get(ticket); + AddItemToBuffer( + time, + item.time); + AddItemToBuffer( + profit, + item.profit); + + // + result = Remove(ticket); + if (!result) + { + return result; + } + + // + AddItemToBuffer( + item, + mGuardedSignals); + result = true; + + // + return result; + } + bool Update( + XProtectedSignal &item // Specified Protected Item + ) + { + // + bool result = false; + + // + datetime time; + result = GetLastItem( + time, + item.time); + if (!result) + { + return result; + } + + // + double profit; + result = GetLastItem( + profit, + item.profit); + if (!result) + { + return result; + } + + // + result = Update( + item.ticket, time, profit); + + // + return result; + } + bool Update( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + ulong ticket = signal.ticket; + datetime time = TimeCurrent(); + double profit = signal.profit; + + // + result = Update( + ticket, + time, + profit); + + // + return result; + } + + // + // Add Or Update ... + bool AddOrUpdate( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsExists(signal.ticket); + if (!isExists) + { + result = Add(signal); + } + else + { + result = Update(signal); + } + + // + return result; + } + + // + // Check Exists ... + bool IsExists( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + int protectedCounts = ArraySize(mGuardedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mGuardedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + + // + // Count Protecteds ... + int Count() + { + // + int result = 0; + + // + result = ArraySize(mGuardedSignals); + + // + return result; + } + + // + // END Guarded Signals Functions ... + // + + // + // START Supported Signals Functions ... + // + + // + // Check can Handle Support Signals or not ... + bool IsSupportEnabled() + { + // + bool result = false; + + // + result = + mSupportMethod != X_SUPPORT_DO_NOTHING; + + // + return result; + } + + // + // Retrieve List Of Supported Signals ... + void GetSupportSignals( + XSignal &result[], // Hold's Result ... + XCTrade &trader // Specified Trader class Instance ... + ) + { + // + CleanBuffer(result); + + // + XSignal signals[]; + trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + for (int i = -0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isSupport = IsSupport(iSignal.comment); + if (isSupport) + { + AddItemToBuffer( + iSignal, + result); + } + } + } + + // + // Retrieve List Of Specific Signals Supported Signals ... + void GetSignalSupports( + XSignal &result[], // Hold's Result ... + XCTrade &trader, // Specified Trader class Instance ... + ulong ticket // Specified Signal Ticket ... + ) + { + // + CleanBuffer(result); + + // + // Validate Args ... + if (ticket <= 0) + { + return; + } + + // + // Check Signal Exists using Trader ... + XSignal parentSignal = trader.GetSignal(ticket); + bool isValid = + parentSignal.ticket > 0 && + parentSignal.ticket == ticket && + StringLen(parentSignal.comment) > 0; + if (!isValid) + { + return; + } + + // + XSignal supportSignals[]; + GetSupportSignals( + supportSignals, + trader); + int supportSignalsCount = ArraySize(supportSignals); + if (supportSignalsCount <= 0) + { + return; + } + + // + for (int i = 0; i < supportSignalsCount; i++) + { + // + XSignal iSignal = supportSignals[i]; + + // + bool isBelongsToParent = IsBelongsToParent( + ticket, + iSignal.comment); + if (isBelongsToParent) + { + AddItemToBuffer( + iSignal, + result); + } + } + } + + // + // Check Specific Support Conditions for Opening Directional Support ... + bool CanDoDirectionalSupport( + XCTrade &trader, // Specified Trader class Instance ... + ulong ticket, // Specified Signal Ticket ... + int numberOfItemsCheck = 30 // Number of Items to check ... + ) + { + // + bool result = false; + + // + // Check Supports Enabled ... + result = IsSupportEnabled(); + if (!result) + { + return result; + } + + // + // Check Support Method Allows Directional ... + result = + mSupportMethod == X_SUPPORT_FULL || + mSupportMethod == X_SUPPORT_IN_DRAWUP_DIRECTIONAL; + if (!result) + { + return result; + } + + // + // Validate Ticket ... + result = ticket > 0; + if (!result) + { + return result; + } + + // + // Check Supports Count ... + int supportedCount = ArraySize(mSupportedSignals); + result = supportedCount > 0; + if (!result) + { + return result; + } + + // + // Check Ticket Exists in Supports ... + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + // Check signal Doesn't have any Support ... + XSignal supports[]; + GetSignalSupports( + supports, + trader, + ticket); + int supportsCount = ArraySize(supports); + result = supportsCount <= 0; + if (!result) + { + return result; + } + + // + // Retrieve Support Model ... + XProtectedSignal sInfo = GetSupport(ticket); + + // + // Validate Model ... + int sTimesCount = ArraySize(sInfo.time); + int sProfitsCount = ArraySize(sInfo.profit); + result = + sInfo.ticket == ticket && + sTimesCount == sProfitsCount && + sTimesCount >= numberOfItemsCheck && + sProfitsCount >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Validate Signal Age ... + XSignal sSignal = trader.GetSignal(ticket); + int sSignalAge = trader.GetSignalAge(sSignal.time); + result = sSignalAge >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Extrat Profits ... + double lastProfits[]; + for (int i = sProfitsCount - 1; i >= (sProfitsCount - numberOfItemsCheck); i++) + { + // + double iProfit = sInfo.profit[i]; + + // + AddItemToBuffer( + iProfit, + lastProfits); + } + + // + string logMsg = ToString(lastProfits); + LogMessage("" + (string)ticket + " lastProfits: \n" + logMsg); + + // + result = false; + + // + // Now implement Business Logics ... + + // + return result; + } + + // + // Check Specific Support Conditions for Opening InDirectional Support ... + bool CanDoInDirectionalSupport( + XCTrade &trader, // Specified Trader class Instance ... + ulong ticket, // Specified Signal Ticket ... + int numberOfItemsCheck = 30 // Number of Items to check ... + ) + { + // + bool result = false; + + // + // Check Supports Enabled ... + result = IsSupportEnabled(); + if (!result) + { + return result; + } + + // + // Check Support Method Allows Directional ... + result = + mSupportMethod == X_SUPPORT_FULL || + mSupportMethod == X_SUPPORT_IN_DRAWDOWN_INDIRECTIONAL; + if (!result) + { + return result; + } + + // + // Validate Ticket ... + result = ticket > 0; + if (!result) + { + return result; + } + + // + // Check Supports Count ... + int supportedCount = ArraySize(mSupportedSignals); + result = supportedCount > 0; + if (!result) + { + return result; + } + + // + // Check Ticket Exists in Supports ... + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + // Check signal Doesn't have any Support ... + XSignal supports[]; + GetSignalSupports( + supports, + trader, + ticket); + int supportsCount = ArraySize(supports); + result = supportsCount <= 0; + if (!result) + { + return result; + } + + // + // Retrieve Support Model ... + XProtectedSignal sInfo = GetSupport(ticket); + + // + // Validate Model ... + int sTimesCount = ArraySize(sInfo.time); + int sProfitsCount = ArraySize(sInfo.profit); + result = + sInfo.ticket == ticket && + sTimesCount == sProfitsCount && + sTimesCount >= numberOfItemsCheck && + sProfitsCount >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Validate Signal Age ... + XSignal sSignal = trader.GetSignal(ticket); + int sSignalAge = trader.GetSignalAge(sSignal.time); + result = sSignalAge >= numberOfItemsCheck; + if (!result) + { + return result; + } + + // + // Extrat Profits ... + double lastProfits[]; + for (int i = sProfitsCount - 1; i >= (sProfitsCount - numberOfItemsCheck); i++) + { + // + double iProfit = sInfo.profit[i]; + + // + AddItemToBuffer( + iProfit, + lastProfits); + } + + // + string logMsg = ToString(lastProfits); + LogMessage("" + (string)ticket + " lastProfits: \n" + logMsg); + + // + result = false; + + // + // Now implement Business Logics ... + + // + return result; + } + + // + // Generate Directional Support Signal for Parent Signal ... + XSignal GenerateDirectionalSupportSignal( + ulong ticket, // Specified Parent Signal Ticket ... + XCTrade &trader // Specified Trader Class ... + ) + { + // + XSignal result = {}; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + XSignal pSignal = trader.GetSignal(ticket); + bool isValidParent = + pSignal.ticket > 0 && + pSignal.ticket == ticket && + StringLen(pSignal.comment) > 0; + if (!isValidParent) + { + return result; + } + + // + ENUM_X_SIGNAL_TYPE type = pSignal.type; + bool isLong = IsLong(type); + + // + double entry = GetEntry( + pSignal.symbol, + type); + double exit = GetExit( + pSignal.symbol, + type); + + // + double reward = PipsToPrice( + pSignal.symbol, + 6); + double risk = PipsToPrice( + pSignal.symbol, + 1); + + // + double tp = + isLong + ? entry + reward + : entry - reward; + + // + double sl = + isLong + ? exit - risk + : exit + risk; + + // + double rfStep = 2; + double rfRate = 0.5; + + // + double volume = NormalizeVolume( + pSignal.volume / 2, + pSignal.symbol, + 2); + + // + // Generate Signal using Trader Class Instance ... + result = trader.GenerateSignal( + // + type, + tp, + sl, + volume, + rfStep, + rfRate + // + ); + + // + return result; + } + + // + // Generate InDirectional Support Signal for Parent Signal ... + XSignal GenerateInDirectionalSupportSignal( + ulong ticket, // Specified Parent Signal Ticket ... + XCTrade &trader // Specified Trader Class ... + ) + { + // + XSignal result = {}; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + XSignal pSignal = trader.GetSignal(ticket); + bool isValidParent = + pSignal.ticket > 0 && + pSignal.ticket == ticket && + StringLen(pSignal.comment) > 0; + if (!isValidParent) + { + return result; + } + + // + ENUM_X_SIGNAL_TYPE type = trader + .GetIndirectionSignalType(pSignal.type); + bool isLong = IsLong(type); + + // + double entry = GetEntry( + pSignal.symbol, + type); + double exit = GetExit( + pSignal.symbol, + type); + + // + double reward = PipsToPrice( + pSignal.symbol, + 6); + double risk = PipsToPrice( + pSignal.symbol, + 1); + + // + double tp = + isLong + ? entry + reward + : entry - reward; + + // + double sl = + isLong + ? exit - risk + : exit + risk; + + // + double rfStep = 2; + double rfRate = 0.5; + + // + double volume = NormalizeVolume( + pSignal.volume / 2, + pSignal.symbol, + 2); + + // + // Generate Signal using Trader Class Instance ... + result = trader.GenerateSignal( + // + type, + tp, + sl, + volume, + rfStep, + rfRate + // + ); + + // + return result; + } + + // + // Generate Specific Signals Support Signal Comment ... + string GenerateSupportSignalComment( + ulong ticket, // Specified Parent Signal Ticket + ENUM_X_SIGNAL_TYPE type, // Specified Support Signal Type + bool isInDirectional = false // Specified Support Signal Direction + ) + { + // + string result = ""; + + // + if (ticket <= 0) + { + return result; + } + + // + string typeString = GetSignalType(type); + string directionStr = GenerateSupportDirection(isInDirectional); + + // + result = + mSupportPrefix + "(" + (string)ticket + ")_" + + X_SIGNAL_TYPE + "(" + typeString + ")_" + + directionStr; + + // + return result; + } + + // + // Get Support Direction String Representation ... + string GenerateSupportDirection( + bool isInDirectional = false // Specified Support Signal Direction + ) + { + // + string result = ""; + + // + result = + isInDirectional + ? mInDirectional + : mDirectional; + + // + return result; + } + + // + // Check an String Is Directional Or not ... + bool IsDirectionalSupport( + string comment // Specified Comment ... + ) + { + // + bool result = false; + + // + result = IsSupport(comment); + if (!result) + { + return result; + } + + // + int sPos = StringFind( + comment, + mDirectional); + result = sPos >= 0; + + // + return result; + } + + // + // Check an String Is In Directional Or not ... + bool IsInDirectionalSupport( + string comment // Specified Comment ... + ) + { + // + bool result = false; + + // + result = IsSupport(comment); + if (!result) + { + return result; + } + + // + int sPos = StringFind( + comment, + mInDirectional); + result = sPos >= 0; + + // + return result; + } + + // + // Check an String Is Support or not ... + bool IsSupport( + string comment // Specified Comment ... + ) + { + // + bool result = false; + + // + int sPos = StringFind( + comment, + mSupportPrefix); + result = sPos >= 0; + + // + return result; + } + + // + // Extract Parent of Support Signal Ticket from a comment ... + ulong ExtractParentTicket( + string comment // Specified Comment ... + ) + { + // + ulong result = 0; + + // + bool isSupport = IsSupport(comment); + if (!isSupport) + { + return result; + } + + // + // TICKET ... + string ticketStr = ExtractString( + comment, + mSupportPrefix + "(", + ")"); + if (StringLen(ticketStr) > 0) + { + result = (ulong)ticketStr; + } + + // + return result; + } + + // + // Check a Comment belongs to Support Signal or not ... + bool IsBelongsToParent( + ulong ticket, // Specified Parent Signal Ticket + string comment // Specified Support Signal Comment + ) + { + // + bool result = false; + + // + // Validate Arg ... + if (ticket <= 0) + { + return result; + } + + // + result = IsSupport(comment); + if (!result) + { + return result; + } + + // + ulong spTicket = ExtractParentTicket(comment); + result = spTicket == ticket; + + // + return result; + } + + // + // Add new Protecte Signal ... + bool AddSupport( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsSupportExists(signal.ticket); + if (isExists) + { + return result; + } + + // + XProtectedSignal item; + + // + datetime time = TimeCurrent(); + + // + item.ticket = signal.ticket; + + // + AddItemToBuffer( + time, + item.time); + + // + AddItemToBuffer( + signal.profit, + item.profit); + + // + AddItemToBuffer( + item, + mSupportedSignals); + + // + return result; + } + + // + // Get All ... + void GetAllSupports( + XProtectedSignal &result[] // Hold's Result + ) + { + // + CopyBuffer( + mSupportedSignals, + result); + } + + // + // Get ... + XProtectedSignal GetSupport( + ulong ticket // Specified Signal Ticket + ) + { + // + XProtectedSignal result; + + // + bool isExists = IsSupportExists(ticket); + if (!isExists) + { + return result; + } + + // + int protectedCounts = ArraySize(mSupportedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mSupportedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = iProtected; + break; + } + } + + // + return result; + } + + // + // Remove ... + bool RemoveSupport( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + int protectedCounts = ArraySize(mSupportedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + XProtectedSignal cleared[]; + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mSupportedSignals[i]; + + // + if (iProtected.ticket != ticket) + { + AddItemToBuffer( + iProtected, + cleared); + } + } + + // + // Update Source by Cleared ... + CopyBuffer( + cleared, + mSupportedSignals); + + // + result = true; + + // + return result; + } + + // + // Update ... + bool UpdateSupport( + ulong ticket, // Specified Signal Ticket + datetime time, // Specified Last Checked time + double profit // Specified Signal Profit + ) + { + // + bool result = false; + + // + int protectedCounts = ArraySize(mSupportedSignals); + result = protectedCounts > 0; + if (!result) + { + return result; + } + + // + result = IsSupportExists(ticket); + if (!result) + { + return result; + } + + // + // Retrieve Struct ... + XProtectedSignal item = GetSupport(ticket); + AddItemToBuffer( + time, + item.time); + AddItemToBuffer( + profit, + item.profit); + + // + result = RemoveSupport(ticket); + if (!result) + { + return result; + } + + // + AddItemToBuffer( + item, + mSupportedSignals); + result = true; + + // + return result; + } + bool UpdateSupport( + XProtectedSignal &item // Specified Protected Item + ) + { + // + bool result = false; + + // + datetime time; + result = GetLastItem( + time, + item.time); + if (!result) + { + return result; + } + + // + double profit; + result = GetLastItem( + profit, + item.profit); + if (!result) + { + return result; + } + + // + result = UpdateSupport( + item.ticket, time, profit); + + // + return result; + } + bool UpdateSupport( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + ulong ticket = signal.ticket; + datetime time = TimeCurrent(); + double profit = signal.profit; + + // + result = UpdateSupport( + ticket, + time, + profit); + + // + return result; + } + + // + // Add Or Update ... + bool AddOrUpdateSupport( + XSignal &signal // Specified Signal + ) + { + // + bool result = false; + + // + bool isExists = IsSupportExists(signal.ticket); + if (!isExists) + { + result = Add(signal); + } + else + { + result = Update(signal); + } + + // + return result; + } + + // + // Check Exists ... + bool IsSupportExists( + ulong ticket // Specified Signal Ticket + ) + { + // + bool result = false; + + // + // Validate Args ... + if (ticket <= 0) + { + return result; + } + + // + int protectedCounts = ArraySize(mSupportedSignals); + if (protectedCounts <= 0) + { + return result; + } + + // + for (int i = 0; i < protectedCounts; i++) + { + // + XProtectedSignal iProtected = mSupportedSignals[i]; + + // + if (iProtected.ticket == ticket) + { + // + result = true; + break; + } + } + + // + return result; + } + + // + // Count Protecteds ... + int CountSupports() + { + // + int result = 0; + + // + result = ArraySize(mSupportedSignals); + + // + return result; + } + + // + // END Suppoprted Signals Functions ... + // + + // + // START Getter/Setter(s) ... + // + + // + int GetOldAge() + { + return mOldAge; + } + + // + bool SetOldAge(int value) + { + // + bool result = false; + + // + result = + value > 0 && + mOldAge != value; + if (!result) + { + return result; + } + + // + mOldAge = value; + + // + return result; + } + + // + ENUM_X_GUARD_ACTIONS GetOldGuardAction() + { + return mOldGuardAction; + } + + // + bool SetOldGuardAction(ENUM_X_GUARD_ACTIONS value) + { + // + bool result = false; + + // + result = value != mOldGuardAction; + if (!result) + { + return result; + } + + // + mOldGuardAction = value; + + // + return result; + } + + // + double GetCriticalFactor() + { + return mCriticalFactor; + } + + // + bool SetCriticalFactor(bool value) + { + // + bool result = false; + + // + result = + value > 0 && + value < 1 && + mCriticalFactor != value; + if (!result) + { + return result; + } + + // + mCriticalFactor = value; + + // + double deposit = mAccountInfo.GetInitialBalance(); + mCriticalValue = deposit * value; + + // + return result; + } + + // + ENUM_X_GUARD_ACTIONS GetCriticalAction() + { + return mCriticalAction; + } + + // + bool SetCriticalAction(ENUM_X_GUARD_ACTIONS value) + { + // + bool result = false; + + // + result = + value != mCriticalAction; + if (!result) + { + return result; + } + + // + mCriticalAction = value; + + // + return result; + } + + // + double GetMaxFactor() + { + return mMaxFactor; + } + + // + bool SetMaxFactor(bool value) + { + // + bool result = false; + + // + result = + value > 0 && + value < 1 && + mMaxFactor != value; + if (!result) + { + return result; + } + + // + mMaxFactor = value; + + // + double deposit = mAccountInfo.GetInitialBalance(); + mMaxValue = deposit * value; + + // + return result; + } + + // + ENUM_X_GUARD_ACTIONS GetMaxAction() + { + return mMaxAction; + } + + // + bool SetMaxAction(ENUM_X_GUARD_ACTIONS value) + { + // + bool result = false; + + // + result = + value != mMaxAction; + if (!result) + { + return result; + } + + // + mMaxAction = value; + + // + return result; + } + + // + ENUM_X_GUARD_SUPPORT_METHODS GetSupportMethod() + { + return mSupportMethod; + } + + // + bool SetSupportMethod(ENUM_X_GUARD_SUPPORT_METHODS value) + { + // + bool result = false; + + // + result = + value != mSupportMethod; + if (!result) + { + return result; + } + + // + mSupportMethod = value; + + // + return result; + } + + // + // END Getter/Setter(s) ... + // + + // + // Generate Signal Guard Attacked Message ... + string GenerateGuardedSignalComment( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason // Specified Guard Reason + ) + { + // + string result = ""; + + // + string reasonMessage = + ( + // + reason == X_GUARDED_OLD + ? "Because of Old Issue" + : reason == X_GUARDED_CRITICAL + ? "Because Of Crtical Drawdown Isuue" + : reason == X_GUARDED_MAX + ? "Because of Max Drawdown Issue" + : "" + // + ) + + " On Profit: " + (string)signal.profit; + + // + result += "Guard Attacked (" + (string)signal.ticket + "), " + reasonMessage + " ..."; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + string mSupportPrefix; + string mDirectional; + string mInDirectional; + + // + XProtectedSignal mGuardedSignals[]; + XProtectedSignal mSupportedSignals[]; + + // + int mOldAge; + ENUM_X_GUARD_ACTIONS mOldGuardAction; + + // + // Critical DrawDown Factor based On Balance ... + double mCriticalFactor; + double mCriticalValue; + + // + // Guard Action for Critical State ... + ENUM_X_GUARD_ACTIONS mCriticalAction; + + // + // Max DrawDown Factor based on Balance ... + double mMaxFactor; + double mMaxValue; + // + // Guard Stopout if Max State touched ... + int mOccuredconsecutiveMaxDraDownTouches; + int mGuardStopoutFiredAfterTouches; + + // + // Guard Action for Max State ... + ENUM_X_GUARD_ACTIONS mMaxAction; + + // + // How to Support Signals ... + ENUM_X_GUARD_SUPPORT_METHODS mSupportMethod; + + // + // Account Info Instance ... + XCAccountInfo mAccountInfo; + + // + // Get Volume Multiplier for Specified Guard Action ... + double GetGuardActionVolumeMultiplier( + ENUM_X_GUARD_ACTIONS action = X_GUARD_DO_NOTHING // Specified Action + ) + { + // + // Partial Close Max In Drawdown Trade ... + double result = 0.0; + if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1) + { + result = 0.01; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_2) + { + result = 0.02; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_3) + { + result = 0.03; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5) + { + result = 0.05; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10) + { + result = 0.10; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_15) + { + result = 0.15; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_20) + { + result = 0.20; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25) + { + result = 0.25; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30) + { + result = 0.30; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40) + { + result = 0.40; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50) + { + result = 0.50; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60) + { + result = 0.60; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_70) + { + result = 0.70; + } + else if (action == X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75) + { + result = 0.75; + } + + // + return result; + } + + // + // Do Specified Guard Action ... + bool DoGuardAction( + XGuardHandlerResult &guardResult, // Hold's Result ... + string &message, // Hold's Message ... + XCTrade &trader, // Specified Trader Class ... + ENUM_X_GUARD_ACTIONS action, // Specified Which Action to Do ... + ENUM_X_GUARD_REASONS reason, // Specified Guard Reason ... + ENUM_TIMEFRAMES period = NULL // Specified Time Frame for Detecting Signal Ages ... + ) + { + // + bool result = false; + + // + message = ""; + + // + string reasonString = + reason == X_GUARDED_OLD + ? "Because of Age Issue" + : "Because of DD " + ( + // + reason == X_GUARDED_CRITICAL ? "Critical" : "Max" + // + ) + + " Issue"; + + // + // Validate Args ... + if (action == X_GUARD_DO_NOTHING) + { + // + message = "Max Allowed Drawdown Reached, but nothing Happens ..."; + + // + return result; + } + + // + // Normalize Period ... + if (period == NULL) + { + period = _Period; + } + + // + // Close All Signals ... + XSignal closed[]; + XSignal maxInDDSignal; + + // + // Handle Perform Guard Action ... + switch (action) + { + // + // Close All ... + case X_GUARD_CLOSE_ALL: + { + // + trader.CloseSignals(closed); + int closedCount = ArraySize(closed); + result = closedCount > 0; + if (!result) + { + break; + } + + // + message = "Closed (" + (string)closedCount + ") Trades by Guard, " + reasonString + " ..."; + } + break; + + // + case X_GUARD_CLOSE_MAX_IN_DD: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_2: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_3: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_15: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_20: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_25: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_30: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_40: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_50: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_60: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_70: + case X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_75: + { + // + // Retrieve Max In Drawdown Trade ... + maxInDDSignal = trader.GetMaxInDrawdownSignal(); + bool isValid = IsValid(maxInDDSignal, trader.GetMagicNumber()) && maxInDDSignal.ticket > 0; + if (!isValid) + { + break; + } + + // + // Close Max In Drawdown Trade ... + if (action == X_GUARD_CLOSE_MAX_IN_DD) + { + // + string comment = "Signal (" + (string)maxInDDSignal.ticket + ") Closed by Guard ..."; + result = trader.Close( + maxInDDSignal.ticket, + comment); + if (result) + { + message = comment; + } + + // + break; + } + + // + int signalAge = 0; + bool canGuard = true; + bool isGuardedBefore = false; + + // + // Do Some Additional Verifications if Guard for Olds Trades ... + if (reason == X_GUARDED_OLD) + { + // + // Retrieve Signal Age ... + signalAge = trader.GetSignalAge( + maxInDDSignal, + period); + + // + // Check Guarded Before Or Not ... + isGuardedBefore = IsExists(maxInDDSignal.ticket); + if (isGuardedBefore) + { + // + // Now We Have to Check Signal Age growse required times to apply Guard Action again ... + // First Calculate Guard Grow Step ... + int ageGrowStep = mOldAge / 10; + + // + XProtectedSignal guardItem = Get(maxInDDSignal.ticket); + datetime lastGuardTime = 0; + if (GetLastItem(lastGuardTime, guardItem.time)) + { + // + int lastGuardIndex = iBarShift( + maxInDDSignal.symbol, + period, + lastGuardTime); + + // + canGuard = + MathAbs(lastGuardIndex) >= ageGrowStep; + } + } + else + { + // + // Check Signal age ... + canGuard = signalAge >= mOldAge; + } + } + + // + // Prevent Moving Forward ... + if (!canGuard) + { + // + result = false; + break; + } + + // + // Partial Close Max In Drawdown Trade ... + double volumeRate = GetGuardActionVolumeMultiplier(action); + + // + double volume = NormalizeVolume( + maxInDDSignal.volume * volumeRate, + maxInDDSignal.symbol); + + // + string commentPrefix = "Signal (" + (string)maxInDDSignal.ticket + ") Partial Closed (" + (string)volumeRate + ") by Guard"; + string comment = commentPrefix + " ..."; + + // + result = trader.ClosePartial( + maxInDDSignal.ticket, + volume, + comment); + if (result) + { + // + reasonString = + reasonString + + (reason == X_GUARDED_OLD + ? " (" + (string)signalAge + ")" + : " (" + (string)maxInDDSignal.profit + ")"); + + // + // Update Guarded Signals ... + if (isGuardedBefore) + { + // + XSignal tSignal = trader.GetSignal(maxInDDSignal.ticket); + + // + if (tSignal.ticket > 0 && tSignal.volume > 0) + { + // + // Update In Guardeds ... + Update(tSignal); + } + else + { + // + // Remove From Guardeds ... + Remove(tSignal.ticket); + } + } + else if (reason == X_GUARDED_OLD) + { + // + // Added to Guardeds ... + Add(maxInDDSignal); + } + + // + message = commentPrefix + reasonString + " ..."; + } + } + break; + + // + // Nothing ... + // Default ... + default: + message = "Max Allowed Drawdown Reached ..."; + break; + } + + // + result = StringLen(message) > 0; + if (!result) + { + return result; + } + + // + if (result) + { + // + if (reason == X_GUARDED_OLD) + { + // + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + AddItemToBuffer( + closed[i], + guardResult.olds); + } + } + + // + if (maxInDDSignal.ticket > 0) + { + AddItemToBuffer( + maxInDDSignal, + guardResult.olds); + } + } + else if (reason == X_GUARDED_CRITICAL) + { + // + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + AddItemToBuffer( + closed[i], + guardResult.criticals); + } + } + + // + if (maxInDDSignal.ticket > 0) + { + AddItemToBuffer( + maxInDDSignal, + guardResult.criticals); + } + } + else if (reason == X_GUARDED_MAX) + { + // + int closedCount = ArraySize(closed); + if (closedCount > 0) + { + // + for (int i = 0; i < closedCount; i++) + { + AddItemToBuffer( + closed[i], + guardResult.maxes); + } + } + + // + if (maxInDDSignal.ticket > 0) + { + AddItemToBuffer( + maxInDDSignal, + guardResult.maxes); + } + } + } + + // + return result; + } +}; + +// +// END Global Definitions: Variables, Properties and etc ... +// diff --git a/XEU5/Classes/x-saherelm.nn.lib.mq5 b/XEU5/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 0000000..8fa40f5 --- /dev/null +++ b/XEU5/Classes/x-saherelm.nn.lib.mq5 @@ -0,0 +1,258 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 NN Class Library +// ---------------------------------------- +// Name: XNNClass +// Description: provides all classes for implementing +// Neural Network ... +// +// +// 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 Global Definitions: Variables, Properties and etc ... +// +class XCNNBase +{ + // + // Public Definitions ... +public: + // + // Constructor ... + void XCNNBase( + int nodes = 10, // Number of Input Nodes + double starterWeight = 0.5, // start weight for each input + double coEfficient = 0.1, // COEfficient Multiplier + double upperRange = 1, // Upper Normal Range Value + double lowerRange = -1, // Lower Normal Range Value + double learningRates = 0.1 // Back Propagation Learning Rate + ) { + // + mNodes = nodes; + mUpperRange = upperRange; + mLowerRange = lowerRange; + mCoEfficient = coEfficient; + mLearningRates = learningRates; + mStarterWeight = starterWeight; + + // + ReConstructWeights(); + } + + // + // Deconstructor ... + void ~XCNNBase() {} + + // + // Protected Definitions ... + void NormalizeInputs(double &inputs[], double &result[]) + { + // + ArrayFree(result); + ArrayResize(result, 1); + + // + // Validate inputs ... + if (ArraySize(inputs) != mNodes) + { + return; + } + + // + // Prepare Result ... + ArrayResize(result, mNodes); + + // + // Calculating min and max range value ... + double minRangeValue = inputs[ArrayMinimum(inputs)]; + double maxRangeValue = inputs[ArrayMaximum(inputs)]; + + // + // Loop through Inputs nd Normalize them ... + for (int i = 0; i < mNodes; i++) + { + // + double normalValue = (((inputs[i] - minRangeValue) * (mUpperRange - mLowerRange)) / (maxRangeValue - minRangeValue)) + mLowerRange; + result[i] = normalValue; + } + } + + // + // Hyperbolic Tangent Activation Function ... + double TanHActivationFunction(double weightedInputs) + { + // + double result = (exp(weightedInputs) - exp(-weightedInputs)) / (exp(weightedInputs) + exp(-weightedInputs)); + return result; + } + + // + // Calculate Weighted Inputs ... + double CalculateWeightedInputs( + double &inputs[], + bool applyCOEfficient = true) + { + // + double result = 0; + + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) + { + // + result = -1; + return result; + } + + // + for (int i = 0; i < mNodes; i++) + { + result += inputs[i] * mWeights[i]; + } + + // + // Multiply if required ... + if (applyCOEfficient) + { + result *= mCoEfficient; + } + + // + return result; + } + + // + // Calculate Hidden Layers ... + virtual double CalculateHiddenLayer(double &inputs[]) + { + // + // this is Default Activation Function which used ... + // you can override this by writing your own ... + double totalWeightedInputs = CalculateWeightedInputs(inputs); + double result = TanHActivationFunction(totalWeightedInputs); + + // + return result; + } + + // + // Calculate Output Layers ... + double CalculateOutputLayer(double &inputs[]) + { + // + double result = -1; + + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) { + return result; + } + + // + double normalizedInputs[]; + NormalizeInputs(inputs, normalizedInputs); + if (ArraySize(normalizedInputs) != mNodes) { + return result; + } + + // + double hiddenLayerResult = CalculateHiddenLayer(normalizedInputs); + + // + result = 1 * hiddenLayerResult; + + // + return result; + } + + // + // Basck Propaggation Learning ... + void BackPropagation( + double &inputs[], + double &outputs, + double targetOutput + ) { + // + // Validate Inputs ... + if (ArraySize(inputs) != mNodes) { + return; + } + + // + double normalizedInputs[]; + NormalizeInputs(inputs, normalizedInputs); + if (ArraySize(normalizedInputs) != mNodes) { + return; + } + + // + double error = targetOutput - outputs; + double derivative = 1 - MathPow(outputs, 2); + + // + for (int i = 0; i < mNodes; i++) { + // + double gradient = error * derivative * inputs[i]; + mWeights[i] = mLearningRates * gradient; + } + } + +protected: + // + // Private Definitions ... +private: + // + // Number of Input Nodes ... + int mNodes; + + // + // Specify Upper range of Normal Values ... + double mUpperRange; + + // + // Specify Lower range of Normal Values ... + double mLowerRange; + + // + // Starter Weight for each input node ... + double mStarterWeight; + + // + // double Input Node Weights ... + double mWeights[]; + + // + // CoEfficient is a multiplyer for weighted inputs ... + double mCoEfficient; + + // + // Back Propagation Learning Rates ... + double mLearningRates; + + // + // ReConstruct Weights ... + void ReConstructWeights() { + // + ArrayFree(mWeights); + ArrayResize(mWeights, mNodes); + + // + for (int i = 0; i< mNodes; i++) { + mWeights[i] = mStarterWeight; + } + } +} +// +// END Global Definitions: Variables, Properties and etc ... +// diff --git a/XEU5/Classes/x-saherelm.provider.lib.mq5 b/XEU5/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 0000000..1dbdcd3 --- /dev/null +++ b/XEU5/Classes/x-saherelm.provider.lib.mq5 @@ -0,0 +1,4430 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XProvider +// Description: provides all indicators based provider classes for use ... +// +// +// 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 Define Enums ... +// + +// +enum ENUM_X_SIGNAL_PROVIDERS +{ + // + // XSP Expert Support Mechanism ... + XSP, + // + // XTD ... + XTD, + // + // XTAM ... + XTAM, + // + // XSI ... + XSI, + // + // XTSFI ... + XTSFI, + // + // XOBDLH ... + XOBDLH, + // + // XCHMACC ... + XCHMACC, + // + // XCHMACMN ... + XCHMAMN, + // + // XCHMACMX ... + XCHMAMX, +}; + +// +// Represent Market Conditions ... +struct XMarketConditions +{ + // + // XTM ... + bool isXTMPeak; + bool isXTMVale; + bool isXTMBullish; + bool isXTMBearish; + bool isXTMNeutural; + bool isXTMEndBullish; + bool isXTMEndBearish; + bool isXTMStartBullish; + bool isXTMStartBearish; + bool isXTMEndBullishByNeutural; + bool isXTMEndBearishByNeutural; + bool isXTMStartBullishAfterNeutural; + bool isXTMStartBearishAfterNeutural; + + // + // XAMA ... + bool isXAMAPeak; + bool isXAMAVale; + bool isXAMABullish; + bool isXAMABearish; + bool isXAMANeutural; + bool isXAMAEndBullish; + bool isXAMAEndBearish; + bool isXAMAStartBullish; + bool isXAMAStartBearish; + bool isXAMAEndBullishByNeutural; + bool isXAMAEndBearishByNeutural; + bool isXAMAStartBullishAfterNeutural; + bool isXAMAStartBearishAfterNeutural; + + // + // XLH ... + bool isXLHHHIncreased; + bool isXLHHHDecreased; + bool isXLHLLIncreased; + bool isXLHLLDecreased; + bool isXLHLowAttachedLL; + bool isXLHHighAttachedHH; + bool isXLHHHSameInLength; + bool isXLHLLSameInLength; + bool isXLHPriceOverSignal; + bool isXLHPriceUnderSignal; + bool isXLHPriceInSignalRange; + bool isXLHPriceCrossedOverSignal; + bool isXLHPriceCrossedUnderSignal; + + // + // XTD ... + bool isXTDSignalPeak; + bool isXTDSignalVale; + bool isXTDBullishPeak; + bool isXTDBullishVale; + bool isXTDBearishPeak; + bool isXTDBearishVale; + bool isXTDBullOverBear; + bool isXTDBullUnderBear; + bool isXTDSignalOverBear; + bool isXTDSignalUnderBear; + bool isXTDBullCrossedOverBear; + bool isXTDBullCrossedUnderBear; + bool isXTDSignalCrossedOverBear; + bool isXTDSignalCrossedUnderBear; + + // + // XFI ... + bool isXFIPeak; + bool isXFIVale; + bool isXFICrossedOverZero; + bool isXFIOverZero; + bool isXFICrossedUnderZero; + bool isXFIUnderZero; + + // + // XTS ... + bool isXTSAllSame; + bool isXTSCurrentMin; + bool isXTSCurrentMax; + bool isXTSCurrentOverFarest; + bool isXTSCurrentOverNearest; + bool isXTSCurrentOverMediest; + bool isXTSCurrentUnderFarest; + bool isXTSCurrentUnderNearest; + bool isXTSCurrentUnderMediest; + bool isXTSCurrentCrossedOverFarest; + bool isXTSCurrentCrossedOverNearest; + bool isXTSCurrentCrossedOverMediest; + bool isXTSCurrentCrossedUnderFarest; + bool isXTSCurrentCrossedUnderNearest; + bool isXTSCurrentCrossedUnderMediest; + + // + // XRSI ... + bool isXRSIPeak; + bool isXRSIVale; + bool isXRSICrossedOverLongExit; + bool isXRSICrossedOverLongEntry; + bool isXRSICrossedUnderShortExit; + bool isXRSICrossedUnderShortEntry; + + // + // XOBD ... + bool isXOBDSwingLow; + bool isXOBDSwingHigh; + + // + // XCHLH ... + // + bool isXCHLHSameHHs; + bool isXCHLHSameLLs; + // + bool isXCHLHSCMCHHSame; + bool isXCHLHSCMCLLSame; + // + bool isXCHLHSCLCHHSame; + bool isXCHLHSCLCLLSame; + // + bool isXCHLHMCLCHHSame; + bool isXCHLHMCLCLLSame; + // + bool isXCHLHMCOnTopOfLC; + bool isXCHLHMCInBottomOfLC; + + // + // XCHMA ... + // + bool isXCHMASCOverMax; + bool isXCHMASCOverMin; + bool isXCHMASCUnderMax; + bool isXCHMASCUnderMin; + // + bool isXCHMASCCrossedOverMax; + bool isXCHMASCCrossedUnderMax; + bool isXCHMASCCrossedOverMin; + bool isXCHMASCCrossedUnderMin; + // + bool isXCHMASCPeak; + bool isXCHMASCVale; + bool isXCHMASCTrendsUp; + bool isXCHMASCTrendsDown; + bool isXCHMASCFastOverSlow; + bool isXCHMASCFastUnderSlow; + bool isXCHMASCFastCrossedOverSlow; + bool isXCHMASCFastCrossedUnderSlow; + // + bool isXCHMAMCPeak; + bool isXCHMAMCVale; + bool isXCHMAMCTrendsUp; + bool isXCHMAMCTrendsDown; + bool isXCHMAMCFastOverSlow; + bool isXCHMAMCFastUnderSlow; + bool isXCHMAMCFastCrossedOverSlow; + bool isXCHMAMCFastCrossedUnderSlow; + // + bool isXCHMALCPeak; + bool isXCHMALCVale; + bool isXCHMALCTrendsUp; + bool isXCHMALCTrendsDown; + bool isXCHMALCFastOverSlow; + bool isXCHMALCFastUnderSlow; + bool isXCHMALCFastCrossedOverSlow; + bool isXCHMALCFastCrossedUnderSlow; +}; + +// +// END Define Enums ... +// + +// +// START Includes Requirements ... +// + +// +// Includes Classes ... +#include "x-saherelm.class.lib.mq5" + +// +// Includes all Indicator's Helpers ... +#include "../Helpers/x-saherelm.xlh.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xtm.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xama.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xobd.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xts.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5" + +// +// END Includes Requirements ... +// + +// +class XCProvider : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCProvider( + // + // Common Requirements ... + string xSymbol, // Which Symbol is Used + ENUM_TIMEFRAMES xPeriod, // Which Period is Used + // + // Signallers Requirements ... + // + // XTD ... + bool xTDEnableSignaller, // Enable Signaller + bool xTDAllowLongSignals, // Allow Long Signals + bool xTDAllowShortSignals, // Allow Short Signals + // + // XTAM ... + bool xTAMEnableSignaller, // Enable Signaller + bool xTAMAllowLongSignals, // Allow Long Signals + bool xTAMAllowShortSignals, // Allow Short Signals + // + // XSI ... + bool xSIEnableSignaller, // Enable Signaller + bool xSIAllowLongSignals, // Allow Long Signals + bool xSIAllowShortSignals, // Allow Short Signals + // + // XTSFI ... + bool xTSFIEnableSignaller, // Enable Signaller + bool xTSFIAllowLongSignals, // Allow Long Signals + bool xTSFIAllowShortSignals, // Allow Short Signals + // + // XOBDLH ... + bool xOBDLHEnableSignaller, // Enable Signaller + bool xOBDLHAllowLongSignals, // Allow Long Signals + bool xOBDLHAllowShortSignals, // Allow Short Signals + // + // XCHMACC ... + bool xCHMACCEnableSignaller, // Enable Signaller + bool xCHMACCAllowLongSignals, // Allow Long Signals + bool xCHMACCAllowShortSignals, // Allow Short Signals + // + // XCHMAMX ... + bool xCHMACMXEnableSignaller, // Enable Signaller + bool xCHMACMXAllowLongSignals, // Allow Long Signals + bool xCHMACMXAllowShortSignals, // Allow Short Signals + // + // XCHMAMN ... + bool xCHMACMNEnableSignaller, // Enable Signaller + bool xCHMACMNAllowLongSignals, // Allow Long Signals + bool xCHMACMNAllowShortSignals // Allow Short Signals + // + ) + { + // + // XTD ... + mXTDEnableSignaller = xTDEnableSignaller; + mXTDAllowLongSignals = xTDAllowLongSignals; + mXTDAllowShortSignals = xTDAllowShortSignals; + + // + // XTAM ... + mXTAMEnableSignaller = xTAMEnableSignaller; + mXTAMAllowLongSignals = xTAMAllowLongSignals; + mXTAMAllowShortSignals = xTAMAllowShortSignals; + + // + // XSI ... + mXSIEnableSignaller = xSIEnableSignaller; + mXSIAllowLongSignals = xSIAllowLongSignals; + mXSIAllowShortSignals = xSIAllowShortSignals; + + // + // XTSFI ... + mXTSFIEnableSignaller = xTSFIEnableSignaller; + mXTSFIAllowLongSignals = xTSFIAllowLongSignals; + mXTSFIAllowShortSignals = xTSFIAllowShortSignals; + + // + // XOBDLH ... + mXOBDLHEnableSignaller = xOBDLHEnableSignaller; + mXOBDLHAllowLongSignals = xOBDLHAllowLongSignals; + mXOBDLHAllowShortSignals = xOBDLHAllowShortSignals; + + // + // XCHMACC ... + mXCHMACCEnableSignaller = xCHMACCEnableSignaller; + mXCHMACCAllowLongSignals = xCHMACCAllowLongSignals; + mXCHMACCAllowShortSignals = xCHMACCAllowShortSignals; + + // + // XCHMAMX ... + mXCHMAMXEnableSignaller = xCHMACMXEnableSignaller; + mXCHMAMXAllowLongSignals = xCHMACMXAllowLongSignals; + mXCHMAMXAllowShortSignals = xCHMACMXAllowShortSignals; + + // + // XCHMAMN ... + mXCHMAMNEnableSignaller = xCHMACMNEnableSignaller; + mXCHMAMNAllowLongSignals = xCHMACMNAllowLongSignals; + mXCHMAMNAllowShortSignals = xCHMACMNAllowShortSignals; + } + + // + // Deconstructor ... + ~XCProvider() {} + + // + // START Common Functions ... + // + + // + // Read All Globally Required Conditions ... + void ReadConditions() + { + // + ClearConditions(); + + // + mXConditions = GenerateMarketConditions(1); + } + + // + // Cleanup Conditions ... + void ClearConditions() + { + // + XMarketConditions mConditions = {}; + + // + mXConditions = mConditions; + } + + // + // Generate Merket Conditions for Specified Bar Index ... + XMarketConditions GenerateMarketConditions( + int bar_index = 1 // Specified Bar Index ... + ) + { + // + XMarketConditions mConditions = {}; + + // + // XTM ... + mConditions.isXTMPeak = XTMIsPeak(bar_index); + mConditions.isXTMVale = XTMIsVale(bar_index); + mConditions.isXTMBullish = XTMIsBullish(bar_index); + mConditions.isXTMBearish = XTMIsBearish(bar_index); + mConditions.isXTMNeutural = XTMIsNeutural(bar_index); + mConditions.isXTMEndBullish = XTMIsEndBullish(bar_index); + mConditions.isXTMEndBearish = XTMIsEndBearish(bar_index); + mConditions.isXTMStartBullish = XTMIsStartBullish(bar_index); + mConditions.isXTMStartBearish = XTMIsStartBearish(bar_index); + mConditions.isXTMEndBullishByNeutural = XTMIsEndBullishByNeutural(bar_index); + mConditions.isXTMEndBearishByNeutural = XTMIsEndBearishByNeutural(bar_index); + mConditions.isXTMStartBullishAfterNeutural = XTMIsStartBullishAfterNeutural(bar_index); + mConditions.isXTMStartBearishAfterNeutural = XTMIsStartBearishAfterNeutural(bar_index); + + // + // XAMA ... + mConditions.isXAMAPeak = XAMAIsPeak(bar_index); + mConditions.isXAMAVale = XAMAIsVale(bar_index); + mConditions.isXAMABullish = XAMAIsBullish(bar_index); + mConditions.isXAMABearish = XAMAIsBearish(bar_index); + mConditions.isXAMANeutural = XAMAIsNeutural(bar_index); + mConditions.isXAMAEndBullish = XAMAIsEndBullish(bar_index); + mConditions.isXAMAEndBearish = XAMAIsEndBearish(bar_index); + mConditions.isXAMAStartBullish = XAMAIsStartBullish(bar_index); + mConditions.isXAMAStartBearish = XAMAIsStartBearish(bar_index); + mConditions.isXAMAEndBullishByNeutural = XAMAIsEndBullishByNeutural(bar_index); + mConditions.isXAMAEndBearishByNeutural = XAMAIsEndBearishByNeutural(bar_index); + mConditions.isXAMAStartBullishAfterNeutural = XAMAIsStartBullishAfterNeutural(bar_index); + mConditions.isXAMAStartBearishAfterNeutural = XAMAIsStartBearishAfterNeutural(bar_index); + + // + // XLH ... + mConditions.isXLHHHIncreased = XLHIsHHIncreased(bar_index); + mConditions.isXLHHHDecreased = XLHIsHHDecreased(bar_index); + mConditions.isXLHLLIncreased = XLHIsLLIncreased(bar_index); + mConditions.isXLHLLDecreased = XLHIsLLDecreased(bar_index); + mConditions.isXLHLowAttachedLL = XLHIsLowAttachedLL(bar_index); + mConditions.isXLHHighAttachedHH = XLHIsHighAttachedHH(bar_index); + mConditions.isXLHHHSameInLength = XLHIsHHSameInLength(bar_index); + mConditions.isXLHLLSameInLength = XLHIsLLSameInLength(bar_index); + mConditions.isXLHPriceOverSignal = XLHIsPriceOverSignal(bar_index); + mConditions.isXLHPriceUnderSignal = XLHIsPriceUnderSignal(bar_index); + mConditions.isXLHPriceInSignalRange = XLHIsPriceInSignalRange(bar_index); + mConditions.isXLHPriceCrossedOverSignal = XLHIsPriceCrossedOverSignal(bar_index); + mConditions.isXLHPriceCrossedUnderSignal = XLHIsPriceCrossedUnderSignal(bar_index); + + // + // XTD ... + mConditions.isXTDSignalPeak = XTDIsSignalPeak(bar_index); + mConditions.isXTDSignalVale = XTDIsSignalVale(bar_index); + mConditions.isXTDBullishPeak = XTDIsBullishPeak(bar_index); + mConditions.isXTDBullishVale = XTDIsBullishVale(bar_index); + mConditions.isXTDBearishPeak = XTDIsBearishPeak(bar_index); + mConditions.isXTDBearishVale = XTDIsBearishVale(bar_index); + mConditions.isXTDBullOverBear = XTDIsBullOverBear(bar_index); + mConditions.isXTDBullUnderBear = XTDIsBullUnderBear(bar_index); + mConditions.isXTDSignalOverBear = XTDIsSignalOverBear(bar_index); + mConditions.isXTDSignalUnderBear = XTDIsSignalUnderBear(bar_index); + mConditions.isXTDBullCrossedOverBear = XTDIsBullCrossedOverBear(bar_index); + mConditions.isXTDBullCrossedUnderBear = XTDIsBullCrossedUnderBear(bar_index); + mConditions.isXTDSignalCrossedOverBear = XTDIsSignalCrossedOverBear(bar_index); + mConditions.isXTDSignalCrossedUnderBear = XTDIsSignalCrossedUnderBear(bar_index); + + // + // XFI ... + mConditions.isXFIPeak = XFIIsPeak(bar_index); + mConditions.isXFIVale = XFIIsVale(bar_index); + mConditions.isXFIOverZero = XFIIsOverZero(bar_index); + mConditions.isXFIUnderZero = XFIIsUnderZero(bar_index); + mConditions.isXFICrossedOverZero = XFIIsCrossedOverZero(bar_index); + mConditions.isXFICrossedUnderZero = XFIIsCrossedUnderZero(bar_index); + + // + // XTS ... + mConditions.isXTSAllSame = XTSIsAllSame(bar_index); + mConditions.isXTSCurrentMin = XTSIsCurrentMin(bar_index); + mConditions.isXTSCurrentMax = XTSIsCurrentMax(bar_index); + mConditions.isXTSCurrentOverFarest = XTSIsCurrentOverFarest(bar_index); + mConditions.isXTSCurrentOverNearest = XTSIsCurrentOverNearest(bar_index); + mConditions.isXTSCurrentOverMediest = XTSIsCurrentOverMediest(bar_index); + mConditions.isXTSCurrentUnderFarest = XTSIsCurrentUnderFarest(bar_index); + mConditions.isXTSCurrentUnderNearest = XTSIsCurrentUnderNearest(bar_index); + mConditions.isXTSCurrentUnderMediest = XTSIsCurrentUnderMediest(bar_index); + mConditions.isXTSCurrentCrossedOverFarest = XTSIsCurrentCrossedOverFarest(bar_index); + mConditions.isXTSCurrentCrossedOverNearest = XTSIsCurrentCrossedOverNearest(bar_index); + mConditions.isXTSCurrentCrossedOverMediest = XTSIsCurrentCrossedOverMediest(bar_index); + mConditions.isXTSCurrentCrossedUnderFarest = XTSIsCurrentCrossedUnderFarest(bar_index); + mConditions.isXTSCurrentCrossedUnderNearest = XTSIsCurrentCrossedUnderNearest(bar_index); + mConditions.isXTSCurrentCrossedUnderMediest = XTSIsCurrentCrossedUnderMediest(bar_index); + + // + // XRSI ... + mConditions.isXRSIPeak = XRSIIsPeak(bar_index); + mConditions.isXRSIVale = XRSIIsVale(bar_index); + mConditions.isXRSICrossedOverLongExit = XRSIIsCrossedOverLongExit(bar_index); + mConditions.isXRSICrossedOverLongEntry = XRSIIsCrossedOverLongEntry(bar_index); + mConditions.isXRSICrossedUnderShortExit = XRSIIsCrossedUnderShortExit(bar_index); + mConditions.isXRSICrossedUnderShortEntry = XRSIIsCrossedUnderShortEntry(bar_index); + + // + // XOBD ... + mConditions.isXOBDSwingLow = XOBDIsSwingLow(bar_index); + mConditions.isXOBDSwingHigh = XOBDIsSwingHigh(bar_index); + + // + // XCHLH ... + // + mConditions.isXCHLHSameHHs = XCHLHIsSameHHs(bar_index); + mConditions.isXCHLHSameLLs = XCHLHIsSameLLs(bar_index); + // + mConditions.isXCHLHSCMCHHSame = XCHLHIsMCSCHasSameHH(bar_index); + mConditions.isXCHLHSCMCLLSame = XCHLHIsMCSCHasSameLL(bar_index); + // + mConditions.isXCHLHSCLCHHSame = XCHLHIsLCSCHasSameHH(bar_index); + mConditions.isXCHLHSCLCLLSame = XCHLHIsLCSCHasSameLL(bar_index); + // + mConditions.isXCHLHMCLCHHSame = XCHLHIsLCMCHasSameHH(bar_index); + mConditions.isXCHLHMCLCLLSame = XCHLHIsLCMCHasSameLL(bar_index); + // + mConditions.isXCHLHMCOnTopOfLC = XCHLHIsMCOnTopOfLC(bar_index); + mConditions.isXCHLHMCInBottomOfLC = XCHLHIsMCInBottomOfLC(bar_index); + + // + // XCHMA ... + // + mConditions.isXCHMASCOverMax = XCHMAIsSCOverMax(bar_index); + mConditions.isXCHMASCOverMin = XCHMAIsSCOverMin(bar_index); + mConditions.isXCHMASCUnderMax = XCHMAIsSCUnderMax(bar_index); + mConditions.isXCHMASCUnderMin = XCHMAIsSCUnderMin(bar_index); + // + mConditions.isXCHMASCCrossedOverMax = XCHMAIsSCCrossedOverMax(bar_index); + mConditions.isXCHMASCCrossedUnderMax = XCHMAIsSCCrossedUnderMax(bar_index); + mConditions.isXCHMASCCrossedOverMin = XCHMAIsSCCrossedOverMin(bar_index); + mConditions.isXCHMASCCrossedUnderMin = XCHMAIsSCCrossedUnderMin(bar_index); + // + mConditions.isXCHMASCPeak = XCHMAIsSCPeak(bar_index); + mConditions.isXCHMASCVale = XCHMAIsSCVale(bar_index); + mConditions.isXCHMASCTrendsUp = XCHMAIsSCTrendsUp(bar_index); + mConditions.isXCHMASCTrendsDown = XCHMAIsSCTrendsDown(bar_index); + mConditions.isXCHMASCFastOverSlow = XCHMAIsSCFastOverSlow(bar_index); + mConditions.isXCHMASCFastUnderSlow = XCHMAIsSCFastUnderSlow(bar_index); + mConditions.isXCHMASCFastCrossedOverSlow = XCHMAIsSCFastCrossedOverSlow(bar_index); + mConditions.isXCHMASCFastCrossedUnderSlow = XCHMAIsSCFastCrossedUnderSlow(bar_index); + // + mConditions.isXCHMAMCPeak = XCHMAIsMCPeak(bar_index); + mConditions.isXCHMAMCVale = XCHMAIsMCVale(bar_index); + mConditions.isXCHMAMCTrendsUp = XCHMAIsMCTrendsUp(bar_index); + mConditions.isXCHMAMCTrendsDown = XCHMAIsMCTrendsDown(bar_index); + mConditions.isXCHMAMCFastOverSlow = XCHMAIsMCFastOverSlow(bar_index); + mConditions.isXCHMAMCFastUnderSlow = XCHMAIsMCFastUnderSlow(bar_index); + mConditions.isXCHMAMCFastCrossedOverSlow = XCHMAIsMCFastCrossedOverSlow(bar_index); + mConditions.isXCHMAMCFastCrossedUnderSlow = XCHMAIsMCFastCrossedUnderSlow(bar_index); + // + mConditions.isXCHMALCPeak = XCHMAIsLCPeak(bar_index); + mConditions.isXCHMALCVale = XCHMAIsLCVale(bar_index); + mConditions.isXCHMALCTrendsUp = XCHMAIsLCTrendsUp(bar_index); + mConditions.isXCHMALCTrendsDown = XCHMAIsLCTrendsDown(bar_index); + mConditions.isXCHMALCFastOverSlow = XCHMAIsLCFastOverSlow(bar_index); + mConditions.isXCHMALCFastUnderSlow = XCHMAIsLCFastUnderSlow(bar_index); + mConditions.isXCHMALCFastCrossedOverSlow = XCHMAIsLCFastCrossedOverSlow(bar_index); + mConditions.isXCHMALCFastCrossedUnderSlow = XCHMAIsLCFastCrossedUnderSlow(bar_index); + + // + return mConditions; + } + + // + // Access Last Readed Market Conditions ... + XMarketConditions GetLastMarketCondition() + { + // + XMarketConditions result = {}; + + // + result = mXConditions; + + // + return result; + } + + // + // Check Market Conditions is Ready for Long Signals or not ... + bool IsReadyForLong( + bool checkXCHMAMin = true, // Force Check XCHMA Min State + bool checkXCHMAMax = true, // Force Check XCHMA Max State + bool checkXCHMACycles = true, // Force Check XCHMA Cycles State + bool checkXCHMAPeaks = true, // Force Check XCHMA Peaks State + bool checkXCHMATrendPowers = true, // Force Check XCHMA Trend Powers + bool checkXOBD = true, // Force Check XOBD State + bool checkXTS = true // Force Check XTS State + ) + { + // + bool result = true; + + // + if (checkXCHMAMin) + { + // + result = + // + // XCHMA MIN ... + !( + // + (mXConditions.isXCHMASCOverMin || + mXConditions.isXCHMASCCrossedOverMin) && + (mXConditions.isXCHMASCUnderMin || + mXConditions.isXCHMASCCrossedUnderMin) + // + ); + } + + // + if (checkXCHMAMax && result) + { + // + result = + // + // XCHMA MAX ... + !( + // + (mXConditions.isXCHMASCOverMax || + mXConditions.isXCHMASCCrossedOverMax) && + (mXConditions.isXCHMASCUnderMax || + mXConditions.isXCHMASCCrossedUnderMax) + // + ) + // + ; + } + + // + if (checkXCHMACycles && result) + { + // + result = + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastOverSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastOverSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastOverSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastOverSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastOverSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastOverSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastOverSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + (mXConditions.isXCHMAMCFastOverSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastOverSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMAPeaks && result) + { + // + result = + // + // XCHMA Check Peaks ... + !( + // + // All Cycles Peak ... + (mXConditions.isXCHMASCPeak && + mXConditions.isXCHMAMCPeak && + mXConditions.isXCHMALCPeak) + // + || + // + ( + // + // SC MC ... + (mXConditions.isXCHMASCPeak && + mXConditions.isXCHMAMCPeak) + // + || + // + // SC LC ... + (mXConditions.isXCHMASCPeak && + mXConditions.isXCHMALCPeak) + // + || + // + // MC LC ... + (mXConditions.isXCHMAMCPeak && + mXConditions.isXCHMALCPeak) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMATrendPowers && result) + { + // + result = + // + // XCHMA Check Trends Power ... + !( + // + // All Trends Down ... + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + // Twisted pairs ... + ( + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown) + // + || + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + (mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ; + } + + // + if (checkXOBD && result) + { + // + result = + // + // XOBD Check Swings ... + !mXConditions.isXOBDSwingLow + // + ; + } + + // + if (checkXTS && result) + { + result = + // + // XTS Check ... + !( + // + mXConditions.isXTSCurrentMin && + // + ( + // + // All Under ... + ( + (mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) && + (mXConditions.isXTSCurrentUnderMediest || + mXConditions.isXTSCurrentCrossedUnderMediest) && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest)) + // + || + // + // Pairs ... + ( + // + ((mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) && + (mXConditions.isXTSCurrentUnderMediest || + mXConditions.isXTSCurrentCrossedUnderMediest)) + // + || + // + ((mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest)) + // + || + // + ((mXConditions.isXTSCurrentUnderMediest || + mXConditions.isXTSCurrentCrossedUnderMediest) && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest)) + // + ) + // + ) + // + ) + // + ; + } + + // + return result; + } + + // + // Check Market Conditions is Ready for Short Signals or not ... + bool IsReadyForShort( + bool checkXCHMAMin = true, // Force Check XCHMA Min State + bool checkXCHMAMax = true, // Force Check XCHMA Max State + bool checkXCHMACycles = true, // Force Check XCHMA Cycles State + bool checkXCHMAVales = true, // Force Check XCHMA Vales State + bool checkXCHMATrendPowers = true, // Force Check XCHMA Trend Powers + bool checkXOBD = true, // Force Check XOBD State + bool checkXTS = true // Force Check XTS State + ) + { + // + bool result = true; + + // + if (checkXCHMAMin) + { + // + result = + // + // XCHMA MIN ... + !( + // + (mXConditions.isXCHMASCOverMin || + mXConditions.isXCHMASCCrossedOverMin) && + (mXConditions.isXCHMASCUnderMin || + mXConditions.isXCHMASCCrossedUnderMin) + // + ); + } + + // + if (checkXCHMAMax && result) + { + // + result = + // + // XCHMA MAX ... + !( + // + (mXConditions.isXCHMASCOverMax || + mXConditions.isXCHMASCCrossedOverMax) && + (mXConditions.isXCHMASCUnderMax || + mXConditions.isXCHMASCCrossedUnderMax) + // + ) + // + ; + } + + // + if (checkXCHMACycles && result) + { + // + result = + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastUnderSlow || + mXConditions.isXCHMASCFastCrossedUnderSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastUnderSlow || + mXConditions.isXCHMAMCFastCrossedUnderSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastUnderSlow || + mXConditions.isXCHMALCFastCrossedUnderSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastUnderSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastUnderSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastUnderSlow || + mXConditions.isXCHMASCFastCrossedUnderSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastUnderSlow || + mXConditions.isXCHMALCFastCrossedUnderSlow) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + (mXConditions.isXCHMAMCFastUnderSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastUnderSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMAVales && result) + { + // + result = + // + // XCHMA Check Vales ... + !( + // + // All Cycles Vale ... + (mXConditions.isXCHMASCVale && + mXConditions.isXCHMAMCVale && + mXConditions.isXCHMALCVale) + // + || + // + ( + // + // SC MC ... + (mXConditions.isXCHMASCVale && + mXConditions.isXCHMAMCVale) + // + || + // + // SC LC ... + (mXConditions.isXCHMASCVale && + mXConditions.isXCHMALCVale) + // + || + // + // MC LC ... + (mXConditions.isXCHMAMCVale && + mXConditions.isXCHMALCVale) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMATrendPowers && result) + { + // + result = + // + // XCHMA Check Trends Power ... + !( + // + // All Trends Down ... + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + // Twisted pairs ... + ( + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown) + // + || + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + (mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ; + } + + // + if (checkXOBD && result) + { + // + result = + // + // XOBD Check Swings ... + !mXConditions.isXOBDSwingHigh + // + ; + } + + // + if (checkXTS && result) + { + // + result = + // + // XTS Check ... + !( + // + mXConditions.isXTSCurrentMax && + // + ( + // + // All Over ... + ( + (mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) && + (mXConditions.isXTSCurrentOverMediest || + mXConditions.isXTSCurrentCrossedOverMediest) && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest)) + // + || + // + // Pairs ... + ( + // + ((mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) && + (mXConditions.isXTSCurrentOverMediest || + mXConditions.isXTSCurrentCrossedOverMediest)) + // + || + // + ((mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest)) + // + || + // + ((mXConditions.isXTSCurrentOverMediest || + mXConditions.isXTSCurrentCrossedOverMediest) && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest)) + // + ) + // + ) + // + ) + // + ; + } + + // + return result; + } + + // + // Converts Market Conditions to Specific String Representation ... + string GenerateConditionsString( + XMarketConditions &condition, // Specify Conditiond + string separator = "\n", // Specify Separator + bool ignoreFalses = true // Ignore False Conditions + ) + { + // + XMarketConditions mConditions = {}; + + // + mConditions = condition; + + // + string result = "\n"; + + // + // XOBD ... + result += + "| XOBD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXOBDSwingLow)) + { + result += "isXOBDSwingLow: " + (string)mConditions.isXOBDSwingLow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXOBDSwingHigh)) + { + result += "isXOBDSwingHigh: " + (string)mConditions.isXOBDSwingHigh + separator; + } + + // + // Separator ... + result += separator; + + // + // XTM ... + result += + "| XTM |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMPeak)) + { + result += "isXTMPeak: " + (string)mConditions.isXTMPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMVale)) + { + result += "isXTMVale: " + (string)mConditions.isXTMVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBullish)) + { + result += "isXTMStartBullish: " + (string)mConditions.isXTMStartBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBullishAfterNeutural)) + { + result += "isXTMStartBullishAfterNeutural: " + (string)mConditions.isXTMStartBullishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMBullish)) + { + result += "isXTMBullish: " + (string)mConditions.isXTMBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBullish)) + { + result += "isXTMEndBullish: " + (string)mConditions.isXTMEndBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBullishByNeutural)) + { + result += "isXTMEndBullishByNeutural: " + (string)mConditions.isXTMEndBullishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBearish)) + { + result += "isXTMStartBearish: " + (string)mConditions.isXTMStartBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBearishAfterNeutural)) + { + result += "isXTMStartBearishAfterNeutural: " + (string)mConditions.isXTMStartBearishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMBearish)) + { + result += "isXTMBearish: " + (string)mConditions.isXTMBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBearish)) + { + result += "isXTMEndBearish: " + (string)mConditions.isXTMEndBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBearishByNeutural)) + { + result += "isXTMEndBearishByNeutural: " + (string)mConditions.isXTMEndBearishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMNeutural)) + { + result += "isXTMNeutural: " + (string)mConditions.isXTMNeutural + separator; + } + + // + // Separator ... + result += separator; + + // + // XAMA ... + result += + "| XAMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAPeak)) + { + result += "isXAMAPeak: " + (string)mConditions.isXAMAPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAVale)) + { + result += "isXAMAVale: " + (string)mConditions.isXAMAVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBullish)) + { + result += "isXAMAStartBullish: " + (string)mConditions.isXAMAStartBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBullishAfterNeutural)) + { + result += "isXAMAStartBullishAfterNeutural: " + (string)mConditions.isXAMAStartBullishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMABullish)) + { + result += "isXAMABullish: " + (string)mConditions.isXAMABullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBullish)) + { + result += "isXAMAEndBullish: " + (string)mConditions.isXAMAEndBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBullishByNeutural)) + { + result += "isXAMAEndBullishByNeutural: " + (string)mConditions.isXAMAEndBullishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBearish)) + { + result += "isXAMAStartBearish: " + (string)mConditions.isXAMAStartBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBearishAfterNeutural)) + { + result += "isXAMAStartBearishAfterNeutural: " + (string)mConditions.isXAMAStartBearishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMABearish)) + { + result += "isXAMABearish: " + (string)mConditions.isXAMABearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBearish)) + { + result += "isXAMAEndBearish: " + (string)mConditions.isXAMAEndBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBearishByNeutural)) + { + result += "isXAMAEndBearishByNeutural: " + (string)mConditions.isXAMAEndBearishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMANeutural)) + { + result += "isXAMANeutural: " + (string)mConditions.isXAMANeutural + separator; + } + + // + // Separator ... + result += separator; + + // + // XTD ... + result += + "| XTD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalPeak)) + { + result += "isXTDSignalPeak: " + (string)mConditions.isXTDSignalPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalVale)) + { + result += "isXTDSignalVale: " + (string)mConditions.isXTDSignalVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullishPeak)) + { + result += "isXTDBullishPeak: " + (string)mConditions.isXTDBullishPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullishVale)) + { + result += "isXTDBullishVale: " + (string)mConditions.isXTDBullishVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBearishPeak)) + { + result += "isXTDBearishPeak: " + (string)mConditions.isXTDBearishPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBearishVale)) + { + result += "isXTDBearishVale: " + (string)mConditions.isXTDBearishVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullOverBear)) + { + result += "isXTDBullOverBear: " + (string)mConditions.isXTDBullOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullUnderBear)) + { + result += "isXTDBullUnderBear: " + (string)mConditions.isXTDBullUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalOverBear)) + { + result += "isXTDSignalOverBear: " + (string)mConditions.isXTDSignalOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalUnderBear)) + { + result += "isXTDSignalUnderBear: " + (string)mConditions.isXTDSignalUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullCrossedOverBear)) + { + result += "isXTDBullCrossedOverBear: " + (string)mConditions.isXTDBullCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullCrossedUnderBear)) + { + result += "isXTDBullCrossedUnderBear: " + (string)mConditions.isXTDBullCrossedUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalCrossedOverBear)) + { + result += "isXTDSignalCrossedOverBear: " + (string)mConditions.isXTDSignalCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalCrossedUnderBear)) + { + result += "isXTDSignalCrossedUnderBear: " + (string)mConditions.isXTDSignalCrossedUnderBear + separator; + } + + // + // Separator ... + result += separator; + + // + // XFI ... + result += + "| XFI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIPeak)) + { + result += "isXFIPeak: " + (string)mConditions.isXFIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIVale)) + { + result += "isXFIVale: " + (string)mConditions.isXFIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIOverZero)) + { + result += "isXFIOverZero: " + (string)mConditions.isXFIOverZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIUnderZero)) + { + result += "isXFIUnderZero: " + (string)mConditions.isXFIUnderZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFICrossedOverZero)) + { + result += "isXFICrossedOverZero: " + (string)mConditions.isXFICrossedOverZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFICrossedUnderZero)) + { + result += "isXFICrossedUnderZero: " + (string)mConditions.isXFICrossedUnderZero + separator; + } + + // + // Separator ... + result += separator; + + // + // XTS ... + result += + "| XTS |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSAllSame)) + { + result += "isXTSAllSame: " + (string)mConditions.isXTSAllSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentMin)) + { + result += "isXTSCurrentMin: " + (string)mConditions.isXTSCurrentMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentMax)) + { + result += "isXTSCurrentMax: " + (string)mConditions.isXTSCurrentMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverFarest)) + { + result += "isXTSCurrentOverFarest: " + (string)mConditions.isXTSCurrentOverFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverNearest)) + { + result += "isXTSCurrentOverNearest: " + (string)mConditions.isXTSCurrentOverNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverMediest)) + { + result += "isXTSCurrentOverMediest: " + (string)mConditions.isXTSCurrentOverMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderFarest)) + { + result += "isXTSCurrentUnderFarest: " + (string)mConditions.isXTSCurrentUnderFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderNearest)) + { + result += "isXTSCurrentUnderNearest: " + (string)mConditions.isXTSCurrentUnderNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderMediest)) + { + result += "isXTSCurrentUnderMediest: " + (string)mConditions.isXTSCurrentUnderMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverFarest)) + { + result += "isXTSCurrentCrossedOverFarest: " + (string)mConditions.isXTSCurrentCrossedOverFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverNearest)) + { + result += "isXTSCurrentCrossedOverNearest: " + (string)mConditions.isXTSCurrentCrossedOverNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverMediest)) + { + result += "isXTSCurrentCrossedOverMediest: " + (string)mConditions.isXTSCurrentCrossedOverMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderFarest)) + { + result += "isXTSCurrentCrossedUnderFarest: " + (string)mConditions.isXTSCurrentCrossedUnderFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderNearest)) + { + result += "isXTSCurrentCrossedUnderNearest: " + (string)mConditions.isXTSCurrentCrossedUnderNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderMediest)) + { + result += "isXTSCurrentCrossedUnderMediest: " + (string)mConditions.isXTSCurrentCrossedUnderMediest + separator; + } + + // + // Separator ... + result += separator; + + // + // XLH ... + result += + "| XLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHIncreased)) + { + result += "isXLHHHIncreased: " + (string)mConditions.isXLHHHIncreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHDecreased)) + { + result += "isXLHHHDecreased: " + (string)mConditions.isXLHHHDecreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLIncreased)) + { + result += "isXLHLLIncreased: " + (string)mConditions.isXLHLLIncreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLDecreased)) + { + result += "isXLHLLDecreased: " + (string)mConditions.isXLHLLDecreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHighAttachedHH)) + { + result += "isXLHHighAttachedHH: " + (string)mConditions.isXLHHighAttachedHH + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLowAttachedLL)) + { + result += "isXLHLowAttachedLL: " + (string)mConditions.isXLHLowAttachedLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHSameInLength)) + { + result += "isXLHHHSameInLength: " + (string)mConditions.isXLHHHSameInLength + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLSameInLength)) + { + result += "isXLHLLSameInLength: " + (string)mConditions.isXLHLLSameInLength + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceCrossedOverSignal)) + { + result += "isXLHPriceCrossedOverSignal: " + (string)mConditions.isXLHPriceCrossedOverSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceOverSignal)) + { + result += "isXLHPriceOverSignal: " + (string)mConditions.isXLHPriceOverSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceCrossedUnderSignal)) + { + result += "isXLHPriceCrossedUnderSignal: " + (string)mConditions.isXLHPriceCrossedUnderSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceUnderSignal)) + { + result += "isXLHPriceUnderSignal: " + (string)mConditions.isXLHPriceUnderSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceInSignalRange)) + { + result += "isXLHPriceInSignalRange: " + (string)mConditions.isXLHPriceInSignalRange + separator; + } + + // + // Separator ... + result += separator; + + // + // XRSI ... + result += + "| XRSI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSIPeak)) + { + result += "isXRSIPeak: " + (string)mConditions.isXRSIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSIVale)) + { + result += "isXRSIVale: " + (string)mConditions.isXRSIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedOverLongExit)) + { + result += "isXRSICrossedOverLongExit: " + (string)mConditions.isXRSICrossedOverLongExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedOverLongEntry)) + { + result += "isXRSICrossedOverLongEntry: " + (string)mConditions.isXRSICrossedOverLongEntry + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedUnderShortExit)) + { + result += "isXRSICrossedUnderShortExit: " + (string)mConditions.isXRSICrossedUnderShortExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedUnderShortEntry)) + { + result += "isXRSICrossedUnderShortEntry: " + (string)mConditions.isXRSICrossedUnderShortEntry + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHLH ... + result += + "| XCHLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSameHHs)) + { + result += "isXCHLHSameHHs: " + (string)mConditions.isXCHLHSameHHs + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSameLLs)) + { + result += "isXCHLHSameLLs: " + (string)mConditions.isXCHLHSameLLs + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCMCHHSame)) + { + result += "isXCHLHSCMCHHSame: " + (string)mConditions.isXCHLHSCMCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCMCLLSame)) + { + result += "isXCHLHSCMCLLSame: " + (string)mConditions.isXCHLHSCMCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCLCHHSame)) + { + result += "isXCHLHSCLCHHSame: " + (string)mConditions.isXCHLHSCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCLCLLSame)) + { + result += "isXCHLHSCLCLLSame: " + (string)mConditions.isXCHLHSCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCLCHHSame)) + { + result += "isXCHLHMCLCHHSame: " + (string)mConditions.isXCHLHMCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCLCLLSame)) + { + result += "isXCHLHMCLCLLSame: " + (string)mConditions.isXCHLHMCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCOnTopOfLC)) + { + result += "isXCHLHMCOnTopOfLC: " + (string)mConditions.isXCHLHMCOnTopOfLC + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCInBottomOfLC)) + { + result += "isXCHLHMCInBottomOfLC: " + (string)mConditions.isXCHLHMCInBottomOfLC + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHMA ... + result += + "| XCHMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCOverMax)) + { + result += "isXCHMASCOverMax: " + (string)mConditions.isXCHMASCOverMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCOverMin)) + { + result += "isXCHMASCOverMin: " + (string)mConditions.isXCHMASCOverMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCUnderMax)) + { + result += "isXCHMASCUnderMax: " + (string)mConditions.isXCHMASCUnderMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCUnderMin)) + { + result += "isXCHMASCUnderMin: " + (string)mConditions.isXCHMASCUnderMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedOverMax)) + { + result += "isXCHMASCCrossedOverMax: " + (string)mConditions.isXCHMASCCrossedOverMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedUnderMax)) + { + result += "isXCHMASCCrossedUnderMax: " + (string)mConditions.isXCHMASCCrossedUnderMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedOverMin)) + { + result += "isXCHMASCCrossedOverMin: " + (string)mConditions.isXCHMASCCrossedOverMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedUnderMin)) + { + result += "isXCHMASCCrossedUnderMin: " + (string)mConditions.isXCHMASCCrossedUnderMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCPeak)) + { + result += "isXCHMASCPeak: " + (string)mConditions.isXCHMASCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCVale)) + { + result += "isXCHMASCVale: " + (string)mConditions.isXCHMASCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCTrendsUp)) + { + result += "isXCHMASCTrendsUp: " + (string)mConditions.isXCHMASCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCTrendsDown)) + { + result += "isXCHMASCTrendsDown: " + (string)mConditions.isXCHMASCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastOverSlow)) + { + result += "isXCHMASCFastOverSlow: " + (string)mConditions.isXCHMASCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastUnderSlow)) + { + result += "isXCHMASCFastUnderSlow: " + (string)mConditions.isXCHMASCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastCrossedOverSlow)) + { + result += "isXCHMASCFastCrossedOverSlow: " + (string)mConditions.isXCHMASCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastCrossedUnderSlow)) + { + result += "isXCHMASCFastCrossedUnderSlow: " + (string)mConditions.isXCHMASCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCPeak)) + { + result += "isXCHMAMCPeak: " + (string)mConditions.isXCHMAMCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCVale)) + { + result += "isXCHMAMCVale: " + (string)mConditions.isXCHMAMCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCTrendsUp)) + { + result += "isXCHMAMCTrendsUp: " + (string)mConditions.isXCHMAMCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCTrendsDown)) + { + result += "isXCHMAMCTrendsDown: " + (string)mConditions.isXCHMAMCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastOverSlow)) + { + result += "isXCHMAMCFastOverSlow: " + (string)mConditions.isXCHMAMCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastUnderSlow)) + { + result += "isXCHMAMCFastUnderSlow: " + (string)mConditions.isXCHMAMCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastCrossedOverSlow)) + { + result += "isXCHMAMCFastCrossedOverSlow: " + (string)mConditions.isXCHMAMCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastCrossedUnderSlow)) + { + result += "isXCHMAMCFastCrossedUnderSlow: " + (string)mConditions.isXCHMAMCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCPeak)) + { + result += "isXCHMALCPeak: " + (string)mConditions.isXCHMALCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCVale)) + { + result += "isXCHMALCVale: " + (string)mConditions.isXCHMALCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCTrendsUp)) + { + result += "isXCHMALCTrendsUp: " + (string)mConditions.isXCHMALCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCTrendsDown)) + { + result += "isXCHMALCTrendsDown: " + (string)mConditions.isXCHMALCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastOverSlow)) + { + result += "isXCHMALCFastOverSlow: " + (string)mConditions.isXCHMALCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastUnderSlow)) + { + result += "isXCHMALCFastUnderSlow: " + (string)mConditions.isXCHMALCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastCrossedOverSlow)) + { + result += "isXCHMALCFastCrossedOverSlow: " + (string)mConditions.isXCHMALCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastCrossedUnderSlow)) + { + result += "isXCHMALCFastCrossedUnderSlow: " + (string)mConditions.isXCHMALCFastCrossedUnderSlow + separator; + } + + // + // Separator ... + result += separator; + + // + return result; + } + + // + // END Common Functions ... + // + + // + // START Actions Based On Signallers ... + // + + // + // START XTD Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXTDignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXTDEnableSignaller) + { + return result; + } + + // + result = true; + mXTDEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXTDSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXTDEnableSignaller) + { + return result; + } + + // + result = true; + mXTDEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXTDLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + mXTDAllowLongSignals) + { + return result; + } + + // + result = true; + mXTDAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXTDLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowLongSignals) + { + return result; + } + + // + result = true; + mXTDAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXTDShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + mXTDAllowShortSignals) + { + return result; + } + + // + result = true; + mXTDAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXTDShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowShortSignals) + { + return result; + } + + // + result = true; + mXTDAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XTDHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXTDSignalCrossedOverBear + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XTDHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXTDSignalCrossedUnderBear + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XTD Signaller ... + // + + // + // START XTAM Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXTAMignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXTAMEnableSignaller) + { + return result; + } + + // + result = true; + mXTAMEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXTAMSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXTAMEnableSignaller) + { + return result; + } + + // + result = true; + mXTAMEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXTAMLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + mXTAMAllowLongSignals) + { + return result; + } + + // + result = true; + mXTAMAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXTAMLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowLongSignals) + { + return result; + } + + // + result = true; + mXTAMAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXTAMShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + mXTAMAllowShortSignals) + { + return result; + } + + // + result = true; + mXTAMAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXTAMShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowShortSignals) + { + return result; + } + + // + result = true; + mXTAMAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XTAMHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + (xAMAMaBuffer[1] > xTMMaBuffer[1] && + xAMAMaBuffer[2] > xTMMaBuffer[2]) + // + && + // + !(xAMAMaBuffer[2] > xTMMaBuffer[2] && + xAMAMaBuffer[3] > xTMMaBuffer[3]) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XTAMHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + (xAMAMaBuffer[1] < xTMMaBuffer[1] && + xAMAMaBuffer[2] < xTMMaBuffer[2]) + // + && + // + !(xAMAMaBuffer[2] < xTMMaBuffer[2] && + xAMAMaBuffer[3] < xTMMaBuffer[3]) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XTAM Signaller ... + // + + // + // START XSI Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXSIignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXSIEnableSignaller) + { + return result; + } + + // + result = true; + mXSIEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXSISignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXSIEnableSignaller) + { + return result; + } + + // + result = true; + mXSIEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXSILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + mXSIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSIAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXSILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSIAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXSIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + mXSIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSIAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXSIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSIAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XSIHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXRSICrossedOverLongEntry && + xRSIBuffer[3] < xRSILongEntryValue + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + true, // XCHMA Cycles + true, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XSIHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXRSICrossedUnderShortEntry && + xRSIBuffer[3] > xRSIShortEntryValue + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort( + true, // XCHMA Min + true, // XCHMA Max + true, // XCHMA Cycles + true, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // END XSI Signaller ... + // + + // + // START XTSFI Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXTSFIignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXTSFIEnableSignaller) + { + return result; + } + + // + result = true; + mXTSFIEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXTSFISignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXTSFIEnableSignaller) + { + return result; + } + + // + result = true; + mXTSFIEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXTSFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + mXTSFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXTSFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXTSFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + mXTSFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXTSFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XTSFIHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + XTSGetMinValue(1) == xTSFarestBuffer[1] && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest) && + (xTSCurrentBuffer[1] < xTSNearestBuffer[1] || + xTSCurrentBuffer[1] < xTSMediestBuffer[1]) && + !(mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XTSFIHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + XTSGetMaxValue(1) == xTSFarestBuffer[1] && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest) && + (xTSCurrentBuffer[1] > xTSNearestBuffer[1] || + xTSCurrentBuffer[1] > xTSMediestBuffer[1]) && + !(mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XTSFI Signaller ... + // + + // + // START XOBDLH Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXOBDLHignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXOBDLHEnableSignaller) + { + return result; + } + + // + result = true; + mXOBDLHEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXOBDLHSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXOBDLHEnableSignaller) + { + return result; + } + + // + result = true; + mXOBDLHEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXOBDLHLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + mXOBDLHAllowLongSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXOBDLHLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowLongSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXOBDLHShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + mXOBDLHAllowShortSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXOBDLHShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowShortSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XOBDLHHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowLongSignals) + { + return result; + } + + // + XMarketConditions xConditions2 = GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xConditions2.isXOBDSwingLow && + xConditions2.isXLHLowAttachedLL && + xLHLLBuffer[1] >= xLHLLBuffer[2] + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + false, // XOBD + false // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XOBDLHHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowShortSignals) + { + return result; + } + + // + XMarketConditions xConditions2 = GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xConditions2.isXOBDSwingHigh && + xConditions2.isXLHHighAttachedHH && + xLHHHBuffer[1] <= xLHHHBuffer[2] + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + false, // XOBD + false // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // END XOBDLH Signaller ... + // + + // + // START XCHMACC Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXCHMACCignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXCHMACCEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMACCEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXCHMACCSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXCHMACCEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMACCEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXCHMACCLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + mXCHMACCAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXCHMACCLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXCHMACCShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + mXCHMACCAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXCHMACCShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XCHMACCHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xCHMAScFastBuffer[1] > xCHMAScSlowBuffer[1] && + xCHMAMcFastBuffer[1] > xCHMAMcSlowBuffer[1] && + xCHMALcFastBuffer[1] > xCHMALcSlowBuffer[1] && + // + xCHMAScFastBuffer[2] > xCHMAScSlowBuffer[2] && + xCHMAMcFastBuffer[2] > xCHMAMcSlowBuffer[2] && + xCHMALcFastBuffer[2] > xCHMALcSlowBuffer[2] && + // + !( + // + xCHMAScFastBuffer[3] > xCHMAScSlowBuffer[3] && + xCHMAMcFastBuffer[3] > xCHMAMcSlowBuffer[3] && + xCHMALcFastBuffer[3] > xCHMALcSlowBuffer[3] + // + ) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XCHMACCHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xCHMAScFastBuffer[1] < xCHMAScSlowBuffer[1] && + xCHMAMcFastBuffer[1] < xCHMAMcSlowBuffer[1] && + xCHMALcFastBuffer[1] < xCHMALcSlowBuffer[1] && + // + xCHMAScFastBuffer[2] < xCHMAScSlowBuffer[2] && + xCHMAMcFastBuffer[2] < xCHMAMcSlowBuffer[2] && + xCHMALcFastBuffer[2] < xCHMALcSlowBuffer[2] && + // + !( + // + xCHMAScFastBuffer[3] < xCHMAScSlowBuffer[3] && + xCHMAMcFastBuffer[3] < xCHMAMcSlowBuffer[3] && + xCHMALcFastBuffer[3] < xCHMALcSlowBuffer[3] + // + ) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XCHMACC Signaller ... + // + + // + // START XCHMAMX Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXCHMAMXignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXCHMAMXEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMXEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXCHMAMXSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXCHMAMXEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMXEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXCHMAMXLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + mXCHMAMXAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXCHMAMXLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXCHMAMXShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + mXCHMAMXAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXCHMAMXShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XCHMAMXHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowLongSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedOverMax && + xCHMAScFastBuffer[2] < xCHMANonSCMax2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMax2 && + MathAbs(xCHMANonSCMax2 - xCHMAScFastBuffer[2]) > MathAbs(xCHMAScFastBuffer[2] - xCHMAScSlowBuffer[2]) && + MathAbs(xCHMANonSCMax2 - xCHMAScSlowBuffer[2]) > MathAbs(xCHMAScFastBuffer[2] - xCHMAScSlowBuffer[2]) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XCHMAMXHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowShortSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedUnderMax && + xCHMAScFastBuffer[2] > xCHMANonSCMax2 && + xCHMAScSlowBuffer[2] > xCHMANonSCMax2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + // + return result; + } + + // + // END XCHMAMX Signaller ... + // + + // + // START XCHMAMN Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXCHMAMNignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXCHMAMNEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMNEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXCHMAMNSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXCHMAMNEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMNEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXCHMAMNLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + mXCHMAMNAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXCHMAMNLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXCHMAMNShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + mXCHMAMNAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXCHMAMNShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XCHMAMNHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowLongSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedOverMin && + xCHMAScFastBuffer[2] < xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMin2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XCHMAMNHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowShortSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedUnderMin && + xCHMAScFastBuffer[2] > xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] > xCHMANonSCMin2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + // + return result; + } + + // + // END XCHMAMN Signaller ... + // + + // + // END Actions Based On Signallers ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // XTD ... + bool mXTDEnableSignaller; + bool mXTDAllowLongSignals; + bool mXTDAllowShortSignals; + + // + // XTAM ... + bool mXTAMEnableSignaller; + bool mXTAMAllowLongSignals; + bool mXTAMAllowShortSignals; + + // + // XSI ... + bool mXSIEnableSignaller; + bool mXSIAllowLongSignals; + bool mXSIAllowShortSignals; + + // + // XTSFI ... + bool mXTSFIEnableSignaller; + bool mXTSFIAllowLongSignals; + bool mXTSFIAllowShortSignals; + + // + // XOBDLH ... + bool mXOBDLHEnableSignaller; + bool mXOBDLHAllowLongSignals; + bool mXOBDLHAllowShortSignals; + + // + // XCHMACC ... + bool mXCHMACCEnableSignaller; + bool mXCHMACCAllowLongSignals; + bool mXCHMACCAllowShortSignals; + + // + // XCHMAMX ... + bool mXCHMAMXEnableSignaller; + bool mXCHMAMXAllowLongSignals; + bool mXCHMAMXAllowShortSignals; + + // + // XCHMAMN ... + bool mXCHMAMNEnableSignaller; + bool mXCHMAMNAllowLongSignals; + bool mXCHMAMNAllowShortSignals; + + // + // Here we Define some Global Market Variables to Analyse MArket Conditions + // using them at each time ... + XMarketConditions mXConditions; +}; \ No newline at end of file diff --git a/XEU5/Documents/.gitkeep b/XEU5/Documents/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Documents/Reports/.gitkeep b/XEU5/Documents/Reports/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Documents/Settings/.gitkeep b/XEU5/Documents/Settings/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Experts/.gitkeep b/XEU5/Experts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Experts/x-saherelm.xeu5.ea.mq5 b/XEU5/Experts/x-saherelm.xeu5.ea.mq5 new file mode 100644 index 0000000..58c5bda --- /dev/null +++ b/XEU5/Experts/x-saherelm.xeu5.ea.mq5 @@ -0,0 +1,347 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ---------------------------------------- +// Name: XAUUSD +// 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 XEU5 EA" +#property strict + +// +// START Inputs ... +// + +input group "Commons"; + +// +// 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" + +// +// XEU5 Signal Provider ... +#include "../Providers/x-saherelm.xeu5.provider.lib.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +bool isXEU5NewHour; +bool isXEU5NewDay; +bool isXEU5NewWeek; +bool isXEU5NewMonth; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = "XEU5EA"; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Apply default Chart Style for EA ... + ApplyChartStyle(); + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize XEU5 Provider ... + if (!XEU5InitSignalProviderLibrary()) + { + 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 ... + + // + // De Initialize XEU5 Provider ... + XEU5DeinitSignalProviderLibrary(reason); + + // + // De Init XDraw Library ... + // OnDeinitDrawLibrary(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXEU5NewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXEU5NewMonth && + xEU5EnableAlerts && + xEU5EnableMonthlyAlerts; + bool canMonthlyReport = + !isFirstMonth && + canMonthlyAlert && + xEU5EnableMonthlyReports; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + // Prepare Monthly Report ... + if (canMonthlyReport) + { + // + string report = xEU5Reporter.GenerateReportString(XREPORT_MONTHLY); + + // + message = "Last Month Report:\n" + report; + } + + // + // Reset Report ... + xEU5Reporter.Reset(XREPORT_MONTHLY); + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXEU5NewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXEU5NewWeek && + xEU5EnableAlerts && + xEU5EnableWeeklyAlerts; + bool canWeeklyReport = + !isFirstWeek && + canWeeklyAlert && + xEU5EnableWeeklyReports; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + // Prepare Weekly Report ... + if (canWeeklyReport) + { + // + string report = xEU5Reporter.GenerateReportString(XREPORT_WEEKLY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xEU5Reporter.Reset(XREPORT_WEEKLY); + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXEU5NewDay = IsNewDay(); + bool canDailyAlert = + isXEU5NewDay && + xEU5EnableAlerts && + xEU5EnableDailyAlerts; + bool canDailyReport = + !isFirstDay && + canDailyAlert && + xEU5EnableDailyReports; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + // Prepare Daily Report ... + if (canDailyReport) + { + // + string report = xEU5Reporter.GenerateReportString(XREPORT_DAILY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xEU5Reporter.Reset(XREPORT_DAILY); + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXEU5NewHour = IsNewHour(); + bool canHourlyAlert = + isXEU5NewHour && + xEU5EnableAlerts && + xEU5EnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + + // + // Prevent Going Forward if user Disable it ... + if (xEU5EnableProvider) + { + // + // Handle Processing on XEU5 Signal Provider ... + XEU5SignalProviderDoControlState(); + } + + // + if (!IsNewCandle()) + { + return; + } + + // + // Prevent Going Forward if user Disable it ... + if (xEU5EnableProvider) + { + // + // Handle Processing on XEU5 Signal Provider ... + XEU5SignalProviderHandleTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + + // + // Prevent Going Forward if user Disable it ... + if (xEU5EnableProvider) + { + // + // Handle Processing Trades on XEU5 Signal Provider ... + XEU5SignalProviderHandleTrade(); + } +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + + // + // Validate XEU5 Provider Inputs ... + result = XEU5ValidateInputs(); + if (!result) + { + return false; + } + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// END Functions ... +// diff --git a/XEU5/Helpers/.gitkeep b/XEU5/Helpers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 new file mode 100644 index 0000000..f565e41 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 @@ -0,0 +1,607 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAMA 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XAMA Indicator States ... +enum ENUM_X_XAMA_STATES +{ + X_XAMA_BULLISH = 1, + X_XAMA_BEARISH = -1, + X_XAMA_NEUTURAL = 0, +}; + +// +// XAMA Indicator Buffer Lines ... +enum ENUM_X_XAMA_BUFFER_LINES +{ + X_XAMA_MA_LINE = 0, + X_XAMA_MC_COLOR_LINE = 1, + X_XAMA_STATE_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XAMA Indicator"; + +// +// input int xAMALength = 18; // Market Length +// input int xAMAFastEMA = 2; // Fast EMA Period +// input int xAMASlowEMA = 30; // Slow EMA Period +// input int xAMAShift = 0; // Shift +// input ENUM_APPLIED_PRICE xAMAAppliedTo = PRICE_CLOSE; // Applied To + +// +// Configurations ... +int xAMALength = 18; // Market Length +int xAMAFastEMA = 2; // Fast EMA Period +int xAMASlowEMA = 30; // Slow EMA Period +int xAMAShift = 0; // Shift +ENUM_APPLIED_PRICE xAMAAppliedTo = PRICE_CLOSE; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xAMAHandler = INVALID_HANDLE; +double xAMAMaBuffer[]; +double xAMAStateBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XAMAValidateInputs() +{ + // + bool result = false; + + // + result = + xAMALength > 2 && + xAMAFastEMA < xAMALength && + xAMAFastEMA < xAMASlowEMA && + xAMAShift >= 0; + + // + if (!result) + { + // + LogMessage("XAMA Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XAMAInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Indicator Handlers ... + ResetLastError(); + + // + // XAMA Handler ... + ArraySetAsSeries(xAMAMaBuffer, true); + ArraySetAsSeries(xAMAStateBuffer, true); + xAMAHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xama.indicator", + // + // Inputs ... + xAMALength, + xAMAFastEMA, + xAMASlowEMA, + xAMAShift, + xAMAAppliedTo + // + ); + if (xAMAHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XAMA Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XAMAReleaseHandlers() +{ + IndicatorRelease(xAMAHandler); +} + +// +// Handle Reading Buffers ... +void XAMAReadBuffers( + int xAMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XAMA Ma Buffer ... + CopyBuffer( + xAMAHandler, + X_XAMA_MA_LINE, + 0, + xAMAItemsPerTick, + xAMAMaBuffer); + + // + // XAMA State Buffer ... + CopyBuffer( + xAMAHandler, + X_XAMA_STATE_LINE, + 0, + xAMAItemsPerTick, + xAMAStateBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XAMA Custom Functions ... +// + +// +// Check SC is Peak ... +bool XAMAIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xAMAMaBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XAMAIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xAMAMaBuffer + // + ); + + // + return result; +} + +// +// Check TM Crossed Up ... +bool XAMAIsStartBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BULLISH && + xAMAStateBuffer[bar_index + 1] != X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Up After Neutural State ... +bool XAMAIsStartBullishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BULLISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Up State ... +bool XAMAIsBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State ... +bool XAMAIsEndBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] != X_XAMA_BULLISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State By Neutural ... +bool XAMAIsEndBullishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_NEUTURAL && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down ... +bool XAMAIsStartBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BEARISH && + xAMAStateBuffer[bar_index + 1] != X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down After Neutural State ... +bool XAMAIsStartBearishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BEARISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Down State ... +bool XAMAIsBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State ... +bool XAMAIsEndBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] != X_XAMA_BEARISH && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State By Neutural ... +bool XAMAIsEndBearishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_NEUTURAL && + xAMAStateBuffer[bar_index + 1] == X_XAMA_BEARISH + // + ; + + // + return result; +} + +// +// Check TM In Neutural State ... +bool XAMAIsNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XAMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xAMAStateBuffer[bar_index] == X_XAMA_NEUTURAL + // + ; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XAMAIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xAMAMaBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XAMA Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..d7071b4 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 @@ -0,0 +1,1032 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHLH Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// Cycles Enumeration ... +enum ENUM_X_XCHLH_CYCLES +{ + X_XCHLH_CYCLE_LONG, + X_XCHLH_CYCLE_MEDIUM, + X_XCHLH_CYCLE_SHORT, +}; + +// +// XCHLH Hot States ... +enum ENUM_X_XCHLH_HOT_STATES +{ + X_XCHLH_HOT_HH = 1, + X_XCHLH_NEUTURAL = 0, + X_XCHLH_HOT_LL = -1, +}; + +// +// XCHLH Buffer Lines ... +enum ENUM_X_XCHLH_BUFFER_LINES +{ + X_XCHLH_LC_HH_LINE = 0, + X_XCHLH_LC_LL_LINE = 1, + X_XCHLH_MC_HH_LINE = 2, + X_XCHLH_MC_LL_LINE = 3, + X_XCHLH_SC_HH_LINE = 4, + X_XCHLH_SC_LL_LINE = 5, + X_XCHLH_SIGNAL_T_LINE = 6, + X_XCHLH_SIGNAL_B_LINE = 7, + X_XCHLH_HOT_STATE_LINE = 8, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// // +// input group "XCHLH Oscillator"; + +// // +// // Common ... +// input group "XCHLH Hot Areas"; +// input bool xCHLHDrawHotAreas = false; // Draw Hot Areas Symbol +// input uchar xCHLHHotHHArrowCode = 234; // Hot HH Arrow Code +// input color xCHLHHotHHArrowColor = clrAqua; // Hot HH Arrow Color +// input uchar xCHLHHotLLArrowCode = 233; // Hot LL Arrow Code +// input color xCHLHHotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// // +// // LC Inputs ... +// input group "XCHLH Long Cycle"; +// input group "XCHLH LC Market"; +// input int xCHLHLcLength = 288; // Length +// input double xCHLHLcThresholdInPips = 0.3; // Threshold In Pips +// input ENUM_SERIESMODE xCHLHLcHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xCHLHLcLLMode = MODE_LOW; // Lowest Low Calculation Method +// input group "XCHLH LC Style"; +// input int xCHLHLcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHLHLcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHLHLcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHLHLcHHColor = clrAqua; // Highest High Color +// input color xCHLHLcLLColor = clrFuchsia; // Lowest Low Color +// input group "XCHLH LC Drawings"; +// input bool xCHLHLcDrawHH = true; // Draw Highest High +// input bool xCHLHLcDrawLL = true; // Draw Lowest Low + +// // +// // MC Inputs ... +// input group "XCHLH Medium Cycle"; +// input group "XCHLH MC Market"; +// input int xCHLHMcLength = 72; // Length +// input double xCHLHMcThresholdInPips = 0.3; // Threshold In Pips +// input ENUM_SERIESMODE xCHLHMcHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xCHLHMcLLMode = MODE_LOW; // Lowest Low Calculation Method +// input group "XCHLH MC Style"; +// input int xCHLHMcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHLHMcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHLHMcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHLHMcHHColor = clrLime; // Highest High Color +// input color xCHLHMcLLColor = clrRed; // Lowest Low Color +// input group "XCHLH MC Drawings"; +// input bool xCHLHMcDrawHH = true; // Draw Highest High +// input bool xCHLHMcDrawLL = true; // Draw Lowest Low + +// // +// // SC Inputs ... +// input group "XCHLH Short Cycle"; +// input group "XCHLH SC Market"; +// input int xCHLHScLength = 7; // Length +// input double xCHLHScThresholdInPips = 0.3; // Threshold In Pips +// input ENUM_SERIESMODE xCHLHScHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xCHLHScLLMode = MODE_LOW; // Lowest Low Calculation Method +// input group "XCHLH SC Style"; +// input int xCHLHScDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHLHScDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHLHScDrawStyle = STYLE_DOT; // Draw Style +// input color xCHLHScHHColor = clrLightBlue; // Highest High Color +// input color xCHLHScLLColor = clrLightSalmon; // Lowest Low Color +// input group "XCHLH SC Drawings"; +// input bool xCHLHScDrawHH = true; // Draw Highest High +// input bool xCHLHScDrawLL = true; // Draw Lowest Low + +// +// Configurations ... +// +// Common ... +bool xCHLHDrawHotAreas = false; // Draw Hot Areas Symbol +uchar xCHLHHotHHArrowCode = 234; // Hot HH Arrow Code +color xCHLHHotHHArrowColor = clrAqua; // Hot HH Arrow Color +uchar xCHLHHotLLArrowCode = 233; // Hot LL Arrow Code +color xCHLHHotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// +// LC Inputs ... +int xCHLHLcLength = 288; // Length +double xCHLHLcThresholdInPips = 0.3; // Threshold In Pips +ENUM_SERIESMODE xCHLHLcHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xCHLHLcLLMode = MODE_LOW; // Lowest Low Calculation Method +int xCHLHLcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHLHLcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHLHLcDrawStyle = STYLE_DOT; // Draw Style +color xCHLHLcHHColor = clrAqua; // Highest High Color +color xCHLHLcLLColor = clrFuchsia; // Lowest Low Color +bool xCHLHLcDrawHH = true; // Draw Highest High +bool xCHLHLcDrawLL = true; // Draw Lowest Low + +// +// MC Inputs ... +int xCHLHMcLength = 72; // Length +double xCHLHMcThresholdInPips = 0.3; // Threshold In Pips +ENUM_SERIESMODE xCHLHMcHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xCHLHMcLLMode = MODE_LOW; // Lowest Low Calculation Method +int xCHLHMcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHLHMcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHLHMcDrawStyle = STYLE_DOT; // Draw Style +color xCHLHMcHHColor = clrLime; // Highest High Color +color xCHLHMcLLColor = clrRed; // Lowest Low Color +bool xCHLHMcDrawHH = true; // Draw Highest High +bool xCHLHMcDrawLL = true; // Draw Lowest Low + +// +// SC Inputs ... +int xCHLHScLength = 7; // Length +double xCHLHScThresholdInPips = 0.3; // Threshold In Pips +ENUM_SERIESMODE xCHLHScHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xCHLHScLLMode = MODE_LOW; // Lowest Low Calculation Method +int xCHLHScDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHLHScDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHLHScDrawStyle = STYLE_DOT; // Draw Style +color xCHLHScHHColor = clrLightBlue; // Highest High Color +color xCHLHScLLColor = clrLightSalmon; // Lowest Low Color +bool xCHLHScDrawHH = true; // Draw Highest High +bool xCHLHScDrawLL = true; // Draw Lowest Low + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xCHLHHandler = INVALID_HANDLE; +double xCHLHLcHHBuffer[]; +double xCHLHLcLLBuffer[]; +double xCHLHMcHHBuffer[]; +double xCHLHMcLLBuffer[]; +double xCHLHScHHBuffer[]; +double xCHLHScLLBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XCHLHValidateInputs() +{ + // + bool result = false; + + // + result = + xCHLHScLength >= 2 && + xCHLHMcLength > xCHLHScLength && + xCHLHLcLength > xCHLHMcLength; + + // + if (!result) + { + // + LogMessage("XCHLH Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XCHLHInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XCHLH Handler ... + ArraySetAsSeries(xCHLHLcHHBuffer, true); + ArraySetAsSeries(xCHLHLcLLBuffer, true); + ArraySetAsSeries(xCHLHMcHHBuffer, true); + ArraySetAsSeries(xCHLHMcLLBuffer, true); + ArraySetAsSeries(xCHLHScHHBuffer, true); + ArraySetAsSeries(xCHLHScLLBuffer, true); + xCHLHHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xchlh.oscillator", + // + // Inputs ... + // + // Commons ... + "", + xCHLHDrawHotAreas, + xCHLHHotHHArrowCode, + xCHLHHotHHArrowColor, + xCHLHHotLLArrowCode, + xCHLHHotLLArrowColor, + // + // LC ... + "", + "", + xCHLHLcLength, + xCHLHLcThresholdInPips, + xCHLHLcHHMode, + xCHLHLcLLMode, + "", + xCHLHLcDrawWidth, + xCHLHLcDrawType, + xCHLHLcDrawStyle, + xCHLHLcHHColor, + xCHLHLcLLColor, + "", + xCHLHLcDrawHH, + xCHLHLcDrawLL, + // + // MC ... + "", + "", + xCHLHMcLength, + xCHLHMcThresholdInPips, + xCHLHMcHHMode, + xCHLHMcLLMode, + "", + xCHLHMcDrawWidth, + xCHLHMcDrawType, + xCHLHMcDrawStyle, + xCHLHMcHHColor, + xCHLHMcLLColor, + "", + xCHLHMcDrawHH, + xCHLHMcDrawLL, + // + // SC ... + "", + "", + xCHLHScLength, + xCHLHScThresholdInPips, + xCHLHScHHMode, + xCHLHScLLMode, + "", + xCHLHScDrawWidth, + xCHLHScDrawType, + xCHLHScDrawStyle, + xCHLHScHHColor, + xCHLHScLLColor, + "", + xCHLHScDrawHH, + xCHLHScDrawLL); + if (xCHLHHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XCHLH Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XCHLHReleaseHandlers() +{ + IndicatorRelease(xCHLHHandler); +} + +// +// Handle Reading Buffers ... +void XCHLHReadBuffers( + int xCHLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XCHLH LC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_LC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHLcHHBuffer); + + // + // XCHLH LC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_LC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHLcLLBuffer); + + // + // XCHLH MC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_MC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHMcHHBuffer); + + // + // XCHLH MC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_MC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHMcLLBuffer); + + // + // XCHLH SC HH Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SC_HH_LINE, + 0, + xCHLHItemsPerTick, + xCHLHScHHBuffer); + + // + // XCHLH SC LL Buffer ... + CopyBuffer( + xCHLHHandler, + X_XCHLH_SC_LL_LINE, + 0, + xCHLHItemsPerTick, + xCHLHScLLBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XCHLH Custom Functions ... +// + +// +// Check LC and MC has Same HH ... +bool XCHLHIsLCMCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double mcValue = xCHLHMcHHBuffer[bar_index]; + + // + result = lcValue == mcValue; + + // + return result; +} + +// +// Check LC and MC has Same LL ... +bool XCHLHIsLCMCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double mcValue = xCHLHMcLLBuffer[bar_index]; + + // + result = lcValue == mcValue; + + // + return result; +} + +// +// Check LC and SC has Same HH ... +bool XCHLHIsLCSCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = lcValue == scValue; + + // + return result; +} + +// +// Check LC and SC has Same LL ... +bool XCHLHIsLCSCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = lcValue == scValue; + + // + return result; +} + +// +// Check MC and SC has Same HH ... +bool XCHLHIsMCSCHasSameHH( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double mcValue = xCHLHMcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = mcValue == scValue; + + // + return result; +} + +// +// Check MC and SC has Same LL ... +bool XCHLHIsMCSCHasSameLL( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double mcValue = xCHLHMcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = mcValue == scValue; + + // + return result; +} + +// +// Check Is Same Highest Highs ... +bool XCHLHIsSameHHs( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcHHBuffer[bar_index]; + double mcValue = xCHLHMcHHBuffer[bar_index]; + double scValue = xCHLHScHHBuffer[bar_index]; + + // + result = + // + lcValue == mcValue && + mcValue == scValue + // + ; + + // + return result; +} + +// +// Check Is Same Lowest Lows ... +bool XCHLHIsSameLLs( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if (!XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + double lcValue = xCHLHLcLLBuffer[bar_index]; + double mcValue = xCHLHMcLLBuffer[bar_index]; + double scValue = xCHLHScLLBuffer[bar_index]; + + // + result = + // + lcValue == mcValue && + mcValue == scValue + // + ; + + // + return result; +} + +// +// Check Medium Cycle is On Top of Long Cycle's Mid ... +bool XCHLHIsMCOnTopOfLC( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + ENUM_X_XCHLH_CYCLES sCycle = X_XCHLH_CYCLE_MEDIUM; + ENUM_X_XCHLH_CYCLES dCycle = X_XCHLH_CYCLE_LONG; + + // + result = + // + XCHLHCheckCycleIsOnTopOfAnother( + bar_index, + sCycle, + dCycle) + // + ; + + // + return result; +} + +// +// Check Medium Cycle is In Bottom of Long Cycle's Mid ... +bool XCHLHIsMCInBottomOfLC( + int bar_index // Specified Bar Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + ENUM_X_XCHLH_CYCLES sCycle = X_XCHLH_CYCLE_MEDIUM; + ENUM_X_XCHLH_CYCLES dCycle = X_XCHLH_CYCLE_LONG; + + // + result = + // + XCHLHCheckCycleIsInBottomOfAnother( + bar_index, + sCycle, + dCycle) + // + ; + + // + return result; +} + +// +// Check and Validate Buffer Sizes ... +bool XCHLHIsValidBufferSizes( + int size // Specified Min Size +) +{ + // + bool result = false; + + // + result = + // + ArraySize(xCHLHLcHHBuffer) > size && + ArraySize(xCHLHLcLLBuffer) > size && + // + ArraySize(xCHLHMcHHBuffer) > size && + ArraySize(xCHLHMcLLBuffer) > size && + // + ArraySize(xCHLHScHHBuffer) > size && + ArraySize(xCHLHScLLBuffer) > size; + + // + return result; +} + +// +// Get Cycle Middle Value ... +double XCHLHGetCycleMid( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Retrieve Cycle Max Value ... + double iMax = XCHLHGetCycleMax( + bar_index, + cycle); + + // + // Retrieve Cycle Min Value ... + double iMin = XCHLHGetCycleMin( + bar_index, + cycle); + + // + result = (iMax - iMin) / 2; + + // + return result; +} + +// +// Get Cycle Max Value ... +double XCHLHGetCycleMax( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + // Long Cycle ... + case X_XCHLH_CYCLE_LONG: + result = xCHLHLcHHBuffer[1]; + break; + + // + // Medium Cycle ... + case X_XCHLH_CYCLE_MEDIUM: + result = xCHLHMcHHBuffer[1]; + break; + + // + // Short Cycle ... + case X_XCHLH_CYCLE_SHORT: + result = xCHLHScHHBuffer[1]; + break; + } + + // + return result; +} + +// +// Get Specified Cycles Max Value ... +double XCHLHGetCyclesMax( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES &cycles[] // Specified Cycle ... +) +{ + // + bool result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + ArraySize(cycles) <= 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycles); i++) + { + // + ENUM_X_XCHLH_CYCLES iCycle = cycles[i]; + + // + double iValue = XCHLHGetCycleMax( + bar_index, + iCycle); + + // + result = result == 0 || result < iValue ? iValue : result; + } + + // + return result; +} + +// +// Get Cycle Min Value ... +double XCHLHGetCycleMin( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + // Long Cycle ... + case X_XCHLH_CYCLE_LONG: + result = xCHLHLcLLBuffer[1]; + break; + + // + // Medium Cycle ... + case X_XCHLH_CYCLE_MEDIUM: + result = xCHLHMcLLBuffer[1]; + break; + + // + // Short Cycle ... + case X_XCHLH_CYCLE_SHORT: + result = xCHLHScLLBuffer[1]; + break; + } + + // + return result; +} + +// +// Get Specified Cycles Min Value ... +double XCHLHGetCyclesMin( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES &cycles[] // Specified Cycle ... +) +{ + // + bool result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + ArraySize(cycles) <= 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycles); i++) + { + // + ENUM_X_XCHLH_CYCLES iCycle = cycles[i]; + + // + double iValue = XCHLHGetCycleMin( + bar_index, + iCycle); + + // + result = result == 0 || result > iValue ? iValue : result; + } + + // + return result; +} + +// +// Check a Cycle is On Top of Another Cycle's Mid ... +bool XCHLHCheckCycleIsOnTopOfAnother( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES sourceCycle, // Specified Source Cycle which Checks ... + ENUM_X_XCHLH_CYCLES destCycle // Specified Dest Cycle which source Checked based on it ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Retrieve Min Value of Source Cycle ... + double iMin = XCHLHGetCycleMin( + bar_index, + sourceCycle); + + // + // Retrieve Mid Value of Dest Cycle ... + double iMid = XCHLHGetCycleMid( + bar_index, + destCycle); + + // + // Generate Result ... + result = + // + iMin >= iMid + // + ; + + // + return result; +} + +// +// Check a Cycle is Under Bottom of Another Cycle's Mid ... +bool XCHLHCheckCycleIsInBottomOfAnother( + int bar_index, // Specified Bar Index ... + ENUM_X_XCHLH_CYCLES sourceCycle, // Specified Source Cycle which Checks ... + ENUM_X_XCHLH_CYCLES destCycle // Specified Dest Cycle which source Checked based on it ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHLHIsValidBufferSizes(bar_index + 1)) + { + return result; + } + + // + // Retrieve Max Value of Source Cycle ... + double iMax = XCHLHGetCycleMax( + bar_index, + sourceCycle); + + // + // Retrieve Mid Value of Dest Cycle ... + double iMid = XCHLHGetCycleMid( + bar_index, + destCycle); + + // + // Generate Result ... + result = + // + iMax <= iMid + // + ; + + // + return result; +} + +// +// END XCHLH Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..e84d762 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 @@ -0,0 +1,2229 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCHMA Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XCHMA Cycles ... +enum ENUM_XCHMA_CYCLES +{ + X_XCHMA_CYCLE_LONG, + X_XCHMA_CYCLE_MEDIUM, + X_XCHMA_CYCLE_SHORT, +}; + +// +// XCHMA Oscillator Hot State Presentation ... +enum ENUM_XCHMA_HOT_STATES +{ + X_XCHMA_HOT_BULLISH = 1, + X_XCHMA_HOT_NEUTURAL = 0, + X_XCHMA_HOT_BEARISH = -1, +}; + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; + +// +// XCHMA Oscillator Buffer Lines ... +enum ENUM_X_XCHMA_BUFFER_LINES +{ + X_XCHMA_LC_FAST_LINE = 0, + X_XCHMA_LC_SLOW_LINE = 1, + X_XCHMA_LC_STATE_LINE = 6, + X_XCHMA_MC_FAST_LINE = 2, + X_XCHMA_MC_SLOW_LINE = 3, + X_XCHMA_MC_STATE_LINE = 7, + X_XCHMA_SC_FAST_LINE = 4, + X_XCHMA_SC_SLOW_LINE = 5, + X_XCHMA_SC_STATE_LINE = 8, + X_XCHMA_HOT_STATE_LINE = 9, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XCHMA Oscillator"; + +// // +// // Commons ... +// input group "XCHMA Hot Areas"; +// input bool xCHMADrawHotAreas = false; // Draw Hot Areas Symbol; +// input uchar xCHMAHotBullishArrowCode = 228; // Hot Bullish Arrow Code; +// input color xCHMAHotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color; +// input uchar xCHMAHotBearishArrowCode = 230; // Hot Bearish Arrow Code; +// input color xCHMAHotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color; + +// // +// // LC Inputs ... +// input group "XCHMA Long Cycle"; +// input group "XCHMA LC Market"; +// input int xCHMALcFastLength = 288; // Fast Length +// input int xCHMALcSlowLength = 576; // Slow Length +// input ENUM_MA_METHOD xCHMALcMethod = MODE_EMA; // Calculation Method +// input ENUM_APPLIED_PRICE xCHMALcAppliedTo = PRICE_CLOSE; // Applied To +// input group "XCHMA LC Style"; +// input int xCHMALcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHMALcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHMALcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHMALcFastColor = clrAqua; // Fast Color +// input color xCHMALcSlowColor = clrFuchsia; // Slow Color +// input group "XCHMA LC Drawings"; +// input bool xCHMALcDrawFast = true; // Draw Fast +// input bool xCHMALcDrawSlow = true; // Draw Slow +// input bool xCHMALcDrawCrosses = false; // Draw Cross Lines + +// // +// // MC Inputs ... +// input group "XCHMA Medium Cycle"; +// input group "XCHMA MC Market"; +// input int xCHMAMcFastLength = 72; // Fast Length +// input int xCHMAMcSlowLength = 144; // Slow Length +// input ENUM_MA_METHOD xCHMAMcMethod = MODE_EMA; // Calculation Method +// input ENUM_APPLIED_PRICE xCHMAMcAppliedTo = PRICE_CLOSE; // Applied To +// input group "XCHMA MC Style"; +// input int xCHMAMcDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHMAMcDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHMAMcDrawStyle = STYLE_DOT; // Draw Style +// input color xCHMAMcFastColor = clrLime; // Fast Color +// input color xCHMAMcSlowColor = clrRed; // Slow Color +// input group "XCHMA MC Drawings"; +// input bool xCHMAMcDrawFast = true; // Draw Fast +// input bool xCHMAMcDrawSlow = true; // Draw Slow +// input bool xCHMAMcDrawCrosses = false; // Draw Cross Lines + +// // +// // SC Inputs ... +// input group "XCHMA Short Cycle"; +// input group "XCHMA SC Market"; +// input int xCHMAScFastLength = 7; // Fast Length +// input int xCHMAScSlowLength = 14; // Slow Length +// input ENUM_MA_METHOD xCHMAScMethod = MODE_SMA; // Calculation Method +// input ENUM_APPLIED_PRICE xCHMAScAppliedTo = PRICE_CLOSE; // Applied To +// input group "XCHMA SC Style"; +// input int xCHMAScDrawWidth = 1; // Draw Width +// input ENUM_DRAW_TYPE xCHMAScDrawType = DRAW_LINE; // Draw Type +// input ENUM_LINE_STYLE xCHMAScDrawStyle = STYLE_SOLID; // Draw Style +// input color xCHMAScFastColor = clrLightBlue; // Fast Color +// input color xCHMAScSlowColor = clrLightSalmon; // Slow Color +// input group "XCHMA SC Drawings"; +// input bool xCHMAScDrawFast = true; // Draw Fast +// input bool xCHMAScDrawSlow = true; // Draw Slow +// input bool xCHMAScDrawCrosses = false; // Draw Cross Lines + +// +// Configurations ... +// +// Commons ... +bool xCHMADrawHotAreas = false; // Draw Hot Areas Symbol; +uchar xCHMAHotBullishArrowCode = 228; // Hot Bullish Arrow Code; +color xCHMAHotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color; +uchar xCHMAHotBearishArrowCode = 230; // Hot Bearish Arrow Code; +color xCHMAHotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color; + +// +// LC Inputs ... +int xCHMALcFastLength = 288; // Fast Length +int xCHMALcSlowLength = 576; // Slow Length +ENUM_MA_METHOD xCHMALcMethod = MODE_EMA; // Calculation Method +ENUM_APPLIED_PRICE xCHMALcAppliedTo = PRICE_CLOSE; // Applied To +int xCHMALcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHMALcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHMALcDrawStyle = STYLE_DOT; // Draw Style +color xCHMALcFastColor = clrAqua; // Fast Color +color xCHMALcSlowColor = clrFuchsia; // Slow Color +bool xCHMALcDrawFast = true; // Draw Fast +bool xCHMALcDrawSlow = true; // Draw Slow +bool xCHMALcDrawCrosses = false; // Draw Cross Lines + +// +// MC Inputs ... +int xCHMAMcFastLength = 72; // Fast Length +int xCHMAMcSlowLength = 144; // Slow Length +ENUM_MA_METHOD xCHMAMcMethod = MODE_EMA; // Calculation Method +ENUM_APPLIED_PRICE xCHMAMcAppliedTo = PRICE_CLOSE; // Applied To +int xCHMAMcDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHMAMcDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHMAMcDrawStyle = STYLE_DOT; // Draw Style +color xCHMAMcFastColor = clrLime; // Fast Color +color xCHMAMcSlowColor = clrRed; // Slow Color +bool xCHMAMcDrawFast = true; // Draw Fast +bool xCHMAMcDrawSlow = true; // Draw Slow +bool xCHMAMcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +int xCHMAScFastLength = 7; // Fast Length +int xCHMAScSlowLength = 14; // Slow Length +ENUM_MA_METHOD xCHMAScMethod = MODE_SMA; // Calculation Method +ENUM_APPLIED_PRICE xCHMAScAppliedTo = PRICE_CLOSE; // Applied To +int xCHMAScDrawWidth = 1; // Draw Width +ENUM_DRAW_TYPE xCHMAScDrawType = DRAW_LINE; // Draw Type +ENUM_LINE_STYLE xCHMAScDrawStyle = STYLE_SOLID; // Draw Style +color xCHMAScFastColor = clrLightBlue; // Fast Color +color xCHMAScSlowColor = clrLightSalmon; // Slow Color +bool xCHMAScDrawFast = true; // Draw Fast +bool xCHMAScDrawSlow = true; // Draw Slow +bool xCHMAScDrawCrosses = false; // Draw Cross Lines + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xCHMAHandler = INVALID_HANDLE; +double xCHMALcFastBuffer[]; +double xCHMALcSlowBuffer[]; +double xCHMAMcFastBuffer[]; +double xCHMAMcSlowBuffer[]; +double xCHMAScFastBuffer[]; +double xCHMAScSlowBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XCHMAValidateInputs() +{ + // + bool result = false; + + // + result = + xCHMAScFastLength >= 2 && + xCHMAScSlowLength > xCHMAScFastLength && + xCHMAMcFastLength > xCHMAScSlowLength && + xCHMAMcSlowLength > xCHMAMcFastLength && + xCHMALcFastLength > xCHMAMcSlowLength && + xCHMALcSlowLength > xCHMALcFastLength; + + // + if (!result) + { + // + LogMessage("XCHMA Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XCHMAInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XCHMA Handler ... + ArraySetAsSeries(xCHMALcFastBuffer, true); + ArraySetAsSeries(xCHMALcSlowBuffer, true); + ArraySetAsSeries(xCHMAMcFastBuffer, true); + ArraySetAsSeries(xCHMAMcSlowBuffer, true); + ArraySetAsSeries(xCHMAScFastBuffer, true); + ArraySetAsSeries(xCHMAScSlowBuffer, true); + xCHMAHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xchma.oscillator", + // + // Inputs ... + "", + xCHMADrawHotAreas, + xCHMAHotBullishArrowCode, + xCHMAHotBullishArrowColor, + xCHMAHotBearishArrowCode, + xCHMAHotBearishArrowColor, + // + // Long Cycle ... + "", + "", + xCHMALcFastLength, + xCHMALcSlowLength, + xCHMALcMethod, + xCHMALcAppliedTo, + "", + xCHMALcDrawWidth, + xCHMALcDrawType, + xCHMALcDrawStyle, + xCHMALcFastColor, + xCHMALcSlowColor, + "", + xCHMALcDrawFast, + xCHMALcDrawSlow, + xCHMALcDrawCrosses, + // + // Medium Cycle ... + "", + "", + xCHMAMcFastLength, + xCHMAMcSlowLength, + xCHMAMcMethod, + xCHMAMcAppliedTo, + "", + xCHMAMcDrawWidth, + xCHMAMcDrawType, + xCHMAMcDrawStyle, + xCHMAMcFastColor, + xCHMAMcSlowColor, + "", + xCHMAMcDrawFast, + xCHMAMcDrawSlow, + xCHMAMcDrawCrosses, + // + // Short Cycle ... + "", + "", + xCHMAScFastLength, + xCHMAScSlowLength, + xCHMAScMethod, + xCHMAScAppliedTo, + "", + xCHMAScDrawWidth, + xCHMAScDrawType, + xCHMAScDrawStyle, + xCHMAScFastColor, + xCHMAScSlowColor, + "", + xCHMAScDrawFast, + xCHMAScDrawSlow, + xCHMAScDrawCrosses); + if (xCHMAHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XCHMA Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XCHMAReleaseHandlers() +{ + IndicatorRelease(xCHMAHandler); +} + +// +// Handle Reading Buffers ... +void XCHMAReadBuffers( + int xCHMAItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XCHMA Long Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_LC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMALcFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_LC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMALcSlowBuffer); + + // + // XCHMA Medium Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_MC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMAMcFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_MC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMAMcSlowBuffer); + + // + // XCHMA Short Cycle ... + // + // XCHMA Fast ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_SC_FAST_LINE, + 0, + xCHMAItemsPerTick, + xCHMAScFastBuffer); + + // + // XCHMA Slow ... + CopyBuffer( + xCHMAHandler, + X_XCHMA_SC_SLOW_LINE, + 0, + xCHMAItemsPerTick, + xCHMAScSlowBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XCHMA Custom Functions ... +// + +// +// Retrieve Max Cycles Value ... +double XCHMAGetMax( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if (!XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // SC Fast ... + result = MathMax( + result, + xCHMAScFastBuffer[bar_index]); + + // + // SC Slow ... + result = MathMax( + result, + xCHMAScSlowBuffer[bar_index]); + + // + // MC Fast ... + result = MathMax( + result, + xCHMAMcFastBuffer[bar_index]); + + // + // MC Slow ... + result = MathMax( + result, + xCHMAMcSlowBuffer[bar_index]); + + // + // LC Fast ... + result = MathMax( + result, + xCHMALcFastBuffer[bar_index]); + + // + // LC Slow ... + result = MathMax( + result, + xCHMALcSlowBuffer[bar_index]); + + // + return result; +} + +// +// Retrieve Max Cycles Value ... +double XCHMAGetMin( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if (!XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = xCHMAScFastBuffer[bar_index]; + + // + // SC Fast ... + result = MathMin( + result, + xCHMAScFastBuffer[bar_index]); + + // + // SC Slow ... + result = MathMin( + result, + xCHMAScSlowBuffer[bar_index]); + + // + // MC Fast ... + result = MathMin( + result, + xCHMAMcFastBuffer[bar_index]); + + // + // MC Slow ... + result = MathMin( + result, + xCHMAMcSlowBuffer[bar_index]); + + // + // LC Fast ... + result = MathMin( + result, + xCHMALcFastBuffer[bar_index]); + + // + // LC Slow ... + result = MathMin( + result, + xCHMALcSlowBuffer[bar_index]); + + // + return result; +} + +// +// Short Cycle Over Max Of Cycle Channels ... +bool XCHMAIsSCOverMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 > nonOfShortCycleMax1 + // + ; + + // + return result; +} + +// +// Short Cycle Under Max Of Cycle Channels ... +bool XCHMAIsSCUnderMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 < nonOfShortCycleMax1 + // + ; + + // + return result; +} + +// +// Short Cycle Over Min Of Cycle Channels ... +bool XCHMAIsSCOverMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 > nonOfShortCycleMin1 + // + ; + + // + return result; +} + +// +// Short Cycle Under Min Of Cycle Channels ... +bool XCHMAIsSCUnderMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 < nonOfShortCycleMin1 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Over Max Of Cycle Channels ... +bool XCHMAIsSCCrossedOverMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMin2 = XCHMAGetCycleMinValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + double nonOfShortCycleMax2 = XCHMAGetCyclesMaxValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 > nonOfShortCycleMax1 && + shortCycleMin2 <= nonOfShortCycleMax2 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Under Max Of Cycle Channels ... +bool XCHMAIsSCCrossedUnderMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMax2 = XCHMAGetCycleMaxValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMax1 = XCHMAGetCyclesMaxValue( + bar_index, + cycles); + double nonOfShortCycleMax2 = XCHMAGetCyclesMaxValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 < nonOfShortCycleMax1 && + shortCycleMax2 >= nonOfShortCycleMax2 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Over Min Of Cycle Channels ... +bool XCHMAIsSCCrossedOverMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMin1 = XCHMAGetCycleMinValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMin2 = XCHMAGetCycleMinValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + double nonOfShortCycleMin2 = XCHMAGetCyclesMinValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMin1 > nonOfShortCycleMin1 && + shortCycleMin2 <= nonOfShortCycleMin2 + // + ; + + // + return result; +} + +// +// Short Cycle Crossed Under Min Of Cycle Channels ... +bool XCHMAIsSCCrossedUnderMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XCHMAIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double shortCycleMax1 = XCHMAGetCycleMaxValue( + bar_index, + X_XCHMA_CYCLE_SHORT); + double shortCycleMax2 = XCHMAGetCycleMaxValue( + bar_index + 1, + X_XCHMA_CYCLE_SHORT); + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double nonOfShortCycleMin1 = XCHMAGetCyclesMinValue( + bar_index, + cycles); + double nonOfShortCycleMin2 = XCHMAGetCyclesMinValue( + bar_index + 1, + cycles); + + // + // Calculate Result ... + result = + // + shortCycleMax1 < nonOfShortCycleMin1 && + shortCycleMax2 >= nonOfShortCycleMin2 + // + ; + + // + return result; +} + +// +// Long Cycle ... +// + +// +// Check LC is Peak ... +bool XCHMAIsLCPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xCHMALcSlowBuffer + // + ); + + // + return result; +} + +// +// Check LC is Vale ... +bool XCHMAIsLCVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xCHMALcSlowBuffer + // + ); + + // + return result; +} + +// +// Check LC Fast Crossed Over Slow ... +bool XCHMAIsLCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Over Slow ... +bool XCHMAIsLCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Crossed Under Slow ... +bool XCHMAIsLCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check LC Fast Under Slow ... +bool XCHMAIsLCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMALcFastBuffer, + xCHMALcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Get Trend Power ... +double XCHMAGetLCTrendPower( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + MathAbs(xCHMALcFastBuffer[bar_index] - xCHMALcSlowBuffer[bar_index]) + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsLCTrendsUp( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetLCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetLCTrendPower(i + 1); + double iTrend = XCHMAGetLCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsUpCount > trendsDownCount + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsLCTrendsDown( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetLCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetLCTrendPower(i + 1); + double iTrend = XCHMAGetLCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsDownCount > trendsUpCount + // + ; + + // + return result; +} + +// +// Medium Cycle ... +// + +// +// Check MC is Peak ... +bool XCHMAIsMCPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xCHMAMcSlowBuffer + // + ); + + // + return result; +} + +// +// Check MC is Vale ... +bool XCHMAIsMCVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xCHMAMcSlowBuffer + // + ); + + // + return result; +} + +// +// Check MC Fast Crossed Over Slow ... +bool XCHMAIsMCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Over Slow ... +bool XCHMAIsMCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Crossed Under Slow ... +bool XCHMAIsMCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check MC Fast Under Slow ... +bool XCHMAIsMCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMAMcFastBuffer, + xCHMAMcSlowBuffer, + bar_index); + + // + return result; +} + +// +// Get Trend Power ... +double XCHMAGetMCTrendPower( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + MathAbs(xCHMAMcFastBuffer[bar_index] - xCHMAMcSlowBuffer[bar_index]) + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsMCTrendsUp( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetMCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetMCTrendPower(i + 1); + double iTrend = XCHMAGetMCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsUpCount > trendsDownCount + // + ; + + // + return result; +} + +// +// Check XTM TrendsDown or Up ... +bool XCHMAIsMCTrendsDown( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetMCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetMCTrendPower(i + 1); + double iTrend = XCHMAGetMCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsDownCount > trendsUpCount + // + ; + + // + return result; +} + +// +// Short Cycle ... +// + +// +// Check SC is Peak ... +bool XCHMAIsSCPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xCHMAScSlowBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XCHMAIsSCVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xCHMAScSlowBuffer + // + ); + + // + return result; +} + +// +// Check SC Fast Crossed Over Slow ... +bool XCHMAIsSCFastCrossedOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Over Slow ... +bool XCHMAIsSCFastOverSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Crossed Under Slow ... +bool XCHMAIsSCFastCrossedUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Check SC Fast Under Slow ... +bool XCHMAIsSCFastUnderSlow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xCHMAScFastBuffer, + xCHMAScSlowBuffer, + bar_index); + + // + return result; +} + +// +// Get SC Trend Power ... +double XCHMAGetSCTrendPower( + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + MathAbs(xCHMAScFastBuffer[bar_index] - xCHMAScSlowBuffer[bar_index]) + // + ; + + // + return result; +} + +// +// Check SC Trends Up ... +bool XCHMAIsSCTrendsUp( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetSCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetSCTrendPower(i + 1); + double iTrend = XCHMAGetSCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsUpCount > trendsDownCount + // + ; + + // + return result; +} + +// +// Check SC Trends Down ... +bool XCHMAIsSCTrendsDown( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + length + 2)) + { + return result; + } + + // + double trend1 = XCHMAGetSCTrendPower(bar_index); + + // + int trendsUpCount = 0; + int trendsDownCount = 0; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iPrevTrend = XCHMAGetSCTrendPower(i + 1); + double iTrend = XCHMAGetSCTrendPower(i); + + // + if ( + trend1 > iTrend && + iTrend >= iPrevTrend && + trend1 >= iPrevTrend) + { + trendsUpCount++; + } + else if ( + trend1 < iTrend && + iTrend <= iPrevTrend && + trend1 <= iPrevTrend) + { + trendsDownCount++; + } + } + + // + result = + // + trendsDownCount > trendsUpCount + // + ; + + // + return result; +} + +// +// Utility Functions ... +// + +// +// Check a Cycle is Over of Another ... +bool XCHMAIsCycleOverAnother( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES sourceCycle, // Specified Cycle ... + ENUM_XCHMA_CYCLES destCycle // Specified Cycle ... +) +{ + // + bool result = false; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceMinValue = XCHMAGetCycleMinValue(bar_index, sourceCycle); + double destMaxValue = XCHMAGetCycleMaxValue(bar_index, destCycle); + + // + result = + // + sourceMinValue > destMaxValue + // + ; + + // + return result; +} + +// +// Check a Cycle is Under of Another ... +bool XCHMAIsCycleUnderAnother( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES sourceCycle, // Specified Cycle ... + ENUM_XCHMA_CYCLES destCycle // Specified Cycle ... +) +{ + // + bool result = false; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceMaxValue = XCHMAGetCycleMaxValue(bar_index, sourceCycle); + double destMinValue = XCHMAGetCycleMinValue(bar_index, destCycle); + + // + result = + // + sourceMaxValue < destMinValue + // + ; + + // + return result; +} + +// +// Get Cycle Min Value ... +double XCHMAGetCycleMinValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + result = MathMin( + xCHMALcFastBuffer[bar_index], + xCHMALcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + result = MathMin( + xCHMAMcFastBuffer[bar_index], + xCHMAMcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_SHORT: + result = MathMin( + xCHMAScFastBuffer[bar_index], + xCHMAScSlowBuffer[bar_index]); + break; + } + + // + return result; +} + +// +// Get Cycles Min Value ... +double XCHMAGetCyclesMinValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES &cycle[] // Specified Cycles ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + // + bar_index <= 0 || + ArraySize(cycle) <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1) + // + ) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycle); i++) + { + // + ENUM_XCHMA_CYCLES iCycle = cycle[i]; + double iValue = XCHMAGetCycleMinValue( + bar_index, + iCycle); + + // + result = result == 0 || result > iValue ? iValue : result; + } + + // + return result; +} + +// +// Get Cycle Max Value ... +double XCHMAGetCycleMaxValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES cycle // Specified Cycle ... +) +{ + // + double result = 0; + + // + // Validate BufferSize ... + if ( + bar_index <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + switch (cycle) + { + // + case X_XCHMA_CYCLE_LONG: + result = MathMax( + xCHMALcFastBuffer[bar_index], + xCHMALcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_MEDIUM: + result = MathMax( + xCHMAMcFastBuffer[bar_index], + xCHMAMcSlowBuffer[bar_index]); + break; + + // + case X_XCHMA_CYCLE_SHORT: + result = MathMax( + xCHMAScFastBuffer[bar_index], + xCHMAScSlowBuffer[bar_index]); + break; + } + + // + return result; +} + +// +// Get Cycles Max Value ... +double XCHMAGetCyclesMaxValue( + int bar_index, // Specified Index ... + ENUM_XCHMA_CYCLES &cycle[] // Specified Cycles ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + // + bar_index <= 0 || + ArraySize(cycle) <= 0 || + !XCHMAIsValidBuffersSize(bar_index + 1) + // + ) + { + return result; + } + + // + // Loop Through Cycles ... + for (int i = 0; i < ArraySize(cycle); i++) + { + // + ENUM_XCHMA_CYCLES iCycle = cycle[i]; + double iValue = XCHMAGetCycleMaxValue( + bar_index, + iCycle); + + // + result = result == 0 || result < iValue ? iValue : result; + } + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XCHMAIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xCHMALcFastBuffer) < size || + ArraySize(xCHMALcSlowBuffer) < size || + // + ArraySize(xCHMAMcFastBuffer) < size || + ArraySize(xCHMAMcSlowBuffer) < size || + // + ArraySize(xCHMAScFastBuffer) < size || + ArraySize(xCHMAScSlowBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Add Specified Object to it's correspond Buffer ... +void Add( + ENUM_XCHMA_CYCLES item, + ENUM_XCHMA_CYCLES &buffer[]) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// END XCHMA Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..19d3417 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 @@ -0,0 +1,358 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XFI Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XFI Oscillator"; + +// // +// input int xFILength = 18; // Market Length +// input ENUM_MA_METHOD xFIMethod = MODE_SMA; // MA Method +// input ENUM_APPLIED_VOLUME xFIAppliedTo = VOLUME_TICK; // Applied To + +// +// Configurations ... +int xFILength = 18; // Market Length +ENUM_MA_METHOD xFIMethod = MODE_SMA; // MA Method +ENUM_APPLIED_VOLUME xFIAppliedTo = VOLUME_TICK; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xFIHandler = INVALID_HANDLE; +double xFIBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XFIValidateInputs() +{ + // + bool result = false; + + // + result = xFILength > 2; + + // + if (!result) + { + // + LogMessage("XFI Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XFIInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XFI Handler ... + ArraySetAsSeries(xFIBuffer, true); + xFIHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xfi.oscillator", + // + // Inputs ... + xFILength, + xFIMethod, + xFIAppliedTo + // + ); + if (xFIHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XFI Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XFIReleaseHandlers() +{ + IndicatorRelease(xFIHandler); +} + +// +// Handle Reading Buffers ... +void XFIReadBuffers( + int xFIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XFI Signal ... + CopyBuffer( + xFIHandler, + 0, + 0, + xFIItemsPerTick, + xFIBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XFI Custom Functions ... +// + +// +// Check SC is Peak ... +bool XFIIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XFIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xFIBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XFIIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XFIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xFIBuffer + // + ); + + // + return result; +} + +// +// Detect XFI Crossed Over Zero ... +bool XFIIsCrossedOverZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] > 0 && + xFIBuffer[bar_index + 1] <= 0; + + // + return result; +} + +// +// Detect XFI Over Zero ... +bool XFIIsOverZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] > 0; + + // + return result; +} + +// +// Detect XFI Crossed Under Zero ... +bool XFIIsCrossedUnderZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] < 0 && + xFIBuffer[bar_index + 1] >= 0; + + // + return result; +} + +// +// Detect XFI Under Zero ... +bool XFIIsUnderZero( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XFIIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + xFIBuffer[bar_index] < 0; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XFIIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xFIBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XFI Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 0000000..e6a92f6 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 @@ -0,0 +1,668 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XLH 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XLH Indicator Buffer Lines ... +enum ENUM_X_XLH_BUFFER_LINES +{ + X_XLH_HH_LINE = 0, + X_XLH_LL_LINE = 1, + X_XLH_SIGNAL_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XLH Indicator"; + +// input int xLHLength = 72; // Length +// input ENUM_SERIESMODE xLHHHMode = MODE_HIGH; // Highest High Calculation Method +// input ENUM_SERIESMODE xLHLLMode = MODE_LOW; // Lowest Low Calculation Method + +// +// Configurations ... +int xLHLength = 72; // Length +ENUM_SERIESMODE xLHHHMode = MODE_HIGH; // Highest High Calculation Method +ENUM_SERIESMODE xLHLLMode = MODE_LOW; // Lowest Low Calculation Method + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +// +int xLHHandler = INVALID_HANDLE; + +// +double xLHHHBuffer[]; +double xLHLLBuffer[]; +double xLHSignalBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XLHValidateInputs() +{ + // + bool result = false; + + // + result = xLHLength >= 2; + + // + if (!result) + { + // + LogMessage("XLH Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XLHInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XLH Handler ... + ArraySetAsSeries(xLHHHBuffer, true); + ArraySetAsSeries(xLHLLBuffer, true); + ArraySetAsSeries(xLHSignalBuffer, true); + + // + xLHHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xlh.indicator", + // + // Inputs ... + xLHLength, + xLHHHMode, + xLHLLMode + // + ); + if (xLHHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XLH Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XLHReleaseHandlers() +{ + IndicatorRelease(xLHHandler); +} + +// +// Handle Reading Buffers ... +void XLHReadBuffers( + int xLHItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // HH Buffer ... + CopyBuffer( + xLHHandler, + X_XLH_HH_LINE, + 0, + xLHItemsPerTick, + xLHHHBuffer + // + ); + + // + // LL Buffer ... + CopyBuffer( + xLHHandler, + X_XLH_LL_LINE, + 0, + xLHItemsPerTick, + xLHLLBuffer + // + ); + + // + // Signal Buffer ... + CopyBuffer( + xLHHandler, + X_XLH_SIGNAL_LINE, + 0, + xLHItemsPerTick, + xLHSignalBuffer + // + ); +} + +// +// END Handler Funcions ... +// + +// +// START XLH Custom Functions ... +// + +// +// TODO: What we have to Implement ... +// - [] + +// +// Check Candle High is HH ... +bool XLHIsHighAttachedHH( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle = GetCandle(bar_index); + + // + result = + // + candle.high == xLHHHBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Candle Low is LL ... +bool XLHIsLowAttachedLL( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle = GetCandle(bar_index); + + // + result = + // + candle.low == xLHLLBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Price Jumping Up Signal ... +bool XLHIsPriceCrossedOverSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + XOHCL candle2 = GetCandle(bar_index + 1); + + // + result = + // + candle1.low > xLHSignalBuffer[bar_index] && + candle2.low < xLHSignalBuffer[bar_index + 1] + // + ; + + // + return result; +} + +// +// Check Price Over Signal ... +bool XLHIsPriceOverSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + + // + result = + // + candle1.low > xLHSignalBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Price Jumping Down Signal ... +bool XLHIsPriceCrossedUnderSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + XOHCL candle2 = GetCandle(bar_index + 1); + + // + result = + // + candle1.high < xLHSignalBuffer[bar_index] && + candle2.high > xLHSignalBuffer[bar_index + 1] + // + ; + + // + return result; +} + +// +// Check Price Down Signal ... +bool XLHIsPriceUnderSignal( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + + // + result = + // + candle1.high < xLHSignalBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check Price Ranging Signal ... +bool XLHIsPriceInSignalRange( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + XOHCL candle1 = GetCandle(bar_index); + + // + result = + // + candle1.high > xLHSignalBuffer[bar_index] && + candle1.low < xLHSignalBuffer[bar_index] + // + ; + + // + return result; +} + +// +// Check HH Increased ... +bool XLHIsHHIncreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xLHHHBuffer + // + ); + + // + return result; +} + +// +// Check HH Decreased ... +bool XLHIsHHDecreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xLHHHBuffer + // + ); + + // + return result; +} + +// +// Check LL Increased ... +bool XLHIsLLIncreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsIncreasing( + bar_index + length, + bar_index, + xLHLLBuffer + // + ); + + // + return result; +} + +// +// Check LL Decreased ... +bool XLHIsLLDecreased( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xLHLLBuffer + // + ); + + // + return result; +} + +// +// Check HH Same in Length ... +bool XLHIsHHSameInLength( + int bar_index, // Specified Index ... + int length = 5 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + double value1 = xLHHHBuffer[bar_index]; + + // + // Loop ... + result = true; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iValue = xLHHHBuffer[i]; + if (iValue != value1) + { + // + result = false; + + // + break; + } + } + + // + return result; +} + +// +// Check LL Same in Length ... +bool XLHIsLLSameInLength( + int bar_index, // Specified Index ... + int length = 5 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XLHIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + double value1 = xLHLLBuffer[bar_index]; + + // + // Loop ... + result = true; + for (int i = bar_index + 1; i < bar_index + length + 1; i++) + { + // + double iValue = xLHLLBuffer[i]; + if (iValue != value1) + { + // + result = false; + + // + break; + } + } + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XLHIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xLHHHBuffer) < size || + ArraySize(xLHLLBuffer) < size || + ArraySize(xLHSignalBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XLH Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 0000000..f90f15b --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 @@ -0,0 +1,249 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XOBD 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XOBD Indicator"; + +// input int xOBDLength = 5; // Swing Length +// input uchar xOBDSwingHighArrowCode = 108; // Swing High Arrow Code +// input color xOBDSwingHighArrowColor = clrMagenta; // Swing High Arrow Color +// input uchar xOBDSwingLowArrowCode = 108; // Swing Low Arrow Code +// input color xOBDSwingLowArrowColor = clrAqua; // Swing Low Arrow Color + +// +// Configurations ... +int xOBDLength = 5; // Swing Length +uchar xOBDSwingHighArrowCode = 108; // Swing High Arrow Code +color xOBDSwingHighArrowColor = clrMagenta; // Swing High Arrow Color +uchar xOBDSwingLowArrowCode = 108; // Swing Low Arrow Code +color xOBDSwingLowArrowColor = clrAqua; // Swing Low Arrow Color + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +// +int xOBDHandler = INVALID_HANDLE; + +// +double xOBDBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XOBDValidateInputs() +{ + // + bool result = false; + + // + result = xOBDLength >= 2; + + // + if (!result) + { + // + LogMessage("XOBD Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XOBDInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XOBD Handler ... + ArraySetAsSeries(xOBDBuffer, true); + + // + xOBDHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xobd.indicator", + // + // Inputs ... + xOBDLength, + xOBDSwingHighArrowCode, + xOBDSwingHighArrowColor, + xOBDSwingLowArrowCode, + xOBDSwingLowArrowColor + // + ); + if (xOBDHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XOBD Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XOBDReleaseHandlers() +{ + IndicatorRelease(xOBDHandler); +} + +// +// Handle Reading Buffers ... +void XOBDReadBuffers( + int xOBDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // OBD Buffer ... + CopyBuffer( + xOBDHandler, + 0, + 0, + xOBDItemsPerTick, + xOBDBuffer + // + ); +} + +// +// END Handler Funcions ... +// + +// +// START XOBD Custom Functions ... +// + +// +// Check is Swing Low Occured or not ... +bool XOBDIsSwingLow( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = xOBDBuffer[bar_index] == X_SWING_LOW; + + // + return result; +} + +// +// Check is Swing High Occured or not ... +bool XOBDIsSwingHigh( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XOBDIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = xOBDBuffer[bar_index] == X_SWING_HIGH; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XOBDIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xOBDBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XOBD Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..e6971b7 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 @@ -0,0 +1,433 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XRSI Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XRSI Oscillator Buffer Lines ... +// + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XRSI Oscillator"; + +// // +// input group "XRSI Market"; +// input int xRSILength = 18; // Market Length +// input ENUM_APPLIED_PRICE xRSIAppliedTo = PRICE_OPEN; // Applied To + +// // +// input group "XRSI Short Entry"; +// input double xRSIShortEntryValue = 70; // Short Entry Level +// input color xRSIShortEntryColor = clrRed; // Short Entry Level Color +// input ENUM_LINE_STYLE xRSIShortEntryLineStyle = STYLE_SOLID; // Short Entry Style + +// // +// input group "XRSI Short Exit"; +// input double xRSIShortExitValue = 40; // Short Exit Level +// input color xRSIShortExitColor = clrRed; // Short Exit Level Color +// input ENUM_LINE_STYLE xRSIShortExitLineStyle = STYLE_DOT; // Short Exit Style + +// // +// input group "XRSI Long Entry"; +// input double xRSILongEntryValue = 30; // Long Entry Level +// input color xRSILongEntryColor = clrRed; // Long Entry Level Color +// input ENUM_LINE_STYLE xRSILongEntryLineStyle = STYLE_SOLID; // Long Entry Style + +// // +// input group "XRSI Long Exit"; +// input double xRSILongExitValue = 60; // Long Exit Level +// input color xRSILongExitColor = clrRed; // Long Exit Level Color +// input ENUM_LINE_STYLE xRSILongExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// Configurations ... +int xRSILength = 18; // Market Length +ENUM_APPLIED_PRICE xRSIAppliedTo = PRICE_OPEN; // Applied To + +// +double xRSIShortEntryValue = 70; // Short Entry Level +color xRSIShortEntryColor = clrRed; // Short Entry Level Color +ENUM_LINE_STYLE xRSIShortEntryLineStyle = STYLE_SOLID; // Short Entry Style + +// +double xRSIShortExitValue = 40; // Short Exit Level +color xRSIShortExitColor = clrRed; // Short Exit Level Color +ENUM_LINE_STYLE xRSIShortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +double xRSILongEntryValue = 30; // Long Entry Level +color xRSILongEntryColor = clrRed; // Long Entry Level Color +ENUM_LINE_STYLE xRSILongEntryLineStyle = STYLE_SOLID; // Long Entry Style + +// +double xRSILongExitValue = 60; // Long Exit Level +color xRSILongExitColor = clrRed; // Long Exit Level Color +ENUM_LINE_STYLE xRSILongExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xRSIHandler = INVALID_HANDLE; +double xRSIBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XRSIValidateInputs() +{ + // + bool result = false; + + // + result = + xRSILongEntryValue < xRSILongExitValue && + xRSIShortEntryValue > xRSIShortExitValue && + xRSIShortEntryValue > xRSILongExitValue && + xRSIShortExitValue < xRSILongExitValue; + + // + if (!result) + { + // + LogMessage("XRSI Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XRSIInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XRSI Handler ... + ArraySetAsSeries(xRSIBuffer, true); + xRSIHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xrsi.oscillator", + // + // Inputs ... + // + // Market ... + "", + xRSILength, + xRSIAppliedTo, + // + // Short Entry ... + "", + xRSIShortEntryValue, + xRSIShortEntryColor, + xRSIShortEntryLineStyle, + // + // Short Exit ... + "", + xRSIShortExitValue, + xRSIShortExitColor, + xRSIShortExitLineStyle, + // + // Long Entry ... + "", + xRSILongEntryValue, + xRSILongEntryColor, + xRSILongEntryLineStyle, + // + // Long Exit ... + "", + xRSILongExitValue, + xRSILongExitColor, + xRSILongExitLineStyle + // + ); + if (xRSIHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XRSI Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XRSIReleaseHandlers() +{ + IndicatorRelease(xRSIHandler); +} + +// +// Handle Reading Buffers ... +void XRSIReadBuffers( + int xRSIItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XRSI Signal ... + CopyBuffer( + xRSIHandler, + 0, + 0, + xRSIItemsPerTick, + xRSIBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XRSI Custom Functions ... +// + +// +// Check SC is Peak ... +bool XRSIIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xRSIBuffer + // + ); + + // + return result; +} + +// +// Check SC is Vale ... +bool XRSIIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xRSIBuffer + // + ); + + // + return result; +} + +// +// RSI Value GO Up from Long Entry ... +bool XRSIIsCrossedOverLongEntry( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] > xRSILongEntryValue && + xRSIBuffer[bar_index + 2] <= xRSILongEntryValue; + + // + return result; +} + +// +// RSI Value GO Up from Long Exit ... +bool XRSIIsCrossedOverLongExit( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] > xRSILongExitValue && + xRSIBuffer[bar_index + 2] <= xRSILongExitValue; + + // + return result; +} + +// +// RSI Value Go Down Short Entry ... +bool XRSIIsCrossedUnderShortEntry( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] < xRSIShortEntryValue && + xRSIBuffer[bar_index + 2] >= xRSIShortEntryValue; + + // + return result; +} + +// +// RSI Value Go Down Short Exit ... +bool XRSIIsCrossedUnderShortExit( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XRSIIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + xRSIBuffer[bar_index + 1] < xRSIShortExitValue && + xRSIBuffer[bar_index + 2] >= xRSIShortExitValue; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XRSIIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xRSIBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XRSI Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..6286228 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 @@ -0,0 +1,931 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTD Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; + +// +// XTD Oscillator Buffer Lines ... +enum ENUM_X_XTD_BUFFER_LINES +{ + X_XTD_BULLISH_POWER_LINE = 0, + X_XTD_BEARISH_POWER_LINE = 1, + X_XTD_SIGNAL_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XTD Oscillator"; + +// input int xTDLength = 18; // Market Length +// input bool xTDDrawCrosses = false; // Draw Cross Arrows +// input uchar xTDBullishArrowCode = 228; // Cross Over Arrow Code +// input color xTDBullishArrowColor = clrAqua; // Cross Over Arrow Color +// input uchar xTDBearishArrowCode = 230; // Cross Under Arrow Code +// input color xTDBearishArrowColor = clrMagenta; // Cross Under Arrow Color + +// +// Configurations ... +int xTDLength = 18; // Market Length +bool xTDDrawCrosses = false; // Draw Cross Arrows +uchar xTDBullishArrowCode = 228; // Cross Over Arrow Code +color xTDBullishArrowColor = clrAqua; // Cross Over Arrow Color +uchar xTDBearishArrowCode = 230; // Cross Under Arrow Code +color xTDBearishArrowColor = clrMagenta; // Cross Under Arrow Color + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTDHandler = INVALID_HANDLE; +double xTDBullishBuffer[]; +double xTDBearishBuffer[]; +double xTDSignalBuffer[]; +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XTDValidateInputs() +{ + // + bool result = false; + + // + result = xTDLength >= 2; + + // + if (!result) + { + // + LogMessage("XTD Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XTDInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTD Handler ... + ArraySetAsSeries(xTDBullishBuffer, true); + ArraySetAsSeries(xTDBearishBuffer, true); + ArraySetAsSeries(xTDSignalBuffer, true); + xTDHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xtd.oscillator", + // + // Inputs ... + xTDLength, + xTDDrawCrosses, + xTDBullishArrowCode, + xTDBullishArrowColor, + xTDBearishArrowCode, + xTDBearishArrowColor); + if (xTDHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTD Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XTDReleaseHandlers() +{ + IndicatorRelease(xTDHandler); +} + +// +// Handle Reading Buffers ... +void XTDReadBuffers( + int xTDItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XTD Bullish Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_BULLISH_POWER_LINE, + 0, + xTDItemsPerTick, + xTDBullishBuffer); + + // + // XTD Bullish Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_BEARISH_POWER_LINE, + 0, + xTDItemsPerTick, + xTDBearishBuffer); + + // + // XTD Signal Buffer ... + CopyBuffer( + xTDHandler, + X_XTD_SIGNAL_LINE, + 0, + xTDItemsPerTick, + xTDSignalBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XTD Custom Functions ... +// + +// +// Check Signal Vale ... +bool XTDIsSignalVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTDSignalBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsSignalPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTDSignalBuffer + // + ); + + // + return result; +} + +// +// Check Signal Vale ... +bool XTDIsBullishVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTDBullishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsBullishPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTDBullishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Vale ... +bool XTDIsBearishVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTDBearishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... +bool XTDIsBearishPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTDBearishBuffer + // + ); + + // + return result; +} + +// +// Check Signal Peak ... + +// +// Check Bullish Crossed Over Bearish ... +bool XTDIsBullCrossedOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Over Bearish ... +bool XTDIsBullOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Crossed Under Bearish ... +bool XTDIsBullCrossedUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Bullish Under Bearish ... +bool XTDIsBullUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xTDBullishBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Crossed Over Bearish ... +bool XTDIsSignalCrossedOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossOver( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Over Bearish ... +bool XTDIsSignalOverBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsOver( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Crossed Under Bearish ... +bool XTDIsSignalCrossedUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsCrossUnder( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check Signal Under Bearish ... +bool XTDIsSignalUnderBear( + int bar_index // Specified Bar Index +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTDIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = IsUnder( + xTDSignalBuffer, + xTDBearishBuffer, + 1); + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTDIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + ArraySize(xTDBullishBuffer) < size || + ArraySize(xTDBullishBuffer) < size || + ArraySize(xTDSignalBuffer) < size) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// Count Signal Crossed Over Bear ... +int XTDCountSignalCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedOverBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Signal Crossed Under Bear ... +int XTDCountSignalCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedUnderBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Bull Crossed Over Bear ... +int XTDCountBullCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedOverBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Count Bull Crossed Under Bear ... +int XTDCountBullCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = 0; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedUnderBear(i); + if (isCrossedOnI) + { + result++; + } + } + + // + return result; +} + +// +// Find Last Signal Crossed Over Bear ... +int XTDFindLastSignalCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedOverBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Signal Crossed Onder Bear ... +int XTDFindLastSignalCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsSignalCrossedUnderBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Bull Crossed Over Bear ... +int XTDFindLastBullCrossedOverBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedOverBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Find Last Bull Crossed Under Bear ... +int XTDFindLastBullCrossedUnderBearIndex( + int bar_index // Specified Bar Index +) +{ + // + int result = -1; + + // + int count = ArraySize(xTDSignalBuffer) - 1; + if ( + bar_index <= 0 || + count <= bar_index + 1) + { + return result; + } + + // + // Loop Through ... + for (int i = bar_index + 1; i < count && result == -1; i++) + { + // + // Check Cross On i Point ... + bool isCrossedOnI = XTDIsBullCrossedUnderBear(i); + if (isCrossedOnI) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// END XTD Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 0000000..a871ed4 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 @@ -0,0 +1,598 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTM 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 1, + X_XTM_BEARISH = -1, + X_XTM_NEUTURAL = 0, +}; + +// +// XTM Indicator Buffer Lines ... +enum ENUM_X_XTM_BUFFER_LINES +{ + X_XTM_MA_LINE = 0, + X_XTM_MC_COLOR_LINE = 1, + X_XTM_STATE_LINE = 2, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// input group "XTM Indicator"; + +// input int xTMMaPeriod = 18; // Period +// input int xTMMaShift = 0; // Shift +// input ENUM_MA_METHOD xTMMaMethod = MODE_EMA; // Method +// input ENUM_APPLIED_PRICE xTMMaAppliedTo = PRICE_OPEN; // Applied To + +// +// Configurations ... +int xTMMaPeriod = 18; // Period +int xTMMaShift = 0; // Shift +ENUM_MA_METHOD xTMMaMethod = MODE_EMA; // Method +ENUM_APPLIED_PRICE xTMMaAppliedTo = PRICE_OPEN; // Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTMHandler = INVALID_HANDLE; +double xTMMaBuffer[]; +double xTMStateBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XTMValidateInputs() +{ + // + bool result = false; + + // + result = xTMMaPeriod >= 2; + + // + if (!result) + { + // + LogMessage("XTM Indicator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Indicators ... +bool XTMInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTM Handler ... + ArraySetAsSeries(xTMMaBuffer, true); + ArraySetAsSeries(xTMStateBuffer, true); + xTMHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xtm.indicator", + // + // Inputs ... + xTMMaPeriod, + xTMMaShift, + xTMMaMethod, + xTMMaAppliedTo); + if (xTMHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTM Indicator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XTMReleaseHandlers() +{ + IndicatorRelease(xTMHandler); +} + +// +// Handle Reading Buffers ... +void XTMReadBuffers( + int xTMItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // Ma Buffer ... + CopyBuffer( + xTMHandler, + X_XTM_MA_LINE, + 0, + xTMItemsPerTick, + xTMMaBuffer); + + // + // State Buffer ... + CopyBuffer( + xTMHandler, + X_XTM_STATE_LINE, + 0, + xTMItemsPerTick, + xTMStateBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XTM Custom Functions ... +// + +// +// Find Peak based On this Indicator ... +bool XTMIsPeak( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + // Must Decreasing ... + bool isIncreasing = IsIncreasing( + bar_index + length, + bar_index, + xTMMaBuffer + // + ); + + // + return result; +} + +// +// Find Vale based On this Indicator ... +bool XTMIsVale( + int bar_index, // Specified Index ... + int length = 10 // Specified Length ... +) +{ + // + bool result = false; + + // + if ( + length <= 0 || + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + length + 1)) + { + return result; + } + + // + result = IsDecreasing( + bar_index + length, + bar_index, + xTMMaBuffer + // + ); + + // + return result; +} + +// +// Check TM Crossed Up ... +bool XTMIsStartBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BULLISH && + xTMStateBuffer[bar_index + 1] != X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Up After Neutural State ... +bool XTMIsStartBullishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BULLISH && + xTMStateBuffer[bar_index + 1] == X_XTM_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Up State ... +bool XTMIsBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State ... +bool XTMIsEndBullish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] != X_XTM_BULLISH && + xTMStateBuffer[bar_index + 1] == X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Ends Up State By Neutural ... +bool XTMIsEndBullishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_NEUTURAL && + xTMStateBuffer[bar_index + 1] == X_XTM_BULLISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down ... +bool XTMIsStartBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BEARISH && + xTMStateBuffer[bar_index + 1] != X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Crossed Down After Neutural State ... +bool XTMIsStartBearishAfterNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BEARISH && + xTMStateBuffer[bar_index + 1] == X_XTM_NEUTURAL + // + ; + + // + return result; +} + +// +// Check TM In Down State ... +bool XTMIsBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State ... +bool XTMIsEndBearish( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] != X_XTM_BEARISH && + xTMStateBuffer[bar_index + 1] == X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM Ends Down State By Neutural ... +bool XTMIsEndBearishByNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_NEUTURAL && + xTMStateBuffer[bar_index + 1] == X_XTM_BEARISH + // + ; + + // + return result; +} + +// +// Check TM In Neutural State ... +bool XTMIsNeutural( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + if ( + bar_index <= 0 || + !XTMIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + // + xTMStateBuffer[bar_index] == X_XTM_NEUTURAL + // + ; + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTMIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xTMMaBuffer) < size || + ArraySize(xTMStateBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +// END XTM Custom Functions ... +// diff --git a/XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 0000000..875eec0 --- /dev/null +++ b/XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 @@ -0,0 +1,1179 @@ +///////////////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTS Oscillator 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 + +// +// Includes ... +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Enum Definitions ... +// + +// +// Methods to Calculate TimeFrames ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// Buffer Lines ... +enum ENUM_X_XTS_BUFFER_LINES +{ + X_XTS_CURRENT_LINE = 0, + X_XTS_NEAREST_LINE = 1, + X_XTS_MEDIEST_LINE = 2, + X_XTS_FAREST_LINE = 3, +}; + +// +// Periods ... +enum ENUM_X_XTS_PERIODS +{ + // + // Current Period ... + X_XTS_PERIOD_CURRENT, + // + // Nearest Period ... + X_XTS_PERIOD_NEAREST, + // + // Mediest Period ... + X_XTS_PERIOD_MEDIEST, + // + // Farest Period ... + X_XTS_PERIOD_FAREST, +}; + +// +// END Enum Definitions ... +// + +// +// START Inputs ... +// + +// // +// input group "XTS Oscillator"; + +// // +// input group "XTS Current Period"; +// input ENUM_APPLIED_PRICE xTSCurrentAppliedTo = PRICE_CLOSE; // Current Applied To +// // +// input group "XTS Nearest Period"; +// input ENUM_X_PERIOD_METHOD xTSNearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +// input ENUM_TIMEFRAMES xTSNearestPeriod = NULL; // Nearest Time Frame +// input ENUM_APPLIED_PRICE xTSNearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// // +// input group "XTS Mediest Period"; +// input ENUM_X_PERIOD_METHOD xTSMediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +// input ENUM_TIMEFRAMES xTSMediestPeriod = NULL; // Mediest Time Frame +// input ENUM_APPLIED_PRICE xTSMediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// // +// input group "XTS Farest Period"; +// input ENUM_X_PERIOD_METHOD xTSFarestMethod = X_PERIOD_AUTO; // How to Find Farest Period +// input ENUM_TIMEFRAMES xTSFarestPeriod = NULL; // Farest Time Frame +// input ENUM_APPLIED_PRICE xTSFarestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// Configurations ... +ENUM_APPLIED_PRICE xTSCurrentAppliedTo = PRICE_CLOSE; // Current Applied To +// +ENUM_X_PERIOD_METHOD xTSNearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +ENUM_TIMEFRAMES xTSNearestPeriod = NULL; // Nearest Time Frame +ENUM_APPLIED_PRICE xTSNearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// +ENUM_X_PERIOD_METHOD xTSMediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +ENUM_TIMEFRAMES xTSMediestPeriod = NULL; // Mediest Time Frame +ENUM_APPLIED_PRICE xTSMediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// +ENUM_X_PERIOD_METHOD xTSFarestMethod = X_PERIOD_AUTO; // How to Find Farest Period +ENUM_TIMEFRAMES xTSFarestPeriod = NULL; // Farest Time Frame +ENUM_APPLIED_PRICE xTSFarestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// END Inputs ... +// + +// +// START Definitions ... +// + +int xTSHandler = INVALID_HANDLE; +double xTSCurrentBuffer[]; +double xTSNearestBuffer[]; +double xTSMediestBuffer[]; +double xTSFarestBuffer[]; + +// +// END Definitions ... +// + +// +// START Handler Functions ... +// + +// +// Validate Inputs ... +bool XTSValidateInputs() +{ + // + bool result = false; + + // + result = true; + + // + if (!result) + { + // + LogMessage("XTS Oscillator Inputs Validation Failed ..."); + } + + // + return result; +} + +// +// Init Oscillators ... +bool XTSInitHandlers() +{ + // + bool result = false; + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTS Handler ... + ArraySetAsSeries(xTSCurrentBuffer, true); + ArraySetAsSeries(xTSNearestBuffer, true); + ArraySetAsSeries(xTSMediestBuffer, true); + ArraySetAsSeries(xTSFarestBuffer, true); + xTSHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.xts.oscillator", + // + // Inputs ... + "", + xTSCurrentAppliedTo, + "", + xTSNearestMethod, + xTSNearestPeriod, + xTSNearestAppliedTo, + "", + xTSMediestMethod, + xTSMediestPeriod, + xTSMediestAppliedTo, + "", + xTSFarestMethod, + xTSFarestPeriod, + xTSFarestAppliedTo + // + ); + if (xTSHandler == INVALID_HANDLE) + { + // + LogMessage("failed to Initialize XTS Oscillator: " + (string)GetLastError()); + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Oscillators ... +void XTSReleaseHandlers() +{ + IndicatorRelease(xTSHandler); +} + +// +// Handle Reading Buffers ... +void XTSReadBuffers( + int xTSItemsPerTick // Number Of Reading Buffer Items Per Tick +) +{ + // + // XTS Current ... + CopyBuffer( + xTSHandler, + X_XTS_CURRENT_LINE, + 0, + xTSItemsPerTick, + xTSCurrentBuffer); + + // + // XTS Nearest ... + CopyBuffer( + xTSHandler, + X_XTS_NEAREST_LINE, + 0, + xTSItemsPerTick, + xTSNearestBuffer); + + // + // XTS Mediest ... + CopyBuffer( + xTSHandler, + X_XTS_MEDIEST_LINE, + 0, + xTSItemsPerTick, + xTSMediestBuffer); + + // + // XTS Farest ... + CopyBuffer( + xTSHandler, + X_XTS_FAREST_LINE, + 0, + xTSItemsPerTick, + xTSFarestBuffer); +} + +// +// END Handler Funcions ... +// + +// +// START XTS Custom Functions ... +// + +// +// Calculate Min Value ... +double XTSGetMinValue( + int bar_index // Specified Index ... +) +{ + // + ENUM_X_XTS_PERIODS periods[]; + XTSGetAllPeriodsEnum(periods); + + // + double result = XTSGetPeriodsMinValue( + periods, + bar_index); + + // + return result; +} + +// +// Calculate Max Value ... +double XTSGetMaxValue( + int bar_index // Specified Index ... +) +{ + // + ENUM_X_XTS_PERIODS periods[]; + XTSGetAllPeriodsEnum(periods); + + // + double result = XTSGetPeriodsMaxValue( + periods, + bar_index); + + // + return result; +} + +// +// Check if all Periods Values are Same ... +bool XTSIsAllSame( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + result = + xTSCurrentBuffer[bar_index] == xTSNearestBuffer[bar_index] && + xTSNearestBuffer[bar_index] == xTSMediestBuffer[bar_index] && + xTSMediestBuffer[bar_index] == xTSFarestBuffer[bar_index]; + + // + return result; +} + +// +// Current ... + +// +// Check Current Buffer is Min Or Not ... +bool XTSIsCurrentMin( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double minValue = XTSGetMinValue(bar_index); + + // + result = + xTSCurrentBuffer[bar_index] == minValue; + + // + return result; +} + +// +// Check Current Buffer is Max Or Not ... +bool XTSIsCurrentMax( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double maxValue = XTSGetMaxValue(bar_index); + + // + result = + xTSCurrentBuffer[bar_index] == maxValue; + + // + return result; +} + +// +// Current VS Nearest ... + +// +// Check Current Crossed Over Nearest ... +bool XTSIsCurrentCrossedOverNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Check Current Over Nearest ... +bool XTSIsCurrentOverNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Check Current Crossed Under Nearest ... +bool XTSIsCurrentCrossedUnderNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Check Current Under Nearest ... +bool XTSIsCurrentUnderNearest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_NEAREST, + bar_index); + + // + return result; +} + +// +// Current VS Mediest ... + +// +// Check Current Crossed Over Mediest ... +bool XTSIsCurrentCrossedOverMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Check Current Over Mediest ... +bool XTSIsCurrentOverMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Check Current Crossed Under Mediest ... +bool XTSIsCurrentCrossedUnderMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Check Current Under Mediest ... +bool XTSIsCurrentUnderMediest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_MEDIEST, + bar_index); + + // + return result; +} + +// +// Current VS Farest ... + +// +// Check Current Crossed Over Farest ... +bool XTSIsCurrentCrossedOverFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Check Current Over Farest ... +bool XTSIsCurrentOverFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodOverAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Check Current Crossed Under Farest ... +bool XTSIsCurrentCrossedUnderFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodCrossedUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Check Current Under Farest ... +bool XTSIsCurrentUnderFarest( + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + result = XTSIsPeriodUnderAnother( + X_XTS_PERIOD_CURRENT, + X_XTS_PERIOD_FAREST, + bar_index); + + // + return result; +} + +// +// Globally Custom Functions ... + +// +// Check a Period Crossed Over another one ... +bool XTSIsPeriodCrossedOverAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + double sourceValue1 = XTSGetPeriodValue( + source, + bar_index + 1); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + double destValue1 = XTSGetPeriodValue( + dest, + bar_index + 1); + + // + result = + sourceValue > destValue && + sourceValue1 <= destValue1; + + // + return result; +} + +// +// Check a Period Over another one ... +bool XTSIsPeriodOverAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + + // + result = + sourceValue > destValue; + + // + return result; +} + +// +// Check a Period Crossed Under another one ... +bool XTSIsPeriodCrossedUnderAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 2)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + double sourceValue1 = XTSGetPeriodValue( + source, + bar_index + 1); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + double destValue1 = XTSGetPeriodValue( + dest, + bar_index + 1); + + // + result = + sourceValue < destValue && + sourceValue1 >= destValue1; + + // + return result; +} + +// +// Check a Period Under another one ... +bool XTSIsPeriodUnderAnother( + ENUM_X_XTS_PERIODS source, // Specified Source Period which Check it's Crossed ... + ENUM_X_XTS_PERIODS dest, // Specified Dest Period Which used to Check Source Crosses ... + int bar_index // Specified Index ... +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + double sourceValue = XTSGetPeriodValue( + source, + bar_index); + + // + double destValue = XTSGetPeriodValue( + dest, + bar_index); + + // + result = + sourceValue < destValue; + + // + return result; +} + +// +// Retrieve Specific Period's Value from Buffer for Specific Bar Index ... +double XTSGetPeriodValue( + ENUM_X_XTS_PERIODS period, // Specified Period to read it's Value ... + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + // Validate Args ... + if ( + bar_index < 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + switch (period) + { + // + case X_XTS_PERIOD_CURRENT: + result = xTSCurrentBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_NEAREST: + result = xTSNearestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_MEDIEST: + result = xTSMediestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_FAREST: + result = xTSFarestBuffer[bar_index]; + break; + } + + // + return result; +} + +// +// Fill All Exists Periods ... +void XTSGetAllPeriodsEnum( + ENUM_X_XTS_PERIODS &result[] // Hold's Result ... +) +{ + // + CleanBuffer(result); + + // + Add( + X_XTS_PERIOD_CURRENT, + result); + + // + Add( + X_XTS_PERIOD_NEAREST, + result); + + // + Add( + X_XTS_PERIOD_MEDIEST, + result); + + // + Add( + X_XTS_PERIOD_FAREST, + result); +} + +// +// Fill All Exists Periods Except ... +void XTSGetAllPeriodsEnumExcept( + ENUM_X_XTS_PERIODS &result[], // Hold's Result ... + ENUM_X_XTS_PERIODS exception // Excepted Period ... +) +{ + // + CleanBuffer(result); + + // + ENUM_X_XTS_PERIODS allPeriods[]; + XTSGetAllPeriodsEnum(allPeriods); + int periodsCount = ArraySize(allPeriods); + if (periodsCount <= 0) + { + return; + } + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = allPeriods[i]; + + // + if (iPeriod != exception) + { + Add( + iPeriod, + result); + } + } +} + +// +// Fill All Exists Periods Except ... +void XTSGetAllPeriodsEnumExcept( + ENUM_X_XTS_PERIODS &result[], // Hold's Result ... + ENUM_X_XTS_PERIODS &exceptions[] // Excepted Periods ... +) +{ + // + CleanBuffer(result); + + // + ENUM_X_XTS_PERIODS allPeriods[]; + XTSGetAllPeriodsEnum(allPeriods); + int periodsCount = ArraySize(allPeriods); + if (periodsCount <= 0) + { + return; + } + + // + int exceptionsCount = ArraySize(exceptions); + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = allPeriods[i]; + + // + bool canAddIPeriod = false; + if (exceptionsCount <= 0) + { + canAddIPeriod = true; + } + else + { + // + // Loop through Exceptions ... + for (int j = 0; j < exceptionsCount; j++) + { + // + ENUM_X_XTS_PERIODS jException = exceptions[j]; + + // + if (iPeriod == jException) + { + // + canAddIPeriod = false; + break; + } + + // + canAddIPeriod = true; + } + } + + // + if (canAddIPeriod) + { + // + Add( + iPeriod, + result); + } + } +} + +// +// Calculate Periods Min Value ... +double XTSGetPeriodsMinValue( + ENUM_X_XTS_PERIODS &periods[], // Specified Periods ... + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + int periodsCount = ArraySize(periods); + + // + // Validate Args ... + if ( + bar_index < 0 || + periodsCount <= 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = periods[i]; + + // + double iValue = 0; + + // + switch (iPeriod) + { + // + case X_XTS_PERIOD_CURRENT: + iValue = xTSCurrentBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_NEAREST: + iValue = xTSNearestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_MEDIEST: + iValue = xTSMediestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_FAREST: + iValue = xTSFarestBuffer[bar_index]; + break; + } + + // + // Compare iValue to result ... + result = + result == 0 || + result > iValue + ? iValue + : result; + } + + // + return result; +} + +// +// Calculate Periods Max Value ... +double XTSGetPeriodsMaxValue( + ENUM_X_XTS_PERIODS &periods[], // Specified Periods ... + int bar_index // Specified Index ... +) +{ + // + double result = 0; + + // + int periodsCount = ArraySize(periods); + + // + // Validate Args ... + if ( + bar_index < 0 || + periodsCount <= 0 || + !XTSIsValidBuffersSize(bar_index + 1)) + { + return result; + } + + // + // Loop ... + for (int i = 0; i < periodsCount; i++) + { + // + ENUM_X_XTS_PERIODS iPeriod = periods[i]; + + // + double iValue = 0; + + // + switch (iPeriod) + { + // + case X_XTS_PERIOD_CURRENT: + iValue = xTSCurrentBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_NEAREST: + iValue = xTSNearestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_MEDIEST: + iValue = xTSMediestBuffer[bar_index]; + break; + + // + case X_XTS_PERIOD_FAREST: + iValue = xTSFarestBuffer[bar_index]; + break; + } + + // + // Compare iValue to result ... + result = + result == 0 || + result < iValue + ? iValue + : result; + } + + // + return result; +} + +// +// Check all Buffers has valid Size ... +bool XTSIsValidBuffersSize( + int size // the size of buffers which min size for requirements +) +{ + // + bool result = false; + + // + if ( + size <= 0 || + // + ArraySize(xTSCurrentBuffer) < size + // + ) + { + result = false; + } + else + { + result = true; + } + + // + return result; +} + +// +void Add( + ENUM_X_XTS_PERIODS item, // Specified Item ... + ENUM_X_XTS_PERIODS &buffer[] // Specified Buffer ... +) +{ + // + int bufferSize = ArraySize(buffer); + + // + ArrayResize( + buffer, + bufferSize + 1); + + // + buffer[bufferSize] = item; +} + +void CleanBuffer( + ENUM_X_XTS_PERIODS &buffer[] // Specified Buffer ... +) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +// END XTS Custom Functions ... +// diff --git a/XEU5/Indicators/.gitkeep b/XEU5/Indicators/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Indicators/x-saherelm.xama.indicator.mq5 b/XEU5/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 0000000..14d1ef7 --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xama.indicator.mq5 @@ -0,0 +1,353 @@ +/////////////////////////////////////////////////////// +// +// 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 int length = 18; // 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_CLOSE; // Applied To +// +// 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() +{ + // + string maBufferLabel = "XAMA " + "(" + (string)length + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // 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/XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 b/XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 0000000..5c74787 --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 @@ -0,0 +1,753 @@ +////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel LH Oscillator +// --------------------------------------------------- +// Name: XCHLH +// Description: detecting HH and LL based on cycles ... +// +// +// 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 XCHLH Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHLH" + +// +// XCHLH Hot States ... +enum ENUM_X_XCHLH_HOT_STATES +{ + X_XCHLH_HOT_HH = 1, + X_XCHLH_NEUTURAL = 0, + X_XCHLH_HOT_LL = -1, +}; + +// +// Including Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotHHArrowCode = 234; // Hot HH Arrow Code +input color hotHHArrowColor = clrAqua; // Hot HH Arrow Color +input uchar hotLLArrowCode = 233; // Hot LL Arrow Code +input color hotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcLength = 28; // Length +input double lcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE lcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE lcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcHHColor = clrAqua; // Highest High Color +input color lcLLColor = clrFuchsia; // Lowest Low Color +input group "LC Drawings"; +input bool lcDrawHH = true; // Draw Highest High +input bool lcDrawLL = true; // Draw Lowest Low + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcLength = 14; // Length +input double mcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE mcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE mcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcHHColor = clrLime; // Highest High Color +input color mcLLColor = clrRed; // Lowest Low Color +input group "MC Drawings"; +input bool mcDrawHH = true; // Draw Highest High +input bool mcDrawLL = true; // Draw Lowest Low + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scLength = 7; // Length +input double scThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE scHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE scLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_DOT; // Draw Style +input color scHHColor = clrLightBlue; // Highest High Color +input color scLLColor = clrLightSalmon; // Lowest Low Color +input group "SC Drawings"; +input bool scDrawHH = true; // Draw Highest High +input bool scDrawLL = true; // Draw Lowest Low +// +// END Inputs ... +// + +// +// 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"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcHHBufferIndex 0 +#define lcLLBufferIndex 1 + +// +double lcHHBuffer[]; +double lcLLBuffer[]; + +// +// MC ... +#define mcHHBufferIndex 2 +#define mcLLBufferIndex 3 + +// +double mcHHBuffer[]; +double mcLLBuffer[]; + +// +// SC ... +#define scHHBufferIndex 4 +#define scLLBufferIndex 5 + +// +double scHHBuffer[]; +double scLLBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // 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 ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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(lcLength, mcLength); + maxLength = MathMax(maxLength, scLength); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = + lcLength >= 4 && + lcLength > mcLength && + lcLength > scLength; + bool isMCInputsValid = + mcLength >= 4 && + mcLength > scLength && + mcLength < lcLength; + bool isSCInputsValid = + scLength >= 4 && + scLength < mcLength && + scLength < lcLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// 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 // Current Candle Index ... +) +{ + // + // LC ... + LCCalculateBuffers(bar_index); + + // + // MC ... + MCCalculateBuffers(bar_index); + + // + // SC ... + SCCalculateBuffers(bar_index); + + // + // SIGNAL ... + SignalCalculateBuffers(bar_index); + + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC HH Buffer ... + string lcHHBufferLabel = ShortName + " LC HH (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcHHDrawType = lcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcHHBufferIndex, PLOT_LABEL, lcHHBufferLabel); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_COLOR, lcHHColor); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_TYPE, lcHHDrawType); + + // + // LC LL Buffer ... + string lcLLBufferLabel = ShortName + " LC LL (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcLLDrawType = lcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcLLBufferIndex, PLOT_LABEL, lcLLBufferLabel); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_COLOR, lcLLColor); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_TYPE, lcLLDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC HH Buffer ... + string mcHHBufferLabel = ShortName + " MC HH (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcHHDrawType = mcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcHHBufferIndex, PLOT_LABEL, mcHHBufferLabel); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_COLOR, mcHHColor); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_TYPE, mcHHDrawType); + + // + // MC LL Buffer ... + string mcLLBufferLabel = ShortName + " MC LL (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcLLDrawType = mcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcLLBufferIndex, PLOT_LABEL, mcLLBufferLabel); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_COLOR, mcLLColor); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_TYPE, mcLLDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC HH Buffer ... + string scHHBufferLabel = ShortName + " SC HH (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scHHDrawType = scDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scHHBufferIndex, PLOT_LABEL, scHHBufferLabel); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_COLOR, scHHColor); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_TYPE, scHHDrawType); + + // + // SC LL Buffer ... + string scLLBufferLabel = ShortName + " SC LL (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scLLDrawType = scDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scLLBufferIndex, PLOT_LABEL, scLLBufferLabel); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_COLOR, scLLColor); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_TYPE, scLLDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Calculations ... +void LCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = lcLength; + ENUM_SERIESMODE hhMode = lcHHMode; + ENUM_SERIESMODE llMode = lcLLMode; + double threshold = PipsToPrice(lcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + lcHHBuffer[bar_index] = hhValue; + lcLLBuffer[bar_index] = llValue; +} + +// +// MC Calculations ... +void MCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = mcLength; + ENUM_SERIESMODE hhMode = mcHHMode; + ENUM_SERIESMODE llMode = mcLLMode; + double threshold = PipsToPrice(mcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + mcHHBuffer[bar_index] = hhValue; + mcLLBuffer[bar_index] = llValue; +} + +// +// SC Calculations ... +void SCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = scLength; + ENUM_SERIESMODE hhMode = scHHMode; + ENUM_SERIESMODE llMode = scLLMode; + double threshold = PipsToPrice(scThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + scHHBuffer[bar_index] = hhValue; + scLLBuffer[bar_index] = llValue; +} + +// +// SIGNAL Calculations ... +void SignalCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC Values ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + double lcDelta = lcHH - lcLL; + double lcAvg = lcDelta / 2; + + // + // MC Values ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + double mcDelta = mcHH - mcLL; + double mcAvg = mcDelta / 2; + + // + // SC Values ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + double scDelta = scHH - scLL; + double scAvg = scDelta / 2; + + // + // Min Value ... + double minValue = MathMin( + scLL, mcLL); + minValue = MathMin( + lcLL, minValue); + + // + // Max Value ... + double maxValue = MathMin( + scHH, mcHH); + maxValue = MathMin( + lcHH, maxValue); +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + // + double lcHH1 = lcHHBuffer[bar_index + 1]; + double lcLL1 = lcLLBuffer[bar_index + 1]; + + // + // MC ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + // + double mcHH1 = mcHHBuffer[bar_index + 1]; + double mcLL1 = mcLLBuffer[bar_index + 1]; + + // + // SC ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + // + double scHH1 = scHHBuffer[bar_index + 1]; + double scLL1 = scLLBuffer[bar_index + 1]; + + // + bool isHotLLState = scLL == mcLL && mcLL == lcLL; + bool isHotLLState1 = scLL1 == mcLL1 && mcLL1 == lcLL1; + // + bool isHotHHState = scHH == mcHH && mcHH == lcHH; + bool isHotHHState1 = scHH1 == mcHH1 && mcHH1 == lcHH1; + + // + bool isHotLL = isHotLLState && !isHotLLState1; + bool isHotHH = isHotHHState && !isHotHHState1; + + // + double hotStateValue = X_XCHLH_NEUTURAL; + if (isHotHH) + { + hotStateValue = X_XCHLH_HOT_HH; + } + else if (isHotLL) + { + hotStateValue = X_XCHLH_HOT_LL; + } + + // + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotHHArea = hotStateValue == 1; + bool isHotLLArea = hotStateValue == -1; + if (isHotHHArea || isHotLLArea) + { + // + bool isHH = isHotHHArea; + + // + double price = isHH ? candle.high : candle.low; + ENUM_ARROW_ANCHOR anchor = isHH ? ANCHOR_BOTTOM : ANCHOR_TOP; + color clr = isHH ? hotHHArrowColor : hotLLArrowColor; + uchar arrowCode = isHH ? hotHHArrowCode : hotLLArrowCode; + string name = "HOT " + (isHH ? "HH" : "LL") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr, + STYLE_SOLID, + 1); + } + } +} +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 b/XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 0000000..12d6c69 --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 @@ -0,0 +1,1153 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel Moving Averages Oscillator +// ---------------------------------------------------------------- +// Name: XCHMA +// Description: trend detecting based on cycles ... +// +// +// 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 XCHMA Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHMA" + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotBullishArrowCode = 228; // Hot Bullish Arrow Code +input color hotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color +input uchar hotBearishArrowCode = 230; // Hot Bearish Arrow Code +input color hotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcFastLength = 20; // Fast Length +input int lcSlowLength = 50; // Slow Length +input ENUM_MA_METHOD lcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE lcAppliedTo = PRICE_CLOSE; // Applied To +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcFastColor = clrAqua; // Fast Color +input color lcSlowColor = clrFuchsia; // Slow Color +input group "LC Drawings"; +input bool lcDrawFast = true; // Draw Fast +input bool lcDrawSlow = true; // Draw Slow +input bool lcDrawCrosses = true; // Draw Cross Lines + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcFastLength = 10; // Fast Length +input int mcSlowLength = 30; // Slow Length +input ENUM_MA_METHOD mcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE mcAppliedTo = PRICE_CLOSE; // Applied To +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcFastColor = clrLime; // Fast Color +input color mcSlowColor = clrRed; // Slow Color +input group "MC Drawings"; +input bool mcDrawFast = true; // Draw Fast +input bool mcDrawSlow = true; // Draw Slow +input bool mcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scFastLength = 7; // Fast Length +input int scSlowLength = 14; // Slow Length +input ENUM_MA_METHOD scMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE scAppliedTo = PRICE_CLOSE; // Applied To +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_SOLID; // Draw Style +input color scFastColor = clrLightBlue; // Fast Color +input color scSlowColor = clrLightSalmon; // Slow Color +input group "SC Drawings"; +input bool scDrawFast = true; // Draw Fast +input bool scDrawSlow = true; // Draw Slow +input bool scDrawCrosses = false; // Draw Cross Lines +// +// END Inputs ... +// + +// +// 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" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcFastBufferIndex 0 +#define lcSlowBufferIndex 1 + +// +double lcFastBuffer[]; +double lcSlowBuffer[]; + +// +// MC ... +#define mcFastBufferIndex 2 +#define mcSlowBufferIndex 3 + +// +double mcFastBuffer[]; +double mcSlowBuffer[]; + +// +// SC ... +#define scFastBufferIndex 4 +#define scSlowBufferIndex 5 + +// +double scFastBuffer[]; +double scSlowBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// LC ... +int lcFastHandler = INVALID_HANDLE; +int lcSlowHandler = INVALID_HANDLE; + +// +// MC ... +int mcFastHandler = INVALID_HANDLE; +int mcSlowHandler = INVALID_HANDLE; + +// +// SC ... +int scFastHandler = INVALID_HANDLE; +int scSlowHandler = 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; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init All Required Handlers ... + if (!InitHandlers()) + { + 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 ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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(lcFastLength, lcSlowLength); + + // + // Get Retrieved Values from indicators ... + // + // LC ... + int lcFastCalculatedBars = BarsCalculated(lcFastHandler); + int lcSlowCalculatedBars = BarsCalculated(lcSlowHandler); + + // + // MC ... + int mcFastCalculatedBars = BarsCalculated(mcFastHandler); + int mcSlowCalculatedBars = BarsCalculated(mcSlowHandler); + + // + // SC ... + int scFastCalculatedBars = BarsCalculated(scFastHandler); + int scSlowCalculatedBars = BarsCalculated(scSlowHandler); + + // + // Check Calculated Bars ... + if ( + // + // LC ... + lcFastCalculatedBars < maxLength || + lcSlowCalculatedBars < maxLength || + // + // MC ... + mcFastCalculatedBars < maxLength || + mcSlowCalculatedBars < maxLength || + // + // SC ... + scFastCalculatedBars < maxLength || + scSlowCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Copy Buffers from indicators ... + // + // LC ... + int lcFastCopiedItems = CopyBuffer(lcFastHandler, 0, 0, limit + 1, lcFastBuffer); + int lcSlowCopiedItems = CopyBuffer(lcSlowHandler, 0, 0, limit + 1, lcSlowBuffer); + + // + // MC ... + int mcFastCopiedItems = CopyBuffer(mcFastHandler, 0, 0, limit + 1, mcFastBuffer); + int mcSlowCopiedItems = CopyBuffer(mcSlowHandler, 0, 0, limit + 1, mcSlowBuffer); + + // + // SC ... + int scFastCopiedItems = CopyBuffer(scFastHandler, 0, 0, limit + 1, scFastBuffer); + int scSlowCopiedItems = CopyBuffer(scSlowHandler, 0, 0, limit + 1, scSlowBuffer); + + // + // Check Copied Items Number ... + if ( + // + // LC ... + lcFastCopiedItems <= 0 || + lcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = lcFastLength >= 4 && lcSlowLength > lcFastLength; + bool isMCInputsValid = mcFastLength >= 4 && mcSlowLength > mcFastLength; + bool isSCInputsValid = scFastLength >= 4 && scSlowLength > scFastLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid && + lcFastLength > mcFastLength && + mcFastLength > scFastLength) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// Init Handlers ... +bool InitHandlers() +{ + // + bool result = false; + + // + // LC ... + result = LCInitHandlers(); + if (!result) + { + return result; + } + + // + // MC ... + result = MCInitHandlers(); + if (!result) + { + return result; + } + + // + // SC ... + result = SCInitHandlers(); + if (!result) + { + return result; + } + + // + 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 // Current Candle Index ... +) +{ + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC Fast Buffer ... + string lcFastBufferLabel = ShortName + " LC Fast (" + (string)lcFastLength + ")"; + ENUM_DRAW_TYPE lcFastDrawType = lcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcFastBuffer, true); + SetIndexBuffer(lcFastBufferIndex, lcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(lcFastBufferIndex, PLOT_LABEL, lcFastBufferLabel); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_COLOR, lcFastColor); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_BEGIN, lcFastLength); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_TYPE, lcFastDrawType); + + // + // LC Slow Buffer ... + string lcSlowBufferLabel = ShortName + " LC Slow (" + (string)lcSlowLength + ")"; + ENUM_DRAW_TYPE lcSlowDrawType = lcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcSlowBuffer, true); + SetIndexBuffer(lcSlowBufferIndex, lcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(lcSlowBufferIndex, PLOT_LABEL, lcSlowBufferLabel); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_COLOR, lcSlowColor); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_BEGIN, lcSlowLength); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_TYPE, lcSlowDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC Fast Buffer ... + string mcFastBufferLabel = ShortName + " MC Fast (" + (string)mcFastLength + ")"; + ENUM_DRAW_TYPE mcFastDrawType = mcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcFastBuffer, true); + SetIndexBuffer(mcFastBufferIndex, mcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(mcFastBufferIndex, PLOT_LABEL, mcFastBufferLabel); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_COLOR, mcFastColor); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_BEGIN, mcFastLength); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_TYPE, mcFastDrawType); + + // + // MC Slow Buffer ... + string mcSlowBufferLabel = ShortName + " MC Slow (" + (string)mcSlowLength + ")"; + ENUM_DRAW_TYPE mcSlowDrawType = mcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcSlowBuffer, true); + SetIndexBuffer(mcSlowBufferIndex, mcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(mcSlowBufferIndex, PLOT_LABEL, mcSlowBufferLabel); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_COLOR, mcSlowColor); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_BEGIN, mcSlowLength); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_TYPE, mcSlowDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC Fast Buffer ... + string scFastBufferLabel = ShortName + " SC Fast (" + (string)scFastLength + ")"; + ENUM_DRAW_TYPE scFastDrawType = scDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scFastBuffer, true); + SetIndexBuffer(scFastBufferIndex, scFastBuffer, INDICATOR_DATA); + PlotIndexSetString(scFastBufferIndex, PLOT_LABEL, scFastBufferLabel); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_COLOR, scFastColor); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_BEGIN, scFastLength); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_TYPE, scFastDrawType); + + // + // SC Slow Buffer ... + string scSlowBufferLabel = ShortName + " SC Slow (" + (string)scSlowLength + ")"; + ENUM_DRAW_TYPE scSlowDrawType = scDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scSlowBuffer, true); + SetIndexBuffer(scSlowBufferIndex, scSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(scSlowBufferIndex, PLOT_LABEL, scSlowBufferLabel); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_COLOR, scSlowColor); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_BEGIN, scSlowLength); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_TYPE, scSlowDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Init Handlers ... +bool LCInitHandlers() +{ + // + ResetLastError(); + + // + // LC Fast Handler ... + lcFastHandler = iMA( + _Symbol, + _Period, + lcFastLength, + 0, + lcMethod, + lcAppliedTo); + if (lcFastHandler == INVALID_HANDLE) + { + // + LogMessage("LC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // LC Slow Handler ... + lcSlowHandler = iMA( + _Symbol, + _Period, + lcSlowLength, + 0, + lcMethod, + lcAppliedTo); + if (lcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("LC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// MC Init Handlers ... +bool MCInitHandlers() +{ + // + ResetLastError(); + + // + // MC Fast Handler ... + mcFastHandler = iMA( + _Symbol, + _Period, + mcFastLength, + 0, + mcMethod, + mcAppliedTo); + if (mcFastHandler == INVALID_HANDLE) + { + // + LogMessage("MC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // MC Slow Handler ... + mcSlowHandler = iMA( + _Symbol, + _Period, + mcSlowLength, + 0, + mcMethod, + mcAppliedTo); + if (mcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("MC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// SC Init Handlers ... +bool SCInitHandlers() +{ + // + ResetLastError(); + + // + // SC Fast Handler ... + scFastHandler = iMA( + _Symbol, + _Period, + scFastLength, + 0, + scMethod, + scAppliedTo); + if (scFastHandler == INVALID_HANDLE) + { + // + LogMessage("SC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // SC Slow Handler ... + scSlowHandler = iMA( + _Symbol, + _Period, + scSlowLength, + 0, + scMethod, + scAppliedTo); + if (scSlowHandler == INVALID_HANDLE) + { + // + LogMessage("SC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// LC State ... +double GetLCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// MC State ... +double GetMCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// SC State ... +double GetSCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcFast = lcFastBuffer[bar_index]; + double lcSlow = lcSlowBuffer[bar_index]; + // + double lcFastPrev = lcFastBuffer[bar_index + 1]; + double lcSlowPrev = lcSlowBuffer[bar_index + 1]; + // + double lcState = GetLCState(bar_index); + + // + // MC ... + double mcFast = mcFastBuffer[bar_index]; + double mcSlow = mcSlowBuffer[bar_index]; + // + double mcFastPrev = mcFastBuffer[bar_index + 1]; + double mcSlowPrev = mcSlowBuffer[bar_index + 1]; + // + double mcState = GetMCState(bar_index); + + // + // SC ... + double scFast = scFastBuffer[bar_index]; + double scSlow = scSlowBuffer[bar_index]; + // + double scFastPrev = scFastBuffer[bar_index + 1]; + double scSlowPrev = scSlowBuffer[bar_index + 1]; + // + double scState = GetSCState(bar_index); + + // + // Detect HOT Bearish Area ... + bool isHotBearishArea = + lcFast < lcSlow && + mcFast < mcSlow && + scFast < scSlow; + // + bool isPrevHotBearishArea = + lcFastPrev < lcSlowPrev && + mcFastPrev < mcSlowPrev && + scFastPrev < scSlowPrev; + + // + // Detect HOT Bearish Area ... + bool isHotBullishArea = + lcFast > lcSlow && + mcFast > mcSlow && + scFast > scSlow; + // + bool isPrevHotBullishArea = + lcFastPrev > lcSlowPrev && + mcFastPrev > mcSlowPrev && + scFastPrev > scSlowPrev; + + // + // Generate HotState Value ... + double hotStateValue = + isHotBullishArea && !isPrevHotBullishArea + ? 1 + : isHotBearishArea && !isPrevHotBearishArea + ? -1 + : 0; + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotBullishArea = hotStateValue == 1; + bool isHotBearishArea = hotStateValue == -1; + if (isHotBullishArea || isHotBearishArea) + { + // + bool isBull = isHotBullishArea; + + // + double price = isBull ? candle.low : candle.high; + ENUM_ARROW_ANCHOR anchor = isBull ? ANCHOR_TOP : ANCHOR_BOTTOM; + color clr = isBull ? hotBullishArrowColor : hotBearishArrowColor; + uchar arrowCode = isBull ? hotBullishArrowCode : hotBearishArrowCode; + string name = "HOT " + (isBull ? "Bullish" : "Bearish") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); + } + } + + // + // Draw LC Crosses ... + if (lcDrawCrosses) + { + // + double lcStateValue = GetLCState(bar_index); + bool isLcFastCrossedOverSlow = lcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isLcFastCrossedUnderSlow = lcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isLcFastCrossedOverSlow || isLcFastCrossedUnderSlow) + { + // + bool isBull = isLcFastCrossedOverSlow; + + // + color clr = isBull ? lcFastColor : lcSlowColor; + string name = "LC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw MC Crosses ... + if (mcDrawCrosses) + { + // + double mcStateValue = GetMCState(bar_index); + bool isMcFastCrossedOverSlow = mcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isMcFastCrossedUnderSlow = mcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isMcFastCrossedOverSlow || isMcFastCrossedUnderSlow) + { + // + bool isBull = isMcFastCrossedOverSlow; + + // + color clr = isBull ? mcFastColor : mcSlowColor; + string name = "MC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw SC Crosses ... + if (scDrawCrosses) + { + // + double scStateValue = GetSCState(bar_index); + bool isScFastCrossedOverSlow = scStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isScFastCrossedUnderSlow = scStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isScFastCrossedOverSlow || isScFastCrossedUnderSlow) + { + // + bool isBull = isScFastCrossedOverSlow; + + // + color clr = isBull ? scFastColor : scSlowColor; + string name = "SC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } +} +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 b/XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 0000000..cfd393c --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 @@ -0,0 +1,317 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XFI Oscillator +// --------------------------------------------- +// Name: XFI +// Description: Price Momentum Power Detection +// 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 XFI Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XFI" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 18; // Length +input ENUM_MA_METHOD method = MODE_SMA; // MA Method +input ENUM_APPLIED_VOLUME appliedTo = VOLUME_TICK; // Applied To +// +// 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_separate_window + +// +#property indicator_buffers 2 +#property indicator_plots 1 + +// +// FI Buffer ... +#define fiBufferIndex 0 +#define fiColorBufferIndex 1 + +// +double fiBuffer[]; +double fiColorBuffer[]; + +// +#property indicator_label1 "XFI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int fiHandler = 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; + + // + fiHandler = iForce( + _Symbol, + _Period, + length, + method, + appliedTo); + if (fiHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing 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(fiHandler); +} + +// +// 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, length); + + // + // Check Calculated Bars ... + int fiCalculatedBars = BarsCalculated(fiHandler); + if (fiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFis = CopyBuffer(fiHandler, 0, 0, limit, fiBuffer); + if (copiedFis <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + 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() +{ + // + string fiBufferLabel = "XFI " + "(" + (string)length + ")"; + + // + // FI Buffer ... + ArraySetAsSeries(fiBuffer, true); + SetIndexBuffer(fiBufferIndex, fiBuffer, INDICATOR_DATA); + PlotIndexSetString(fiBufferIndex, PLOT_LABEL, fiBufferLabel); + + // + // FI Color Buffer ... + ArraySetAsSeries(fiColorBuffer, true); + SetIndexBuffer(fiColorBufferIndex, fiColorBuffer, 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 +) +{ + // + double iValue = fiBuffer[bar_index]; + + // + double iColorIndex = + iValue > 0 ? 0 : iValue < 0 ? 2 + : 1; + + // + // Set Buffer Color Index ... + fiColorBuffer[bar_index] = iColorIndex; +} +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xlh.indicator.mq5 b/XEU5/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 0000000..4dfc64e --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xlh.indicator.mq5 @@ -0,0 +1,346 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XLH Indicator +// --------------------------------------------- +// Name: XLH +// Description: Moving Average 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 XLH Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XLH" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 14; // Length +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method +// +// 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 3 + +// +// HH Buffer ... +#define hhBufferIndex 0 + +// +double hhBuffer[]; + +// +#property indicator_label1 "XLH HH" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// LL Buffer ... +#define llBufferIndex 1 + +// +double llBuffer[]; + +// +#property indicator_label2 "XLH LL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrFuchsia +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Signal Buffer ... +#define signalBufferIndex 2 + +// +double signalBuffer[]; + +// +#property indicator_label3 "XLH S" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // 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, length); + + // + 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 = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // HH Buffer ... + string hhBufferLabel = ShortName + " HH " + "(" + (string)length + ")"; + ArraySetAsSeries(hhBuffer, true); + SetIndexBuffer(hhBufferIndex, hhBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hhBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(hhBufferIndex, PLOT_LABEL, hhBufferLabel); + + // + // LL Buffer ... + string llBufferLabel = ShortName + " LL " + "(" + (string)length + ")"; + ArraySetAsSeries(llBuffer, true); + SetIndexBuffer(llBufferIndex, llBuffer, INDICATOR_DATA); + PlotIndexSetInteger(llBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(llBufferIndex, PLOT_LABEL, llBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + " S " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// 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 Threshold ... + // + // HH Buffer ... + int hhIndex = iHighest( + _Symbol, + _Period, + hhMode, + length, + bar_index); + double hhValue = GetAppliedPrice( + hhIndex, + hhMode); + + // + hhBuffer[bar_index] = hhValue; + + // + // LL Buffer ... + int llIndex = iLowest( + _Symbol, + _Period, + llMode, + length, + bar_index); + double llValue = GetAppliedPrice( + llIndex, + llMode); + + // + llBuffer[bar_index] = llValue; + + // + XOHCL c = GetCandle(bar_index); + double lhDiff = hhValue - llValue; + double signalValue = (lhDiff / 2); + + // + signalBuffer[bar_index] = (hhValue - signalValue); +} +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xobd.indicator.mq5 b/XEU5/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 0000000..4ac05cf --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xobd.indicator.mq5 @@ -0,0 +1,390 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Indicator +// ----------------------------------------------------- +// Name: XOBD +// Description: detect Order Blocks based on Swings ... +// +// +// 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 XOBD Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XOBD" +// +// END Constants ... +// + +// +// START Inputs ... +// +// +input int length = 5; // Swing Length + +// +input uchar swingHighArrowCode = 108; // Swing High Arrow Code +input color swingHighArrowColor = clrMagenta; // Swing High Arrow Color + +// +input uchar swingLowArrowCode = 108; // Swing Low Arrow Code +input color swingLowArrowColor = clrAqua; // Swing Low Arrow Color +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Include Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 1 +#property indicator_plots 0 + +// +#define swingBufferIndex 0 +double swingBuffer[]; +// +// 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 (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // 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 ... + OnDeinitDrawLibrary(); +} + +// +// 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, length * 3); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + 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() +{ + // + ArraySetAsSeries(swingBuffer, true); + SetIndexBuffer(swingBufferIndex, swingBuffer, 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) +{ + // + // GetCandleSwing(bar_index); + ENUM_X_SWING_TYPE type = X_NO_SWING; + + // + // Try To Detect Order Blocks ... + bool isSwingLow = false; + bool isSwingHigh = false; + + // + // Reading Candles Data ... + XOHCL candles[]; + for (int i = bar_index; i < bar_index + ((length * 2) + 2); i++) + { + // + XOHCL iCandle = GetCandle( + _Symbol, + _Period, + i); + + // + Add( + iCandle, + candles); + } + + // + // Swing Low ... + isSwingLow = + // + candles[1].close > candles[2].close && + candles[2].close > candles[3].close && + // + candles[3].close < candles[4].close && + // + candles[5].close > candles[4].close && + candles[6].close > candles[5].close + // + ; + + // + if (isSwingLow) + { + type = X_SWING_LOW; + } + + // + if (!isSwingLow) + { + // + // Swing High ... + isSwingHigh = + // + candles[1].close < candles[2].close && + candles[2].close < candles[3].close && + // + candles[3].close > candles[4].close && + // + candles[5].close < candles[4].close && + candles[6].close < candles[5].close + // + ; + + // + if (isSwingHigh) + { + type = X_SWING_HIGH; + } + } + + // + switch (type) + { + // + // Swing High ... + case X_SWING_HIGH: + // + swingBuffer[bar_index] = type; + DrawSwingArrow(1, bar_index); + break; + + // + // Swinmg Low ... + case X_SWING_LOW: + // + swingBuffer[bar_index] = type; + DrawSwingArrow(0, bar_index); + break; + + // + // No Swing ... + default: + case X_NO_SWING: + // + swingBuffer[bar_index] = 0; + break; + } +} + +// +// Draw a Swing Arrow Shape ... +void DrawSwingArrow( + int type, // Swing Type: 0 - Low / 1 - High ... + int bar_index) +{ + // + bool isSwingHigh = type == 1; + XOHCL candle = GetCandle(bar_index + 3); + double arrowDistanceInPoint = 0; + + // + // Define Required Object Properties fro Draw an Arrow ... + datetime time = iTime(_Symbol, _Period, bar_index + 3); + double purePrice = isSwingHigh ? candle.high : candle.low; + color clr = isSwingHigh ? swingHighArrowColor : swingLowArrowColor; + ENUM_ARROW_ANCHOR anchor = isSwingHigh ? ANCHOR_BOTTOM : ANCHOR_TOP; + uchar arrowCode = uchar(isSwingHigh ? swingHighArrowCode : swingLowArrowCode); + double price = isSwingHigh ? purePrice + arrowDistanceInPoint : purePrice - arrowDistanceInPoint; + string name = "Swing " + (isSwingHigh ? "High" : "Low") + "_" + (string)time + "_" + (string)purePrice; + + // + // Draw desired Arrow ... + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); +} +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 b/XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 0000000..5659e07 --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 @@ -0,0 +1,397 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Oscillator +// ------------------------------------------------------ +// Name: XRSI +// Description: detect market conditions based on RSI ... +// +// +// 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 XRSI Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XRSI" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 14; // Market Length +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +input group "Short Entry"; +input double shortEntryValue = 70; // Short Entry Level +input color shortEntryColor = clrRed; // Short Entry Level Color +input ENUM_LINE_STYLE shortEntryLineStyle = STYLE_DOT; // Short Entry Style + +// +input group "Short Exit"; +input double shortExitValue = 40; // Short Exit Level +input color shortExitColor = clrRed; // Short Exit Level Color +input ENUM_LINE_STYLE shortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +input group "Long Entry"; +input double longEntryValue = 30; // Long Entry Level +input color longEntryColor = clrRed; // Long Entry Level Color +input ENUM_LINE_STYLE longEntryLineStyle = STYLE_DOT; // Long Entry Style + +// +input group "Long Exit"; +input double longExitValue = 60; // Long Exit Level +input color longExitColor = clrRed; // Long Exit Level Color +input ENUM_LINE_STYLE longExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// START Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_separate_window +#property indicator_buffers 2 +#property indicator_plots 1 + +// +#define rsiBufferIndex 0 +#define rsiColorBufferIndex 1 + +// +double rsiBuffer[]; +double rsiColorBuffer[]; + +// +#property indicator_label1 "XRSI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int rsiHandler = 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; + + // + rsiHandler = iRSI( + _Symbol, + _Period, + length, + appliedTo); + if (rsiHandler == INVALID_HANDLE) + { + 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(rsiHandler); +} + +// +// 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, length); + + // + int rsiCalculatedBars = BarsCalculated(rsiHandler); + if (rsiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + int rsiCopiedItems = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + if (rsiCopiedItems <= 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 = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RSI ... + string rsiBufferLabel = ShortName + " (" + (string)length + ")"; + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rsiBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(rsiBufferIndex, PLOT_LABEL, rsiBufferLabel); + + // + // RSI Color Buffer ... + ArraySetAsSeries(rsiColorBuffer, true); + SetIndexBuffer(rsiColorBufferIndex, rsiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set Indicator Levels here ... + // OB, ExitLong, ExitShort, OS ... + IndicatorSetInteger(INDICATOR_LEVELS, 4); + + // + // SHORTENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, shortEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, shortEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, shortEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 0, "Short Entry"); + + // + // LONGEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, longExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, longExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, shortExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 1, "Long Exit"); + + // + // SHORTEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, shortExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 2, shortExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 2, longEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 2, "Short Exit"); + + // + // LONGENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 3, longEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 3, longEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 3, longExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 3, "Long Entry"); + + // + // Set Maximum and Minimum for subwindow + IndicatorSetInteger(INDICATOR_DIGITS, 2); + IndicatorSetDouble(INDICATOR_MINIMUM, 0); + IndicatorSetDouble(INDICATOR_MAXIMUM, 100); +} + +// +// 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) +{ + // + double iValue = rsiBuffer[bar_index]; + + // + double iColorIndex = 0; + + // + if ( + iValue >= shortEntryValue || + iValue <= longEntryValue || + (iValue < longExitValue && + iValue > shortExitValue)) + { + iColorIndex = 0; + } + else if ( + iValue <= shortEntryValue && + iValue >= longExitValue) + { + iColorIndex = 2; + } + else if ( + iValue < shortExitValue && + iValue > longEntryValue) + { + iColorIndex = 1; + } + + // + rsiColorBuffer[bar_index] = iColorIndex; +} + +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 b/XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 0000000..5f46d18 --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 @@ -0,0 +1,465 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Trend Detector Oscillator +// -------------------------------------------------- +// Name: XTD +// Description: trend detecting in both sides ... +// +// +// 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 XTD Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTD" + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; +// +// END Constants ... +// + +// +// Include Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// START Inputs ... +// +input int length = 14; // Market Length +input bool drawCrosses = true; // Draw Cross Arrows + +// +// Bullish ... +input uchar bullishArrowCode = 228; // Cross Over Arrow Code +input color bullishArrowColor = clrAqua; // Cross Over Arrow Color + +// +// Bearish ... +input uchar bearishArrowCode = 230; // Cross Under Arrow Code +input color bearishArrowColor = clrMagenta; // Cross Under Arrow Color +// +// END Inputs ... +// + +// +// 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"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +#define bullishBufferIndex 0 +#define bearishBufferIndex 1 +#define signalBufferIndex 2 + +// +double bullishBuffer[]; +double bearishBuffer[]; +double signalBuffer[]; + +// +#property indicator_label1 "XBullPower" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#property indicator_label2 "XBearPower" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#property indicator_label3 "XSignal" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +int xtdBullishCandleCount = 0; +int xtdBearishCandleCount = 0; +// +// 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; + + // + // 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 ... + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); +} + +// +// 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, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i, close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 5) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish Buffer ... + string bullishBufferLabel = ShortName + "BullPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bullishBuffer, true); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bullishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bullishBufferIndex, PLOT_LABEL, bullishBufferLabel); + + // + // Bearish Buffer ... + string bearishBufferLabel = ShortName + "BearPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bearishBuffer, true); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bearishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bearishBufferIndex, PLOT_LABEL, bearishBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + "Signal " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// 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, + const double &close[]) +{ + // + // Reset Global Counters ... + xtdBullishCandleCount = 0; + xtdBearishCandleCount = 0; + + // + // Loop through Closes ... + for (int i = bar_index; i <= bar_index + length; i++) + { + for (int j = i + 1; j <= bar_index + length; j++) + { + // + if (close[i] > close[j]) + { + xtdBullishCandleCount++; + } + + // + if (close[i] < close[j]) + { + xtdBearishCandleCount++; + } + } + } + + // + // Bullish Power Buffer ... + bullishBuffer[bar_index] = MathAbs(xtdBullishCandleCount); + + // + // Bearish Power Buffer ... + bearishBuffer[bar_index] = MathAbs(xtdBearishCandleCount); + + // + // Signal Buffer ... + signalBuffer[bar_index] = bullishBuffer[bar_index] - bearishBuffer[bar_index]; + + // + // Check and Draw Crosses if it's Specified ... + if (drawCrosses) + { + DrawCrosses(bar_index); + } +} + +// +// +double GetState( + int bar_index // Specified Bar Index +) +{ + // + // Check Cross Points ... + // bullishCrossedOverBearish = 2; + // bullishOverBearish = 1; + // bullishCrossedUnderBearish = -2; + // bullishUnderBearish = -1; + // OtherWise = 0; + bool isBullishCrossedOverBearish = IsCrossOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishCrossedUnderBearish = IsCrossUnder( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishOverBearish = IsOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishUnderBearish = IsUnder( + bullishBuffer, + bearishBuffer, + bar_index); + + // + double result = X_XTD_NEUTURAL; + if (isBullishCrossedOverBearish) + { + result = X_XTD_BULLISH_CROSSED_OVER_BEARISH; + } + else if (isBullishCrossedUnderBearish) + { + result = X_XTD_BULLISH_CROSSED_UNDER_BEARISH; + } + else if (isBullishOverBearish) + { + result = X_XTD_BULLISH_OVER_BEARISH; + } + else if (isBullishUnderBearish) + { + result = X_XTD_BULLISH_UNDER_BEARISH; + } + else + { + result = X_XTD_NEUTURAL; + } + + // + return result; +} + +// +// Draw Crosses ... +void DrawCrosses( + int bar_index // the bars which required to draw cross arrow on it ... +) +{ + // + double stateValue = GetState(bar_index); + + // + bool isOver = stateValue == 2; + double low = iLow(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + + // + double price = isOver ? low : high; + datetime time = iTime(_Symbol, _Period, bar_index); + ENUM_ARROW_ANCHOR anchor = isOver ? ANCHOR_TOP : ANCHOR_BOTTOM; + uchar arrowCode = isOver ? bullishArrowCode : bearishArrowCode; + color arrowColor = isOver ? bullishArrowColor : bearishArrowColor; + string crossName = "Trend " + (isOver ? "Up" : "Down") + "_" + (string)time + "_" + (string)price; + + // + DrawArrow( + 0, + crossName, + 0, + time, + price, + arrowCode, + anchor, + arrowColor); +} +// +// END Functions ... +// diff --git a/XEU5/Indicators/x-saherelm.xtm.indicator.mq5 b/XEU5/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 0000000..eac88e0 --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xtm.indicator.mq5 @@ -0,0 +1,349 @@ +/////////////////////////////////////////////////////// +// +// 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 int maPeriod = 14; // Period +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Applied To +// +// 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() +{ + // + string maBufferLabel = "XTM " + "(" + (string)maPeriod + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // 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/XEU5/Indicators/x-saherelm.xts.oscillator.mq5 b/XEU5/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 0000000..46e9fbf --- /dev/null +++ b/XEU5/Indicators/x-saherelm.xts.oscillator.mq5 @@ -0,0 +1,558 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTS Oscillator +// --------------------------------------------- +// Name: XTS +// Description: Time Sections Oscillator ... +// +// +// 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 XTS Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XTS" + +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// XTS Oscillator States ... + +// +// END Constants ... +// + +// +// START Inputs ... +// +input group "Current Period"; +input ENUM_APPLIED_PRICE currentAppliedTo = PRICE_CLOSE; // Current Applied To +// +input group "Nearest Period"; +input ENUM_X_PERIOD_METHOD nearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +input ENUM_TIMEFRAMES nearestPeriod = NULL; // Nearest Time Frame +input ENUM_APPLIED_PRICE nearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// +input group "Mediest Period"; +input ENUM_X_PERIOD_METHOD mediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +input ENUM_TIMEFRAMES mediestPeriod = NULL; // Mediest Time Frame +input ENUM_APPLIED_PRICE mediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// +input group "Farest Period"; +input ENUM_X_PERIOD_METHOD farestMethod = X_PERIOD_AUTO; // How to Find Farest Period +input ENUM_TIMEFRAMES farestPeriod = NULL; // Farest Time Frame +input ENUM_APPLIED_PRICE farestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// 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" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// Current ... +#define currentBufferIndex 0 + +double currentBuffer[]; + +#property indicator_label1 "XTS C" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// Nearest ... +#define nearestBufferIndex 1 + +double nearestBuffer[]; + +#property indicator_label2 "XTS N" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrAqua +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// Mediest ... +#define mediestBufferIndex 2 + +double mediestBuffer[]; + +#property indicator_label3 "XTS M" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrLime +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// Farest ... +#define farestBufferIndex 3 + +double farestBuffer[]; + +#property indicator_label4 "XTS F" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLightBlue +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +ENUM_TIMEFRAMES mNearestPeriod = NULL; +ENUM_TIMEFRAMES mMediestPeriod = NULL; +ENUM_TIMEFRAMES mFarestPeriod = 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; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Oscillator ShortName ... + SetOscillatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// 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 = 30; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + int maxLength = 30; + + // + // Current ... + ArraySetAsSeries(currentBuffer, true); + SetIndexBuffer(currentBufferIndex, currentBuffer, INDICATOR_DATA); + PlotIndexSetInteger(currentBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Nearest ... + ArraySetAsSeries(nearestBuffer, true); + SetIndexBuffer(nearestBufferIndex, nearestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(nearestBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Mediest ... + ArraySetAsSeries(mediestBuffer, true); + SetIndexBuffer(mediestBufferIndex, mediestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mediestBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Farest ... + ArraySetAsSeries(farestBuffer, true); + SetIndexBuffer(farestBufferIndex, farestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(farestBufferIndex, PLOT_DRAW_BEGIN, maxLength); +} + +// +// Set Oscillator Short Name and also we can define Buffers Labels ... +void SetOscillatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Current ... + CalculateCurrent(bar_index); + + // + // Nearest ... + CalculateNearest(bar_index); + + // + // Mediest ... + CalculateMediest(bar_index); + + // + // Farest ... + CalculateFarest(bar_index); + + // + // Commenting ... + string comment = GenerateDescriptionComment(); + Comment(comment); +} + +// +// Current ... +void CalculateCurrent(int bar_index) +{ + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + _Period, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + currentAppliedTo); + + // + currentBuffer[bar_index] = value; +} + +// +// Nearest ... +void CalculateNearest(int bar_index) +{ + // + if (mNearestPeriod == NULL) + { + // + switch (nearestMethod) + { + // + case X_PERIOD_AUTO: + mNearestPeriod = GetNearestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mNearestPeriod = nearestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mNearestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + nearestAppliedTo); + + // + nearestBuffer[bar_index] = value; +} + +// +// Mediest ... +void CalculateMediest(int bar_index) +{ + // + if (mMediestPeriod == NULL) + { + // + switch (mediestMethod) + { + // + case X_PERIOD_AUTO: + mMediestPeriod = GetMediestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mMediestPeriod = mediestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mMediestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + mediestAppliedTo); + + // + mediestBuffer[bar_index] = value; +} + +// +// Farest ... +void CalculateFarest(int bar_index) +{ + // + if (mFarestPeriod == NULL) + { + // + switch (farestMethod) + { + // + case X_PERIOD_AUTO: + mFarestPeriod = GetFarestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mFarestPeriod = farestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mFarestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + farestAppliedTo); + + // + farestBuffer[bar_index] = value; +} + +// +// Generate Comment ... +string GenerateDescriptionComment() +{ + // + string result = ""; + + // + result += "Nearest : " + EnumToString(mNearestPeriod) + "\n"; + result += "Mediest : " + EnumToString(mMediestPeriod) + "\n"; + result += "Farest : " + EnumToString(mFarestPeriod) + "\n"; + + // + return result; +} +// +// END Functions ... +// diff --git a/XEU5/Libraries/.gitkeep b/XEU5/Libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Libraries/x-saherelm.alert.lib.mq5 b/XEU5/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 0000000..1079063 --- /dev/null +++ b/XEU5/Libraries/x-saherelm.alert.lib.mq5 @@ -0,0 +1,200 @@ +/////////////////////////////////////////////////////// +// +// 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); + } +} +void SendAlert( + XSignal &signal, // the Signal Object which requred to Alert + bool asExecuted = true // determines Alert Signal as Executed Signal or not +) +{ + // + // Prepare Message ... + string message = asExecuted ? ExecutedSignalToString(signal) : SignalToString(signal); + + // + // Do Alerting ... + SendAlert(message); +} +// +// END Provided Functions ... +// diff --git a/XEU5/Libraries/x-saherelm.common.lib.mq5 b/XEU5/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..290dde9 --- /dev/null +++ b/XEU5/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,4429 @@ +/////////////////////////////////////////////////////// +// +// 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; +} + +// +// 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_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetAsk() : GetBid(); + result = NormalizePrice(result); + + // + return result; +} +double GetEntry( + string symbol, // Specified Symbol + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetAsk(symbol) : GetBid(symbol); + result = NormalizePrice(result, symbol); + + // + return result; +} + +// +// Get Signal Exit ... +double GetExit( + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetBid() : GetAsk(); + result = NormalizePrice(result); + + // + return result; +} +double GetExit( + string symbol, // Specified Symbol + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + // Validate Arg ... + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + bool isLong = type == X_SIGNAL_LONG; + result = isLong ? GetBid(symbol) : GetAsk(symbol); + result = NormalizePrice(result, symbol); + + // + 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; +} + +// +// 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; +} + +// +// 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 HasStrongBody(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 = HasStrongBody(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 = HasStrongBody(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 = HasStrongBody(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; +} + +// +// 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; +} + +// +// 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; +} + +// +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; +} + +// +// Validate Struct ... +bool IsValid(XSignal &model, ulong magicNumber) +{ + // + bool result = false; + + // + // Validate Signal Type ... + result = model.type != X_SIGNAL_UNKNOWN; + if (!result) + { + return result; + } + + // + // Check Symbol ... + result = StringLen(model.symbol) == 0 ? true : model.symbol == _Symbol; + if (!result) + { + return result; + } + + // + // Check magic number ... + result = model.magicNumber <= 0 ? true : model.magicNumber == magicNumber; + if (!result) + { + return result; + } + + // + // Check Entry ... + result = model.entry > 0; + if (!result) + { + return result; + } + + // + // Check SL ... + result = model.sl == 0 ? true : model.type == X_SIGNAL_LONG ? model.sl < model.entry + : model.sl > model.entry; + if (!result) + { + return result; + } + + // + // Check TP ... + result = model.tp == 0 ? true : model.type == X_SIGNAL_LONG ? model.tp > model.entry + : model.tp < model.entry; + if (!result) + { + return result; + } + + // + // Check Volume ... + result = model.volume > 0; + if (!result) + { + return result; + } + + // + // Check Time ... + result = model.time > 0; + if (!result) + { + return result; + } + + // + return result; +} + +// +void CleanBuffer(int &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(ulong &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(double &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XSignal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XDeal &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +void CleanBuffer(XOrder &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; +} +void Add( + XSignal &item, // item want to add + XSignal &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XDeal &item, // item want to add + XDeal &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XOrder &item, // item want to add + XOrder &buffer[] // Destination buffer +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// 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; +} + +// +// Check a Signal is Long or not ... +bool IsLong(ENUM_X_SIGNAL_TYPE type) +{ + return type == X_SIGNAL_LONG; +} +bool IsLong(XSignal &signal) +{ + // + bool result = IsLong(signal.type); + + // + return result; +} + +// +// Check a Signal is Short or not ... +bool IsShort(ENUM_X_SIGNAL_TYPE type) +{ + return type == X_SIGNAL_SHORT; +} +bool IsShort(XSignal &signal) +{ + // + bool result = IsShort(signal.type); + + // + return result; +} + +// +// Retrieve a Signal Type String Value ... +string GetSignalType(ENUM_X_SIGNAL_TYPE type) +{ + // + string result = ""; + + // + if (type == X_SIGNAL_UNKNOWN) + { + return result; + } + + // + result = type == X_SIGNAL_LONG ? "Long" : "Short"; + + // + return result; +} +string GetSignalType(XSignal &signal) +{ + // + string result = ""; + + // + result = GetSignalType(signal.type); + + // + return result; +} +ENUM_X_SIGNAL_TYPE GetSignalType(string typeStr) +{ + // + ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN; + + // + if (typeStr == GetSignalType(X_SIGNAL_LONG)) + { + result = X_SIGNAL_LONG; + } + else if (typeStr == GetSignalType(X_SIGNAL_SHORT)) + { + result = X_SIGNAL_SHORT; + } + + // + return result; +} + +// +// Retrieve Signal Execution String ... +string GetSignalExecutionError(int error) +{ + // + string result = ""; + + // + switch (error) + { + // + case X_TRADER_INVALID_SIGNAL_ERROR: + result = "Invalid Signal ..."; + break; + + // + case X_TRADER_NOT_ENOUGH_EQUITY_ERROR: + result = "Not Enough Equity for Trade ..."; + break; + + // + case X_TRADER_NOT_ENOUGH_BALANCE_ERROR: + result = "Not Enough Balance for Trade ..."; + break; + + // + case X_TRADER_NOT_ENOUGH_MARIGIN_ERROR: + result = "Not Enough Marigin For Trade ..."; + break; + + // + case X_TRADER_MAX_TRADES_REACHED_ERROR: + result = "Max Allowed Trade Reached ..."; + break; + + // + case X_TRADER_UNKNOWN_ERROR: + default: + result = "Unknown Issue ..."; + break; + } + + // + return result; +} + +// +// 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; +} + +// +// +// + +// +// 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 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; +} + +// +// END Provided Functions ... +// diff --git a/XEU5/Libraries/x-saherelm.draw.lib.mq5 b/XEU5/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ece98c8 --- /dev/null +++ b/XEU5/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2345 @@ +/////////////////////////////////////////////////////// +// +// 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(); +} + +// +void DrawSignalShape( + XSignal &signal, // Specify Signal to Draw + color longColor = clrAqua, // Long Signals Color + color shortColor = clrFuchsia, // Short Signal Color + color entryColor = clrGold // Signal Entry Price Color +) +{ + // + // Draw Signal Info : + // - Draw Entry Price Line; + // - Draw SL; + // - Draw TP; + // - Risk Free; + + // + bool isLong = signal.type == X_SIGNAL_LONG; + + // + color tpColor = longColor; + color slColor = shortColor; + + // + string name = "T(" + (string)signal.ticket + ")" + "_" + "TY(" + EnumToString(signal.type) + ")"; + + // + string tpName = "TP_" + name; + if (IsDrawExists(tpName)) + { + RemoveDraw(tpName); + } + + // + string slName = "SL_" + name; + if (IsDrawExists(slName)) + { + RemoveDraw(slName); + } + + // + string riskFreeName = "RF_" + name; + if (IsDrawExists(riskFreeName)) + { + RemoveDraw(riskFreeName); + } + + // + string entryName = "Entry_" + name; + if (IsDrawExists(entryName)) + { + RemoveDraw(entryName); + } + + // + string vlName = "Time_" + name; + if (IsDrawExists(vlName)) + { + RemoveDraw(vlName); + } + + // + int signalBarIndex = iBarShift( + signal.symbol, + _Period, + signal.time); + + // + datetime time1 = iTime( + signal.symbol, + _Period, + signalBarIndex + 1); + datetime time2 = iTime( + signal.symbol, + _Period, + signalBarIndex - 1); + + // + // Entry ... + bool isTrendLineDrawn = DrawTrendLine( + 0, + entryName, + 0, + time1, + signal.entry, + time2, + signal.entry, + entryColor); + + // + // TP ... + bool isTPDrawn = false; + if (signal.tp > 0) + { + // + isTPDrawn = DrawTrendLine( + 0, + tpName, + 0, + time1, + signal.tp, + time2, + signal.tp, + tpColor, + STYLE_SOLID, + 1, + false, + true); + } + + // + // RISKFREE ... + bool isRFDrawn = false; + if (signal.riskFreeStep > 0) + { + // + double firstStepPrice = isLong ? signal.entry + PipsToPrice(signal.riskFreeStep) + : signal.entry - PipsToPrice(signal.riskFreeStep); + + // + isRFDrawn = DrawTrendLine( + 0, + riskFreeName, + 0, + time1, + firstStepPrice, + time2, + firstStepPrice, + tpColor, + STYLE_DOT, + 1, + false, + true); + } + + // + // SL ... + bool isSLDrawn = false; + if (signal.sl > 0) + { + // + isSLDrawn = DrawTrendLine( + 0, + slName, + 0, + time1, + signal.sl, + time2, + signal.sl, + slColor, + STYLE_SOLID, + 1, + false, + true); + } + + // + // Draw a Vertical Line ... + bool isVerticalLineDrawn = DrawVerticalLine( + 0, + vlName, + 0, + signal.time, + slColor); +} + +// +// 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; +} + +// +// 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 sub_window = 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, sub_window, 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 back_clr = 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, back_clr); + + // + // 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 ... +// + +// +// END Regular Draws ... +// + +// +// START Chart Style Drawers ... +// +// +// Apply Styles On Chart ... +void ApplyChartStyle( + int chartId = -1, // chart's ID + ENUM_CHART_MODE mode = CHART_CANDLES, // chart's mode + bool showBidLine = true, // show bid line + bool showAskLine = true, // show ask line + bool showGrid = false, // show grids on chart + bool showVolumes = false, // show volumes + bool showTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool autoScroll = true, // chart autoscroll + bool quickNavigation = true, // chart quick navigation state + color foreGroundColor = clrWhite, // chart's foreground color + color backGroundColor = clrBlack, // chart's background color + color upColor = clrGreen, // Up Color + color downColor = clrRed, // Down Color + color bullishColor = clrGreen, // Bullish color + color bearishColor = clrRed, // Bearish color + color gridColor = clrGray, // grid color + color bidLineColor = clrGray, // bid line color + color askLineColor = clrRed, // ask line color + color lineColor = clrLime, // line mode and doji candlestick color + color stopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color volumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (chartId == -1) + { + chartId = 0; + } + + // + ChartSetInteger(chartId, CHART_MODE, mode); + ChartSetInteger(chartId, CHART_SHOW_BID_LINE, showBidLine); + ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, showAskLine); + ChartSetInteger(chartId, CHART_SHOW_GRID, showGrid); + ChartSetInteger(chartId, CHART_SHOW_VOLUMES, showVolumes); + ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, showTradeLevels); + ChartSetInteger(chartId, CHART_AUTOSCROLL, autoScroll); + ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, quickNavigation); + ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, foreGroundColor); + ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, backGroundColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_UP, upColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, downColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, bullishColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, bearishColor); + ChartSetInteger(chartId, CHART_COLOR_GRID, gridColor); + ChartSetInteger(chartId, CHART_COLOR_BID, bidLineColor); + ChartSetInteger(chartId, CHART_COLOR_ASK, askLineColor); + ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, stopColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, lineColor); + ChartSetInteger(chartId, CHART_COLOR_VOLUME, volumesColor); +} +// +// END Chart Style Drawers ... +// \ No newline at end of file diff --git a/XEU5/Libraries/x-saherelm.http.lib.mq5 b/XEU5/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 0000000..97f7ac0 --- /dev/null +++ b/XEU5/Libraries/x-saherelm.http.lib.mq5 @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Http Library +// ------------------------------------------ +// Name: XHttp +// Description: provide http communication +// 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 Model Definition ... +// +enum X_HTTP_METHOD +{ + X_HTTP_GET, + X_HTTP_POST +}; +// +// END Model Definition ... +// + +// +// START Inputs ... +// +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Initial Library if required ... +bool OnInInitHttpLibrary() +{ + return false; +} + +// +// DeInitial Library if required ... +void OnDeinitHttpLibrary() +{ +} + +// +// 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; +} + +// +// 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; + } + + // + result = WebRequest( + strMethod, + url, + headers, + timeout, + payload, + response, + responseHeaders + ); + + // + 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; +} +// +// END Provided Functions ... +// diff --git a/XEU5/Libraries/x-saherelm.log.lib.mq5 b/XEU5/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 0000000..70f1bda --- /dev/null +++ b/XEU5/Libraries/x-saherelm.log.lib.mq5 @@ -0,0 +1,261 @@ +/////////////////////////////////////////////////////// +// +// 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); +} + +// +// 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); +} + +// +// Convert a Signal to String Message ... +string SignalToString(const XSignal &signal) +{ + // + string result = "\n"; + + // + result += "Signal: " + "\n"; + result += "id: " + (string)signal.id + "\n"; + result += "symbol: " + signal.symbol + "\n"; + result += "type: " + EnumToString(signal.type) + "\n"; + result += "magicNumber: " + (string)signal.magicNumber + "\n"; + result += "ticket: " + (string)signal.ticket + "\n"; + result += "entry: " + (string)signal.entry + "\n"; + result += "tp: " + (string)signal.tp + "\n"; + result += "sl: " + (string)signal.sl + "\n"; + result += "riskFreeStep: " + (string)signal.riskFreeStep + "\n"; + result += "riskFreeRate: " + (string)signal.riskFreeRate + "\n"; + result += "profit: " + (string)signal.profit + "\n"; + result += "time: " + (string)signal.time + "\n"; + result += "volume: " + (string)signal.volume + "\n"; + result += "comment: " + signal.comment + "\n"; + + // + return result; +} + +// +// Convert an Executed Signal to String Message ... +string ExecutedSignalToString(const XSignal &signal) +{ + // + string result = ""; + + // + result += (signal.type == X_SIGNAL_LONG ? "Buy" : "Sell") + " Signal Executed provided on (" + signal.symbol + " _ " + EnumToString(_Period) + ") by this comment: " + signal.comment; + + // + return result; +} + +// +// Logging Signal ... +void LogSignal(const XSignal &signal) +{ + // + string message = SignalToString(signal); + + // + LogMessage(message); +} + +// +// Log Signal Execution ... +void LogExecutedSignal(const XSignal &signal) +{ + // + string message = ExecutedSignalToString(signal); + + // + LogMessage(message); +} + +// +// Convert a Deal to String ... +string DealToString(const XDeal &deal) +{ + // + string result = "\n"; + + // + result += "Deal:" + "\n"; + result += " " + "\n"; + result += "time: " + (string)deal.time + "\n"; + result += "ticket: " + (string)deal.ticket + "\n"; + result += "order: " + (string)deal.order + "\n"; + result += "positionId: " + (string)deal.positionId + "\n"; + result += "type: " + EnumToString(deal.type) + "\n"; + result += "entry: " + EnumToString(deal.entry) + "\n"; + result += "reason: " + EnumToString(deal.reason) + "\n"; + result += "symbol: " + deal.symbol + "\n"; + result += "price: " + (string)deal.price + "\n"; + result += "profit: " + (string)deal.profit + "\n"; + result += "swap: " + (string)deal.swap + "\n"; + result += "commission: " + (string)deal.commission + "\n"; + result += "volume: " + (string)deal.volume + "\n"; + result += "comment: " + deal.comment + "\n"; + + // + return result; +} + +// +// Log Specific Deal ... +void LogDeal(const XDeal &deal) +{ + // + string message = DealToString(deal); + + // + LogMessage(message); +} + +// +// Convert an Order to String ... +string OrderToString(const XOrder &order) +{ + // + string result = "\n"; + + // + result += "Order: " + "\n"; + result += "magic: " + (string)order.magic + "\n"; + result += "positionId: " + (string)order.positionId + "\n"; + result += "symbol: " + (string)order.symbol + "\n"; + result += "ticket: " + (string)order.ticket + "\n"; + result += "timeSetup: " + (string)order.timeSetup + "\n"; + result += "timeDone: " + (string)order.timeDone + "\n"; + result += "timeExpiration: " + (string)order.timeExpiration + "\n"; + result += "priceOpen: " + (string)order.priceOpen + "\n"; + result += "priceCurrent: " + (string)order.priceCurrent + "\n"; + result += "priceStopLimit: " + (string)order.priceStopLimit + "\n"; + result += "stopLoss: " + (string)order.stopLoss + "\n"; + result += "takeProfit: " + (string)order.takeProfit + "\n"; + result += "volumeInitial: " + (string)order.volumeInitial + "\n"; + result += "volumeCurrent: " + (string)order.volumeCurrent + "\n"; + result += "comment: " + order.comment + "\n"; + result += "type: " + EnumToString(order.type) + "\n"; + result += "state: " + EnumToString(order.state) + "\n"; + result += "typeFilling: " + EnumToString(order.typeFilling) + "\n"; + result += "typeTime: " + EnumToString(order.typeTime) + "\n"; + result += "reason: " + EnumToString(order.reason) + "\n"; + + // + return result; +} + +// +// Log Specific Order ... +void LogOrder(const XOrder &order) +{ + // + string message = OrderToString(order); + + // + LogMessage(message); +} + +// +// END Provided Functions ... +// diff --git a/XEU5/Libraries/x-saherelm.models.lib.mq5 b/XEU5/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 0000000..b98ae3e --- /dev/null +++ b/XEU5/Libraries/x-saherelm.models.lib.mq5 @@ -0,0 +1,438 @@ +/////////////////////////////////////////////////////// +// +// 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 +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + double high; + double open; + double close; + double low; +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +// XTrader Execution Signal Result ... +enum ENUM_EXECUTION_SIGNAL_RESULT +{ + // + X_TRADER_UNKNOWN_ERROR, + X_TRADER_SUCCEED_EXECUTION, + X_TRADER_INVALID_SIGNAL_ERROR, + X_TRADER_NOT_ENOUGH_EQUITY_ERROR, + X_TRADER_MAX_TRADES_REACHED_ERROR, + X_TRADER_NOT_ENOUGH_BALANCE_ERROR, + X_TRADER_NOT_ENOUGH_MARIGIN_ERROR + // +}; + +// +// Signal Types ... +enum ENUM_X_SIGNAL_TYPE +{ + X_SIGNAL_LONG, + X_SIGNAL_SHORT, + X_SIGNAL_UNKNOWN, +}; + +// +// Signal Structure ... +struct XSignal +{ + // + // Identifier ... + ulong id; + + // + // Which Symbol used for Signal ... + string symbol; + + // + // Which Type of operations ... + ENUM_X_SIGNAL_TYPE type; + + // + // Magic Number ... + ulong magicNumber; + + // + // Ticket ... + ulong ticket; + + // + // Entry/Open Price ... + double entry; + + // + // TP ... + double tp; + + // + // SL ... + double sl; + + // + // Make Risk Free Trade on this Value if provided ... + double riskFreeStep; + + // + // a Multiplier for determines how much trade volume exit on risk free time ... + double riskFreeRate; + + // + // Trade Profit ... + double profit; + + // + // Time of Operation ... + datetime time; + + // + // Volume ... + double volume; + + // + // Comment ... + string comment; +}; + +// +// Signal Additional Info ... +struct XProvidedSignal +{ + // + // Suggested TP ... + double tp; + + // + // Suggested SL ... + double sl; + + // + // Signallers ... + string signallers[]; +}; + +// +// Model Specific 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 Specific Order ... +struct XOrder +{ + // + // the ID of expert that placed the order ... + ulong magic; + + // + // the ID of position ... + ulong positionId; + + // + // the name of order symbol ... + string symbol; + + // + // the ticket of an order, previously selected for access ... + ulong ticket; + + // + // the time of order placement ... + datetime timeSetup; + + // + // the time of order execution or cancellation ... + datetime timeDone; + + // + // the order expiration time ... + datetime timeExpiration; + + // + // the order price ... + double priceOpen; + + // + // the current price by order symbol ... + double priceCurrent; + + // + // the price of a pending order ... + double priceStopLimit; + + // + // the order's Stop Loss ... + double stopLoss; + + // + // the order's Take Profit ... + double takeProfit; + + // + // the initial volume of order ... + double volumeInitial; + + // + // the unfilled volume of order ... + double volumeCurrent; + + // + // the order comment ... + string comment; + + // + // the order type ... + // -------------------- + // ORDER_TYPE_BUY => Market Buy order ... + // ORDER_TYPE_SELL => Market Sell order ... + // ORDER_TYPE_BUY_LIMIT => Buy Limit pending order ... + // ORDER_TYPE_SELL_LIMIT => Sell Limit pending order ... + // ORDER_TYPE_BUY_STOP => Buy Stop pending order ... + // ORDER_TYPE_SELL_STOP => Sell Stop pending order ... + // ORDER_TYPE_BUY_STOP_LIMIT => Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price ... + // ORDER_TYPE_SELL_STOP_LIMIT => Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price ... + // ORDER_TYPE_CLOSE_BY => Order to close a position by an opposite one ... + ENUM_ORDER_TYPE type; + + // + // the order state ... + // -------------------------- + // ORDER_STATE_STARTED => Order checked, but not yet accepted by broker ... + // ORDER_STATE_PLACED => Order accepted ... + // ORDER_STATE_CANCELED => Order canceled by client ... + // ORDER_STATE_PARTIAL => Order partially executed ... + // ORDER_STATE_FILLED => Order fully executed ... + // ORDER_STATE_REJECTED => Order rejected ... + // ORDER_STATE_EXPIRED => Order expired ... + // ORDER_STATE_REQUEST_ADD => Order is being registered (placing to the trading system) + // ORDER_STATE_REQUEST_MODIFY => Order is being modified (changing its parameters) ... + // ORDER_STATE_REQUEST_CANCEL => Order is being deleted (deleting from the trading system) ... + ENUM_ORDER_STATE state; + + // + // the order filling type ... + // ---------------------------- + // ORDER_FILLING_FOK => Fill or Kill + // An order can be executed in the specified volume only. + // If the necessary amount of a financial instrument is currently unavailable in the market, + // the order will not be executed. + // The desired volume can be made up of several available offers. + // The possibility of using FOK orders is determined at the trade server. + // ORDER_FILLING_IOC => Immediate or Cancel + // A trader agrees to execute a deal with the volume maximally available in the market within that indicated in the order. + // If the request cannot be filled completely, an order with the available volume will be executed, + // and the remaining volume will be canceled. + // The possibility of using IOC orders is determined at the trade server. + // ORDER_FILLING_BOC => Passive (Book or Cancel) + // The BoC order assumes that the order can only be placed in the Depth of Market and cannot be immediately executed. + // If the order can be executed immediately when placed, then it is canceled. + // In fact, the BOC policy guarantees that the price of the placed order will be worse than + // the current market. BoC orders are used to implement passive trading, + // so that the order is not executed immediately when placed and does not affect current liquidity. + // Only limit and stop limit orders are supported (ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT, ORDER_TYPE_SELL_STOP_LIMIT). + // ORDER_FILLING_RETURN => Return + // In case of partial filling, an order with remaining volume is not canceled but processed further. + // Return orders are not allowed in the Market Execution + // mode (market execution — SYMBOL_TRADE_EXECUTION_MARKET). + ENUM_ORDER_TYPE_FILLING typeFilling; + + // + // the type of order at the time of the expiration ... + // -------------------------------------------------------- + // ORDER_TIME_GTC => Good till cancel order ... + // ORDER_TIME_DAY => Good till current trade day order ... + // ORDER_TIME_SPECIFIED => Good till expired order ... + // ORDER_TIME_SPECIFIED_DAY => The order will be effective till 23:59:59 of the specified day. + // If this time is outside a trading session, the order expires in the nearest trading time ... + ENUM_ORDER_TYPE_TIME typeTime; + + // + // The reason for order placing ... + // -------------------------------------- + // ORDER_REASON_SL => The order was placed as a result of Stop Loss activation ... + // ORDER_REASON_TP => The order was placed as a result of Take Profit activation ... + // ORDER_REASON_SO => The order was placed as a result of the Stop Out event ... + // ORDER_REASON_WEB => The order was placed from a web platform ... + // ORDER_REASON_CLIENT => The order was placed from a desktop terminal ... + // ORDER_REASON_MOBILE => The order was placed from a mobile application ... + // ORDER_REASON_EXPERT => The order was placed from an MQL5-program, i.e. by an Expert Advisor or a script ... + ENUM_ORDER_REASON reason; +}; +// +// END Provided Functions ... +// diff --git a/XEU5/Providers/.gitkeep b/XEU5/Providers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 b/XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 new file mode 100644 index 0000000..c077b65 --- /dev/null +++ b/XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 @@ -0,0 +1,13599 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XEU5 Signal Provider Indicators Library +// ---------------------------------------------------------------- +// +// 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 Provider Inputs ... +#include "x-saherelm.xeu5.provider.inputs.lib.mq5" + +// +// Include Provider Class ... +#include "../Classes/x-saherelm.provider.lib.mq5" + +// +// Signallers ... +input group "XEU5 Signallers"; + +// +// XTD ... +input group "XEU5 XTD Signaller"; +input bool xEU5XTDEnableSignaller = true; // Enable Signaller +input bool xEU5XTDAllowLongSignals = true; // Enable Long Signals +input bool xEU5XTDAllowShortSignals = true; // Enable Short Signals + +// +// XTAM ... +input group "XEU5 XTAM Signaller"; +input bool xEU5XTAMEnableSignaller = true; // Enable Signaller +input bool xEU5XTAMAllowLongSignals = true; // Enable Long Signals +input bool xEU5XTAMAllowShortSignals = true; // Enable Short Signals + +// +// XSI ... +input group "XEU5 XSI Signaller"; +input bool xEU5XSIEnableSignaller = true; // Enable Signaller +input bool xEU5XSIAllowLongSignals = true; // Enable Long Signals +input bool xEU5XSIAllowShortSignals = true; // Enable Short Signals + +// +// XTSFI ... +input group "XEU5 XTSFI Signaller"; +input bool xEU5XTSFIEnableSignaller = true; // Enable Signaller +input bool xEU5XTSFIAllowLongSignals = true; // Enable Long Signals +input bool xEU5XTSFIAllowShortSignals = true; // Enable Short Signals + +// +// XOBDLH ... +input group "XEU5 XOBDLH Signaller"; +input bool xEU5XOBDLHEnableSignaller = true; // Enable Signaller +input bool xEU5XOBDLHAllowLongSignals = true; // Enable Long Signals +input bool xEU5XOBDLHAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACC ... +input group "XEU5 XCHMACC Signaller"; +input bool xEU5XCHMACCEnableSignaller = true; // Enable Signaller +input bool xEU5XCHMACCAllowLongSignals = true; // Enable Long Signals +input bool xEU5XCHMACCAllowShortSignals = true; // Enable Short Signals + +// +// XCHMAMX ... +input group "XEU5 XCHMAMX Signaller"; +input bool xEU5XCHMAMXEnableSignaller = true; // Enable Signaller +input bool xEU5XCHMAMXAllowLongSignals = true; // Enable Long Signals +input bool xEU5XCHMAMXAllowShortSignals = true; // Enable Short Signals + +// +// XCHMAMN ... +input group "XEU5 XCHMAMN Signaller"; +input bool xEU5XCHMAMNEnableSignaller = true; // Enable Signaller +input bool xEU5XCHMAMNAllowLongSignals = true; // Enable Long Signals +input bool xEU5XCHMAMNAllowShortSignals = true; // Enable Short Signals + +// +bool xEU5IsTestMode = true; +int xEU5MaxLengthOfInputs = 0; +int xEU5CalculatedBars = 0; + +// +// Signaller Variables ... +// +// XTD ... +bool xEU5MXTDEnableSignaller = xEU5XTDEnableSignaller; +bool xEU5MXTDAllowLongSignals = xEU5XTDAllowLongSignals; +bool xEU5MXTDAllowShortSignals = xEU5XTDAllowShortSignals; + +// +// XTAM ... +bool xEU5MXTAMEnableSignaller = xEU5XTAMEnableSignaller; +bool xEU5MXTAMAllowLongSignals = xEU5XTAMAllowLongSignals; +bool xEU5MXTAMAllowShortSignals = xEU5XTAMAllowShortSignals; + +// +// XSI ... +bool xEU5MXSIEnableSignaller = xEU5XSIEnableSignaller; +bool xEU5MXSIAllowLongSignals = xEU5XSIAllowLongSignals; +bool xEU5MXSIAllowShortSignals = xEU5XSIAllowShortSignals; + +// +// XTSFI ... +bool xEU5MXTSFIEnableSignaller = xEU5XTSFIEnableSignaller; +bool xEU5MXTSFIAllowLongSignals = xEU5XTSFIAllowLongSignals; +bool xEU5MXTSFIAllowShortSignals = xEU5XTSFIAllowShortSignals; + +// +// XOBDLH ... +bool xEU5MXOBDLHEnableSignaller = xEU5XOBDLHEnableSignaller; +bool xEU5MXOBDLHAllowLongSignals = xEU5XOBDLHAllowLongSignals; +bool xEU5MXOBDLHAllowShortSignals = xEU5XOBDLHAllowShortSignals; + +// +// XCHMACC ... +bool xEU5MXCHMACCEnableSignaller = xEU5XCHMACCEnableSignaller; +bool xEU5MXCHMACCAllowLongSignals = xEU5XCHMACCAllowLongSignals; +bool xEU5MXCHMACCAllowShortSignals = xEU5XCHMACCAllowShortSignals; + +// +// XCHMAMX ... +bool xEU5MXCHMAMXEnableSignaller = xEU5XCHMAMXEnableSignaller; +bool xEU5MXCHMAMXAllowLongSignals = xEU5XCHMAMXAllowLongSignals; +bool xEU5MXCHMAMXAllowShortSignals = xEU5XCHMAMXAllowShortSignals; + +// +// XCHMAMN ... +bool xEU5MXCHMAMNEnableSignaller = xEU5XCHMAMNEnableSignaller; +bool xEU5MXCHMAMNAllowLongSignals = xEU5XCHMAMNAllowLongSignals; +bool xEU5MXCHMAMNAllowShortSignals = xEU5XCHMAMNAllowShortSignals; + +// +XCProvider *xEU5Provider; + +// +// Validate Indicators Inputs ... +bool XEU5ValidateIndicatorsInputs() +{ + // + bool result = false; + + // + // XTM ... + result = XTMValidateInputs(); + if (!result) + { + return result; + } + + // + // XAMA ... + result = XAMAValidateInputs(); + if (!result) + { + return result; + } + + // + // XTD ... + result = XTDValidateInputs(); + if (!result) + { + return result; + } + + // + // XFI ... + result = XFIValidateInputs(); + if (!result) + { + return result; + } + + // + // XTS ... + result = XTSValidateInputs(); + if (!result) + { + return result; + } + + // + // XOBD ... + result = XOBDValidateInputs(); + if (!result) + { + return result; + } + + // + // XLH ... + result = XLHValidateInputs(); + if (!result) + { + return result; + } + + // + // XRSI ... + result = XRSIValidateInputs(); + if (!result) + { + return result; + } + + // + // XCHLH ... + result = XCHLHValidateInputs(); + if (!result) + { + return result; + } + + // + // XCHMA ... + result = XCHMAValidateInputs(); + if (!result) + { + return result; + } + + // + // Make an Instance Of XCProvider Class for Use ... + xEU5Provider = new XCProvider( + // + // Commons ... + _Symbol, + _Period, + // + // Signallers ... + // + // XTD ... + xEU5MXTDEnableSignaller, + xEU5MXTDAllowLongSignals, + xEU5MXTDAllowShortSignals, + // + // XTAM ... + xEU5MXTAMEnableSignaller, + xEU5MXTAMAllowLongSignals, + xEU5MXTAMAllowShortSignals, + // + // XSI ... + xEU5MXSIEnableSignaller, + xEU5MXSIAllowLongSignals, + xEU5MXSIAllowShortSignals, + // + // XTSFI ... + xEU5MXTSFIEnableSignaller, + xEU5MXTSFIAllowLongSignals, + xEU5MXTSFIAllowShortSignals, + // + // XOBDLH ... + xEU5MXOBDLHEnableSignaller, + xEU5MXOBDLHAllowLongSignals, + xEU5MXOBDLHAllowShortSignals, + // + // XCHMACC ... + xEU5MXCHMACCEnableSignaller, + xEU5MXCHMACCAllowLongSignals, + xEU5MXCHMACCAllowShortSignals, + // + // XCHMAMX ... + xEU5MXCHMAMXEnableSignaller, + xEU5MXCHMAMXAllowLongSignals, + xEU5MXCHMAMXAllowShortSignals, + // + // XCHMAMN ... + xEU5MXCHMAMNEnableSignaller, + xEU5MXCHMAMNAllowLongSignals, + xEU5MXCHMAMNAllowShortSignals + // + ); + + // + result = true; + + // + return result; +} + +// +// Init Indicators ... +bool XEU5InitIndicators() +{ + // + bool result = false; + + // + // Make it Enable when we need to Log Market Conditions ... + // xEU5IsTestMode = false; // IsRunningOnTestMode(); + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xEU5MaxLengthOfInputs = MathMax( + xTMMaPeriod, + xEU5NumberOfItemsPerTick); + + // + // XAMA ... + xEU5MaxLengthOfInputs = MathMax( + xAMALength, + xEU5NumberOfItemsPerTick); + xEU5MaxLengthOfInputs = MathMax( + xAMAFastEMA, + xEU5NumberOfItemsPerTick); + xEU5MaxLengthOfInputs = MathMax( + xAMASlowEMA, + xEU5NumberOfItemsPerTick); + + // + // XLH ... + xEU5MaxLengthOfInputs = MathMax( + xLHLength, + xEU5NumberOfItemsPerTick); + + // + // XTD ... + xEU5MaxLengthOfInputs = MathMax( + xTDLength, + xEU5MaxLengthOfInputs); + + // + // XFI ... + xEU5MaxLengthOfInputs = MathMax( + xFILength, + xEU5MaxLengthOfInputs); + + // + // XRSI ... + xEU5MaxLengthOfInputs = MathMax( + xRSILength, + xEU5MaxLengthOfInputs); + + // + // XOBD ... + xEU5MaxLengthOfInputs = MathMax( + xOBDLength, + xEU5MaxLengthOfInputs); + + // + // XCHLH ... + xEU5MaxLengthOfInputs = MathMax( + xCHLHLcLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHLHMcLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHLHScLength, + xEU5MaxLengthOfInputs); + + // + // XCHMA ... + xEU5MaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xEU5MaxLengthOfInputs); + xEU5MaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xEU5MaxLengthOfInputs); + + // + // Validate Indicators Inputs before Initialization ... + result = XEU5ValidateIndicatorsInputs(); + if (!result) + { + return result; + } + + // + // Validate Signallers ... + + // + // XTD ... + bool isXTDEnable = + xEU5XTDEnableSignaller && + (xEU5XTDAllowLongSignals || + xEU5XTDAllowShortSignals); + + // + // XTAM ... + bool isXTAMEnable = + xEU5XTAMEnableSignaller && + (xEU5XTAMAllowLongSignals || + xEU5XTAMAllowShortSignals); + + // + // XSI ... + bool isXSIEnable = + xEU5XSIEnableSignaller && + (xEU5XSIAllowLongSignals || + xEU5XSIAllowShortSignals); + + // + // XTSFI ... + bool isXTSFIEnable = + xEU5XTSFIEnableSignaller && + (xEU5XTSFIAllowLongSignals || + xEU5XTSFIAllowShortSignals); + + // + // XOBDLH ... + bool isXOBDLHEnable = + xEU5XOBDLHEnableSignaller && + (xEU5XOBDLHAllowLongSignals || + xEU5XOBDLHAllowShortSignals); + + // + // XCHMACC ... + bool isXCHMACCEnable = + xEU5XCHMACCEnableSignaller && + (xEU5XCHMACCAllowLongSignals || + xEU5XCHMACCAllowShortSignals); + + // + // XCHMAMX ... + bool isXCHMAMXEnable = + xEU5XCHMAMXEnableSignaller && + (xEU5XCHMAMXAllowLongSignals || + xEU5XCHMAMXAllowShortSignals); + + // + // XCHMAMN ... + bool isXCHMAMNEnable = + xEU5XCHMAMNEnableSignaller && + (xEU5XCHMAMNAllowLongSignals || + xEU5XCHMAMNAllowShortSignals); + + // + bool hasSignaller = + // + isXTDEnable || + isXTAMEnable || + isXSIEnable || + isXTSFIEnable || + isXOBDLHEnable || + isXCHMACCEnable || + isXCHMAMXEnable || + isXCHMAMNEnable + // + ; + result = hasSignaller; + if (!result) + { + // + LogMessage("XEU5 doesn't enable any Signaller ..."); + + // + return result; + } + + // + // Initialize Indicator/Oscillator Handlers ... + ResetLastError(); + + // + // XTM Init ... + result = XTMInitHandlers(); + if (!result) + { + return result; + } + + // + // XAMA Init ... + result = XAMAInitHandlers(); + if (!result) + { + return result; + } + + // + // XLH Init ... + result = XLHInitHandlers(); + if (!result) + { + return result; + } + + // + // XTD Init ... + result = XTDInitHandlers(); + if (!result) + { + return result; + } + + // + // XFI Init ... + result = XFIInitHandlers(); + if (!result) + { + return result; + } + + // + // XTS Init ... + result = XTSInitHandlers(); + if (!result) + { + return result; + } + + // + // XRSI Init ... + result = XRSIInitHandlers(); + if (!result) + { + return result; + } + + // + // XOBD Init ... + result = XOBDInitHandlers(); + if (!result) + { + return result; + } + + // + // XCLH Init ... + result = XCHLHInitHandlers(); + if (!result) + { + return result; + } + + // + // XCHMA Init ... + result = XCHMAInitHandlers(); + if (!result) + { + return result; + } + + // + result = true; + + // + return result; +} + +// +// Release Indicators ... +void XEU5ReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XAMAReleaseHandlers(); + XLHReleaseHandlers(); + XTDReleaseHandlers(); + XFIReleaseHandlers(); + XTSReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XEU5HandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xEU5CalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xEU5NumberOfItemsPerTick); + XAMAReadBuffers(xEU5NumberOfItemsPerTick); + XLHReadBuffers(xEU5NumberOfItemsPerTick); + XTDReadBuffers(xEU5NumberOfItemsPerTick); + XFIReadBuffers(xEU5NumberOfItemsPerTick); + XTSReadBuffers(xEU5NumberOfItemsPerTick); + XRSIReadBuffers(xEU5NumberOfItemsPerTick); + XOBDReadBuffers(xEU5NumberOfItemsPerTick); + XCHMAReadBuffers(xEU5NumberOfItemsPerTick); + XCHLHReadBuffers(xEU5NumberOfItemsPerTick); + + // + xEU5Provider.ReadConditions(); +} + +// +// +// START Combination Functions ... +// +// + +// +// Can Open Long Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Long Signals ... +bool XEU5CanOpenLongTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XEU5HasLongSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + xEU5Provider.ClearConditions(); + } + + // + return result; +} + +// +// Can Close Long Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Long Signals ... +bool XEU5CanCloseLongTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// Can Open Short Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Short Signals ... +bool XEU5CanOpenShortTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XEU5HasShortSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + xEU5Provider.ClearConditions(); + } + + // + return result; +} + +// +// Can Close Short Trade ... +// this is a Function will Check all market Conditions and get all +// Strategy requirement Verifications for Short Signals ... +bool XEU5CanCloseShortTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// Check Market Conditions by Combination of Power of All tools for LONGs ... +bool XEU5HasLongSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XEU5XTDHasLongSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XEU5XTAMHasLongSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XEU5XSIHasLongSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XTSFI ... + bool isXTSFIHasSignal = XEU5XTSFIHasLongSignal(); + if (isXTSFIHasSignal) + { + // + Add( + EnumToString(XTSFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XEU5XOBDLHHasLongSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XEU5XCHMACCHasLongSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMAMNHasSignal = XEU5XCHMAMNHasLongSignal(); + if (isXCHMAMNHasSignal) + { + // + Add( + EnumToString(XCHMAMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMAMXHasSignal = XEU5XCHMAMXHasLongSignal(); + if (isXCHMAMXHasSignal) + { + // + Add( + EnumToString(XCHMAMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXTSFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMAMNHasSignal + // + || + // + isXCHMAMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xEU5IsTestMode) + { + // + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + string message = xEU5Provider.GenerateConditionsString(mConditions); + + // + LogMessage( + "Long Signal Provided by: \n" + + info.signallers[ArraySize(info.signallers) - 1] + "\n" + + "Pusher: " + (string)ArraySize(info.signallers) + "\n" + + "Market Conditions: " + message); + } + } + + // + return result; +} + +// +// Check Market Conditions by Combination of Power of All tools for SHORTs ... +bool XEU5HasShortSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XEU5XTDHasShortSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XEU5XTAMHasShortSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XEU5XSIHasShortSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XTSFI ... + bool isXTSFIHasSignal = XEU5XTSFIHasShortSignal(); + if (isXTSFIHasSignal) + { + // + Add( + EnumToString(XTSFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XEU5XOBDLHHasShortSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XEU5XCHMACCHasShortSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMAMNHasSignal = XEU5XCHMAMNHasShortSignal(); + if (isXCHMAMNHasSignal) + { + // + Add( + EnumToString(XCHMAMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMAMXHasSignal = XEU5XCHMAMXHasShortSignal(); + if (isXCHMAMXHasSignal) + { + // + Add( + EnumToString(XCHMAMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXTSFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMAMNHasSignal + // + || + // + isXCHMAMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xEU5IsTestMode) + { + // + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + string message = xEU5Provider.GenerateConditionsString(mConditions); + + // + LogMessage( + "Short Signal Provided by: \n" + + info.signallers[ArraySize(info.signallers) - 1] + "\n" + + "Pusher: " + (string)ArraySize(info.signallers) + "\n" + + "Market Conditions: " + message); + } + } + + // + return result; +} + +// +// +// END Combination Signaling ... +// +// + +// +// START Signal Providers ... +// + +// +// Disbale All Signallers Longs ... +void XEU5DisableLongSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + // + xEU5Provider.DisbaleXTDLongs(); + xEU5MXTDAllowLongSignals = false; + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + // + xEU5Provider.DisbaleXTAMLongs(); + xEU5MXTAMAllowLongSignals = false; + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + // + xEU5Provider.DisbaleXSILongs(); + xEU5MXSIAllowLongSignals = false; + } + + // + // XTSFI ... + if (xEU5MXTSFIEnableSignaller) + { + // + xEU5Provider.DisbaleXTSFILongs(); + xEU5MXTSFIAllowLongSignals = false; + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + // + xEU5Provider.DisbaleXOBDLHLongs(); + xEU5MXOBDLHAllowLongSignals = false; + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + // + xEU5Provider.DisbaleXCHMACCLongs(); + xEU5MXCHMACCAllowLongSignals = false; + } + + // + // XCHMAMX ... + if (xEU5MXCHMAMXEnableSignaller) + { + // + xEU5Provider.DisbaleXCHMAMXLongs(); + xEU5MXCHMAMXAllowLongSignals = false; + } + + // + // XCHMAMN ... + if (xEU5MXCHMAMNEnableSignaller) + { + // + xEU5Provider.DisbaleXCHMAMNLongs(); + xEU5MXCHMAMNAllowLongSignals = false; + } +} + +// +// Enable All Signallers Longs ... +// Only if they are Configured as Enable at Settings ... +void XEU5EnableLongSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + // + xEU5MXTDAllowLongSignals = + xEU5XTDAllowLongSignals + ? true + : xEU5MXTDAllowLongSignals; + + // + if (xEU5MXTDAllowLongSignals) + { + xEU5Provider.EnableXTDLongs(); + } + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + // + xEU5MXTAMAllowLongSignals = + xEU5XTAMAllowLongSignals + ? true + : xEU5MXTAMAllowLongSignals; + + // + if (xEU5MXTAMAllowLongSignals) + { + xEU5Provider.EnableXTAMLongs(); + } + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + // + xEU5MXSIAllowLongSignals = + xEU5XSIAllowLongSignals + ? true + : xEU5MXSIAllowLongSignals; + + // + if (xEU5MXSIAllowLongSignals) + { + xEU5Provider.EnableXSILongs(); + } + } + + // + // XTSFI ... + if (xEU5MXTSFIEnableSignaller) + { + // + xEU5MXTSFIAllowLongSignals = + xEU5XTSFIAllowLongSignals + ? true + : xEU5MXTSFIAllowLongSignals; + + // + if (xEU5MXTSFIAllowLongSignals) + { + xEU5Provider.EnableXTSFILongs(); + } + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + // + xEU5MXOBDLHAllowLongSignals = + xEU5XOBDLHAllowLongSignals + ? true + : xEU5MXOBDLHAllowLongSignals; + + // + if (xEU5MXOBDLHAllowLongSignals) + { + xEU5Provider.EnableXOBDLHLongs(); + } + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + // + xEU5MXCHMACCAllowLongSignals = + xEU5XCHMACCAllowLongSignals + ? true + : xEU5MXCHMACCAllowLongSignals; + + // + if (xEU5MXCHMACCAllowLongSignals) + { + xEU5Provider.EnableXCHMACCLongs(); + } + } + + // + // XCHMAMX ... + if (xEU5MXCHMAMXEnableSignaller) + { + // + xEU5MXCHMAMXAllowLongSignals = + xEU5XCHMAMXAllowLongSignals + ? true + : xEU5MXCHMAMXAllowLongSignals; + + // + if (xEU5MXCHMAMXAllowLongSignals) + { + xEU5Provider.EnableXCHMAMXLongs(); + } + } + + // + // XCHMAMN ... + if (xEU5MXCHMAMNEnableSignaller) + { + // + xEU5MXCHMAMNAllowLongSignals = + xEU5XCHMAMNAllowLongSignals + ? true + : xEU5MXCHMAMNAllowLongSignals; + + // + if (xEU5MXCHMAMNAllowLongSignals) + { + xEU5Provider.EnableXCHMAMNLongs(); + } + } +} + +// +// Disable All Signallers Shorts ... +void XEU5DisableShortSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + // + xEU5Provider.DisableXTDShorts(); + xEU5MXTDAllowShortSignals = false; + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + // + xEU5Provider.DisableXTAMShorts(); + xEU5MXTAMAllowShortSignals = false; + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + // + xEU5Provider.DisableXSIShorts(); + xEU5MXSIAllowShortSignals = false; + } + + // + // XTSFI ... + if (xEU5MXTSFIEnableSignaller) + { + // + xEU5Provider.DisableXTSFIShorts(); + xEU5MXTSFIAllowShortSignals = false; + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + // + xEU5Provider.DisableXOBDLHShorts(); + xEU5MXOBDLHAllowShortSignals = false; + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + // + xEU5Provider.DisableXCHMACCShorts(); + xEU5MXCHMACCAllowShortSignals = false; + } + + // + // XCHMAMX ... + if (xEU5MXCHMAMXEnableSignaller) + { + // + xEU5Provider.DisableXCHMAMXShorts(); + xEU5MXCHMAMXAllowShortSignals = false; + } + + // + // XCHMAMN ... + if (xEU5MXCHMAMNEnableSignaller) + { + // + xEU5Provider.DisableXCHMAMNShorts(); + xEU5MXCHMAMNAllowShortSignals = false; + } +} + +// +// Enable All Signallers Shorts ... +// Only if they are Configured as Enable at Settings ... +void XEU5EnableShortSignallers() +{ + // + // XTD ... + if (xEU5MXTDEnableSignaller) + { + // + xEU5MXTDAllowShortSignals = + xEU5XTDAllowShortSignals + ? true + : xEU5MXTDAllowShortSignals; + + // + if (xEU5MXTDAllowShortSignals) + { + xEU5Provider.EnableXTDShorts(); + } + } + + // + // XTAM ... + if (xEU5MXTAMEnableSignaller) + { + // + xEU5MXTAMAllowShortSignals = + xEU5XTAMAllowShortSignals + ? true + : xEU5MXTAMAllowShortSignals; + + // + if (xEU5MXTAMAllowShortSignals) + { + xEU5Provider.EnableXTAMShorts(); + } + } + + // + // XSI ... + if (xEU5MXSIEnableSignaller) + { + // + xEU5MXSIAllowShortSignals = + xEU5XSIAllowShortSignals + ? true + : xEU5MXSIAllowShortSignals; + + // + if (xEU5MXSIAllowShortSignals) + { + xEU5Provider.EnableXSIShorts(); + } + } + + // + // XTSFI ... + if (xEU5MXTSFIEnableSignaller) + { + // + xEU5MXTSFIAllowShortSignals = + xEU5XTSFIAllowShortSignals + ? true + : xEU5MXTSFIAllowShortSignals; + + // + if (xEU5MXTSFIAllowShortSignals) + { + xEU5Provider.EnableXTSFIShorts(); + } + } + + // + // XOBDLH ... + if (xEU5MXOBDLHEnableSignaller) + { + // + xEU5MXOBDLHAllowShortSignals = + xEU5XOBDLHAllowShortSignals + ? true + : xEU5MXOBDLHAllowShortSignals; + + // + if (xEU5MXOBDLHAllowShortSignals) + { + xEU5Provider.EnableXOBDLHShorts(); + } + } + + // + // XCHMACC ... + if (xEU5MXCHMACCEnableSignaller) + { + // + xEU5MXCHMACCAllowShortSignals = + xEU5XCHMACCAllowShortSignals + ? true + : xEU5MXCHMACCAllowShortSignals; + + // + if (xEU5MXCHMACCAllowShortSignals) + { + xEU5Provider.EnableXCHMACCShorts(); + } + } + + // + // XCHMAMX ... + if (xEU5MXCHMAMXEnableSignaller) + { + // + xEU5MXCHMAMXAllowShortSignals = + xEU5XCHMAMXAllowShortSignals + ? true + : xEU5MXCHMAMXAllowShortSignals; + + // + if (xEU5MXCHMAMXAllowShortSignals) + { + xEU5Provider.EnableXCHMAMXShorts(); + } + } + + // + // XCHMAMN ... + if (xEU5MXCHMAMNEnableSignaller) + { + // + xEU5MXCHMAMNAllowShortSignals = + xEU5XCHMAMNAllowShortSignals + ? true + : xEU5MXCHMAMNAllowShortSignals; + + // + if (xEU5MXCHMAMNAllowShortSignals) + { + xEU5Provider.EnableXCHMAMNShorts(); + } + } +} + +// +// +// + +// +// XTD Long Signal Checking ... +bool XEU5XTDHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTDEnableSignaller || + !xEU5MXTDAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XTDHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTSCurrentMin && + mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + ((mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest) && + (mConditions.isXTSCurrentUnderMediest || + mConditions.isXTSCurrentCrossedUnderMediest) && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCLLSame) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHMASCCrossedOverMin && + mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + ( + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTSCurrentMax) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTSCurrentUnderNearest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXFICrossedOverZero && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ( + (mConditions.isXCHMAMCVale && + mConditions.isXTDBearishVale) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) + // + || + // + (mConditions.isXLHLLIncreased && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXTSCurrentUnderFarest && + (mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest)) + // + ) + // + ) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHMAMCTrendsDown) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ( + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + ( + // + ( + // + mConditions.isXAMANeutural + // + || + // + (mConditions.isXLHLLDecreased && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXAMAStartBullish) + // + ) + // + ) + // + ) + // + || + // + // + ((mConditions.isXTSCurrentMax && + mConditions.isXLHHHDecreased) && + ( + // + (mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCLLSame && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBullish && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBullish && + mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBearish && + mConditions.isXTDBearishVale && + mConditions.isXTMStartBullish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCVale && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBullish) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXCHMALCVale && + mConditions.isXTMStartBullish && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased) + // + || + // + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) + // + ) + // + ) + // + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXLHHHDecreased && + mConditions.isXFICrossedOverZero) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXAMAStartBearish && + mConditions.isXTDSignalCrossedOverBear) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTSCurrentUnderFarest && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXAMAVale && + mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXLHLLIncreased) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXFICrossedOverZero && + mConditions.isXTDSignalCrossedOverBear && + mConditions.isXLHPriceCrossedUnderSignal) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTSCurrentCrossedOverFarest && + mConditions.isXTSCurrentCrossedOverNearest && + mConditions.isXTSCurrentCrossedOverMediest && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXLHHHIncreased && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderMediest && + mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXCHMASCTrendsUp && + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXTDSignalCrossedOverBear && + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderNearest) + // + || + // + (mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderNearest) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTDBearishVale && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) + // + || + // + ((mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDSignalCrossedOverBear) && + ( + // + ( + // + mConditions.isXCHMASCCrossedOverMax + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXCHMASCCrossedOverMax && + mConditions.isXTDSignalCrossedOverBear) + // + || + // + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) + // + || + // + ((mConditions.isXTMNeutural && + mConditions.isXAMANeutural) && + ( + // + ( + // + (mConditions.isXTSCurrentUnderFarest || + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXTDSignalCrossedOverBear) + // + ) && + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + ( + // + mConditions.isXRSICrossedOverLongExit + // + || + // + (mConditions.isXTSAllSame && + mConditions.isXAMAStartBullish && + mConditions.isXTDSignalCrossedOverBear) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXAMAStartBullish) + // + || + // + ((mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest) && + (mConditions.isXTSCurrentUnderMediest || + mConditions.isXTSCurrentCrossedUnderMediest)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXTSCurrentMax || + mConditions.isXTSCurrentUnderFarest) && + mConditions.isXTDBearishVale && + mConditions.isXLHLLDecreased && + mConditions.isXLHPriceCrossedOverSignal && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + ((mConditions.isXCHLHSCMCHHSame && + mConditions.isXTDSignalCrossedOverBear) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXLHHighAttachedHH) + // + || + // + (mConditions.isXCHLHMCLCLLSame && + ( + // + (mConditions.isXCHMASCCrossedOverMin && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMASCCrossedOverMax && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) || + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + // + ( + // + ((mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest) && + (mConditions.isXTSCurrentUnderMediest || + mConditions.isXTSCurrentCrossedUnderMediest)) + // + ) + // + ) + // + ) + // + ) + // + || + // + (( + // + (mConditions.isXFICrossedOverZero && + mConditions.isXTDSignalCrossedOverBear) + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverMediest) + // + ) && + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentMax && + mConditions.isXCHMASCCrossedOverMax && + mConditions.isXTDSignalCrossedOverBear) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXAMAStartBullish) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCHHSame && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTMEndBullish && + mConditions.isXTDBearishVale && + mConditions.isXFICrossedOverZero && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXFICrossedOverZero && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXTSCurrentMax && + mConditions.isXTDSignalCrossedOverBear) && + ( + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) + // + || + // + (mConditions.isXAMAEndBullish && + mConditions.isXCHLHSCMCLLSame && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTD Short Signal Checking ... +bool XEU5XTDHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTDEnableSignaller || + !xEU5MXTDAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XTDHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTDBullOverBear && + mConditions.isXFICrossedOverZero && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTDBullOverBear && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXFIOverZero && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear) + // + || + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + ((mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish) && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXCHLHSameLLs && + mConditions.isXCHMAMCTrendsUp && + mConditions.isXLHLowAttachedLL) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullOverBear) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTDBullOverBear && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXCHMASCTrendsUp && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + mConditions.isXCHMASCTrendsUp + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverNearest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMALCTrendsDown && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTDBullOverBear && + (mConditions.isXAMANeutural || + mConditions.isXTSCurrentOverFarest)) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMASCTrendsUp) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTDBullOverBear && + ( + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTMEndBullish && + mConditions.isXAMAEndBullish && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + mConditions.isXCHMAMCTrendsUp + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTAM Long Signal Checking ... +bool XEU5XTAMHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTAMEnableSignaller || + !xEU5MXTAMAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XTAMHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXLHLLIncreased && + mConditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCLLSame) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + ) + // + ) + // + || + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + ((mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHMCLCLLSame) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMABearish && + mConditions.isXTMEndBearish && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHLHSCMCLLSame && + (mConditions.isXTSCurrentUnderFarest || + mConditions.isXTSCurrentUnderMediest)) + // + || + // + (mConditions.isXCHLHMCLCHHSame && + (mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest)) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXTSAllSame && + mConditions.isXCHMASCVale && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ( + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest && + mConditions.isXTDBullCrossedUnderBear) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXLHPriceCrossedOverSignal && + mConditions.isXTSCurrentCrossedOverFarest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMALCVale && + ( + // + mConditions.isXLHHHDecreased + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBearishVale) + // + ) + // + ) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHMASCFastCrossedOverSlow) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) && + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentMax && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXAMAStartBullish && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCVale || + mConditions.isXCHLHSameHHs) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHLHSameHHs && + mConditions.isXLHLLDecreased && + mConditions.isXLHHighAttachedHH) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBearishVale && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHMASCPeak && + (mConditions.isXCHMAMCTrendsDown || + mConditions.isXCHMAMCFastUnderSlow)) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBearish && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBearish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXFICrossedOverZero && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTAM Short Signal Checking ... +bool XEU5XTAMHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTAMEnableSignaller || + !xEU5MXTAMAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XTAMHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXFIOverZero && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentOverFarest) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTMNeutural || + mConditions.isXTMEndBullish) && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHMASCTrendsUp && + mConditions.isXTSCurrentOverNearest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHMASCTrendsUp) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXCHMASCPeak && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ( + // + mConditions.isXCHMAMCTrendsUp + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin && + mConditions.isXCHMALCTrendsUp && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + ((mConditions.isXAMAVale && + mConditions.isXCHMASCVale && + mConditions.isXTSCurrentMin) && + ( + // + mConditions.isXRSICrossedUnderShortExit + // + || + // + mConditions.isXTDBullishVale + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMin && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXLHLowAttachedLL) && + ( + // + mConditions.isXCHMALCTrendsDown + // + || + // + (mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXLHPriceCrossedUnderSignal) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + mConditions.isXRSICrossedUnderShortExit + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMBearish && + mConditions.isXCHMASCVale && + mConditions.isXAMABearish && + mConditions.isXCHLHSameLLs && + mConditions.isXTSCurrentMin && + mConditions.isXCHMASCTrendsUp && + mConditions.isXLHLowAttachedLL) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + ( + // + mConditions.isXRSICrossedUnderShortExit + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMASCVale && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin && + mConditions.isXLHLowAttachedLL) && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHLHSameLLs && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + ( + // + mConditions.isXRSICrossedUnderShortExit + // + || + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTDSignalVale && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullishVale) && + ( + // + (mConditions.isXTSAllSame && + mConditions.isXLHHHDecreased && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXLHLowAttachedLL && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXTSCurrentOverFarest) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear) && + ( + // + (mConditions.isXCHMASCTrendsUp && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + (mConditions.isXTDBullOverBear || + mConditions.isXTSCurrentOverFarest)) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + (mConditions.isXTSCurrentOverFarest || + mConditions.isXTSCurrentOverMediest)) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMin && + mConditions.isXCHMAMCTrendsUp && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMASCTrendsUp) + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish) + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXCHMALCVale && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHSCMCHHSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXTSCurrentMin && + mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedUnderZero && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest && + mConditions.isXTDBullCrossedUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSI Long Signal Checking ... +bool XEU5XSIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXSIEnableSignaller || + !xEU5MXSIAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XSIHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentUnderNearest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTSAllSame && + mConditions.isXCHLHSameLLs && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased && + mConditions.isXTMStartBullish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentUnderFarest) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBullish) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTSCurrentMin && + mConditions.isXTSCurrentMax) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish)) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBullish && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXAMAEndBearish && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + ((mConditions.isXTMVale && + mConditions.isXAMAVale) + // + && + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale) + // + && + // + (mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame)) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale) + // + || + // + (mConditions.isXTMVale && + mConditions.isXTMNeutural && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXAMAStartBullish && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale) + // + || + // + (mConditions.isXLHHHDecreased && + mConditions.isXLHLLDecreased) + // + || + // + ((mConditions.isXTMVale || + mConditions.isXTMNeutural || + mConditions.isXTMEndBearish) && + mConditions.isXAMANeutural) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHLHSCMCLLSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSI Short Signal Checking ... +bool XEU5XSIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXSIEnableSignaller || + !xEU5MXSIAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XSIHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXLHHHIncreased && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTDSignalOverBear) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTMBullish && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish)) && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMASCTrendsUp && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + || + // + ((mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) && + ( + // + (mConditions.isXFIOverZero && + mConditions.isXCHMAMCPeak && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCVale && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin && + mConditions.isXTMStartBearish && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest && + mConditions.isXTSCurrentCrossedUnderFarest && + mConditions.isXTSCurrentCrossedUnderNearest && + mConditions.isXTSCurrentCrossedUnderMediest) + // + )) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak) + // + || + // + (mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentOverNearest) + // + || + // + (((mConditions.isXTMBullish || + mConditions.isXTMStartBullish) && + (mConditions.isXAMABullish || + mConditions.isXAMAStartBullish)) && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCVale && + mConditions.isXLHHHIncreased && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXFIOverZero && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCHHSame) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXTMEndBullish && + mConditions.isXTSCurrentMin && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXAMAStartBearish) + // + || + // + ((mConditions.isXCHMASCPeak && + mConditions.isXTSCurrentOverFarest) && + ( + // + mConditions.isXTMNeutural + // + || + // + mConditions.isXTSCurrentOverMediest + // + || + // + (mConditions.isXTMBullish && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXLHHHIncreased) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMin && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish) + // + || + // + ((mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCVale) && + ( + // + (mConditions.isXLHHHIncreased && + mConditions.isXLHLLIncreased) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTSCurrentMin) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTDBullOverBear && + (mConditions.isXTDSignalOverBear || + mConditions.isXTDSignalCrossedOverBear)) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + (mConditions.isXFIOverZero || + mConditions.isXTSCurrentOverFarest)) + // + || + // + (mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTSCurrentMax && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMASCTrendsUp) + // + ) + // + ) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMASCTrendsUp) + // + || + // + ((mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCVale) && + ( + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXCHLHSCMCHHSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTSFI Long Signal Checking ... +bool XEU5XTSFIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTSFIEnableSignaller || + !xEU5MXTSFIAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XTSFIHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXAMAEndBearish && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + ((mConditions.isXTMNeutural && + mConditions.isXTSCurrentUnderMediest) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedUnderZero) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish) && + mConditions.isXCHLHSameHHs && + mConditions.isXLHLLIncreased && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBearishVale && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedUnderZero && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABearish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHMAMCTrendsDown && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMASCOverMax && + mConditions.isXCHMASCOverMin && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMAMCVale && + ( + // + mConditions.isXCHMALCVale + // + || + // + (mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + (mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXAMAStartBullish) + // + || + // + (mConditions.isXLHLLDecreased && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXTMNeutural || + mConditions.isXTMStartBullish) && + mConditions.isXLHHHDecreased && + (mConditions.isXAMANeutural || + mConditions.isXAMAStartBearish) && + mConditions.isXTSCurrentUnderMediest) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMAMCVale && + ( + // + mConditions.isXCHMALCVale + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCPeak && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish)) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish) && + mConditions.isXTMStartBearish) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + ((mConditions.isXCHLHSCMCHHSame && + mConditions.isXTSCurrentUnderMediest) && + ( + // + mConditions.isXCHMALCVale + // + || + // + (mConditions.isXCHMALCTrendsDown && + mConditions.isXTSCurrentCrossedUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXCHMALCVale && + mConditions.isXAMAStartBullish && + mConditions.isXFICrossedOverZero && + mConditions.isXTDBullCrossedOverBear && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXTDBearishVale && + mConditions.isXCHLHSCMCHHSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTSFI Short Signal Checking ... +bool XEU5XTSFIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXTSFIEnableSignaller || + !xEU5MXTSFIAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XTSFIHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMALCVale && + mConditions.isXCHLHMCLCLLSame) && + ( + // + mConditions.isXCHMASCTrendsDown + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBearish && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + (((mConditions.isXTMVale || + mConditions.isXTMNeutural) && + mConditions.isXAMANeutural) && + (mConditions.isXFIOverZero || + mConditions.isXFICrossedOverZero) && + mConditions.isXTSCurrentOverMediest) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalCrossedOverBear) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTSCurrentCrossedUnderNearest) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXTDBearishVale && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBullish) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXTMNeutural || + mConditions.isXTMEndBullish) && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish) && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXCHMALCPeak && + mConditions.isXTDBullOverBear && + (mConditions.isXFIOverZero || + mConditions.isXFICrossedOverZero)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXAMANeutural && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverMediest) && + ( + // + mConditions.isXTMNeutural + // + || + // + (mConditions.isXTMBullish && + mConditions.isXLHLLDecreased) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXFIOverZero && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXLHHHDecreased && + (mConditions.isXTMBullish || + mConditions.isXTMStartBullish) && + mConditions.isXAMABullish && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTDBullCrossedOverBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXLHHHDecreased && + mConditions.isXFICrossedOverZero && + mConditions.isXTDBullCrossedOverBear) + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXCHMALCPeak && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXFIOverZero && + mConditions.isXCHMALCPeak && + mConditions.isXLHHHDecreased && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTDBullCrossedUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBearish && + mConditions.isXTDBullUnderBear && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXTMBullish || + mConditions.isXTMStartBullish) && + (mConditions.isXAMABullish || + mConditions.isXAMAStartBullish) && + (mConditions.isXFIOverZero || + mConditions.isXFICrossedOverZero) && + mConditions.isXCHLHSameLLs) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMASCTrendsUp) + // + || + // + (mConditions.isXCHLHSameLLs && + mConditions.isXTDBearishVale && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXCHMALCPeak && + mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTSCurrentCrossedUnderFarest) + // + || + // + ((mConditions.isXCHMAMCVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest) && + ( + // + mConditions.isXTSCurrentUnderNearest + // + || + // + (mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMASCTrendsUp) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXLHHHDecreased && + mConditions.isXLHLLDecreased && + mConditions.isXTSCurrentOverMediest) + // + || + // + ((mConditions.isXFIOverZero && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish) + // + || + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + (mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMALCVale && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + mConditions.isXOBDSwingLow + // + || + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHLHSameLLs && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXTDBullCrossedUnderBear && + mConditions.isXTSCurrentCrossedOverMediest) + // + || + // + ((mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) && + ( + // + mConditions.isXCHMALCPeak + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentCrossedOverMediest) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXFIOverZero && + mConditions.isXTSCurrentCrossedOverMediest) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMBearish && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXFIOverZero && + mConditions.isXLHHHIncreased && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXFICrossedOverZero) + // + || + // + (mConditions.isXAMABearish && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHMCLCLLSame && + (mConditions.isXTMNeutural || + mConditions.isXTMEndBearish)) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXTMStartBearish && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderFarest) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXFICrossedUnderZero && + mConditions.isXTSCurrentCrossedUnderNearest) + // + || + // + ((mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXCHMALCPeak && + mConditions.isXCHMAMCVale) && + ( + // + mConditions.isXLHPriceCrossedUnderSignal + // + || + // + (mConditions.isXCHLHSCMCLLSame && + mConditions.isXFICrossedUnderZero && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + (((mConditions.isXTMBullish || + mConditions.isXTMNeutural || + mConditions.isXTMStartBullish) && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + (mConditions.isXTMStartBullish || + mConditions.isXTMEndBullish)) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXAMAStartBearish) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXFIOverZero && + mConditions.isXTMEndBearish && + mConditions.isXFICrossedOverZero) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCVale && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXCHMALCPeak && + mConditions.isXLHHHDecreased && + mConditions.isXCHLHSCMCLLSame) + // + || + // + ((mConditions.isXTMNeutural && + mConditions.isXAMAStartBearish) && + ( + // + (mConditions.isXCHLHSameLLs && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXLHHHDecreased) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTSCurrentOverMediest && + ( + // + ((mConditions.isXCHMALCVale && + mConditions.isXCHLHSCMCLLSame) && + ( + // + (mConditions.isXAMAVale && + mConditions.isXCHMASCUnderMax && + mConditions.isXCHMASCUnderMin) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXCHMASCTrendsUp && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + ((mConditions.isXCHMAMCVale && + mConditions.isXTSCurrentOverMediest) && + ( + // + mConditions.isXLHHHDecreased + // + || + // + mConditions.isXTSCurrentCrossedOverMediest + // + || + // + (mConditions.isXTMVale && + mConditions.isXTMNeutural && + mConditions.isXAMAVale && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMALCTrendsDown) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXFIOverZero && + mConditions.isXTMEndBearish && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXCHMALCPeak && + ( + // + mConditions.isXCHLHMCLCLLSame + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentCrossedOverMediest) + // + || + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDSignalUnderBear) && + ( + // + mConditions.isXTDBullCrossedUnderBear + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ( + // + ((mConditions.isXCHMALCVale && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXFIOverZero && + mConditions.isXCHMASCTrendsUp) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXLHHHIncreased && + mConditions.isXTMStartBearish && + mConditions.isXCHLHSCMCHHSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMASCVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + mConditions.isXCHLHSameLLs + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXFIOverZero && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXLHHHDecreased) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXLHHHDecreased && + mConditions.isXTSCurrentCrossedUnderNearest) + // + || + // + (mConditions.isXCHLHSCMCLLSame && + ( + // + (mConditions.isXCHLHMCLCHHSame && + ( + // + (mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXTMStartBearish) + // + || + // + ((mConditions.isXTMNeutural || + mConditions.isXTMEndBearish) && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish)) + // + || + // + (mConditions.isXTMVale && + mConditions.isXCHMAMCVale && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest) + // + ) + // + ) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish) + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXCHMAMCVale && + mConditions.isXTMEndBearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXCHMALCPeak && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMABearish && + mConditions.isXFIOverZero && + mConditions.isXCHMAMCVale && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABearish && + mConditions.isXCHMAMCVale && + mConditions.isXLHHHDecreased && + mConditions.isXFICrossedUnderZero && + mConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + ) + // + || + // + ((mConditions.isXAMAVale && + mConditions.isXCHMALCPeak) && + ( + // + mConditions.isXTMNeutural + // + || + // + (mConditions.isXTMVale && + mConditions.isXTMEndBearish && + mConditions.isXLHLLDecreased) + // + ) + // + ) + // + || + // + (mConditions.isXTMVale && + mConditions.isXTMNeutural && + mConditions.isXAMABearish && + mConditions.isXCHMAMCVale && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHMASCUnderMax && + mConditions.isXCHMASCUnderMin && + mConditions.isXTSCurrentOverMediest) && + ( + // + mConditions.isXCHMAMCTrendsDown + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMASCTrendsUp && + mConditions.isXTMStartBearish && + mConditions.isXTDBullOverBear && + mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + ((mConditions.isXCHMAMCVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXAMAVale && + mConditions.isXTMBullish) + // + || + // + (mConditions.isXAMAVale && + (mConditions.isXTMNeutural || + mConditions.isXTMEndBearish)) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXTMNeutural && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXCHLHMCLCLLSame && + mConditions.isXLHPriceCrossedOverSignal) + // + || + // + (mConditions.isXTDBullUnderBear && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentOverMediest) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXFIOverZero && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXAMABullish && + mConditions.isXTDBullCrossedOverBear) + // + ) + // + ) + // + || + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXLHLLIncreased && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMASCTrendsUp) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXCHMAMCTrendsUp && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXFIOverZero && + mConditions.isXCHMALCPeak) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXLHHHDecreased) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + ((mConditions.isXTMBullish || + mConditions.isXTMStartBullish) + // + && + // + (mConditions.isXAMABullish || + mConditions.isXAMAStartBullish)) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTDBullCrossedUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXLHPriceCrossedOverSignal) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXLHLLIncreased && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXLHHHIncreased && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMASCTrendsUp) + // + || + // + (mConditions.isXTSCurrentOverMediest && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBearish && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXCHMALCVale && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMASCTrendsUp) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsUp && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentOverMediest) + // + || + // + ((mConditions.isXTMBullish || + mConditions.isXTMStartBullish) && + (mConditions.isXAMABullish || + mConditions.isXAMAStartBullish) && + (mConditions.isXTSCurrentOverMediest || + mConditions.isXTSCurrentCrossedOverMediest)) + // + )) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + ((mConditions.isXTSCurrentOverMediest || + mConditions.isXTSCurrentCrossedOverMediest) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMAMCVale && + mConditions.isXLHHHDecreased && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXFIOverZero && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXTDBullCrossedUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXTMStartBearish) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHLHSameLLs) + // + ) + // + ) + // + || + // + (mConditions.isXCHMASCTrendsUp && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XOBDLH Long Signal Checking ... +bool XEU5XOBDLHHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXOBDLHEnableSignaller || + !xEU5MXOBDLHAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + XMarketConditions xMConditions2 = xEU5Provider.GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XOBDLHHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMALCVale && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHLHSCMCLLSame) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTSCurrentUnderFarest) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTMEndBearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXTMVale && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXAMAStartBearish) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame) + // + || + // + ((mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHSameLLs) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) + // + || + // + ((mConditions.isXCHMASCVale && + mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCLLSame) && + ( + // + mConditions.isXTSCurrentMax + // + || + // + mConditions.isXLHLowAttachedLL + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTSCurrentUnderFarest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXCHMALCPeak && + mConditions.isXTMEndBearish && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTDBearishVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXTMStartBearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXAMAStartBearish) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTSAllSame && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXTMStartBearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXLHLowAttachedLL) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXCHLHSameLLs) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXAMANeutural && + mConditions.isXTMStartBullish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XOBDLH Short Signal Checking ... +bool XEU5XOBDLHHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXOBDLHEnableSignaller || + !xEU5MXOBDLHAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XOBDLHHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + ((mConditions.isXTMNeutural && + mConditions.isXAMANeutural) && + ( + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMASCCrossedUnderMax) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp && + mConditions.isXCHMALCPeak && + mConditions.isXCHMALCTrendsUp) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXFIOverZero && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXTDBullOverBear) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTMEndBullish && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTMEndBullish) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMin && + mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXFIOverZero && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + ((mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak) && + ( + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverMediest && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak) && + ( + // + (mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullCrossedOverBear) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXCHMASCTrendsUp && + mConditions.isXCHMAMCTrendsUp) + // + || + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak) + // + ) + // + ) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak && + mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + ((mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak) && + ( + // + (mConditions.isXCHMAMCTrendsUp && + mConditions.isXCHMALCTrendsUp) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMASCTrendsUp && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMStartBullish && + mConditions.isXTDBullOverBear && + mConditions.isXAMAStartBullish && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMASCTrendsUp && + mConditions.isXCHMAMCTrendsUp) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak && + mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXFIOverZero && + mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentMax && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACC Long Signal Checking ... +bool XEU5XCHMACCHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACCEnableSignaller || + !xEU5MXCHMACCAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XCHMACCHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + ( + // + (mConditions.isXCHMALCPeak && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame && + (mConditions.isXTSCurrentOverFarest || + mConditions.isXTDSignalCrossedUnderBear)) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMANeutural && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXTMStartBullish && + mConditions.isXFICrossedUnderZero) + // + || + // + ( + (mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXAMAStartBullish) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXLHLLDecreased) + // + ) + // + ) + // + ) + // + ) + // + )) + // + || + // + (((mConditions.isXTMNeutural && + mConditions.isXTMEndBullish && + mConditions.isXFICrossedUnderZero) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear)) + // + && + // + (mConditions.isXCHMALCPeak && + ( + // + mConditions.isXCHMALCTrendsDown + // + || + // + (mConditions.isXCHLHMCLCHHSame && + (mConditions.isXTDSignalUnderBear || + mConditions.isXTDSignalCrossedUnderBear)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + ( + // + (mConditions.isXCHMALCPeak && + ( + // + (mConditions.isXTDSignalUnderBear && + ( + // + (mConditions.isXAMAVale && + mConditions.isXAMABearish) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMAStartBearish && + mConditions.isXFICrossedUnderZero) + // + || + // + ((mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish) && + mConditions.isXTMStartBullish && + mConditions.isXFICrossedOverZero) + // + || + // + (mConditions.isXCHLHMCLCHHSame && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDBullUnderBear) + // + ) + // + ) + // + || + // + ((mConditions.isXAMABearish && + (mConditions.isXTMNeutural || + mConditions.isXTMBearish)) && + mConditions.isXTSCurrentUnderMediest && + (mConditions.isXTDBullCrossedUnderBear || + (mConditions.isXTDBullUnderBear && + mConditions.isXFICrossedUnderZero))) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentOverFarest && + mConditions.isXLHPriceCrossedUnderSignal) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + ( + // + (mConditions.isXCHMALCPeak && + ( + // + (mConditions.isXTSCurrentMax && + ( + // + (mConditions.isXAMABearish && + mConditions.isXTDBullCrossedOverBear) + // + || + // + (mConditions.isXTMStartBullish && + ( + // + ( + // + mConditions.isXAMAStartBullish + // + || + // + (mConditions.isXAMAEndBearish && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + (mConditions.isXLHLLDecreased && + mConditions.isXTMStartBullish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMEndBullish && + mConditions.isXAMAEndBullish) + // + || + // + (mConditions.isXTSCurrentMax && + (mConditions.isXTMBullish || + mConditions.isXTMStartBullish) && + (mConditions.isXAMABullish || + mConditions.isXAMAStartBullish) && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + mConditions.isXTDBearishVale + // + || + // + mConditions.isXRSICrossedOverLongExit + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXTDSignalUnderBear && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXTSCurrentUnderFarest) + // + ) + // + ) + // + ) + // + ) + // + || + // + (mConditions.isXCHMASCTrendsDown && + ( + // + (mConditions.isXCHMALCPeak && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXFIUnderZero && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXLHPriceCrossedOverSignal) + // + ) + // + ) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsDown)) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMALCPeak && + ( + // + ( + // + mConditions.isXCHMALCTrendsDown + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + ( + mConditions.isXTDSignalUnderBear && + ( + // + mConditions.isXTSAllSame + // + || + // + ((mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest)) + // + ) + // + ) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHMALCTrendsUp && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXLHPriceCrossedOverSignal && + (mConditions.isXCHMAMCTrendsDown && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow))) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXCHMAMCTrendsDown) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + (mConditions.isXCHMALCTrendsDown && + ( + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + ) + // + ) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHLHSameHHs && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderNearest) + // + || + // + ( + (mConditions.isXAMABullish && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBullish && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXTSCurrentMax) && + ( + // + (mConditions.isXTDBullOverBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTDBullCrossedOverBear && + mConditions.isXLHPriceCrossedOverSignal) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + ( + (mConditions.isXCHMAMCTrendsDown && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish) + // + || + (mConditions.isXLHLLDecreased && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXCHMAMCPeak && + ( + // + (mConditions.isXTDBearishVale && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + )) + // + || + // + (mConditions.isXCHMASCPeak && + mConditions.isXCHLHSameHHs && + (mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest) && + (mConditions.isXTSCurrentUnderMediest || + mConditions.isXTSCurrentCrossedUnderMediest)) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + ( + // + (mConditions.isXCHMALCPeak && + mConditions.isXTMNeutural && + mConditions.isXTMEndBullish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCTrendsDown && + ( + // + (((mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax) && + ( + // + mConditions.isXCHLHMCLCHHSame + // + || + // + (mConditions.isXTDSignalUnderBear && + mConditions.isXCHMALCPeak) + // + || + // + (mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedOverZero) + // + ) + // + ) + // + ) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXCHMAMCPeak && + mConditions.isXTMEndBullish && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTSCurrentUnderNearest) + // + ) + // + ) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHMALCPeak && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + ( + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHLHSCMCHHSame) && + ( + // + mConditions.isXTSCurrentUnderNearest + // + || + // + (mConditions.isXLHLLIncreased && + mConditions.isXTDBullUnderBear && + mConditions.isXLHHighAttachedHH && + mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedUnderZero) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMALCTrendsDown && + ( + // + (mConditions.isXCHMALCPeak && + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentMax && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXTMBullish && + mConditions.isXAMABullish && + (mConditions.isXTSCurrentMin || + mConditions.isXTSCurrentMax)) && + ( + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHLHSameHHs && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXLHLLIncreased && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXTDBullUnderBear && + mConditions.isXLHHighAttachedHH && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACC Short Signal Checking ... +bool XEU5XCHMACCHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMACCEnableSignaller || + !xEU5MXCHMACCAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XCHMACCHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTDBullOverBear && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBullish && + mConditions.isXTDSignalOverBear && + mConditions.isXTSCurrentOverFarest) + // + || + // + ((mConditions.isXFIOverZero && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) && + ( + // + (mConditions.isXAMAStartBearish && + mConditions.isXFICrossedOverZero) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXAMAStartBullish) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + ( + // + // + ((mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXLHLLIncreased && + mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentOverNearest) + // + || + // + (((mConditions.isXTMNeutural || + mConditions.isXTMEndBearish) && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBullish)) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXTSAllSame && + mConditions.isXCHMAMCTrendsDown) + // + ) + // + ) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin && + mConditions.isXCHMALCTrendsUp && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMALCVale && + ( + // + ((mConditions.isXTMEndBearish || + mConditions.isXTMNeutural) && + (mConditions.isXAMABearish || + mConditions.isXAMANeutural) && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear && + mConditions.isXFICrossedOverZero && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBearish && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXCHMALCVale && + ( + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTMStartBearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentOverMediest) + // + || + // + ((mConditions.isXTMNeutural || + mConditions.isXTMEndBearish) && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish) && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest) + // + || + // + ((mConditions.isXTMNeutural && + mConditions.isXAMABearish && + mConditions.isXTMEndBearish && + mConditions.isXTDBullOverBear) && + ( + // + mConditions.isXCHLHSCMCLLSame + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXFICrossedOverZero && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentCrossedOverFarest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullOverBear && + mConditions.isXAMAStartBearish && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) && + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXTSCurrentMin && + mConditions.isXCHMASCUnderMin) + // + ) + // + ) + // + || + // + ((mConditions.isXTMStartBearish && + mConditions.isXTDBullOverBear && + mConditions.isXAMAStartBearish) && + ( + // + (mConditions.isXTSCurrentMin && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTSCurrentOverFarest && + mConditions.isXLHPriceCrossedUnderSignal) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + ( + // + mConditions.isXCHMALCTrendsDown + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXFIOverZero && + mConditions.isXFICrossedOverZero) + // + || + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin) && + ( + // + (mConditions.isXFICrossedUnderZero && + mConditions.isXTDBullCrossedUnderBear) + // + || + // + (mConditions.isXCHMALCTrendsUp && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTDBullOverBear && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXFICrossedUnderZero && + mConditions.isXLHPriceCrossedUnderSignal) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCTrendsDown && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXTSCurrentOverNearest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMASCTrendsDown && + mConditions.isXTSCurrentOverNearest) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXTSCurrentOverNearest || + mConditions.isXTSCurrentCrossedOverNearest) && + (mConditions.isXTSCurrentOverFarest || + mConditions.isXTSCurrentCrossedOverFarest)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMin) && + ( + // + ((mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMALCTrendsUp) + // + || + // + ((mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMASCVale) + // + || + // + ((mConditions.isXCHLHSameLLs && + mConditions.isXLHHHIncreased && + mConditions.isXLHLowAttachedLL) && + ( + // + mConditions.isXCHMAMCTrendsDown + // + || + // + mConditions.isXCHMASCCrossedUnderMin + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCVale && + mConditions.isXTDBullCrossedUnderBear) && + ( + // + (mConditions.isXCHLHSCMCLLSame && + mConditions.isXLHLowAttachedLL) + // + || + // + (mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHMALCTrendsDown && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMAMCVale && + mConditions.isXTSCurrentMin && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + ((mConditions.isXAMABearish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) && + ( + // + (mConditions.isXTMEndBearish && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTSCurrentMin && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + ((mConditions.isXTMBearish && + mConditions.isXAMABearish) && + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverNearest) + // + || + // + (mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + ( + // + ((mConditions.isXTMNeutural && + mConditions.isXAMANeutural) && + ( + // + (mConditions.isXCHMAMCTrendsDown && + mConditions.isXTSCurrentOverMediest) + // + || + // + (mConditions.isXFIUnderZero && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullUnderBear && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest && + mConditions.isXTSCurrentCrossedUnderFarest && + mConditions.isXTSCurrentCrossedUnderNearest && + mConditions.isXTSCurrentCrossedUnderMediest) + // + ) + // + ) + // + || + // + (mConditions.isXTSCurrentOverFarest && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXTMEndBearish && + mConditions.isXAMAEndBearish && + mConditions.isXTDBullOverBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMANeutural && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXFIOverZero && + mConditions.isXTMStartBullish && + mConditions.isXTDBullOverBear && + mConditions.isXAMAStartBullish && + mConditions.isXTSCurrentOverNearest) + // + ) + // + ) + // + || + // + ((mConditions.isXTDSignalVale && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullishVale && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMANeutural) + // + ) + // + ) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMANeutural && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMin && + mConditions.isXCHMASCOverMin && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXCHMASCUnderMax && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest && + mConditions.isXTSCurrentOverNearest) + // + || + // + ((mConditions.isXTMNeutural || + mConditions.isXTMEndBearish) && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish) && + mConditions.isXFIOverZero && + mConditions.isXTDBullOverBear && + mConditions.isXFICrossedOverZero && + mConditions.isXTSCurrentOverNearest) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXFIOverZero && + mConditions.isXTSCurrentMax && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMin) && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXLHLLIncreased && + mConditions.isXCHMALCTrendsUp && + mConditions.isXAMAStartBearish) + // + || + // + ((mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXLHLLIncreased && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTSCurrentMin && + mConditions.isXAMAEndBullish && + mConditions.isXTMStartBearish && + mConditions.isXTDBullOverBear && + mConditions.isXCHMAMCTrendsDown) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMin && + mConditions.isXTDBullUnderBear && + mConditions.isXCHMALCTrendsDown && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderNearest && + mConditions.isXTSCurrentUnderMediest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMAMN Long Signal Checking ... +bool XEU5XCHMAMNHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMAMNEnableSignaller || + !xEU5MXCHMAMNAllowLongSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XCHMAMNHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown) && + ( + // + ( + // + (mConditions.isXCHMALCVale && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased && + mConditions.isXLHLLDecreased && + mConditions.isXTMStartBullish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased && + mConditions.isXLHLLDecreased && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + (((mConditions.isXTMVale || + mConditions.isXTMNeutural) && + mConditions.isXTMEndBearish) && + (mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish) && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + // LC Vale ... + (mConditions.isXCHMALCVale && + ( + // + (mConditions.isXCHMAMCVale && + ( + // + (mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + mConditions.isXCHMASCTrendsDown + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXLHLLIncreased && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + || + // + ((mConditions.isXCHMAMCVale && + mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown) && + ( + // + ((mConditions.isXCHMASCPeak && + mConditions.isXCHMALCVale) && + ( + // + mConditions.isXCHMAMCVale + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXLHHHDecreased && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDSignalUnderBear && + mConditions.isXTSCurrentUnderNearest) + // + || + // + (mConditions.isXCHMALCVale && + ( + // + mConditions.isXCHMASCTrendsDown + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXTMStartBullish && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCTrendsDown && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + (mConditions.isXCHLHMCLCHHSame || + mConditions.isXCHLHMCLCLLSame) && + mConditions.isXTSCurrentUnderNearest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown) && + ( + // + mConditions.isXCHMALCVale + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + ((mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale) + // + || + // + (mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMax && + mConditions.isXTDBullUnderBear) + // + ) + // + ) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXTDSignalUnderBear) + // + || + // + mConditions.isXCHMASCTrendsDown + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + // LC Vale ... + (mConditions.isXCHMALCVale && + ( + // + (mConditions.isXCHMAMCVale && + ( + // + (mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXTDBullUnderBear && + mConditions.isXLHHighAttachedHH && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMAMN Short Signal Checking ... +bool XEU5XCHMAMNHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMAMNEnableSignaller || + !xEU5MXCHMAMNAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XCHMAMNHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSAllSame && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXTMBearish || + mConditions.isXTMNeutural) && + mConditions.isXAMANeutural && + mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXLHLLIncreased && + mConditions.isXTSCurrentOverNearest) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentOverFarest) && + ( + // + (mConditions.isXFIOverZero && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBullish && + mConditions.isXTMStartBearish) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXTSCurrentMax && + mConditions.isXTSCurrentOverNearest && + mConditions.isXTSCurrentOverMediest && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMALCVale && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedUnderZero && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + mConditions.isXRSICrossedUnderShortExit + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXTSCurrentOverFarest && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMAStartBearish) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXAMANeutural && + mConditions.isXTMEndBearish && + mConditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMAMX Long Signal Checking ... +bool XEU5XCHMAMXHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMAMXEnableSignaller || + !xEU5MXCHMAMXAllowLongSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XCHMAMXHasLongConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMALCPeak && + ( + // + (mConditions.isXCHMALCTrendsDown && + ( + // + ( + // + mConditions.isXCHMASCPeak + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHLHSameHHs && + mConditions.isXLHHighAttachedHH && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXLHHHDecreased && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXLHPriceCrossedOverSignal) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + || + // + (((mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMALCTrendsDown) || + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown) || + (mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown)) && + ( + // + (mConditions.isXCHMAMCPeak + // + || + // + mConditions.isXRSICrossedOverLongExit) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHLHSCMCHHSame) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMASCTrendsDown && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMAMX Short Signal Checking ... +bool XEU5XCHMAMXHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xEU5MXCHMAMXEnableSignaller || + !xEU5MXCHMAMXAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xEU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xEU5Provider.XCHMAMXHasShortConditions() + // + && + // + // Exceptions: + // there some commonly Exceptions which makes our choice incorrect, + // here we are combined knownly Exceptions ... + !( + // + // for Exception we used XLH Conditions as follow ... + // + // Check Conditions if Price In Signal Range ... + (mConditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceInSignalRange ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXCHMASCVale && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMin) + // + || + // + (((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + (mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentOverFarest) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak) + // + || + // + (mConditions.isXTSCurrentMin && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXAMAStartBearish) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXLHHHIncreased && + mConditions.isXTDBullOverBear && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMAMCTrendsUp && + mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentMin && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXLHLowAttachedLL) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceInSignalRange ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((mConditions.isXLHPriceUnderSignal || + mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceUnderSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + ((mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak) && + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale) + // + || + // + (mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + || + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMALCPeak && + mConditions.isXTSCurrentMin && + mConditions.isXCHMAMCTrendsDown) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXTMBearish && + mConditions.isXCHMAMCPeak && + mConditions.isXAMAStartBearish && + mConditions.isXTSCurrentOverFarest) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXTSCurrentMin && + mConditions.isXLHHHDecreased && + mConditions.isXTMStartBearish && + mConditions.isXCHMALCTrendsUp && + mConditions.isXAMAStartBearish) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + mConditions.isXCHMALCPeak + // + || + // + (mConditions.isXTSAllSame && + mConditions.isXAMAEndBullish && + mConditions.isXTMStartBearish && + mConditions.isXTDBullOverBear && + mConditions.isXLHLowAttachedLL) + // + ) + // + ) + // + || + // + (((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) && + ( + // + ( + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXLHLowAttachedLL) && + ( + // + (mConditions.isXTSCurrentMin && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXTDBullOverBear && + mConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceUnderSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXCHLHSameLLs && + mConditions.isXTSCurrentMin && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXLHLowAttachedLL) + // + ) + // + ) + // + || + // + (mConditions.isXTSCurrentMin && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXLHLowAttachedLL && + ((mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((mConditions.isXLHPriceOverSignal || + mConditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceOverSignal ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMAMCPeak && + mConditions.isXTSCurrentMin && + mConditions.isXCHMAMCTrendsUp) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMASCVale && + mConditions.isXTSCurrentMin && + mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXTMBearish && + mConditions.isXCHMAMCPeak && + mConditions.isXAMANeutural && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame) && + ( + // + mConditions.isXTSCurrentOverFarest + // + || + // + (mConditions.isXTSCurrentMin && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + ((mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) && + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMALCPeak && + mConditions.isXAMANeutural && + mConditions.isXTMStartBearish) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMASCTrendsUp && + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXFIUnderZero && + (mConditions.isXTMBearish || + mConditions.isXTMStartBearish) && + (mConditions.isXAMABearish || + mConditions.isXAMAStartBearish) && + (mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // PriceOverSignal ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!mConditions.isXLHPriceOverSignal && + !mConditions.isXLHPriceUnderSignal && + !mConditions.isXLHPriceInSignalRange && + !mConditions.isXLHPriceCrossedOverSignal && + !mConditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // PriceFree ... + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // PriceFree ... + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// END Signal Providers ... +// diff --git a/XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 b/XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 new file mode 100644 index 0000000..03e0a50 --- /dev/null +++ b/XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 @@ -0,0 +1,280 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XEU5 Signal Provider Library Inputs +// ----------------------------------------------------------- +// +// 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 Logger ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Classes ... +#include "../Classes/x-saherelm.class.lib.mq5" + +// +input group "XEU5 Provider"; + +// +// Commonly Used Configurations ... +input group "XEU5 Common"; +// +// Provider ... +input bool xEU5EnableProvider = true; // Enable Provider +input int xEU5NumberOfItemsPerTick = 30; // Number Of items Readed In Each Tick +// +// Alerts ... +input bool xEU5EnableAlerts = true; // Enable Events Alert +input bool xEU5EnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xEU5EnableDailyAlerts = false; // Send Alert on each new Day +input bool xEU5EnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xEU5EnableMonthlyAlerts = true; // Send Alert on each new Month +// +// Reports ... +input bool xEU5EnableDailyReports = false; // Send Report on each new Day +input bool xEU5EnableWeeklyReports = false; // Send Report on each new Week +input bool xEU5EnableMonthlyReports = true; // Send Report on each new Month + +// +// Trader and Expert Specific Configurations ... +input group "XEU5 Trader"; +input int xEU5MagicNumber = 16940560; // Trader MagicNumber +input int xEU5Slippage = 10; // Trader Slippage + +// +// Trades Management Configurations ... +input group "XEU5 Trade Management"; +input bool xEU5AllowLongTrades = true; // Allow Long Trades +input bool xEU5AllowShortTrades = true; // Allow Short Trades + +// +// Risk Management Configurations ... +input group "XEU5 Risk Management"; +// +input bool xEU5UseVirtualTPSl = false; // Use Virtual TP SL +// +// Trade Count ... +input int xEU5MaxAllowedTrades = 10; // Max Allowed Trades at Same Time +input ENUM_X_CROSS_SIGNAL_METHOD xEU5CrossSignalsMethod = X_CROSS_SIGNAL_REGULAR; // Handle Cross Signals Method +// +// Max Allowed Trade Age ... +input int xEU5MaxAllowedTradeAge = 1500; // Detect Long Time Trades +input ENUM_X_GUARD_ACTIONS xEU5OldTradesAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1; // What to do with Old Trades +// +// Trade Volume Specific Configurations ... +input double xEU5StaticVolumeFactor = 0.0002; // Static Volume baesd on Balance +input ENUM_STATIC_VOLUME_METHODS xEU5StaticVolumeMethod = X_STATIC_VOLUME_BASED_ON_BALANCE; // How to Calculate Static Volume +input double xEU5VolumeMultiplier = 0; // Volume Increase Multiplier +input double xEU5ApplyVolumeMultiplierFactor = 0; // Apply Volume Multiplier Rate based on Balance +input double xEU5MaxSupportedVolumePerTradeFactor = 0; // Max Supported Volume Per Trade Factor based on Balance +input double xEU5IncreasedMaxSupportedVolumeRate = 0; // Increase Max Supported Volume based on Balance +// +// Trade Profits ... +input double xEU5MinRewardInPips = 15; // Minimum Reward Per Trade in Pips +input double xEU5RiskFreeStepInPips = 6; // Make Trades Risk Free Steps in Pips +input double xEU5RiskFreeRate = 0.6; // Volume Multiplier for Risk Free Trades +// +// Guard Riskable Money and Profits ... +input double xEU5CriticalDrawDownFactor = 0.40; // Critical Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xEU5CriticalGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5; // Specify Guard Action on Critical Drawdown +input double xEU5MaxAllowedDrawDownFactor = 0.45; // Max Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xEU5MaxAllowedGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10; // Specify Guard Action on Max Allowed Drawdown +input int xEU5GuardStopoutFiredAfterTouches = 5; // Guard Stopout all Trades if Max Allowed Drawdown touched + +// +// Account Conditions for Trading ... +input double xEU5BalanceFactorForOpenTrades = 0.5; // Minimum Balance for Open Trades +input double xEU5FreeMarginFactorForOpenTrades = 0.8; // Minimum Free Margin for Open Trades + +// +// Validate Inputs before Initialization ... +bool XEU5ValidateInputs() +{ + // + bool result = false; + + // + // Implement Other Verifications ... + + // + // Check Trading Availability ... + bool isTradeAvailable = xEU5AllowLongTrades || xEU5AllowShortTrades; + if (!isTradeAvailable) + { + LogMessage("XEU5 => Warning: Trading disabled ..."); + } + + // + // Chekc Number of reading items per tick ... + result = xEU5NumberOfItemsPerTick >= 5; + if (!result) + { + // + LogMessage("XEU5 invalid Number of items Reading Per Tick ..."); + + // + return result; + } + + // + // Check Max Allowed Trades Count ... + result = isTradeAvailable && xEU5MaxAllowedTrades >= 1; + if (!result) + { + // + LogMessage("XEU5 Number of Trades not valid ..."); + + // + return result; + } + + // + // Check Free Margin ... + result = + isTradeAvailable && + xEU5FreeMarginFactorForOpenTrades > 0 && + xEU5FreeMarginFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XEU5 Invalid Free Margin ..."); + + // + return result; + } + + // + // Check min Balance for Open Trades ... + result = + isTradeAvailable && + xEU5BalanceFactorForOpenTrades > 0 && + xEU5BalanceFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XEU5 Invalid Min Balance for Open Trades ..."); + + // + return result; + } + + // + // Check Min Reward Per Trade ... + result = xEU5MinRewardInPips > 0; + if (!result) + { + // + LogMessage("XEU5 Invalid Min Reward Per Trade ..."); + + // + return result; + } + + // + // Check Trades Volume ... + result = xEU5StaticVolumeFactor > 0; + if (!result) + { + // + LogMessage("XEU5 Invalid Static Volume ..."); + + // + return result; + } + + // + // Check Volume Multiplier ... + result = xEU5VolumeMultiplier >= 0; + if (!result) + { + // + LogMessage("XEU5 Invalid Volume Multiplier ..."); + + // + return result; + } + + // + result = + xEU5CriticalDrawDownFactor == 0 || (xEU5CriticalDrawDownFactor > 0 && + xEU5CriticalDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XEU5 Invalid Critical DrawDown Factor ..."); + + // + return result; + } + + // + result = + xEU5MaxAllowedDrawDownFactor == 0 || (xEU5MaxAllowedDrawDownFactor > 0 && + xEU5MaxAllowedDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XEU5 Invalid Max Allowed DrawDown Factor ..."); + + // + return result; + } + + // + // Check Guard Actions ... + // + result = + xEU5CriticalDrawDownFactor > 0 && + xEU5CriticalDrawDownFactor < 1 && + xEU5MaxAllowedDrawDownFactor > 0 && + xEU5MaxAllowedDrawDownFactor < 1; + if (!result) + { + // + LogMessage("XEU5 For Critical Drawdown, you have to Specify Max Drawdown also ..."); + + // + return result; + } + + // + result = xEU5CriticalDrawDownFactor > 0 && xEU5CriticalDrawDownFactor < xEU5MaxAllowedDrawDownFactor; + if (!result) + { + // + LogMessage("XEU5 Critical Drawdown must Smaller than Max Drawdown ..."); + + // + return result; + } + + // + if (xEU5CriticalDrawDownFactor > 0 && xEU5CriticalGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XEU5 IMPORTANT you Specified Critical Drawdown, but there is no any Guard Action ..."); + } + + // + if (xEU5MaxAllowedDrawDownFactor > 0 && xEU5MaxAllowedGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XEU5 IMPORTANT you Specified Max Allowed Drawdown, but there is no any Guard Action ..."); + } + + // + result = true; + + // + return result; +} \ No newline at end of file diff --git a/XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 b/XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 new file mode 100644 index 0000000..c57de45 --- /dev/null +++ b/XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 @@ -0,0 +1,1370 @@ +//////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XEU5 Signal Provider Library +// -------------------------------------------------------- +// Name: XEU5SignalProvider +// Description: XEU5 based 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 + +#define XEU5ProviderName "XEU5" + +// +// START Inputs ... +// + +#include "x-saherelm.xeu5.provider.inputs.lib.mq5"; + +// +// END Inputs ... +// + +// +// 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 Class Libraries ... +#include "../Classes/x-saherelm.class.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +XCGuard *xEU5Guard; +XCTrade *xEU5Trader; +XCReporter *xEU5Reporter; +XCCollector *xEU5Collector; +XCAccountInfo *xEU5AccountInfo; +XCVolumeManager *xEU5VolumeManager; + +// +#include "x-saherelm.xeu5.provider.indicators.lib.mq5" + +// +// Controlling Variables ... +bool xEU5MEnableProvider = false; +bool xEU5MAllowLongTrades = false; +bool xEU5MAllowShortTrades = false; + +// +double xEU5Deposit = 0; +double xEU5Balance = 0; +double xEU5MinReward = 0; +double xEU5FreeMargin = 0; +double xEU5BalanceForOpenTrades = 0; +double xEU5FreeMarginForOpenTrades = 0; + +// +// Guard ... +double xEU5CriticalDrawDown = 0; +double xEU5MaxAllowedDrawDown = 0; + +// +double xEU5MaxDrawUp = 0; +double xEU5MaxDrawDown = 0; + +// +int NOT_ENOUGH_MONEY_ERROR = 4756; +const string XEU5_SUPPORT_ID = "SP"; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// Initial Library if required ... +bool XEU5InitSignalProviderLibrary() +{ + // + bool result = false; + + // + if (!xEU5EnableProvider) + { + return result; + } + + // + // Controlling Variables ... + xEU5MEnableProvider = xEU5EnableProvider; + xEU5MAllowLongTrades = xEU5AllowLongTrades; + xEU5MAllowShortTrades = xEU5AllowShortTrades; + + // + // Validate Inputs ... + result = XEU5ValidateInputs(); + if (!result) + { + return result; + } + + // + // Init Indicators ... + result = XEU5InitIndicators(); + if (!result) + { + return result; + } + + // + xEU5Reporter = new XCReporter(); + xEU5Collector = new XCCollector(); + xEU5AccountInfo = new XCAccountInfo(); + + // + // Calculate Account Deposit ... + xEU5Deposit = xEU5AccountInfo.GetInitialBalance(); + + // + // Prepare Min Reward ... + if (xEU5MinRewardInPips > 0) + { + xEU5MinReward = PipsToPrice(xEU5MinRewardInPips); + } + + // + // Calculate Min Balance for Trades ... + if (xEU5BalanceFactorForOpenTrades > 0) + { + xEU5BalanceForOpenTrades = xEU5BalanceFactorForOpenTrades * xEU5Deposit; + } + + // + // Claculate Min Free Marging for Trades ... + if (xEU5FreeMarginFactorForOpenTrades > 0) + { + xEU5FreeMarginForOpenTrades = xEU5FreeMarginFactorForOpenTrades * xEU5Deposit; + } + + // + // Calculate Init Time Critical DrawDown Value ... + if (xEU5CriticalDrawDownFactor > 0) + { + xEU5CriticalDrawDown = xEU5CriticalDrawDownFactor * xEU5Deposit; + } + + // + // Calculate Init Time Max Allowed DrawDown Value ... + if (xEU5MaxAllowedDrawDownFactor > 0) + { + xEU5MaxAllowedDrawDown = xEU5MaxAllowedDrawDownFactor * xEU5Deposit; + } + + // + // Instant Volume Manager ... + xEU5VolumeManager = new XCVolumeManager( + xEU5StaticVolumeFactor, + xEU5StaticVolumeMethod, + xEU5VolumeMultiplier, + xEU5ApplyVolumeMultiplierFactor, + xEU5MaxSupportedVolumePerTradeFactor, + xEU5IncreasedMaxSupportedVolumeRate); + + // + // Make XCTrader instance ... + xEU5Trader = new XCTrade( + XEU5ProviderName, + _Symbol, + xEU5Slippage, + xEU5MagicNumber, + xEU5UseVirtualTPSl, + xEU5MaxAllowedTrades, + xEU5FreeMarginForOpenTrades, + xEU5BalanceForOpenTrades); + + // + // Instantiate Account Guard ... + xEU5Guard = new XCGuard( + // + // Old Trades ... + xEU5MaxAllowedTradeAge, + xEU5OldTradesAction, + // + // Critical DrawDown ... + xEU5CriticalDrawDownFactor, + xEU5CriticalGuardAction, + // + // Max Allowed DrawDown ... + xEU5MaxAllowedDrawDownFactor, + xEU5MaxAllowedGuardAction, + xEU5GuardStopoutFiredAfterTouches, + // + // xEU5GuardSupportMethod + X_SUPPORT_DO_NOTHING + // + ); + + // + // Reset Calculations Buffers and Variables ... + XEU5ResetCollectors(); + + // + XEU5UpdateReports(); + + // + result = true; + + // + // Logging State ... + XEU5IssueInitializationSucceedAlert(); + + // + return result; +} + +// +// DeInitial Library if required ... +void XEU5DeinitSignalProviderLibrary(const int reason) +{ + // + // Release Handlers ... + XEU5ReleaseIndicators(); + + // + // Logging State ... + XEU5IssueDeinitializationSucceedAlert(); +} + +// +// this is a Globally Function which do all of +// checkings and positions handling ... +void XEU5SignalProviderHandleTick() +{ + // + // Check Provider is Enable or Not ... + if (!xEU5MEnableProvider) + { + return; + } + + // + XEU5SignalProviderDoControlState(); + + // + // Reading Indicator Buffers ... + XEU5HandleReadingBuffers(); + if (xEU5CalculatedBars < xEU5MaxLengthOfInputs) + { + return; + } + + // + // Handle Open Trades ... + XEU5HandleOpenTrades(); + + // + // Handle Close Trades ... + XEU5HandleCloseTrades(); + + // + // DrawDown and DrawUp ... + XEU5HandleCalculateDrawDownUp(); +} + +// +// Do Control Checks here ... +void XEU5SignalProviderDoControlState() +{ + // + // Update account Balance ... + xEU5Balance = xEU5AccountInfo.GetBalance(); + xEU5FreeMargin = xEU5AccountInfo.GetFreeMargin(); + + // + // Check Provider is Enable or Not ... + if (!xEU5MEnableProvider) + { + return; + } + + // + // Protect Account by Guarding Maximum Drawdown ... + // TODO: add Guard Result here ... + string guardMessage = ""; + XGuardHandlerResult guardHandlerResult; + bool isGuarded = xEU5Guard.Guard( + guardHandlerResult, + guardMessage, + xEU5Trader, + _Period); + if (isGuarded) + { + // + // Criticals ... + int criticalsCount = ArraySize(guardHandlerResult.criticals); + if (criticalsCount > 0) + { + // + for (int i = 0; i < criticalsCount; i++) + { + // + XSignal iSignal = guardHandlerResult.criticals[i]; + + // + XEU5OnGuard( + iSignal, + X_GUARDED_CRITICAL, + guardMessage); + } + } + + // + // Maxes ... + int maxesCount = ArraySize(guardHandlerResult.maxes); + if (maxesCount > 0) + { + // + for (int i = 0; i < maxesCount; i++) + { + // + XSignal iSignal = guardHandlerResult.maxes[i]; + + // + XEU5OnGuard( + iSignal, + X_GUARDED_MAX, + guardMessage, + guardHandlerResult.isStopOut); + } + } + + // + // Olds ... + int oldsCount = ArraySize(guardHandlerResult.olds); + if (oldsCount > 0) + { + // + for (int i = 0; i < oldsCount; i++) + { + // + XSignal iSignal = guardHandlerResult.olds[i]; + + // + XEU5OnGuard( + iSignal, + X_GUARDED_OLD, + guardMessage); + } + } + } + + // + // Signal Protection ... + XSignal protectSupports[]; + bool isSupported = xEU5Guard.ProtectSignals( + protectSupports, + xEU5Trader); + if (isSupported) + { + // + LogMessage("Guard do Support Trdae ..."); + } + + // + // Handling Signals ... + XTraderHandlerResult signalHandlerResult; + xEU5Trader.HandleSignals( + signalHandlerResult, + false // Ignore Risk Free Trdaes + ); + + // + // Handle Sl Reports ... + int handledSLsCount = ArraySize(signalHandlerResult.sl); + if (handledSLsCount > 0) + { + // + for (int i = 0; i < handledSLsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.sl[i]; + XEU5OnSL(iSignal); + } + } + + // + // Handle TP Reports ... + int handledTPsCount = ArraySize(signalHandlerResult.tp); + if (handledTPsCount > 0) + { + // + for (int i = 0; i < handledTPsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.tp[i]; + XEU5OnTP(iSignal); + } + } + + // + // Handle RFs as TP Reports ... + int handledRFsCount = ArraySize(signalHandlerResult.rf); + if (handledRFsCount > 0) + { + // + for (int i = 0; i < handledRFsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.rf[i]; + XEU5OnRF(iSignal); + } + } +} + +// +// Handle Trades when OnTrade Event Hnadler Calls ... +void XEU5SignalProviderHandleTrade() +{ + // + // Check Provider Enabled ... + if (!xEU5MEnableProvider) + { + return; + } + + // + // Handle OnTrade Event ... + XOnTradeHandlerResult result = {}; + xEU5Trader.HandleOnTradeEvent( + result); + + // + // Detected TP or SL ... + if (result.hasNewDeal) + { + // + XDeal last = xEU5Trader.GetLastDeal(); + + // + if (last.reason == DEAL_REASON_SL) + { + xEU5Reporter.AddTradeSLInReports(); + } + else if (last.reason == DEAL_REASON_TP) + { + xEU5Reporter.AddTradeTPInReports(); + } + } +} + +// +// Handle Open Trades ... +void XEU5HandleOpenTrades() +{ + // + // Check Can Trade ... + bool canTrade = xEU5MAllowLongTrades || xEU5MAllowShortTrades; + if (!canTrade) + { + return; + } + + // + // Check Max Open Trades ... + int openSignals = xEU5Trader.Count(); + bool canOpenPositions = openSignals < xEU5MaxAllowedTrades; + if (!canOpenPositions) + { + return; + } + + // + // Check Signals Exists ... + XProvidedSignal longSignalInfo; + XProvidedSignal shortSignalInfo; + bool hasLongSignal = XEU5CanOpenLongTrade(longSignalInfo); + bool hasShortSignal = XEU5CanOpenShortTrade(shortSignalInfo); + if (!hasLongSignal && !hasShortSignal) + { + return; + } + + // + // Update Reports ... + XEU5UpdateReports(); + + // + // Open Long Trades ... + if ( + // + hasLongSignal && + xEU5MAllowLongTrades) + { + // + bool isOpened = XEU5OpenLongPosition(longSignalInfo); + } + + // + // Open Short Trades ... + if ( + // + hasShortSignal && + xEU5MAllowShortTrades) + { + // + bool isOpened = XEU5OpenShortPosition(shortSignalInfo); + } +} + +// +// Handle Close Trades ... +void XEU5HandleCloseTrades() +{ + // + // Force Close Long Trades ... + bool isClosedLongTrades = false; + bool canCloseLongTrades = XEU5CanCloseLongTrade(); + if (xEU5MAllowLongTrades && canCloseLongTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; + + // + XSignal closed[]; + xEU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedLongTrades = closedTradesCount > 0; + if (isClosedLongTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XEU5OnFC(iSignal); + } + } + } + + // + // Force Close Short Trades ... + bool isClosedShortTrades = false; + bool canCloseShortTrades = XEU5CanCloseShortTrade(); + if (xEU5MAllowShortTrades && canCloseShortTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; + + // + XSignal closed[]; + xEU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedShortTrades = closedTradesCount > 0; + if (isClosedShortTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XEU5OnFC(iSignal); + } + } + } +} + +// +// Open Long Position ... +bool XEU5OpenLongPosition( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // Calculate Required Data for Position ... + double entry = GetEntry(_Symbol, X_SIGNAL_LONG); + double sl = info.sl > 0 ? info.sl : 0; + // entry - (200 * _Point); + // info.sl > 0 ? info.sl : 0; + double tp = info.tp > 0 ? info.tp : entry + xEU5MinReward; + double riskFreeRate = xEU5RiskFreeRate; + double riskFreeStep = xEU5RiskFreeStepInPips; + double volume = XEU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xEU5Trader.GenerateSignal( + X_SIGNAL_LONG, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xEU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xEU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XEU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xEU5CrossSignalsMethod != X_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal( + signal, + false, // Ignore Number of Trades ... + true // Check Account Conditions ... + ); + result = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (result) + { + // + // Update Reports ... + string providers[]; + ArrayCopy( + providers, + info.signallers + ); + + // + XSignal tSignal = xEU5Trader.GetSignal(signal.ticket); + + // + XEU5OnSignal( + tSignal, + providers); + } + else + { + XEU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Open Short Position ... +bool XEU5OpenShortPosition( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // Calculate Required Data for Position ... + double entry = GetEntry(_Symbol, X_SIGNAL_SHORT); + double sl = info.sl > 0 ? info.sl : 0; + // entry + (200 * _Point); + // info.sl > 0 ? info.sl : 0; + double tp = info.tp > 0 ? info.tp : entry - xEU5MinReward; + double riskFreeRate = xEU5RiskFreeRate; + double riskFreeStep = xEU5RiskFreeStepInPips; + double volume = XEU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xEU5Trader.GenerateSignal( + X_SIGNAL_SHORT, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xEU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xEU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XEU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xEU5CrossSignalsMethod != X_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xEU5Trader.ExecuteSignal( + signal, + false, // Ignore Number of Trades ... + true // Check Account Conditions ... + ); + result = executionResult == X_TRADER_SUCCEED_EXECUTION; + if (result) + { + string providers[]; + ArrayCopy( + providers, + info.signallers + ); + + // + XSignal tSignal = xEU5Trader.GetSignal(signal.ticket); + + // + XEU5OnSignal( + tSignal, + providers); + } + else + { + XEU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Apply Cross Signal Actions ... +void XEU5HnadleCrossSignal( + XSignal &signal // Specified Signal ... +) +{ + // + // Check Cross Signal Handling Enabled ... + if (xEU5CrossSignalsMethod == X_CROSS_SIGNAL_DO_NOTHING) + { + return; + } + + // + // First We have to Change Cross Signals Comment ... + string comment = xEU5Trader.GenerateSignalComment( + signal, + true); + + // + signal.comment = comment; + + // + // If Every thing is Regular, prevent any changes here ... + if (xEU5CrossSignalsMethod == X_CROSS_SIGNAL_REGULAR) + { + return; + } + + // + // Retrieve Max in Drawdown Signal ... + XSignal maxInDDSignal = xEU5Trader.GetMaxInDrawdownSignal(); + + // + // Validate Signal ... + bool isValidSignal = + maxInDDSignal.ticket > 0 && + maxInDDSignal.symbol == signal.symbol && + IsValid(maxInDDSignal, xEU5MagicNumber); + if (!isValidSignal) + { + return; + } + + // + double volume = signal.volume; + bool isDirectional = maxInDDSignal.type == signal.type; + + // + // Prevent any changes on Regular Conditions ... + bool isRegular = + isDirectional + ? ( + // + xEU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_REGULAR || + xEU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT + // + ) + : ( + // + xEU5CrossSignalsMethod == X_CROSS_SIGNAL_INDIRECTION_REGULAR || + xEU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_IMPORTANT_INDIRECTION_REGULAR + // + ); + if (isRegular) + { + return; + } + + // + // Important Act needs to Multiply volume by 2 ... + volume *= 2; + + // + // Set Volume of signal ... + signal.volume = volume; +} + +// +// Calculate Usefull data ... +void XEU5HandleCalculateDrawDownUp() +{ + // + XSignal signals[]; + xEU5Trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + double profit = 0; + double volume = 0; + XCollector collector = {}; + double maxAllowedVolume = xEU5VolumeManager.GetMaxAllowedVolume(); + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + profit += iSignal.profit; + + // + volume = + volume == 0 || + volume < iSignal.volume + ? iSignal.volume + : volume; + } + + // + if (profit < 0) + { + // + xEU5MaxDrawDown = + xEU5MaxDrawDown == 0 || + xEU5MaxDrawDown > MathAbs(profit) + ? MathAbs(profit) + : xEU5MaxDrawDown; + + // + // Update Buffers ... + datetime time = iTime(_Symbol, _Period, 0); + + // + // Calculate Max Allowed Drawdown ... + // + collector.time = time; + collector.volume = volume; + collector.maxDrawDown = xEU5MaxDrawDown; + collector.maxAllowedVolume = maxAllowedVolume; + collector.minBalanceForOpenTrade = xEU5Trader.GetMinBalanceForOpenTrades(); + } + else + { + // + xEU5MaxDrawUp = + xEU5MaxDrawUp == 0 || + xEU5MaxDrawUp < profit + ? profit + : xEU5MaxDrawUp; + } + + // + // Update Collector ... + xEU5Collector.Add(collector); + + // + // Update Reports ... + xEU5Reporter.UpdateMaxDrawUpInReports(xEU5MaxDrawUp); + xEU5Reporter.UpdateMaxDrawDownInReports(xEU5MaxDrawDown); + xEU5Reporter.UpdateMaxSameTimeTradesInReports(signalsCount); +} + +// +// START Event Handlers ... +// + +// +// Runs When a Signal Successfully Executed ... +void XEU5OnSignal( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + // Issue Propper Alert ... + XEU5IssueSignalExecutionAlert( + signal, + providers); + + // + // Add Signal To Supports on Guard ... + xEU5Guard.AddSupport(signal); + + // + // Update Reports ... + xEU5Reporter.AddSignalToReports( + signal, + providers); +} + +// +// Runs when a Position Got Take Profit ... +void XEU5OnTP( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueTPAlert(signal); + + // + // Remove Signal From Guard Protector ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeTPInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Got Stop Loss ... +void XEU5OnSL( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueSLAlert(signal); + + // + // Remove Signal From Guard Protector ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Risk Free ... +void XEU5OnRF( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueRFAlert(signal); + + // + // Remove Signal From Guard Protector ... + // since RiskFree Signals has SL ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Force Closed ... +void XEU5OnFC( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XEU5IssueFCAlert(signal); + + // + // Remove Signal From Guard Protector ... + xEU5Guard.Remove(signal.ticket); + xEU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// Runs when a Position Guarded ... +void XEU5OnGuard( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason, // Reason of Guard Applied + string message, // Guard Returned Message + bool isStopOut = false // Specified StopOut Fired or not +) +{ + // + // Chekc StopOut ... + if (isStopOut) + { + // + LogMessage(message); + + // + xEU5MEnableProvider = false; + } + + // + // Issue Propper Alert ... + XEU5IssueGuardAlert(signal, reason, isStopOut); + + // + // Update Reports ... + xEU5Reporter.AddTradeSLInReports(); + XEU5UpdateReports(); +} + +// +// END Event Handlers ... +// + +// +// END Provided Functions ... +// + +// +// START Private Functions ... +// + +// +// START Volume Baseed Functions ... +// + +// +// Calculating Volume for Tradings ... +double XEU5CalculateVolume( + double forceMultiplier = 0 // some times we get more than one signal at the same time, here we increase volume using this ... +) +{ + // + // Check Open Trades ... + int openSignals = xEU5Trader.Count(); + + // + double result = xEU5VolumeManager.CalculateVolume( + openSignals, + _Symbol); + + // + result *= forceMultiplier; + + // + // Normalize Volume ... + result = NormalizeVolume(result, _Symbol, 2); + + // + return result; +} + +// +// END Volume Baseed Functions ... +// + +// +// START Report/Collect and Guard Functions ... +// + +// +// Update Report Info ... +void XEU5UpdateReports() +{ + // + double staticVolume = xEU5VolumeManager.GetStaticVolume(); + string staticVolumeCalculationMethod = EnumToString(xEU5StaticVolumeMethod); + double maxAllowedVolume = xEU5VolumeManager.GetMaxAllowedVolume(); + double volumeIncreaseMultiplier = xEU5VolumeManager.GetVolumeMultiplier(); + double balanceGowingToApplyMultiplier = xEU5VolumeManager.GetIncreaseMultiplierBalance(); + + double balanceGrowingToIncreaseMaxAllowedVolume = xEU5VolumeManager.GetIncreaseMaxAllowedVolumeBalance(); + + // + // Update Reports Volume Info ... + xEU5Reporter.UpdateReportsVolumeInfo( + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Calculate Max Allowed Drawdown ... + double minBalanceForTradeBasedOnBalance = xEU5Trader.GetMinBalanceForOpenTrades(); + xEU5Reporter.UpdateMinBalanceForOpenTradesInReports(minBalanceForTradeBasedOnBalance); +} + +// +// Reset XEU5 Info Buffers ... +void XEU5ResetCollectors() +{ + // + // Reset Calculations Buffers and Variables ... + xEU5MaxDrawUp = 0; + xEU5MaxDrawDown = 0; + + // + xEU5Trader.Reset(); + xEU5Reporter.Reset(); + xEU5Collector.Reset(); + xEU5VolumeManager.ResetForceVolumeMultiplier(); +} + +// +// END Report/Collect and Guard Functions ... +// + +// +// START Alert Functions ... +// + +// +// Send Alert ... +void XEU5IssueAlert(string message) +{ + // + // Validate Args ... + if (StringLen(message) <= 0) + { + return; + } + + // + if (xEU5EnableAlerts) + { + SendAlert(message); + } + else + { + LogMessage(message); + } +} + +// +// Send Take Profit Alert on Specific Signal ... +void XEU5IssueTPAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalTPComment(signal); + + // + XEU5IssueAlert(message); +} + +// +// Send Stop Loss Alert on Specific Signal ... +void XEU5IssueSLAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalSLComment(signal); + + // + XEU5IssueAlert(message); +} + +// +// Send Force Close Alert on Specific Signal ... +void XEU5IssueFCAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalForceCloseComment(signal); + + // + XEU5IssueAlert(message); +} + +// +// Send Risk Free Alert on Specific Signal ... +void XEU5IssueRFAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xEU5Trader.GenerateSignalRFComment(signal, 0); + + // + XEU5IssueAlert(message); +} + +// +// Send Guard Alert on Specific Signal ... +void XEU5IssueGuardAlert( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason, // Specified Guard Reason + bool isStopOut = false // Specified StopOut Fired or not +) +{ + // + string message = ""; + + // + message = xEU5Guard.GenerateGuardedSignalComment( + signal, + reason); + + // + XEU5IssueAlert(message); +} + +// +// Send Initialization Succeed Alert ... +void XEU5IssueInitializationSucceedAlert() +{ + // + string message = "Initializion of (" + XEU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; + XEU5IssueAlert(message); +} + +// +// Send De Initialization Succeed Alert ... +void XEU5IssueDeinitializationSucceedAlert() +{ + // + string message = "De Initializion of (" + XEU5ProviderName + " Provider" + ") Succeeded ..."; + XEU5IssueAlert(message); +} + +// +// Send Signal Successfully Execution Alert ... +void XEU5IssueSignalExecutionAlert( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + string message = xEU5Trader.ToString(signal); + + // + string providersMsg = ToString(providers); + if (StringLen(providersMsg) > 0) + { + message += ", Providers: " + providersMsg; + } + + // + XEU5IssueAlert(message); +} + +// +// Send Signal Execution Alert ... +void XEU5IssueSignalExecutionError(int error) +{ + // + string message = GetSignalExecutionError(error); + if (StringLen(message) == 0) + { + return; + } + + // + XEU5IssueAlert(message); +} + +// +// END Alert Functions ... +// + +// +// END Private Functions ... +// diff --git a/XEU5/Settings/.gitkeep b/XEU5/Settings/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/XEU5/Settings/xeu5.longs.vbb.set b/XEU5/Settings/xeu5.longs.vbb.set new file mode 100644 index 0000000000000000000000000000000000000000..273e17a67e016fae53a997ad63e98c2250decebf GIT binary patch literal 7584 zcmcgw+j1H?5bfu!%0KV{8^<_~olEgR>^MnPj9tb_{K~?ZPz#3Q5|gd{_T8MLo<`Cz z1Y#_TVrHb#^yxl2>ekHv|GkllOr#~>C6f-WhjNGGf$ZadD0?_pajeQQdaLMrEzji$ z#}_z1kw1jbPvx8RV5K6rIQLb=o#TShJ^}xI*63M z63P2N#Jw4M>3PqMq_-Lw`{)h*rDt9F;qIu9wEQR9ZQ%EC{2SMwV4X-Bv$tZL&?kDs z=pV2Zqv!@qK0&Epe1F~EdqF~RNN3Dy!R0MedqtSR#Z>a3S;j}Y%h*9Zmo)Y06Wz6 z_Livs31)eFOI&w1@=iWO>lL}gTn?SGJD5?gY(FAY3{^DGpM4i7q-fmwACp=SbL*>|0iODGuAoJ!UXsa*PplC zgtAp}+uDxfyaHDfw?kML65g39Yvi%prGmSQcVy!1s zn(5{O%*Bz`u|BxRWG-VBDtgJ4u^e*~&u|~e)%69>_FbLJ*z5RKc4EFm-_H?4-^Db-xrf>FG0=hxHz)zM6=X*-BS8wIBLpI}^*QseIx7z73A~hQf8;aanJU zRrD+GuAJ_eV>Q~xVTHS7R;GJcAHx&+b_orP;2EKdot$B4*t%9dC2G45NNy~_$`F65gd^8&N=DcUWtdJ3)G zgVSX#9Rzq`mSBDM$odX$J)0oEhl+GA;|yn!YK%OVXSlLVygnLwZR{Nekud`rbG*-Z ztXX`iV)EmDiaF;*Dtgymz1=g{%)Hla#cdw25#W(y~9*b&2Gb#Ni zR-94ax_RgBrHv=U`96b1z6J3+#9g7z&}YK39aJQ}P|+q-DGuX*ZmoQrLEND z?H^)nhF)6Ub2DkJdd5ClLwjjiSH8OuwULrvqTPo697XrZ!1OlM6S^HzQpokPvh1qzXy;*UT-gn z{GTAo+e_lUyOnqH30%+Q3b7nIW_J)#&ul*yd z{Q3aKLYR)JmD^=}`z#N~I&l z={dB-yZ#2Ku+G?yH@01%msOxG;V!JX`u(e`+()S7%30QQ-=}-euJK6KZft@9J;aCg zybC+1!{pkX6@|Uw`c-~pLfe_QDNXC+)YTsIjeC-H;=$E3);W*D1p1%OKQFlnW-H^i zl^y$e4Xh^ags{%bPneg>XUr$>XTYNmKd*#%Z?^}idG0csqR3NU?4^&OM$Y2Ldz_0; zVcigxPGDCLk-E@W_*mBCcGVZ`I$AJ^XHsL8GS+%RrWtQ8 zfn4lq9s7f4Oy)9Hp|X|S8OuI5v4-bB?yk>R+jn&?mvi(|9(hxPT|7DScUZ`^_Ccx5 zbGBilbIgm)b+5x)(TVX6ZNGpIedp5%_a36>eV`Suoi~clo~zgDo7&AvZQg1BvgLJ` zBUq8v>8--iG{-oFHmtWm`PGD{%vQR)$^FnCJDFHkO=Szu_ibRzHx%ykj>~#;?4rl4 zyLP-|j#Y1;2Nj-@S(zRneGE%z+Z8x4f@RF+e3Me#A}Xw~+<|qREcMOt#*MX6zxaksc zw=V8Hy|l41jQ2St@-2wpA?{1nmdx|K^H2K$O4OzM@G&0Pjv{_z)JyK{AF<-Z`9ypC z(>|U}C#^WasI}wh#V4KcJiu=c{Jvw~E^ZfZt+&A93~#T?v%@!3ofW?KEzjTP+^6#W z>5tz@c&-e!kOy}zzRcG|B5o-k!n0@0jj|4Z!YpeEWo)J+MxL7Ls3)7C%6VyVrH1s# z##&Nh+eDpOk1S`U#Fg?>qZ;c-iRle?+WAJf+RT*LnvT@?F6&8&@uj>)ru``IH(;-y zn-XWQB{kAjno?qY3Y3}kPVrlxE5g|+@ecK*M!Z_rE-=5qH}TCe=j>fzPCdKAJl3@v V%o{(1d1FVIH+G15sOvc~{~r_GJ~03Q literal 0 HcmV?d00001 diff --git a/XEU5/Settings/xeu5.vbb.set b/XEU5/Settings/xeu5.vbb.set new file mode 100644 index 0000000000000000000000000000000000000000..c3b40992523f1f6026475f1412702542a0c8bd53 GIT binary patch literal 7566 zcmcgw+j1I55bbAIkQ$Be}=*h3w;hD0{dc;L3J}r(^jIPy4tY z$glE~JQJ>;%4g|AN+x%>4&ha#pBRu68%W$1zHD?gF0~^0ULIIhR zK>rcOX6U8neK(WZs%7k>Hq@7z_2eHnqB>IYbF{m_@8kM6oc_W8^mAV?^Cs;AWkKQU4b`ZCRA9e4!Udrcc`XnB0K<)(CxqQX% z4zmW%ezx{qUpU@cU^Ja9vZ=TsLO8aG{DISdTPYe(j1}5GkXT-9Y213u?jhtbuD6%O z_%Gn)?Im&F-N;+{h*;0$622U{$i9U~ePsI?VZ<8_weWE8jPp$g6HT8wv2(N8K<$7sW$gQ$Wkhd zn5U;eiFf@qSYe&99dFTgj$T%Qu7ta=ftvjaRr?V8>IhF7vvHs9J-ddp4{CQ~8xhcl ze^}3Z(1REz*Y2z+?A5lfBsYufq_1I}u%6t60hY|CDA7AYU%YkRk z{v0;*TsU6BeYHT{KK7OoV;*&nQ}1I~ai4p==! ztUZ9!YAl8O{xCphefG%u4sJc`Ape0VQeSSC;p#H+YHKWi?%{k9^2kNQ^LbGBd4Xyexep7E#f3F|BOUlZp_eQ&&WV_j4)zTY=WTht=Wqtw5u_Z#PR zo?W_F8G8E+68R3quMqc3wU%+`+44_3p_$K#rMu92>hNtpk-rJ5CHM7@Xz|+FM1B0z zKAsJeTD-=nwR!g}#OIvwG{7$p{JLXbF8rzQ23(xt-L*P9d_UD$;agvI{x+vRmG94f z{7S-8Wr(ufxpEo7pDwq@hoRmzTfMaI66Z}?Z ziEwsGwnLn>eAgrGg7I^F1z(?W&fW#%#MuqwG16`rZ~YMCtsODm+8N^^(o-`2KMu<~ AmjD0& literal 0 HcmV?d00001 diff --git a/XEU5/Templates/.gitkeep b/XEU5/Templates/.gitkeep new file mode 100644 index 0000000..e69de29

1AUCY%B9UJg?G%dSu(I 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 RFBjN)Y;Kq=+%N_He*m=Vnf?F( literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xobd.oscillator.ex5 b/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xobd.oscillator.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..175eb86ece621aeefc1543c861c7b146d99d4cd1 GIT binary patch literal 11052 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 WqYzkYw_#jwpbO%z^`O(f6Z{`0o(|#w literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xrsi.oscillator.ex5 b/EURUSD-5M-V0.1/EX5/Indicators/x-saherelm.xrsi.oscillator.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..a206d3faea6fe479313dd8d00e6e4952b3a1e1b2 GIT binary patch literal 17482 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 Yc}|AOqsfkrcEX>gi6W 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 BOcekC literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.alert.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.alert.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..66cdadc6f063f64f86bb46c729c6b5e98ef94934 GIT binary patch literal 7392 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 KW;8t&i~nDV;NepM literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.http.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.http.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..3d13e4f16e057bab2113bcd3ad46fb3d6d36b9e0 GIT binary patch literal 4574 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 literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.log.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.log.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..7569a3f7a44fd5bf75425b155ae7a4f8227d055d GIT binary patch literal 5906 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 literal 0 HcmV?d00001 diff --git a/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.nn.lib.ex5 b/EURUSD-5M-V0.1/EX5/Libraries/x-saherelm.nn.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..2977459528a566ebd6f14acf5d36fc80bda6f04b GIT binary patch literal 4374 zcmdT>cQoAH*8U-Cl*o+eU82_^dSr|?+NdE2f-&k4AzJY2CeeaHqDS;zqZ7R)2%@*> zz4zerzTdt7-L<~&-@EtPd!PM0=bW{ky%i0`@LmB26i@E}|Jc&M>i>2CkO7n&gZ{d>3`mmFd%Td zZK3~6{y$KE2WBKdL&ip9pruGIL?j2hYs=DPX{O+`+@ZOGvsw=Ff8dnvx-9%FLHTf1 zTnfVY_?IBR&Uwm!5Q@dWa0u5_zG2a<=Y3OZSJP)WvUA_l?FjR05z7Zl>s=OTpR=Q> z6As?cBdMVK!F_GR7~}-Ds~0m@QdF0Oo@W^S78HBU$3j3+OK|08F&Ocr`6K7@>|eqQ z30RRu?6dG`(yCLtDRRh$Mh1#JZKoeirRJX(CgTm(vvNq(J7?(dT{iM<>LRa=CX~c- zgDKG}hPsr@K8{8*IA%I%MQLTGVonU(B8+JSXBo-wR*m}tf0%tc}e)S z?EvqaQj@Ktzt6ki&!5;>_8vbI7t|BrtKuVNh9!mnRxfA$d2*?Oa5?AMO&%o$$vJ0g z{{a<$$UAvY`-aO2zJV4O7{IPr(OjAcGqi`N2xQb4QjBdjZ5IcKL$USUA<+__2hiSi zcv`%UPXfI7lnV~hpZ*TbihFPcg~Uf5R(SP=^)?;j<&w>xddPajaaj+Qpank8Hy_>b zR=%z>7=Lsxd9-y&VUDOkT3+a5nuI`E)kHArXe+QC9^TSOm@ooKFN{mDprgh!;dztv zfzAwmzNWKp+;i!hdH-d>_^iNM)cn&kKOwC_%OTEij%7;*!+1^UFZwI*ic0pjyXlFh z@)b-Z+Akhc^=arWAH-nvX{osaJ_i4@K6&_aQ$+^X_7Vwh