From 604b48c5a38c2c560cee14c8ae03de48b4dccc19 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 25 Jan 2024 04:11:24 +0330 Subject: [PATCH] Initial Commit ... --- .gitignore | 21 + .gitkeep | 0 .vscode/SetExecutionPolicy.md | 1 + .vscode/launch.json | 20 + .vscode/settings.json | 5 + .vscode/tasks.json | 35 + .vscode/vscode-kanban.json | 785 + .vscode/vscode-kanban.json.bkp | 738 + BKP/Main/Classes/x-saherelm.class.lib.mq5 | 10316 ++++++++++++ BKP/Main/Classes/x-saherelm.nn.lib.mq5 | 258 + BKP/Main/Classes/x-saherelm.provider.lib.mq5 | 4430 +++++ BKP/Main/Experts/x-saherelm.xeu5.ea.mq5 | 347 + .../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 ++ .../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 + BKP/Main/Libraries/x-saherelm.alert.lib.mq5 | 200 + BKP/Main/Libraries/x-saherelm.common.lib.mq5 | 4429 +++++ BKP/Main/Libraries/x-saherelm.draw.lib.mq5 | 2345 +++ BKP/Main/Libraries/x-saherelm.http.lib.mq5 | 177 + BKP/Main/Libraries/x-saherelm.log.lib.mq5 | 261 + BKP/Main/Libraries/x-saherelm.models.lib.mq5 | 438 + ...-saherelm.xeu5.provider.indicators.lib.mq5 | 13599 ++++++++++++++++ .../x-saherelm.xeu5.provider.inputs.lib.mq5 | 280 + .../x-saherelm.xeu5.provider.lib.mq5 | 1370 ++ BKP/Temp/XEmptyPreparedProjet.zip | Bin 0 -> 184021 bytes ...-saherelm.xau5.provider.indicators.lib.mq5 | 9556 +++++++++++ BKP/Temp/xau5.indicators.provider.txt | 8161 ++++++++++ Classes/x-saherelm.class.lib.mq5 | 10316 ++++++++++++ Classes/x-saherelm.nn.lib.mq5 | 258 + Classes/x-saherelm.provider.lib.mq5 | 4430 +++++ Compile-MQL.ps1 | 47 + Documents/.gitkeep | 0 Documents/Docs/MarketConditions.md | 946 ++ Documents/MT Settings/x-xchlh-xeu5.set | Bin 0 -> 1670 bytes Documents/MT Settings/x-xchma-xeu5.set | Bin 0 -> 1894 bytes Documents/MT Settings/x-xlh-xeu5.set | Bin 0 -> 126 bytes Documents/MT Settings/x-xobd-xeu5.set | Bin 0 -> 296 bytes Documents/MT Settings/x-xrsi-xeu5.set | Bin 0 -> 772 bytes Documents/MT Settings/x-xtd-xeu5.set | Bin 0 -> 324 bytes Documents/MT Settings/x-xtm-xeu5.set | Bin 0 -> 166 bytes Documents/MT Templates/x-test-m5.tpl | Bin 0 -> 15982 bytes Documents/MT Templates/x-xeu5.tpl | Bin 0 -> 1834090 bytes .../MT Templates/x-xeu5.without.xrsi.tpl | Bin 0 -> 1831778 bytes .../MT Templates/x-xeu5.without.xrsi.xtd.tpl | Bin 0 -> 3299472 bytes Documents/Templates/X-Strategy-Template.mq5 | 7468 +++++++++ .../Templates/XTempSignallerFunctions.txt | 171 + Experts/x-saherelm.xeu5.ea.mq5 | 347 + .../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 ++ Indicators/x-saherelm.xama.indicator.mq5 | 353 + Indicators/x-saherelm.xchlh.oscillator.mq5 | 753 + Indicators/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 + Libraries/x-saherelm.alert.lib.mq5 | 200 + Libraries/x-saherelm.common.lib.mq5 | 4429 +++++ Libraries/x-saherelm.draw.lib.mq5 | 2345 +++ Libraries/x-saherelm.http.lib.mq5 | 177 + Libraries/x-saherelm.log.lib.mq5 | 261 + Libraries/x-saherelm.models.lib.mq5 | 438 + MQL5.code-workspace | 8 + Projects/.gitkeep | 0 Projects/XAU5/Classes/.gitkeep | 0 .../XAU5/Classes/x-saherelm.class.lib.mq5 | 10316 ++++++++++++ Projects/XAU5/Classes/x-saherelm.nn.lib.mq5 | 258 + .../XAU5/Classes/x-saherelm.provider.lib.mq5 | 4430 +++++ Projects/XAU5/Documents/.gitkeep | 0 Projects/XAU5/Documents/Reports/.gitkeep | 0 Projects/XAU5/Documents/Settings/.gitkeep | 0 .../Documents/Settings/xau5.longs.vbb.set | Bin 0 -> 7568 bytes .../XAU5/Documents/Settings/xau5.xsi.vbb.set | Bin 0 -> 7584 bytes Projects/XAU5/Experts/.gitkeep | 0 Projects/XAU5/Experts/x-saherelm.xau5.ea.mq5 | 347 + Projects/XAU5/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 ++ Projects/XAU5/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 + Projects/XAU5/Libraries/.gitkeep | 0 .../XAU5/Libraries/x-saherelm.alert.lib.mq5 | 200 + .../XAU5/Libraries/x-saherelm.common.lib.mq5 | 4429 +++++ .../XAU5/Libraries/x-saherelm.draw.lib.mq5 | 2345 +++ .../XAU5/Libraries/x-saherelm.http.lib.mq5 | 177 + .../XAU5/Libraries/x-saherelm.log.lib.mq5 | 261 + .../XAU5/Libraries/x-saherelm.models.lib.mq5 | 438 + Projects/XAU5/Providers/.gitkeep | 0 ...-saherelm.xau5.provider.indicators.lib.mq5 | 7655 +++++++++ .../x-saherelm.xau5.provider.inputs.lib.mq5 | 280 + .../x-saherelm.xau5.provider.lib.mq5 | 1370 ++ Projects/XAU5/Settings/.gitkeep | 0 Projects/XAU5/Templates/.gitkeep | 0 Projects/XBTU5/Classes/.gitkeep | 0 .../XBTU5/Classes/x-saherelm.class.lib.mq5 | 10316 ++++++++++++ Projects/XBTU5/Classes/x-saherelm.nn.lib.mq5 | 258 + .../XBTU5/Classes/x-saherelm.provider.lib.mq5 | 4430 +++++ Projects/XBTU5/Documents/.gitkeep | 0 Projects/XBTU5/Documents/Reports/.gitkeep | 0 Projects/XBTU5/Documents/Settings/.gitkeep | 0 Projects/XBTU5/Experts/.gitkeep | 0 .../XBTU5/Experts/x-saherelm.xbtu5.ea.mq5 | 347 + Projects/XBTU5/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 ++ Projects/XBTU5/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 + Projects/XBTU5/Libraries/.gitkeep | 0 .../XBTU5/Libraries/x-saherelm.alert.lib.mq5 | 200 + .../XBTU5/Libraries/x-saherelm.common.lib.mq5 | 4429 +++++ .../XBTU5/Libraries/x-saherelm.draw.lib.mq5 | 2345 +++ .../XBTU5/Libraries/x-saherelm.http.lib.mq5 | 177 + .../XBTU5/Libraries/x-saherelm.log.lib.mq5 | 261 + .../XBTU5/Libraries/x-saherelm.models.lib.mq5 | 438 + Projects/XBTU5/Providers/.gitkeep | 0 ...saherelm.xbtu5.provider.indicators.lib.mq5 | 6705 ++++++++ .../x-saherelm.xbtu5.provider.inputs.lib.mq5 | 280 + .../x-saherelm.xbtu5.provider.lib.mq5 | 1370 ++ Projects/XBTU5/Settings/.gitkeep | 0 Projects/XBTU5/Templates/.gitkeep | 0 Projects/XEU5/Classes/.gitkeep | 0 .../XEU5/Classes/x-saherelm.class.lib.mq5 | 10316 ++++++++++++ Projects/XEU5/Classes/x-saherelm.nn.lib.mq5 | 258 + .../XEU5/Classes/x-saherelm.provider.lib.mq5 | 4430 +++++ Projects/XEU5/Documents/.gitkeep | 0 Projects/XEU5/Documents/Reports/.gitkeep | 0 Projects/XEU5/Documents/Settings/.gitkeep | 0 Projects/XEU5/Experts/.gitkeep | 0 Projects/XEU5/Experts/x-saherelm.xeu5.ea.mq5 | 347 + Projects/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 ++ Projects/XEU5/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 + Projects/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 + Projects/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 ++ Projects/XEU5/Settings/.gitkeep | 0 Projects/XEU5/Settings/xeu5.longs.vbb.set | Bin 0 -> 7584 bytes Projects/XEU5/Settings/xeu5.shorts.vbb.set | Bin 0 -> 7584 bytes Projects/XEU5/Settings/xeu5.vbb.set | Bin 0 -> 7566 bytes Projects/XEU5/Templates/.gitkeep | 0 ...-saherelm.xeu5.provider.indicators.lib.mq5 | 13599 ++++++++++++++++ .../x-saherelm.xeu5.provider.inputs.lib.mq5 | 280 + Providers/x-saherelm.xeu5.provider.lib.mq5 | 1370 ++ README.md | 11 + package.json | 108 + 234 files changed, 274318 insertions(+) create mode 100644 .gitignore create mode 100644 .gitkeep create mode 100644 .vscode/SetExecutionPolicy.md create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 .vscode/vscode-kanban.json create mode 100644 .vscode/vscode-kanban.json.bkp create mode 100644 BKP/Main/Classes/x-saherelm.class.lib.mq5 create mode 100644 BKP/Main/Classes/x-saherelm.nn.lib.mq5 create mode 100644 BKP/Main/Classes/x-saherelm.provider.lib.mq5 create mode 100644 BKP/Main/Experts/x-saherelm.xeu5.ea.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 BKP/Main/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 BKP/Main/Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 BKP/Main/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 BKP/Main/Libraries/x-saherelm.common.lib.mq5 create mode 100644 BKP/Main/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 BKP/Main/Libraries/x-saherelm.http.lib.mq5 create mode 100644 BKP/Main/Libraries/x-saherelm.log.lib.mq5 create mode 100644 BKP/Main/Libraries/x-saherelm.models.lib.mq5 create mode 100644 BKP/Main/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 create mode 100644 BKP/Main/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 create mode 100644 BKP/Main/Providers/x-saherelm.xeu5.provider.lib.mq5 create mode 100644 BKP/Temp/XEmptyPreparedProjet.zip create mode 100644 BKP/Temp/x-saherelm.xau5.provider.indicators.lib.mq5 create mode 100644 BKP/Temp/xau5.indicators.provider.txt create mode 100644 Classes/x-saherelm.class.lib.mq5 create mode 100644 Classes/x-saherelm.nn.lib.mq5 create mode 100644 Classes/x-saherelm.provider.lib.mq5 create mode 100644 Compile-MQL.ps1 create mode 100644 Documents/.gitkeep create mode 100644 Documents/Docs/MarketConditions.md create mode 100644 Documents/MT Settings/x-xchlh-xeu5.set create mode 100644 Documents/MT Settings/x-xchma-xeu5.set create mode 100644 Documents/MT Settings/x-xlh-xeu5.set create mode 100644 Documents/MT Settings/x-xobd-xeu5.set create mode 100644 Documents/MT Settings/x-xrsi-xeu5.set create mode 100644 Documents/MT Settings/x-xtd-xeu5.set create mode 100644 Documents/MT Settings/x-xtm-xeu5.set create mode 100644 Documents/MT Templates/x-test-m5.tpl create mode 100644 Documents/MT Templates/x-xeu5.tpl create mode 100644 Documents/MT Templates/x-xeu5.without.xrsi.tpl create mode 100644 Documents/MT Templates/x-xeu5.without.xrsi.xtd.tpl create mode 100644 Documents/Templates/X-Strategy-Template.mq5 create mode 100644 Documents/Templates/XTempSignallerFunctions.txt create mode 100644 Experts/x-saherelm.xeu5.ea.mq5 create mode 100644 Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 Libraries/x-saherelm.alert.lib.mq5 create mode 100644 Libraries/x-saherelm.common.lib.mq5 create mode 100644 Libraries/x-saherelm.draw.lib.mq5 create mode 100644 Libraries/x-saherelm.http.lib.mq5 create mode 100644 Libraries/x-saherelm.log.lib.mq5 create mode 100644 Libraries/x-saherelm.models.lib.mq5 create mode 100644 MQL5.code-workspace create mode 100644 Projects/.gitkeep create mode 100644 Projects/XAU5/Classes/.gitkeep create mode 100644 Projects/XAU5/Classes/x-saherelm.class.lib.mq5 create mode 100644 Projects/XAU5/Classes/x-saherelm.nn.lib.mq5 create mode 100644 Projects/XAU5/Classes/x-saherelm.provider.lib.mq5 create mode 100644 Projects/XAU5/Documents/.gitkeep create mode 100644 Projects/XAU5/Documents/Reports/.gitkeep create mode 100644 Projects/XAU5/Documents/Settings/.gitkeep create mode 100644 Projects/XAU5/Documents/Settings/xau5.longs.vbb.set create mode 100644 Projects/XAU5/Documents/Settings/xau5.xsi.vbb.set create mode 100644 Projects/XAU5/Experts/.gitkeep create mode 100644 Projects/XAU5/Experts/x-saherelm.xau5.ea.mq5 create mode 100644 Projects/XAU5/Helpers/.gitkeep create mode 100644 Projects/XAU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 Projects/XAU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 Projects/XAU5/Indicators/.gitkeep create mode 100644 Projects/XAU5/Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 Projects/XAU5/Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 Projects/XAU5/Libraries/.gitkeep create mode 100644 Projects/XAU5/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 Projects/XAU5/Libraries/x-saherelm.common.lib.mq5 create mode 100644 Projects/XAU5/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 Projects/XAU5/Libraries/x-saherelm.http.lib.mq5 create mode 100644 Projects/XAU5/Libraries/x-saherelm.log.lib.mq5 create mode 100644 Projects/XAU5/Libraries/x-saherelm.models.lib.mq5 create mode 100644 Projects/XAU5/Providers/.gitkeep create mode 100644 Projects/XAU5/Providers/x-saherelm.xau5.provider.indicators.lib.mq5 create mode 100644 Projects/XAU5/Providers/x-saherelm.xau5.provider.inputs.lib.mq5 create mode 100644 Projects/XAU5/Providers/x-saherelm.xau5.provider.lib.mq5 create mode 100644 Projects/XAU5/Settings/.gitkeep create mode 100644 Projects/XAU5/Templates/.gitkeep create mode 100644 Projects/XBTU5/Classes/.gitkeep create mode 100644 Projects/XBTU5/Classes/x-saherelm.class.lib.mq5 create mode 100644 Projects/XBTU5/Classes/x-saherelm.nn.lib.mq5 create mode 100644 Projects/XBTU5/Classes/x-saherelm.provider.lib.mq5 create mode 100644 Projects/XBTU5/Documents/.gitkeep create mode 100644 Projects/XBTU5/Documents/Reports/.gitkeep create mode 100644 Projects/XBTU5/Documents/Settings/.gitkeep create mode 100644 Projects/XBTU5/Experts/.gitkeep create mode 100644 Projects/XBTU5/Experts/x-saherelm.xbtu5.ea.mq5 create mode 100644 Projects/XBTU5/Helpers/.gitkeep create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 Projects/XBTU5/Indicators/.gitkeep create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 Projects/XBTU5/Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 Projects/XBTU5/Libraries/.gitkeep create mode 100644 Projects/XBTU5/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 Projects/XBTU5/Libraries/x-saherelm.common.lib.mq5 create mode 100644 Projects/XBTU5/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 Projects/XBTU5/Libraries/x-saherelm.http.lib.mq5 create mode 100644 Projects/XBTU5/Libraries/x-saherelm.log.lib.mq5 create mode 100644 Projects/XBTU5/Libraries/x-saherelm.models.lib.mq5 create mode 100644 Projects/XBTU5/Providers/.gitkeep create mode 100644 Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.indicators.lib.mq5 create mode 100644 Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.inputs.lib.mq5 create mode 100644 Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.lib.mq5 create mode 100644 Projects/XBTU5/Settings/.gitkeep create mode 100644 Projects/XBTU5/Templates/.gitkeep create mode 100644 Projects/XEU5/Classes/.gitkeep create mode 100644 Projects/XEU5/Classes/x-saherelm.class.lib.mq5 create mode 100644 Projects/XEU5/Classes/x-saherelm.nn.lib.mq5 create mode 100644 Projects/XEU5/Classes/x-saherelm.provider.lib.mq5 create mode 100644 Projects/XEU5/Documents/.gitkeep create mode 100644 Projects/XEU5/Documents/Reports/.gitkeep create mode 100644 Projects/XEU5/Documents/Settings/.gitkeep create mode 100644 Projects/XEU5/Experts/.gitkeep create mode 100644 Projects/XEU5/Experts/x-saherelm.xeu5.ea.mq5 create mode 100644 Projects/XEU5/Helpers/.gitkeep create mode 100644 Projects/XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 create mode 100644 Projects/XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 create mode 100644 Projects/XEU5/Indicators/.gitkeep create mode 100644 Projects/XEU5/Indicators/x-saherelm.xama.indicator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xlh.indicator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xobd.indicator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xtm.indicator.mq5 create mode 100644 Projects/XEU5/Indicators/x-saherelm.xts.oscillator.mq5 create mode 100644 Projects/XEU5/Libraries/.gitkeep create mode 100644 Projects/XEU5/Libraries/x-saherelm.alert.lib.mq5 create mode 100644 Projects/XEU5/Libraries/x-saherelm.common.lib.mq5 create mode 100644 Projects/XEU5/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 Projects/XEU5/Libraries/x-saherelm.http.lib.mq5 create mode 100644 Projects/XEU5/Libraries/x-saherelm.log.lib.mq5 create mode 100644 Projects/XEU5/Libraries/x-saherelm.models.lib.mq5 create mode 100644 Projects/XEU5/Providers/.gitkeep create mode 100644 Projects/XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 create mode 100644 Projects/XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 create mode 100644 Projects/XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 create mode 100644 Projects/XEU5/Settings/.gitkeep create mode 100644 Projects/XEU5/Settings/xeu5.longs.vbb.set create mode 100644 Projects/XEU5/Settings/xeu5.shorts.vbb.set create mode 100644 Projects/XEU5/Settings/xeu5.vbb.set create mode 100644 Projects/XEU5/Templates/.gitkeep create mode 100644 Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 create mode 100644 Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 create mode 100644 Providers/x-saherelm.xeu5.provider.lib.mq5 create mode 100644 README.md create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..85592b0b --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# +Logs +Images +Include +Scripts +Profiles +Experts/Advisors +Experts/Examples +Indicators/Examples + +# +experts.dat +*.ex5 +*.log + +# +node_modules +package-lock.json + +# +.VSCodeCounter diff --git a/.gitkeep b/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.vscode/SetExecutionPolicy.md b/.vscode/SetExecutionPolicy.md new file mode 100644 index 00000000..34bb7738 --- /dev/null +++ b/.vscode/SetExecutionPolicy.md @@ -0,0 +1 @@ +Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..0aa69099 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Compile XEA", + "skipFiles": [ + "/**" + ], + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run-script", "compileEA" + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..1569039d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "C_Cpp.errorSquiggles": "disabled", + "C_Cpp.intelliSenseEngineFallback": "enabled", + "C_Cpp.default.compilerPath": "" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..c7d6d4d6 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,35 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Compile XEA", + "type": "shell", + "command": "C:\\Users\\saherelm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Compile-MQL.ps1 C:\\Users\\saherelm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Experts\\x-saherelm.ea.mq5", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": false + } + }, + { + "label": "Compile-MQL", + "type": "shell", + "command": "C:\\Users\\saherelm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Compile-MQL.ps1 ${file}", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": false + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/.vscode/vscode-kanban.json b/.vscode/vscode-kanban.json new file mode 100644 index 00000000..7a18dbcb --- /dev/null +++ b/.vscode/vscode-kanban.json @@ -0,0 +1,785 @@ +{ + "todo": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T05:52:38.201Z", + "description": { + "content": "- [] add supports for OAuth implementation;", + "mime": "text/markdown" + }, + "id": "28", + "references": [], + "title": "Add Support for OAuth" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T05:53:36.313Z", + "description": { + "content": "- [] add a Mechanism for Push Commands to Robot;\n- [] enable all base configurations to locally changes using commands;", + "mime": "text/markdown" + }, + "id": "29", + "references": [], + "title": "Add SUpport for Push Commands" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-22T01:30:28.887Z", + "description": { + "content": "- [] Pause/Resume;\n- [] Restart;\n- [] Stop Opening New Positions for Withdrawal Actions;\n- [] add support for enable disable signallers;\n- [] etc;", + "mime": "text/markdown" + }, + "id": "45", + "references": [], + "title": "add support for some actions button on chart of EA" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-28T08:23:14.444Z", + "id": "56", + "references": [], + "title": "add Support for XSupport and InDirectional Support Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T17:22:24.427Z", + "description": { + "content": "- [] XTD;\n- [] XSI;\n- [] XOBDLH;\n- [] XCHMACC;\n- [] XCHMACMN;\n- [] XCHMACMX;\n\nthis task is not so important at the moment, doint this later ...", + "mime": "text/markdown" + }, + "id": "36", + "references": [], + "title": "Do a Refactor On Long Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T09:48:13.509Z", + "id": "32", + "references": [], + "title": "R&D about placing stop limit orders for Indirectional Supports", + "description": { + "content": "since there are many issues to manage them, for the moment i will ignore this.\n,aybe working on it later ...", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-23T22:21:14.112Z", + "description": { + "content": "ignore adding sl on partial closed and risk free signals for the moment ...", + "mime": "text/markdown" + }, + "id": "46", + "references": [], + "title": "resolve InvalidStop on Partial Closing" + } + ], + "in-progress": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2024-01-19T15:09:51.323Z", + "description": { + "content": "- Attack Guards Duplicate if Profit less than Prev Guard Attack;\n- When Guard Attacks Multiple times, Start Grid Support Trades;\n- Remove Signal Protector Stuffs;", + "mime": "text/markdown" + }, + "id": "59", + "references": [], + "title": "Change Guard Mechanism" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-30T06:09:35.026Z", + "details": { + "content": "- [x] Found Conditions related to new Indicator/Oscillator(s);\n- [x] attached Conditions to XEU5 Provider;\n- [x] fix and Refactor Signals Issues on Brokers and Logs;\n- [x] Re Test in all Brokers;\n- [x] implement Signal Providers based on New Indicator/Oscillator(s);\n- [x] add supports for TP and SL adding for each Signaller;\n- [x] Complete Support mechanism in Guard class;\n- [x] Test Support before Cleanup and Refactor Signals;\n- [x] do some test on guard stopout;\n- [x] Register AMarket Account;\n- [x] Register Alpari Account;\n- [x] Register Errante Account;\n- [] fix server hdd issues;\n- [] complete all rust desk and anydesk ids for systems;", + "mime": "text/markdown" + }, + "id": "57", + "references": [], + "title": "IMP Works TODO:" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-24T01:13:49.250Z", + "id": "49", + "references": [], + "title": "start backbone of XAUUSD robot for MQL5" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2024-01-19T15:26:34.083Z", + "id": "60", + "references": [], + "title": "remove virtual TP SL from Inputs" + } + ], + "testing": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-23T22:56:31.075Z", + "description": { + "content": "- [] Nothing;\n- [] Close If In DD;\n- [] Partial Close if in DD _5;\n- [] Partial Close if in DD _10;\n- [] Partial Close if in DD _15;\n- [] Partial Close if in DD _20;\n- [] Partial Close if in DD _25;\n", + "mime": "text/markdown" + }, + "id": "48", + "references": [], + "title": "add a mechanism for acting for long time trades ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-23T22:21:39.744Z", + "id": "47", + "references": [], + "title": "add a method for generating Collector logs ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-22T01:07:29.299Z", + "description": { + "content": "- [x] report library;\n- [x] define report models;\n- [x] define report mechanism;\n- [x] implement Logger Reports;\n- [x] report String Generators;\n- [x] use reports in ea;", + "mime": "text/markdown" + }, + "id": "44", + "references": [], + "title": "add a Report library and define all required reports inside it" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T11:07:59.089Z", + "description": { + "content": "- [x] XTD;\n- [x] XSI;\n- [x] XOBDLH;\n- [x] XCHMACC;\n- [x] XCHMACMX;\n- [x] XCHMACMN;", + "mime": "text/markdown" + }, + "id": "33", + "references": [], + "title": "add config sections to select providers long and short signalling" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-27T11:37:45.679Z", + "id": "54", + "references": [], + "title": "add handlers for TakeProfit or LoseProfit Events" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-19T10:19:40.648Z", + "id": "40", + "references": [], + "title": "add settings for Trade Management and risk management" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-20T13:38:04.017Z", + "description": { + "content": "add Start Alert and Prompt Some Values on it ...\nprepare Comments for informing usefull data ...", + "mime": "text/markdown" + }, + "id": "41", + "references": [], + "title": "add start Alert" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:06:27.820Z", + "description": { + "content": "- [x] Check Signal State;\n- [x] Calculate Volume;\n- [x] In Directional Supporting;\n\nimplemented, but since have issues on managing, ignore use them ...", + "mime": "text/markdown" + }, + "id": "24", + "references": [], + "title": "add Support for Indirectional Supporting Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T05:51:40.742Z", + "description": { + "content": "- [x] Add Support for Hourly Alarams;\n- [x] Add Support for Daily Alarams;\n- [x] Add Support for Weekly Info Alarams;\n- [x] ...", + "mime": "text/markdown" + }, + "id": "27", + "references": [], + "title": "Add support for Info Alarms" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:07:37.092Z", + "description": { + "content": "- [x] Calculate How CLose Pyramid in Count;\n- [x] How Close Pyramid in Profit;\n- [x] How Close Pyramid in Max Draw Down;\n\nthese functionalities implemented successfully, but since we don't use any Supporting mechanism and limit number of same time trades.", + "mime": "text/markdown" + }, + "id": "25", + "references": [], + "title": "add Support for Pyramid Closing Trades" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-20T20:08:43.804Z", + "description": { + "content": "wee need this buffer to Increase or Decrease volumes ...", + "mime": "text/markdown" + }, + "id": "42", + "references": [], + "title": "Add Support for Save Max In DrawDown in Buffer", + "details": { + "content": "- [] add an specific library;\n- [] define all requirement;\n- [] add utility functions;\n- [] use it;", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-28T08:21:10.141Z", + "id": "55", + "references": [], + "title": "add support for Stop Out Action in Guard Class", + "details": { + "content": "attached it but need to test ...", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:05:41.976Z", + "description": { + "content": "- [x] Max Count;\n- [x] for In DD Long Signals;\n- [x] Volume Calculations;\n\nimplemented, but ignore to use them, for moment, since they have issues on managing ...", + "mime": "text/markdown" + }, + "id": "23", + "references": [], + "title": "add Support for Support Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:04:44.044Z", + "description": { + "content": "check partial Closing works correctly;\n\n- [x] for Longs;\n- [x] for Shorts;", + "mime": "text/markdown" + }, + "id": "22", + "references": [], + "title": "Check Partial Closing" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T17:03:45.572Z", + "id": "35", + "references": [], + "title": "Complete Input Validators for XEU5", + "description": { + "content": "- [x] XTM;\n- [x] XTD;\n- [x] XRSI;\n- [x] XOBD;\n- [x] XLH;\n- [x] XCHLH;\n- [x] XCHMA;", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:03:50.981Z", + "description": { + "content": "Complete Remained Short Signals:\n\n- [x] XCHMA Crosses;\n- [x] XCHMA Under Max;\n- [x] XCHMA Under Min;", + "mime": "text/markdown" + }, + "id": "20", + "references": [], + "title": "Complete Remained Short Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-24T01:15:14.065Z", + "id": "50", + "references": [], + "title": "create a signal protector class for handling signals states on time pasted" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T11:08:47.584Z", + "id": "34", + "references": [], + "title": "Disbale Conditions Logs ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-24T07:37:10.876Z", + "id": "52", + "references": [], + "title": "extends new section based indicators" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:04:18.085Z", + "description": { + "content": "fix volume calculation for signals;\n\n- [x] static volume;\n- [x] base volume multiplier;\n- [x] grow rate based on balance increasing;\n- [x] max volume duplicator;\n- [x] decrease volume for support trades;", + "mime": "text/markdown" + }, + "id": "21", + "references": [], + "title": "Fix Volume Calculation" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-24T07:36:28.060Z", + "description": { + "content": "- [] implement helpers lib for new indicators;\n- [] try to test them into a new ea;\n- [] combine them with our product;\n", + "mime": "text/markdown" + }, + "id": "51", + "references": [], + "title": "implement new indicators helpers lib" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-21T00:12:42.225Z", + "id": "43", + "references": [], + "title": "increase min balance for trading based on account balance ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2024-01-03T12:04:41.939Z", + "id": "58", + "references": [], + "title": "make settings input related to Indicators and Oscillators hidden or private" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T09:27:48.310Z", + "description": { + "content": "- [x] Close Support Trades;\n- [x] Close InDirectional Trades;\n- [x] Increase/Decrease Volume Multiplier based on TP(s) and SL(s);\n\nimplement OnTrade requirements for later usage, everythings works correctly, but for the moment i ignore use it ...", + "mime": "text/markdown" + }, + "id": "31", + "references": [], + "title": "Read OnTrade Event Documentation" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-24T17:48:18.009Z", + "description": { + "content": "- [] XSignal Structure;\n- [] XTrader Class;\n- [] Draw Signal, TP's and SL, and Volumes;\n", + "mime": "text/markdown" + }, + "id": "53", + "references": [], + "title": "Refactor XSignal and Create a new One also New Trader" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-19T08:18:38.795Z", + "id": "39", + "references": [], + "title": "Remove UnUsed Settings for Production" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T06:44:02.085Z", + "description": { + "content": "- [x] XTD;\n- [x] XSI;\n- [x] XOBDLH;\n- [x] XCHMACC;\n- [x] XCHMACMX;\n- [x] XCHMACMN;", + "mime": "text/markdown" + }, + "id": "30", + "references": [], + "title": "rename signal providers to propper names" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-19T08:17:38.115Z", + "id": "38", + "references": [], + "title": "Test and Add support for Equity and Max Drawdown Management" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-17T13:13:33.447Z", + "id": "37", + "references": [], + "title": "there is an stop on combining on meta quote broker fix this ...", + "details": { + "content": "do a refactor on all brokers, higgh priority criterias ...", + "mime": "text/markdown" + } + } + ], + "done": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-06T16:40:25.004Z", + "description": { + "content": "add supports to plot trend arrow in tdma indicator", + "mime": "text/markdown" + }, + "id": "18", + "references": [], + "title": "add supports to plot trend arrow in tdma indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:07:56.408Z", + "details": { + "content": "- [x] cleanup old structure supports;\n- [x] cleanup old structure indirectional;\n- [x] cleanup old structure max in draw down;\n- [x] cleanup old structure old signals;\n- etc ...", + "mime": "text/markdown" + }, + "id": "26", + "references": [], + "title": "Cleanup Provider UnUsed Functions;" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T09:30:44.836Z", + "description": { + "content": "handle all requirement for neural network class.", + "mime": "text/markdown" + }, + "details": { + "content": "required many things for testing ...", + "mime": "text/markdown" + }, + "id": "11", + "references": [], + "title": "create a neural network class" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:24:26.792Z", + "description": { + "content": "create a signal provider template based on XRSI", + "mime": "text/markdown" + }, + "id": "14", + "references": [], + "title": "create a signal provider template based on XRSI" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T08:05:13.515Z", + "description": { + "content": "create account info library", + "mime": "text/markdown" + }, + "details": { + "content": "define it as a class in class lib ...", + "mime": "text/markdown" + }, + "id": "9", + "references": [], + "title": "create account info library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T15:43:14.906Z", + "details": { + "content": "create alert library:\n\n- [] add configurationinputs;\n- [] add alert functions;\n- [] mail;\n- [] push;\n- [] terminal;", + "mime": "text/markdown" + }, + "id": "4", + "references": [], + "title": "create alert library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T09:30:05.284Z", + "description": { + "content": "create an x-ea provider template:\n\n- [x] create event handlers;\n- [x] add required config inputs;\n- [x] define access to classes;\n- [x] etc ...", + "mime": "text/markdown" + }, + "id": "10", + "references": [], + "title": "create an x-ea provider template" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T13:34:50.719Z", + "description": { + "content": "create common library", + "mime": "text/markdown" + }, + "details": { + "content": "created but must add required functions in working times ...", + "mime": "text/markdown" + }, + "id": "13", + "references": [], + "title": "create common library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T21:31:53.418Z", + "details": { + "content": "create draw library:\n\n- [x] configurations input like objPrefix;\n- [x] draw functions;\n- [x] draw chart setting;", + "mime": "text/markdown" + }, + "id": "5", + "references": [], + "title": "create draw library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T09:41:01.882Z", + "description": { + "content": "create http library", + "mime": "text/markdown" + }, + "id": "12", + "references": [], + "title": "create http library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T12:23:14.619Z", + "details": { + "content": "- [x] add input for logTag;\n- [x] add input for enableLogging;\n- [x] add reuired logging functions;", + "mime": "text/markdown" + }, + "id": "1", + "references": [], + "title": "create logger library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T15:40:11.509Z", + "description": { + "content": "create ma colorify indicator.\nsomething like TrendMagic ...", + "mime": "text/markdown" + }, + "id": "3", + "references": [], + "title": "create ma colorify indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T15:39:38.300Z", + "description": { + "content": "create ma indicator", + "mime": "text/markdown" + }, + "id": "2", + "references": [], + "title": "create ma indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T21:38:20.129Z", + "description": { + "content": "create models library", + "mime": "text/markdown" + }, + "id": "6", + "references": [], + "title": "create models library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:25:20.394Z", + "description": { + "content": "create OrderBlock Finder Indicator", + "mime": "text/markdown" + }, + "id": "17", + "references": [], + "title": "create OrderBlock Finder Indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T08:04:33.131Z", + "description": { + "content": "create Trade Class", + "mime": "text/markdown" + }, + "id": "8", + "references": [], + "title": "create Trade Class" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T23:54:36.761Z", + "description": { + "content": "create XTrendDetector Indicator ", + "mime": "text/markdown" + }, + "id": "7", + "references": [], + "title": "create XTrendDetector Indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-07T19:28:10.103Z", + "details": { + "content": "- [x] Adaptive Moving Average; Implemented\n- [x] Bolinger Bands; No\n- [x] Envelopes; No\n- [x] Fractal Adaptive Moving Average; No\n- [x] Bears/Bulls Power; No\n- [x] Chaikin Oscillator; MayBe\n- [X] Commodity Channel Index; AN No\n- [] DeMarker;\n- [] Force Index;\n- [] MACD;\n- [] Momentum;\n- [] Moving Average Of Oscillators;\n- [] Accumulation/Distribution;\n- [] On Balance Volume;", + "mime": "text/markdown" + }, + "id": "19", + "references": [], + "title": "R&D about Exists Examples" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:24:44.656Z", + "description": { + "content": "rename XRSI Provider Name to something else", + "mime": "text/markdown" + }, + "id": "15", + "references": [], + "title": "rename XRSI Provider Name to something else" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:25:01.625Z", + "description": { + "content": "start implementing XTPW indicator", + "mime": "text/markdown" + }, + "id": "16", + "references": [], + "title": "start implementing XTPW indicator" + } + ] +} \ No newline at end of file diff --git a/.vscode/vscode-kanban.json.bkp b/.vscode/vscode-kanban.json.bkp new file mode 100644 index 00000000..522bcc67 --- /dev/null +++ b/.vscode/vscode-kanban.json.bkp @@ -0,0 +1,738 @@ +{ + "todo": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T05:52:38.201Z", + "description": { + "content": "- [] add supports for OAuth implementation;", + "mime": "text/markdown" + }, + "id": "28", + "references": [], + "title": "Add Support for OAuth" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T05:53:36.313Z", + "description": { + "content": "- [] add a Mechanism for Push Commands to Robot;\n- [] enable all base configurations to locally changes using commands;", + "mime": "text/markdown" + }, + "id": "29", + "references": [], + "title": "Add SUpport for Push Commands" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-22T01:30:28.887Z", + "description": { + "content": "- [] Pause/Resume;\n- [] Restart;\n- [] Stop Opening New Positions for Withdrawal Actions;\n- [] add support for enable disable signallers;\n- [] etc;", + "mime": "text/markdown" + }, + "id": "45", + "references": [], + "title": "add support for some actions button on chart of EA" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T17:22:24.427Z", + "description": { + "content": "- [] XTD;\n- [] XSI;\n- [] XOBDLH;\n- [] XCHMACC;\n- [] XCHMACMN;\n- [] XCHMACMX;\n\nthis task is not so important at the moment, doint this later ...", + "mime": "text/markdown" + }, + "id": "36", + "references": [], + "title": "Do a Refactor On Long Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T09:48:13.509Z", + "id": "32", + "references": [], + "title": "R&D about placing stop limit orders for Indirectional Supports", + "description": { + "content": "since there are many issues to manage them, for the moment i will ignore this.\n,aybe working on it later ...", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-23T22:21:14.112Z", + "description": { + "content": "ignore adding sl on partial closed and risk free signals for the moment ...", + "mime": "text/markdown" + }, + "id": "46", + "references": [], + "title": "resolve InvalidStop on Partial Closing" + } + ], + "in-progress": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-28T08:23:14.444Z", + "id": "56", + "references": [], + "title": "add Support for XSupport and InDirectional Support Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-24T07:37:10.876Z", + "id": "52", + "references": [], + "title": "extends new section based indicators" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-24T07:36:28.060Z", + "description": { + "content": "- [] implement helpers lib for new indicators;\n- [] try to test them into a new ea;\n- [] combine them with our product;\n", + "mime": "text/markdown" + }, + "id": "51", + "references": [], + "title": "implement new indicators helpers lib" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-24T01:13:49.250Z", + "id": "49", + "references": [], + "title": "start backbone of XAUUSD robot for MQL5" + } + ], + "testing": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-23T22:56:31.075Z", + "description": { + "content": "- [] Nothing;\n- [] Close If In DD;\n- [] Partial Close if in DD _5;\n- [] Partial Close if in DD _10;\n- [] Partial Close if in DD _15;\n- [] Partial Close if in DD _20;\n- [] Partial Close if in DD _25;\n", + "mime": "text/markdown" + }, + "id": "48", + "references": [], + "title": "add a mechanism for acting for long time trades ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-23T22:21:39.744Z", + "id": "47", + "references": [], + "title": "add a method for generating Collector logs ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-22T01:07:29.299Z", + "description": { + "content": "- [x] report library;\n- [x] define report models;\n- [x] define report mechanism;\n- [x] implement Logger Reports;\n- [x] report String Generators;\n- [x] use reports in ea;", + "mime": "text/markdown" + }, + "id": "44", + "references": [], + "title": "add a Report library and define all required reports inside it" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T11:07:59.089Z", + "description": { + "content": "- [x] XTD;\n- [x] XSI;\n- [x] XOBDLH;\n- [x] XCHMACC;\n- [x] XCHMACMX;\n- [x] XCHMACMN;", + "mime": "text/markdown" + }, + "id": "33", + "references": [], + "title": "add config sections to select providers long and short signalling" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-27T11:37:45.679Z", + "id": "54", + "references": [], + "title": "add handlers for TakeProfit or LoseProfit Events" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-19T10:19:40.648Z", + "id": "40", + "references": [], + "title": "add settings for Trade Management and risk management" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-20T13:38:04.017Z", + "description": { + "content": "add Start Alert and Prompt Some Values on it ...\nprepare Comments for informing usefull data ...", + "mime": "text/markdown" + }, + "id": "41", + "references": [], + "title": "add start Alert" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:06:27.820Z", + "description": { + "content": "- [x] Check Signal State;\n- [x] Calculate Volume;\n- [x] In Directional Supporting;\n\nimplemented, but since have issues on managing, ignore use them ...", + "mime": "text/markdown" + }, + "id": "24", + "references": [], + "title": "add Support for Indirectional Supporting Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T05:51:40.742Z", + "description": { + "content": "- [x] Add Support for Hourly Alarams;\n- [x] Add Support for Daily Alarams;\n- [x] Add Support for Weekly Info Alarams;\n- [x] ...", + "mime": "text/markdown" + }, + "id": "27", + "references": [], + "title": "Add support for Info Alarms" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:07:37.092Z", + "description": { + "content": "- [x] Calculate How CLose Pyramid in Count;\n- [x] How Close Pyramid in Profit;\n- [x] How Close Pyramid in Max Draw Down;\n\nthese functionalities implemented successfully, but since we don't use any Supporting mechanism and limit number of same time trades.", + "mime": "text/markdown" + }, + "id": "25", + "references": [], + "title": "add Support for Pyramid Closing Trades" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-20T20:08:43.804Z", + "description": { + "content": "wee need this buffer to Increase or Decrease volumes ...", + "mime": "text/markdown" + }, + "id": "42", + "references": [], + "title": "Add Support for Save Max In DrawDown in Buffer", + "details": { + "content": "- [] add an specific library;\n- [] define all requirement;\n- [] add utility functions;\n- [] use it;", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:05:41.976Z", + "description": { + "content": "- [x] Max Count;\n- [x] for In DD Long Signals;\n- [x] Volume Calculations;\n\nimplemented, but ignore to use them, for moment, since they have issues on managing ...", + "mime": "text/markdown" + }, + "id": "23", + "references": [], + "title": "add Support for Support Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:04:44.044Z", + "description": { + "content": "check partial Closing works correctly;\n\n- [x] for Longs;\n- [x] for Shorts;", + "mime": "text/markdown" + }, + "id": "22", + "references": [], + "title": "Check Partial Closing" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T17:03:45.572Z", + "id": "35", + "references": [], + "title": "Complete Input Validators for XEU5", + "description": { + "content": "- [x] XTM;\n- [x] XTD;\n- [x] XRSI;\n- [x] XOBD;\n- [x] XLH;\n- [x] XCHLH;\n- [x] XCHMA;", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:03:50.981Z", + "description": { + "content": "Complete Remained Short Signals:\n\n- [x] XCHMA Crosses;\n- [x] XCHMA Under Max;\n- [x] XCHMA Under Min;", + "mime": "text/markdown" + }, + "id": "20", + "references": [], + "title": "Complete Remained Short Signals" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-24T01:15:14.065Z", + "id": "50", + "references": [], + "title": "create a signal protector class for handling signals states on time pasted" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T11:08:47.584Z", + "id": "34", + "references": [], + "title": "Disbale Conditions Logs ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:04:18.085Z", + "description": { + "content": "fix volume calculation for signals;\n\n- [x] static volume;\n- [x] base volume multiplier;\n- [x] grow rate based on balance increasing;\n- [x] max volume duplicator;\n- [x] decrease volume for support trades;", + "mime": "text/markdown" + }, + "id": "21", + "references": [], + "title": "Fix Volume Calculation" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-21T00:12:42.225Z", + "id": "43", + "references": [], + "title": "increase min balance for trading based on account balance ..." + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T09:27:48.310Z", + "description": { + "content": "- [x] Close Support Trades;\n- [x] Close InDirectional Trades;\n- [x] Increase/Decrease Volume Multiplier based on TP(s) and SL(s);\n\nimplement OnTrade requirements for later usage, everythings works correctly, but for the moment i ignore use it ...", + "mime": "text/markdown" + }, + "id": "31", + "references": [], + "title": "Read OnTrade Event Documentation" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-24T17:48:18.009Z", + "description": { + "content": "- [] XSignal Structure;\n- [] XTrader Class;\n- [] Draw Signal, TP's and SL, and Volumes;\n", + "mime": "text/markdown" + }, + "id": "53", + "references": [], + "title": "Refactor XSignal and Create a new One also New Trader" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-19T08:18:38.795Z", + "id": "39", + "references": [], + "title": "Remove UnUsed Settings for Production" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T06:44:02.085Z", + "description": { + "content": "- [x] XTD;\n- [x] XSI;\n- [x] XOBDLH;\n- [x] XCHMACC;\n- [x] XCHMACMX;\n- [x] XCHMACMN;", + "mime": "text/markdown" + }, + "id": "30", + "references": [], + "title": "rename signal providers to propper names" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-19T08:17:38.115Z", + "id": "38", + "references": [], + "title": "Test and Add support for Equity and Max Drawdown Management" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-17T13:13:33.447Z", + "id": "37", + "references": [], + "title": "there is an stop on combining on meta quote broker fix this ...", + "details": { + "content": "do a refactor on all brokers, higgh priority criterias ...", + "mime": "text/markdown" + } + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-28T08:21:10.141Z", + "id": "55", + "references": [], + "title": "add support for Stop Out Action in Guard Class", + "details": { + "content": "attached it but need to test ...", + "mime": "text/markdown" + } + } + ], + "done": [ + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-06T16:40:25.004Z", + "description": { + "content": "add supports to plot trend arrow in tdma indicator", + "mime": "text/markdown" + }, + "id": "18", + "references": [], + "title": "add supports to plot trend arrow in tdma indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "category": "XEU5", + "creation_time": "2023-12-16T03:07:56.408Z", + "details": { + "content": "- [x] cleanup old structure supports;\n- [x] cleanup old structure indirectional;\n- [x] cleanup old structure max in draw down;\n- [x] cleanup old structure old signals;\n- etc ...", + "mime": "text/markdown" + }, + "id": "26", + "references": [], + "title": "Cleanup Provider UnUsed Functions;" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T09:30:44.836Z", + "description": { + "content": "handle all requirement for neural network class.", + "mime": "text/markdown" + }, + "details": { + "content": "required many things for testing ...", + "mime": "text/markdown" + }, + "id": "11", + "references": [], + "title": "create a neural network class" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:24:26.792Z", + "description": { + "content": "create a signal provider template based on XRSI", + "mime": "text/markdown" + }, + "id": "14", + "references": [], + "title": "create a signal provider template based on XRSI" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T08:05:13.515Z", + "description": { + "content": "create account info library", + "mime": "text/markdown" + }, + "details": { + "content": "define it as a class in class lib ...", + "mime": "text/markdown" + }, + "id": "9", + "references": [], + "title": "create account info library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T15:43:14.906Z", + "details": { + "content": "create alert library:\n\n- [] add configurationinputs;\n- [] add alert functions;\n- [] mail;\n- [] push;\n- [] terminal;", + "mime": "text/markdown" + }, + "id": "4", + "references": [], + "title": "create alert library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T09:30:05.284Z", + "description": { + "content": "create an x-ea provider template:\n\n- [x] create event handlers;\n- [x] add required config inputs;\n- [x] define access to classes;\n- [x] etc ...", + "mime": "text/markdown" + }, + "id": "10", + "references": [], + "title": "create an x-ea provider template" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T13:34:50.719Z", + "description": { + "content": "create common library", + "mime": "text/markdown" + }, + "details": { + "content": "created but must add required functions in working times ...", + "mime": "text/markdown" + }, + "id": "13", + "references": [], + "title": "create common library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T21:31:53.418Z", + "details": { + "content": "create draw library:\n\n- [x] configurations input like objPrefix;\n- [x] draw functions;\n- [x] draw chart setting;", + "mime": "text/markdown" + }, + "id": "5", + "references": [], + "title": "create draw library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T09:41:01.882Z", + "description": { + "content": "create http library", + "mime": "text/markdown" + }, + "id": "12", + "references": [], + "title": "create http library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T12:23:14.619Z", + "details": { + "content": "- [x] add input for logTag;\n- [x] add input for enableLogging;\n- [x] add reuired logging functions;", + "mime": "text/markdown" + }, + "id": "1", + "references": [], + "title": "create logger library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T15:40:11.509Z", + "description": { + "content": "create ma colorify indicator.\nsomething like TrendMagic ...", + "mime": "text/markdown" + }, + "id": "3", + "references": [], + "title": "create ma colorify indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T15:39:38.300Z", + "description": { + "content": "create ma indicator", + "mime": "text/markdown" + }, + "id": "2", + "references": [], + "title": "create ma indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T21:38:20.129Z", + "description": { + "content": "create models library", + "mime": "text/markdown" + }, + "id": "6", + "references": [], + "title": "create models library" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:25:20.394Z", + "description": { + "content": "create OrderBlock Finder Indicator", + "mime": "text/markdown" + }, + "id": "17", + "references": [], + "title": "create OrderBlock Finder Indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-04T08:04:33.131Z", + "description": { + "content": "create Trade Class", + "mime": "text/markdown" + }, + "id": "8", + "references": [], + "title": "create Trade Class" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-01T23:54:36.761Z", + "description": { + "content": "create XTrendDetector Indicator ", + "mime": "text/markdown" + }, + "id": "7", + "references": [], + "title": "create XTrendDetector Indicator" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-12-07T19:28:10.103Z", + "details": { + "content": "- [x] Adaptive Moving Average; Implemented\n- [x] Bolinger Bands; No\n- [x] Envelopes; No\n- [x] Fractal Adaptive Moving Average; No\n- [x] Bears/Bulls Power; No\n- [x] Chaikin Oscillator; MayBe\n- [X] Commodity Channel Index; AN No\n- [] DeMarker;\n- [] Force Index;\n- [] MACD;\n- [] Momentum;\n- [] Moving Average Of Oscillators;\n- [] Accumulation/Distribution;\n- [] On Balance Volume;", + "mime": "text/markdown" + }, + "id": "19", + "references": [], + "title": "R&D about Exists Examples" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:24:44.656Z", + "description": { + "content": "rename XRSI Provider Name to something else", + "mime": "text/markdown" + }, + "id": "15", + "references": [], + "title": "rename XRSI Provider Name to something else" + }, + { + "assignedTo": { + "name": "Hadi Khazaee Asl" + }, + "creation_time": "2023-11-05T20:25:01.625Z", + "description": { + "content": "start implementing XTPW indicator", + "mime": "text/markdown" + }, + "id": "16", + "references": [], + "title": "start implementing XTPW indicator" + } + ] +} \ No newline at end of file diff --git a/BKP/Main/Classes/x-saherelm.class.lib.mq5 b/BKP/Main/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 00000000..68f48471 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Classes/x-saherelm.nn.lib.mq5 b/BKP/Main/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 00000000..8fa40f53 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Classes/x-saherelm.provider.lib.mq5 b/BKP/Main/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 00000000..1dbdcd3f --- /dev/null +++ b/BKP/Main/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/BKP/Main/Experts/x-saherelm.xeu5.ea.mq5 b/BKP/Main/Experts/x-saherelm.xeu5.ea.mq5 new file mode 100644 index 00000000..58c5bdac --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f565e415 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..d7071b48 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e84d762f --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..19d3417c --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 00000000..e6a92f65 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f90f15b2 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e6971b7a --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..6286228b --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 00000000..a871ed42 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/BKP/Main/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..875eec08 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xama.indicator.mq5 b/BKP/Main/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xchlh.oscillator.mq5 b/BKP/Main/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 00000000..5c74787c --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xchma.oscillator.mq5 b/BKP/Main/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 00000000..12d6c691 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xfi.oscillator.mq5 b/BKP/Main/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 00000000..cfd393ca --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xlh.indicator.mq5 b/BKP/Main/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 00000000..4dfc64e2 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xobd.indicator.mq5 b/BKP/Main/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 00000000..4ac05cf6 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xrsi.oscillator.mq5 b/BKP/Main/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 00000000..5659e07d --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xtd.oscillator.mq5 b/BKP/Main/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 00000000..5f46d187 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xtm.indicator.mq5 b/BKP/Main/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 00000000..eac88e0a --- /dev/null +++ b/BKP/Main/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/BKP/Main/Indicators/x-saherelm.xts.oscillator.mq5 b/BKP/Main/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 00000000..46e9fbf9 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Libraries/x-saherelm.alert.lib.mq5 b/BKP/Main/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 00000000..10790632 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Libraries/x-saherelm.common.lib.mq5 b/BKP/Main/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 00000000..290dde9b --- /dev/null +++ b/BKP/Main/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/BKP/Main/Libraries/x-saherelm.draw.lib.mq5 b/BKP/Main/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 00000000..ece98c83 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Libraries/x-saherelm.http.lib.mq5 b/BKP/Main/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 00000000..97f7ac0a --- /dev/null +++ b/BKP/Main/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/BKP/Main/Libraries/x-saherelm.log.lib.mq5 b/BKP/Main/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 00000000..70f1bda4 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Libraries/x-saherelm.models.lib.mq5 b/BKP/Main/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 00000000..b98ae3e8 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 b/BKP/Main/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 new file mode 100644 index 00000000..c077b65f --- /dev/null +++ b/BKP/Main/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/BKP/Main/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 b/BKP/Main/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 new file mode 100644 index 00000000..03e0a509 --- /dev/null +++ b/BKP/Main/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/BKP/Main/Providers/x-saherelm.xeu5.provider.lib.mq5 b/BKP/Main/Providers/x-saherelm.xeu5.provider.lib.mq5 new file mode 100644 index 00000000..c57de45d --- /dev/null +++ b/BKP/Main/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/BKP/Temp/XEmptyPreparedProjet.zip b/BKP/Temp/XEmptyPreparedProjet.zip new file mode 100644 index 0000000000000000000000000000000000000000..8ba604e3f85f91b8e2e91b4041a44be1a6788f7e GIT binary patch literal 184021 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šQmW9*j$k}rn(7bRLRds%^r9#95` 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 aHvaAb1W;N604%_NN5F+k5Adx3!2bX;9s&~p literal 0 HcmV?d00001 diff --git a/BKP/Temp/x-saherelm.xau5.provider.indicators.lib.mq5 b/BKP/Temp/x-saherelm.xau5.provider.indicators.lib.mq5 new file mode 100644 index 00000000..cd1bb2ad --- /dev/null +++ b/BKP/Temp/x-saherelm.xau5.provider.indicators.lib.mq5 @@ -0,0 +1,9556 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAU5 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_XAU5_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 XAU5MarketConditions +{ + // + // 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.xau5.provider.inputs.lib.mq5" + +// +// Signallers ... +input group "XAU5 Signallers"; + +// +// XTD ... +input group "XAU5 XTD Signaller"; +input bool xAU5XTDEnableSignaller = true; // Enable Signaller +// input bool xAU5XTDEnableTPSL = false; // Enable TP/SL +input bool xAU5XTDAllowLongSignals = true; // Enable Long Signals +input bool xAU5XTDAllowShortSignals = true; // Enable Short Signals + +// +// XTAM ... +input group "XAU5 XTAM Signaller"; +input bool xAU5XTAMEnableSignaller = true; // Enable Signaller +// input bool xAU5XTAMEnableTPSL = false; // Enable TP/SL +input bool xAU5XTAMAllowLongSignals = true; // Enable Long Signals +input bool xAU5XTAMAllowShortSignals = true; // Enable Short Signals + +// +// XSI ... +input group "XAU5 XSI Signaller"; +input bool xAU5XSIEnableSignaller = true; // Enable Signaller +// input bool xAU5SIXEnableTPSL = false; // Enable TP/SL +input bool xAU5XSIAllowLongSignals = true; // Enable Long Signals +input bool xAU5XSIAllowShortSignals = true; // Enable Short Signals + +// +// XSTFI ... +input group "XAU5 XSTFI Signaller"; +input bool xAU5XSTFIEnableSignaller = true; // Enable Signaller +// input bool xAU5XSTFIEnableTPSL = false; // Enable TP/SL +input bool xAU5XSTFIAllowLongSignals = true; // Enable Long Signals +input bool xAU5XSTFIAllowShortSignals = true; // Enable Short Signals + +// +// XOBDLH ... +input group "XAU5 XOBDLH Signaller"; +input bool xAU5XOBDLHEnableSignaller = true; // Enable Signaller +// input bool xAU5XOBDLHEnableTPSL = false; // Enable TP/SL +input bool xAU5XOBDLHAllowLongSignals = true; // Enable Long Signals +input bool xAU5XOBDLHAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACC ... +input group "XAU5 XCHMACC Signaller"; +input bool xAU5XCHMACCEnableSignaller = true; // Enable Signaller +// input bool xAU5XCHMACCEnableTPSL = false; // Enable TP/SL +input bool xAU5XCHMACCAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACCAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACMX ... +input group "XAU5 XCHMACMX Signaller"; +input bool xAU5XCHMACMXEnableSignaller = true; // Enable Signaller +// input bool xAU5XCHMACMXEnableTPSL = false; // Enable TP/SL +input bool xAU5XCHMACMXAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACMXAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACMN ... +input group "XAU5 XCHMACMN Signaller"; +input bool xAU5XCHMACMNEnableSignaller = true; // Enable Signaller +// input bool xAU5XCHMACMNEnableTPSL = false; // Enable TP/SL +input bool xAU5XCHMACMNAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACMNAllowShortSignals = true; // Enable Short Signals + +// +// Imports all Indicators Helper here ... +// input group "XAU5 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 xAU5IsTestMode = true; +int xAU5MaxLengthOfInputs = 0; +int xAU5CalculatedBars = 0; + +// +// Signaller Variables ... +// +// XTD ... +bool xAU5MXTDEnableSignaller = xAU5XTDEnableSignaller; +// bool xAU5MXTDEnableTPSL = xAU5XTDEnableTPSL; +bool xAU5MXTDAllowLongSignals = xAU5XTDAllowLongSignals; +bool xAU5MXTDAllowShortSignals = xAU5XTDAllowShortSignals; + +// +// XTAM ... +bool xAU5MXTAMEnableSignaller = xAU5XTAMEnableSignaller; +// bool xAU5MXTAMEnableTPSL = xAU5XTAMEnableTPSL; +bool xAU5MXTAMAllowLongSignals = xAU5XTAMAllowLongSignals; +bool xAU5MXTAMAllowShortSignals = xAU5XTAMAllowShortSignals; + +// +// XSI ... +bool xAU5MXSIEnableSignaller = xAU5XSIEnableSignaller; +// bool xAU5MSIXEnableTPSL = xAU5SIXEnableTPSL; +bool xAU5MXSIAllowLongSignals = xAU5XSIAllowLongSignals; +bool xAU5MXSIAllowShortSignals = xAU5XSIAllowShortSignals; + +// +// XSTFI ... +bool xAU5MXSTFIEnableSignaller = xAU5XSTFIEnableSignaller; +// bool xAU5MXSTFIEnableTPSL = xAU5XSTFIEnableTPSL; +bool xAU5MXSTFIAllowLongSignals = xAU5XSTFIAllowLongSignals; +bool xAU5MXSTFIAllowShortSignals = xAU5XSTFIAllowShortSignals; + +// +// XOBDLH ... +bool xAU5MXOBDLHEnableSignaller = xAU5XOBDLHEnableSignaller; +// bool xAU5MXOBDLHEnableTPSL = xAU5XOBDLHEnableTPSL; +bool xAU5MXOBDLHAllowLongSignals = xAU5XOBDLHAllowLongSignals; +bool xAU5MXOBDLHAllowShortSignals = xAU5XOBDLHAllowShortSignals; + +// +// XCHMACC ... +bool xAU5MXCHMACCEnableSignaller = xAU5XCHMACCEnableSignaller; +// bool xAU5MXCHMACCEnableTPSL = xAU5XCHMACCEnableTPSL; +bool xAU5MXCHMACCAllowLongSignals = xAU5XCHMACCAllowLongSignals; +bool xAU5MXCHMACCAllowShortSignals = xAU5XCHMACCAllowShortSignals; + +// +// XCHMAMX ... +bool xAU5MXCHMACMXEnableSignaller = xAU5XCHMACMXEnableSignaller; +// bool xAU5MXCHMACMXEnableTPSL = xAU5XCHMACMXEnableTPSL; +bool xAU5MXCHMACMXAllowLongSignals = xAU5XCHMACMXAllowLongSignals; +bool xAU5MXCHMACMXAllowShortSignals = xAU5XCHMACMXAllowShortSignals; + +// +// XCHMAMN ... +bool xAU5MXCHMACMNEnableSignaller = xAU5XCHMACMNEnableSignaller; +// bool xAU5MXCHMACMNEnableTPSL = xAU5XCHMACMNEnableTPSL; +bool xAU5MXCHMACMNAllowLongSignals = xAU5XCHMACMNAllowLongSignals; +bool xAU5MXCHMACMNAllowShortSignals = xAU5XCHMACMNAllowShortSignals; + +// +// Funded Next Resolve Guards ... +bool isXAU5OnFundedNext = true; + +// +// Here we Define some Global Market Variables to Analyse MArket Conditions +// using them at each time ... +XAU5MarketConditions xAU5Conditions = {}; + +// +// Validate Indicators Inputs ... +bool XAU5ValidateIndicatorsInputs() +{ + // + 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 XAU5InitIndicators() +{ + // + bool result = false; + + // + // Make it Enable when we need to Log Market Conditions ... + // xAU5IsTestMode = false; // IsRunningOnTestMode(); + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xAU5MaxLengthOfInputs = MathMax( + xTMMaPeriod, + xAU5NumberOfItemsPerTick); + + // + // XAMA ... + xAU5MaxLengthOfInputs = MathMax( + xAMALength, + xAU5NumberOfItemsPerTick); + xAU5MaxLengthOfInputs = MathMax( + xAMAFastEMA, + xAU5NumberOfItemsPerTick); + xAU5MaxLengthOfInputs = MathMax( + xAMASlowEMA, + xAU5NumberOfItemsPerTick); + + // + // XLH ... + xAU5MaxLengthOfInputs = MathMax( + xLHLength, + xAU5NumberOfItemsPerTick); + + // + // XTD ... + xAU5MaxLengthOfInputs = MathMax( + xTDLength, + xAU5MaxLengthOfInputs); + + // + // XFI ... + xAU5MaxLengthOfInputs = MathMax( + xFILength, + xAU5MaxLengthOfInputs); + + // + // XRSI ... + xAU5MaxLengthOfInputs = MathMax( + xRSILength, + xAU5MaxLengthOfInputs); + + // + // XOBD ... + xAU5MaxLengthOfInputs = MathMax( + xOBDLength, + xAU5MaxLengthOfInputs); + + // + // XCHLH ... + xAU5MaxLengthOfInputs = MathMax( + xCHLHLcLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHLHMcLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHLHScLength, + xAU5MaxLengthOfInputs); + + // + // XCHMA ... + xAU5MaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xAU5MaxLengthOfInputs); + + // + // Validate Indicators Inputs before Initialization ... + result = XAU5ValidateIndicatorsInputs(); + if (!result) + { + return result; + } + + // + // Validate Signallers ... + + // + // XTD ... + bool isXTDEnable = + xAU5XTDEnableSignaller && + (xAU5XTDAllowLongSignals || + xAU5XTDAllowShortSignals); + + // + // XTAM ... + bool isXTAMEnable = + xAU5XTAMEnableSignaller && + (xAU5XTAMAllowLongSignals || + xAU5XTAMAllowShortSignals); + + // + // XSI ... + bool isXSIEnable = + xAU5XSIEnableSignaller && + (xAU5XSIAllowLongSignals || + xAU5XSIAllowShortSignals); + + // + // XSTFI ... + bool isXSTFIEnable = + xAU5XSTFIEnableSignaller && + (xAU5XSTFIAllowLongSignals || + xAU5XSTFIAllowShortSignals); + + // + // XOBDLH ... + bool isXOBDLHEnable = + xAU5XOBDLHEnableSignaller && + (xAU5XOBDLHAllowLongSignals || + xAU5XOBDLHAllowShortSignals); + + // + // XCHMACC ... + bool isXCHMACCEnable = + xAU5XCHMACCEnableSignaller && + (xAU5XCHMACCAllowLongSignals || + xAU5XCHMACCAllowShortSignals); + + // + // XCHMACMX ... + bool isXCHMACMXEnable = + xAU5XCHMACMXEnableSignaller && + (xAU5XCHMACMXAllowLongSignals || + xAU5XCHMACMXAllowShortSignals); + + // + // XCHMACMN ... + bool isXCHMACMNEnable = + xAU5XCHMACMNEnableSignaller && + (xAU5XCHMACMNAllowLongSignals || + xAU5XCHMACMNAllowShortSignals); + + // + bool hasSignaller = + // + isXTDEnable || + isXTAMEnable || + isXSIEnable || + isXSTFIEnable || + isXOBDLHEnable || + isXCHMACCEnable || + isXCHMACMXEnable || + isXCHMACMNEnable + // + ; + result = hasSignaller; + if (!result) + { + // + LogMessage("XAU5 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 XAU5ReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XAMAReleaseHandlers(); + XLHReleaseHandlers(); + XTDReleaseHandlers(); + XFIReleaseHandlers(); + XTSReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XAU5HandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xAU5CalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xAU5NumberOfItemsPerTick); + XAMAReadBuffers(xAU5NumberOfItemsPerTick); + XLHReadBuffers(xAU5NumberOfItemsPerTick); + XTDReadBuffers(xAU5NumberOfItemsPerTick); + XFIReadBuffers(xAU5NumberOfItemsPerTick); + XTSReadBuffers(xAU5NumberOfItemsPerTick); + XRSIReadBuffers(xAU5NumberOfItemsPerTick); + XOBDReadBuffers(xAU5NumberOfItemsPerTick); + XCHMAReadBuffers(xAU5NumberOfItemsPerTick); + XCHLHReadBuffers(xAU5NumberOfItemsPerTick); + + // + XAU5ReadConditions(); +} + +// +// +// 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 XAU5CanOpenLongTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XAU5HasLongSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + XAU5ClearConditions(); + } + + // + 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 XAU5CanCloseLongTrade() +{ + // + 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 XAU5CanOpenShortTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XAU5HasShortSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + XAU5ClearConditions(); + } + + // + 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 XAU5CanCloseShortTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// Read All Globally Required Conditions ... +void XAU5ReadConditions() +{ + // + XAU5ClearConditions(); + + // + xAU5Conditions = XAU5GenerateMarketConditions(1); +} + +// +// Cleanup Conditions ... +void XAU5ClearConditions() +{ + // + XAU5MarketConditions mConditions = {}; + + // + xAU5Conditions = mConditions; +} + +// +// Generate Merket Conditions for Specified Bar Index ... +XAU5MarketConditions XAU5GenerateMarketConditions( + int bar_index = 1 // Specified Bar Index ... +) +{ + // + XAU5MarketConditions 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 XAU5HasLongSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XAU5XTDHasLongSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XAU5XTAMHasLongSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XAU5XSIHasLongSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XAU5XSTFIHasLongSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XAU5XOBDLHHasLongSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XAU5XCHMACCHasLongSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMACMNHasSignal = XAU5XCHMACMNHasLongSignal(); + if (isXCHMACMNHasSignal) + { + // + Add( + EnumToString(XCHMACMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMACMXHasSignal = XAU5XCHMACMXHasLongSignal(); + 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 (xAU5IsTestMode) + { + // + string message = XAU5GetConditionsString(xAU5Conditions, "\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 XAU5HasShortSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XAU5XTDHasShortSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XAU5XTAMHasShortSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XAU5XSIHasShortSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XAU5XSTFIHasShortSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XAU5XOBDLHHasShortSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XAU5XCHMACCHasShortSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMACMNHasSignal = XAU5XCHMACMNHasShortSignal(); + if (isXCHMACMNHasSignal) + { + // + Add( + EnumToString(XCHMACMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMACMXHasSignal = XAU5XCHMACMXHasShortSignal(); + 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 (xAU5IsTestMode) + { + // + string message = XAU5GetConditionsString(xAU5Conditions, "\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 XAU5DisableLongSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowLongSignals = false; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowLongSignals = false; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowLongSignals = false; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowLongSignals = false; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowLongSignals = false; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowLongSignals = false; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowLongSignals = false; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowLongSignals = false; + } +} + +// +// Enable All Signallers Longs ... +// Only if they are Configured as Enable at Settings ... +void XAU5EnableLongSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowLongSignals = + xAU5XTDAllowLongSignals + ? true + : xAU5MXTDAllowLongSignals; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowLongSignals = + xAU5XTAMAllowLongSignals + ? true + : xAU5MXTAMAllowLongSignals; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowLongSignals = + xAU5XSIAllowLongSignals + ? true + : xAU5MXSIAllowLongSignals; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowLongSignals = + xAU5XSTFIAllowLongSignals + ? true + : xAU5MXSTFIAllowLongSignals; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowLongSignals = + xAU5XOBDLHAllowLongSignals + ? true + : xAU5MXOBDLHAllowLongSignals; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowLongSignals = + xAU5XCHMACCAllowLongSignals + ? true + : xAU5MXCHMACCAllowLongSignals; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowLongSignals = + xAU5XCHMACMXAllowLongSignals + ? true + : xAU5MXCHMACMXAllowLongSignals; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowLongSignals = + xAU5XCHMACMNAllowLongSignals + ? true + : xAU5MXCHMACMNAllowLongSignals; + } +} + +// +// Disable All Signallers Shorts ... +void XAU5DisableShortSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowShortSignals = false; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowShortSignals = false; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowShortSignals = false; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowShortSignals = false; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowShortSignals = false; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowShortSignals = false; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowShortSignals = false; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowShortSignals = false; + } +} + +// +// Enable All Signallers Shorts ... +// Only if they are Configured as Enable at Settings ... +void XAU5EnableShortSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowShortSignals = + xAU5XTDAllowShortSignals + ? true + : xAU5MXTDAllowShortSignals; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowShortSignals = + xAU5XTAMAllowShortSignals + ? true + : xAU5MXTAMAllowShortSignals; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowShortSignals = + xAU5XSIAllowShortSignals + ? true + : xAU5MXSIAllowShortSignals; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowShortSignals = + xAU5XSTFIAllowShortSignals + ? true + : xAU5MXSTFIAllowShortSignals; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowShortSignals = + xAU5XOBDLHAllowShortSignals + ? true + : xAU5MXOBDLHAllowShortSignals; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowShortSignals = + xAU5XCHMACCAllowShortSignals + ? true + : xAU5MXCHMACCAllowShortSignals; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowShortSignals = + xAU5XCHMACMXAllowShortSignals + ? true + : xAU5MXCHMACMXAllowShortSignals; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowShortSignals = + xAU5XCHMACMNAllowShortSignals + ? true + : xAU5MXCHMACMNAllowShortSignals; + } +} + +// +// Check Market Conditions is Ready for Long Signals or not ... +bool XAU5ReadyForLong( + 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 ... + !( + // + (xAU5Conditions.isXCHMASCOverMin || + xAU5Conditions.isXCHMASCCrossedOverMin) && + (xAU5Conditions.isXCHMASCUnderMin || + xAU5Conditions.isXCHMASCCrossedUnderMin) + // + ); + } + + // + if (checkXCHMAMax && result) + { + // + result = + // + // XCHMA MAX ... + !( + // + (xAU5Conditions.isXCHMASCOverMax || + xAU5Conditions.isXCHMASCCrossedOverMax) && + (xAU5Conditions.isXCHMASCUnderMax || + xAU5Conditions.isXCHMASCCrossedUnderMax) + // + ) + // + ; + } + + // + if (checkXCHMACycles && result) + { + // + result = + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMAPeaks && result) + { + // + result = + // + // XCHMA Check Peaks ... + !( + // + // All Cycles Peak ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMALCPeak) + // + || + // + ( + // + // SC MC ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMAMCPeak) + // + || + // + // SC LC ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMALCPeak) + // + || + // + // MC LC ... + (xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMALCPeak) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMATrendPowers && result) + { + // + result = + // + // XCHMA Check Trends Power ... + !( + // + // All Trends Down ... + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + // Twisted pairs ... + ( + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ; + } + + // + if (checkXOBD && result) + { + // + result = + // + // XOBD Check Swings ... + !xAU5Conditions.isXOBDSwingLow + // + ; + } + + // + if (checkXTS && result) + { + result = + // + // XTS Check ... + !( + // + xAU5Conditions.isXTSCurrentMin && + // + ( + // + // All Under ... + ( + (xAU5Conditions.isXTSCurrentUnderNearest || + xAU5Conditions.isXTSCurrentCrossedUnderNearest) && + (xAU5Conditions.isXTSCurrentUnderMediest || + xAU5Conditions.isXTSCurrentCrossedUnderMediest) && + (xAU5Conditions.isXTSCurrentUnderFarest || + xAU5Conditions.isXTSCurrentCrossedUnderFarest)) + // + || + // + // Pairs ... + ( + // + ((xAU5Conditions.isXTSCurrentUnderNearest || + xAU5Conditions.isXTSCurrentCrossedUnderNearest) && + (xAU5Conditions.isXTSCurrentUnderMediest || + xAU5Conditions.isXTSCurrentCrossedUnderMediest)) + // + || + // + ((xAU5Conditions.isXTSCurrentUnderNearest || + xAU5Conditions.isXTSCurrentCrossedUnderNearest) && + (xAU5Conditions.isXTSCurrentUnderFarest || + xAU5Conditions.isXTSCurrentCrossedUnderFarest)) + // + || + // + ((xAU5Conditions.isXTSCurrentUnderMediest || + xAU5Conditions.isXTSCurrentCrossedUnderMediest) && + (xAU5Conditions.isXTSCurrentUnderFarest || + xAU5Conditions.isXTSCurrentCrossedUnderFarest)) + // + ) + // + ) + // + ) + // + ; + } + + // + return result; +} + +// +// Check Market Conditions is Ready for Short Signals or not ... +bool XAU5ReadyForShort( + 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 ... + !( + // + (xAU5Conditions.isXCHMASCOverMin || + xAU5Conditions.isXCHMASCCrossedOverMin) && + (xAU5Conditions.isXCHMASCUnderMin || + xAU5Conditions.isXCHMASCCrossedUnderMin) + // + ); + } + + // + if (checkXCHMAMax && result) + { + // + result = + // + // XCHMA MAX ... + !( + // + (xAU5Conditions.isXCHMASCOverMax || + xAU5Conditions.isXCHMASCCrossedOverMax) && + (xAU5Conditions.isXCHMASCUnderMax || + xAU5Conditions.isXCHMASCCrossedUnderMax) + // + ) + // + ; + } + + // + if (checkXCHMACycles && result) + { + // + result = + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) + // + && + // + // MC ... + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMAVales && result) + { + // + result = + // + // XCHMA Check Vales ... + !( + // + // All Cycles Vale ... + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale) + // + || + // + ( + // + // SC MC ... + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCVale) + // + || + // + // SC LC ... + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMALCVale) + // + || + // + // MC LC ... + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMATrendPowers && result) + { + // + result = + // + // XCHMA Check Trends Power ... + !( + // + // All Trends Down ... + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + // Twisted pairs ... + ( + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ; + } + + // + if (checkXOBD && result) + { + // + result = + // + // XOBD Check Swings ... + !xAU5Conditions.isXOBDSwingHigh + // + ; + } + + // + if (checkXTS && result) + { + // + result = + // + // XTS Check ... + !( + // + xAU5Conditions.isXTSCurrentMax && + // + ( + // + // All Over ... + ( + (xAU5Conditions.isXTSCurrentOverNearest || + xAU5Conditions.isXTSCurrentCrossedOverNearest) && + (xAU5Conditions.isXTSCurrentOverMediest || + xAU5Conditions.isXTSCurrentCrossedOverMediest) && + (xAU5Conditions.isXTSCurrentOverFarest || + xAU5Conditions.isXTSCurrentCrossedOverFarest)) + // + || + // + // Pairs ... + ( + // + ((xAU5Conditions.isXTSCurrentOverNearest || + xAU5Conditions.isXTSCurrentCrossedOverNearest) && + (xAU5Conditions.isXTSCurrentOverMediest || + xAU5Conditions.isXTSCurrentCrossedOverMediest)) + // + || + // + ((xAU5Conditions.isXTSCurrentOverNearest || + xAU5Conditions.isXTSCurrentCrossedOverNearest) && + (xAU5Conditions.isXTSCurrentOverFarest || + xAU5Conditions.isXTSCurrentCrossedOverFarest)) + // + || + // + ((xAU5Conditions.isXTSCurrentOverMediest || + xAU5Conditions.isXTSCurrentCrossedOverMediest) && + (xAU5Conditions.isXTSCurrentOverFarest || + xAU5Conditions.isXTSCurrentCrossedOverFarest)) + // + ) + // + ) + // + ) + // + ; + } + + // + return result; +} + +// +// XTD Long Signal Checking ... +bool XAU5XTDHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTDEnableSignaller || + !xAU5MXTDAllowLongSignals) + { + 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 ... + ( + // + xAU5Conditions.isXTDSignalCrossedOverBear + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + XAU5ReadyForLong() + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXLHHHDecreased && + xAU5Conditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + ( + // + (xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXAMAEndBullish) + // + || + // + (xAU5Conditions.isXTSCurrentMax && + (xAU5Conditions.isXCHMALCTrendsUp || + xAU5Conditions.isXCHMALCTrendsDown) && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXTDBearishVale) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXLHLLIncreased) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + (xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + (xAU5Conditions.isXCHMALCVale && + ( + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXAMAStartBullish) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + (xAU5Conditions.isXAMAVale && + xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXAMAStartBearish) + // + || + // + (xAU5Conditions.isXCHLHMCLCLLSame && + (xAU5Conditions.isXCHMAMCVale && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow))) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXAMAEndBearish && + xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXLHLLIncreased) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + ((xAU5Conditions.isXCHMAMCVale || + xAU5Conditions.isXLHLLDecreased) && + (xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow))) + // + || + // + (xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXLHLLIncreased && + (xAU5Conditions.isXCHMALCVale && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + ( + // + (xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) && + ( + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXCHLHMCLCHHSame && + (xAU5Conditions.isXTDSignalOverBear || + xAU5Conditions.isXTDSignalCrossedOverBear)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCVale && + (xAU5Conditions.isXCHMAMCPeak + // + || + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXTDBearishVale) + // + ) + // + ) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXLHLLIncreased && + xAU5Conditions.isXTMStartBullish && + xAU5Conditions.isXAMAStartBullish && + (xAU5Conditions.isXTDSignalOverBear || + xAU5Conditions.isXTDSignalCrossedOverBear)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCTrendsDown || + xAU5Conditions.isXCHMALCTrendsUp) && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXTDSignalCrossedOverBear) && + ( + // + (xAU5Conditions.isXTMStartBullish && + xAU5Conditions.isXAMAStartBullish && + xAU5Conditions.isXFICrossedOverZero) + // + || + // + (xAU5Conditions.isXCHLHSameHHs && + xAU5Conditions.isXLHHighAttachedHH) + // + ) + // + ) + // + || + // + (xAU5Conditions.isXCHMALCVale && + (xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow))) + // + || + // + (xAU5Conditions.isXLHLLDecreased && + xAU5Conditions.isXCHLHSCMCHHSame && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHLHSCMCHHSame && + xAU5Conditions.isXCHLHMCLCLLSame && + xAU5Conditions.isXLHHighAttachedHH && + (xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHMALCTrendsUp && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXTSAllSame && + xAU5Conditions.isXCHLHSameHHs && + xAU5Conditions.isXLHHighAttachedHH && + xAU5Conditions.isXRSICrossedOverLongExit) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHLHSCMCHHSame && + xAU5Conditions.isXCHLHSCMCLLSame) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXLHHighAttachedHH && + ( + // + (xAU5Conditions.isXCHLHSCMCHHSame && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXTSAllSame && + xAU5Conditions.isXCHLHSameHHs && + xAU5Conditions.isXRSICrossedOverLongExit) + // + ) + // + ) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHMALCTrendsUp && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTD Short Signal Checking ... +bool XAU5XTDHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTDEnableSignaller || + !xAU5MXTDAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTAM Long Signal Checking ... +bool XAU5XTAMHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTAMEnableSignaller || + !xAU5MXTAMAllowLongSignals) + { + 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 ... + ( + XAU5ReadyForLong()) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXLHLLIncreased) + // + || + // + (xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXTSCurrentUnderMediest) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + (xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXTMEndBearish && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXAMAEndBearish && + xAU5Conditions.isXTDBullOverBear && + xAU5Conditions.isXTDSignalUnderBear && + xAU5Conditions.isXCHLHMCLCLLSame && + xAU5Conditions.isXRSICrossedUnderShortExit) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXCHLHSameHHs && + xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXLHHighAttachedHH) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTAM Short Signal Checking ... +bool XAU5XTAMHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTAMEnableSignaller || + !xAU5MXTAMAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSI Long Signal Checking ... +bool XAU5XSIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSIEnableSignaller || + !xAU5MXSIAllowLongSignals) + { + 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 ... + ( + // + xAU5Conditions.isXRSICrossedOverLongEntry && + xRSIBuffer[3] < xRSILongEntryValue + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + XAU5ReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + true, // XCHMA Cycles + true, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXTMBearish && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXLHLLDecreased && + xAU5Conditions.isXCHLHSCMCLLSame && + xAU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTSCurrentUnderFarest && + xAU5Conditions.isXTSCurrentUnderMediest) + // + || + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale) + // + || + // + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCPeak) + // + || + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXAMAEndBearish && + xAU5Conditions.isXCHLHSCMCLLSame && + xAU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale) + // + || + // + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXTMStartBullish && + xAU5Conditions.isXAMAStartBullish && + xAU5Conditions.isXCHLHSCMCHHSame && + xAU5Conditions.isXCHLHSCMCLLSame && + xAU5Conditions.isXLHHighAttachedHH && + xAU5Conditions.isXFICrossedOverZero && + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSI Short Signal Checking ... +bool XAU5XSIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSIEnableSignaller || + !xAU5MXSIAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSTFI Long Signal Checking ... +bool XAU5XSTFIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSTFIEnableSignaller || + !xAU5MXSTFIAllowLongSignals) + { + 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] && + (xAU5Conditions.isXTSCurrentOverFarest || + xAU5Conditions.isXTSCurrentCrossedOverFarest) && + (xTSCurrentBuffer[1] < xTSNearestBuffer[1] || + xTSCurrentBuffer[1] < xTSMediestBuffer[1]) && + !(xAU5Conditions.isXTSCurrentUnderNearest || + xAU5Conditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + XAU5ReadyForLong() + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXTMStartBearish && + xAU5Conditions.isXAMAStartBearish && + (xAU5Conditions.isXCHMASCVale && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTMStartBearish && + xAU5Conditions.isXAMAStartBearish && + xAU5Conditions.isXTDBullOverBear && + xAU5Conditions.isXTDSignalCrossedUnderBear && + xAU5Conditions.isXLHHHIncreased && + xAU5Conditions.isXLHHHSameInLength && + xAU5Conditions.isXCHLHSCMCHHSame && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXLHHHIncreased && + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHMALCTrendsUp && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + (xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXAMAEndBearish && + xAU5Conditions.isXTMStartBullish && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + ((xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXFICrossedUnderZero) + // + || + // + (xAU5Conditions.isXLHHHDecreased && + xAU5Conditions.isXLHLLDecreased && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXCHLHSameHHs && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale && + xAU5Conditions.isXLHHHIncreased) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXLHHHDecreased && + xAU5Conditions.isXTSCurrentUnderMediest) + // + || + // + (xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMAMCTrendsUp && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCTrendsUp && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXCHLHSCMCHHSame && + xAU5Conditions.isXLHHighAttachedHH) + // + || + // + (xAU5Conditions.isXOBDSwingHigh && + xAU5Conditions.isXTMEndBullish && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXTDBullOverBear && + xAU5Conditions.isXTDSignalOverBear && + xAU5Conditions.isXCHLHSCMCHHSame && + xAU5Conditions.isXCHLHMCLCLLSame && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXLHHHIncreased && + xAU5Conditions.isXCHLHSCMCHHSame && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSTFI Short Signal Checking ... +bool XAU5XSTFIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSTFIEnableSignaller || + !xAU5MXSTFIAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XOBDLH Long Signal Checking ... +bool XAU5XOBDLHHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXOBDLHEnableSignaller || + !xAU5MXOBDLHAllowLongSignals) + { + return result; + } + + // + XAU5MarketConditions xAU5Conditions2 = XAU5GenerateMarketConditions(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 ... + ( + // + xAU5Conditions2.isXOBDSwingLow && + xAU5Conditions2.isXLHLowAttachedLL && + xLHLLBuffer[1] >= xLHLLBuffer[2] + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + XAU5ReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + false, // XOBD + false // XTS + ) + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXTMBearish && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXAMABearish && + xAU5Conditions.isXLHHHDecreased) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXCHLHSameLLs && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale) + // + || + // + ((xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXTMBearish && + xAU5Conditions.isXAMABearish && + xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXFIUnderZero && + xAU5Conditions.isXCHLHSameLLs && + xAU5Conditions.isXTDBullUnderBear && + xAU5Conditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XOBDLH Short Signal Checking ... +bool XAU5XOBDLHHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXOBDLHEnableSignaller || + !xAU5MXOBDLHAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACC Long Signal Checking ... +bool XAU5XCHMACCHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACCEnableSignaller || + !xAU5MXCHMACCAllowLongSignals) + { + 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] + // + ) + // + && + // + xAU5Conditions.isXCHMASCOverMax && + !xAU5Conditions.isXCHMASCUnderMax + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + XAU5ReadyForLong() + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCTrendsUp || + xAU5Conditions.isXCHMALCTrendsDown) && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTSAllSame && + xAU5Conditions.isXTSCurrentMin && + xAU5Conditions.isXTSCurrentMax) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXCHMALCTrendsUp && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXLHLLIncreased && + xAU5Conditions.isXCHLHMCLCHHSame && + (xAU5Conditions.isXCHMASCTrendsDown && + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow))) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACC Short Signal Checking ... +bool XAU5XCHMACCHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACCEnableSignaller || + !xAU5MXCHMACCAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMN Long Signal Checking ... +bool XAU5XCHMACMNHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMNEnableSignaller || + !xAU5MXCHMACMNAllowLongSignals) + { + 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); + + // + // 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 ... + ( + // + xAU5Conditions.isXCHMASCCrossedOverMin && + xCHMAScFastBuffer[2] < xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMin2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + XAU5ReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXLHLLIncreased && + xAU5Conditions.isXAMAStartBullish && + xAU5Conditions.isXTDSignalUnderBear && + xAU5Conditions.isXTDBullCrossedOverBear && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXTMStartBullish) + // + || + // + ((xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMBullish && + xAU5Conditions.isXAMABullish && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale && + xAU5Conditions.isXTDBullOverBear && + xAU5Conditions.isXTDSignalOverBear) + // + || + // + (xAU5Conditions.isXCHMASCPeak && + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXTMStartBullish && + xAU5Conditions.isXFICrossedOverZero) + // + || + // + ((xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHLHSCMCHHSame && + xAU5Conditions.isXTDBullUnderBear && + xAU5Conditions.isXLHHighAttachedHH && + xAU5Conditions.isXTDSignalUnderBear) + // + || + // + ((xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + ((xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow) && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXCHMALCTrendsUp && + (xAU5Conditions.isXCHMALCFastUnderSlow || + xAU5Conditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMN Short Signal Checking ... +bool XAU5XCHMACMNHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMNEnableSignaller || + !xAU5MXCHMACMNAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMX Long Signal Checking ... +bool XAU5XCHMACMXHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMXEnableSignaller || + !xAU5MXCHMACMXAllowLongSignals) + { + 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 ... + ( + // + xAU5Conditions.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 ... + ( + // + XAU5ReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXTSCurrentMin && + xAU5Conditions.isXAMAEndBearish && + xAU5Conditions.isXCHLHMCLCHHSame) + // + || + // + (xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXTDBearishVale && + xAU5Conditions.isXCHLHMCLCHHSame) + // + || + // + ((xAU5Conditions.isXCHMAMCPeak && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) || + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMX Short Signal Checking ... +bool XAU5XCHMACMXHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMXEnableSignaller || + !xAU5MXCHMACMXAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// END Signal Providers ... +// + +// +// START Utilities ... +// + +// +// Converts Market Conditions to Specific String Representation ... +string XAU5GetConditionsString( + XAU5MarketConditions &condition, // Specify Conditiond + string separator = ",", // Specify Separator + bool ignoreFalses = true // Ignore False Conditions +) +{ + // + XAU5MarketConditions 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_XAU5_SIGNAL_PROVIDERS item, + ENUM_XAU5_SIGNAL_PROVIDERS &items[]) +{ + // + ArrayResize( + items, + ArraySize(items) + 1); + + // + items[ArraySize(items) - 1] = item; +} +// +// START Utilities ... +// \ No newline at end of file diff --git a/BKP/Temp/xau5.indicators.provider.txt b/BKP/Temp/xau5.indicators.provider.txt new file mode 100644 index 00000000..634f3e0c --- /dev/null +++ b/BKP/Temp/xau5.indicators.provider.txt @@ -0,0 +1,8161 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAU5 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_XAU5_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 XAU5MarketConditions +{ + // + // 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.xau5.provider.inputs.lib.mq5" + +// +// Signallers ... +input group "XAU5 Signallers"; + +// +// XTD ... +input group "XAU5 XTD Signaller"; +input bool xAU5XTDEnableSignaller = true; // Enable Signaller +// input bool xAU5XTDEnableTPSL = false; // Enable TP/SL +input bool xAU5XTDAllowLongSignals = true; // Enable Long Signals +input bool xAU5XTDAllowShortSignals = true; // Enable Short Signals + +// +// XTAM ... +input group "XAU5 XTAM Signaller"; +input bool xAU5XTAMEnableSignaller = true; // Enable Signaller +// input bool xAU5XTAMEnableTPSL = false; // Enable TP/SL +input bool xAU5XTAMAllowLongSignals = true; // Enable Long Signals +input bool xAU5XTAMAllowShortSignals = true; // Enable Short Signals + +// +// XSI ... +input group "XAU5 XSI Signaller"; +input bool xAU5XSIEnableSignaller = true; // Enable Signaller +// input bool xAU5SIXEnableTPSL = false; // Enable TP/SL +input bool xAU5XSIAllowLongSignals = true; // Enable Long Signals +input bool xAU5XSIAllowShortSignals = true; // Enable Short Signals + +// +// XSTFI ... +input group "XAU5 XSTFI Signaller"; +input bool xAU5XSTFIEnableSignaller = true; // Enable Signaller +// input bool xAU5XSTFIEnableTPSL = false; // Enable TP/SL +input bool xAU5XSTFIAllowLongSignals = true; // Enable Long Signals +input bool xAU5XSTFIAllowShortSignals = true; // Enable Short Signals + +// +// XOBDLH ... +input group "XAU5 XOBDLH Signaller"; +input bool xAU5XOBDLHEnableSignaller = true; // Enable Signaller +// input bool xAU5XOBDLHEnableTPSL = false; // Enable TP/SL +input bool xAU5XOBDLHAllowLongSignals = true; // Enable Long Signals +input bool xAU5XOBDLHAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACC ... +input group "XAU5 XCHMACC Signaller"; +input bool xAU5XCHMACCEnableSignaller = true; // Enable Signaller +// input bool xAU5XCHMACCEnableTPSL = false; // Enable TP/SL +input bool xAU5XCHMACCAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACCAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACMX ... +input group "XAU5 XCHMACMX Signaller"; +input bool xAU5XCHMACMXEnableSignaller = true; // Enable Signaller +// input bool xAU5XCHMACMXEnableTPSL = false; // Enable TP/SL +input bool xAU5XCHMACMXAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACMXAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACMN ... +input group "XAU5 XCHMACMN Signaller"; +input bool xAU5XCHMACMNEnableSignaller = true; // Enable Signaller +// input bool xAU5XCHMACMNEnableTPSL = false; // Enable TP/SL +input bool xAU5XCHMACMNAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACMNAllowShortSignals = true; // Enable Short Signals + +// +// Imports all Indicators Helper here ... +// input group "XAU5 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 xAU5IsTestMode = true; +int xAU5MaxLengthOfInputs = 0; +int xAU5CalculatedBars = 0; + +// +// Signaller Variables ... +// +// XTD ... +bool xAU5MXTDEnableSignaller = xAU5XTDEnableSignaller; +// bool xAU5MXTDEnableTPSL = xAU5XTDEnableTPSL; +bool xAU5MXTDAllowLongSignals = xAU5XTDAllowLongSignals; +bool xAU5MXTDAllowShortSignals = xAU5XTDAllowShortSignals; + +// +// XTAM ... +bool xAU5MXTAMEnableSignaller = xAU5XTAMEnableSignaller; +// bool xAU5MXTAMEnableTPSL = xAU5XTAMEnableTPSL; +bool xAU5MXTAMAllowLongSignals = xAU5XTAMAllowLongSignals; +bool xAU5MXTAMAllowShortSignals = xAU5XTAMAllowShortSignals; + +// +// XSI ... +bool xAU5MXSIEnableSignaller = xAU5XSIEnableSignaller; +// bool xAU5MSIXEnableTPSL = xAU5SIXEnableTPSL; +bool xAU5MXSIAllowLongSignals = xAU5XSIAllowLongSignals; +bool xAU5MXSIAllowShortSignals = xAU5XSIAllowShortSignals; + +// +// XSTFI ... +bool xAU5MXSTFIEnableSignaller = xAU5XSTFIEnableSignaller; +// bool xAU5MXSTFIEnableTPSL = xAU5XSTFIEnableTPSL; +bool xAU5MXSTFIAllowLongSignals = xAU5XSTFIAllowLongSignals; +bool xAU5MXSTFIAllowShortSignals = xAU5XSTFIAllowShortSignals; + +// +// XOBDLH ... +bool xAU5MXOBDLHEnableSignaller = xAU5XOBDLHEnableSignaller; +// bool xAU5MXOBDLHEnableTPSL = xAU5XOBDLHEnableTPSL; +bool xAU5MXOBDLHAllowLongSignals = xAU5XOBDLHAllowLongSignals; +bool xAU5MXOBDLHAllowShortSignals = xAU5XOBDLHAllowShortSignals; + +// +// XCHMACC ... +bool xAU5MXCHMACCEnableSignaller = xAU5XCHMACCEnableSignaller; +// bool xAU5MXCHMACCEnableTPSL = xAU5XCHMACCEnableTPSL; +bool xAU5MXCHMACCAllowLongSignals = xAU5XCHMACCAllowLongSignals; +bool xAU5MXCHMACCAllowShortSignals = xAU5XCHMACCAllowShortSignals; + +// +// XCHMAMX ... +bool xAU5MXCHMACMXEnableSignaller = xAU5XCHMACMXEnableSignaller; +// bool xAU5MXCHMACMXEnableTPSL = xAU5XCHMACMXEnableTPSL; +bool xAU5MXCHMACMXAllowLongSignals = xAU5XCHMACMXAllowLongSignals; +bool xAU5MXCHMACMXAllowShortSignals = xAU5XCHMACMXAllowShortSignals; + +// +// XCHMAMN ... +bool xAU5MXCHMACMNEnableSignaller = xAU5XCHMACMNEnableSignaller; +// bool xAU5MXCHMACMNEnableTPSL = xAU5XCHMACMNEnableTPSL; +bool xAU5MXCHMACMNAllowLongSignals = xAU5XCHMACMNAllowLongSignals; +bool xAU5MXCHMACMNAllowShortSignals = xAU5XCHMACMNAllowShortSignals; + +// +// Funded Next Resolve Guards ... +bool isXAU5OnFundedNext = true; + +// +// Here we Define some Global Market Variables to Analyse MArket Conditions +// using them at each time ... +XAU5MarketConditions xAU5Conditions = {}; + +// +// Validate Indicators Inputs ... +bool XAU5ValidateIndicatorsInputs() +{ + // + 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 XAU5InitIndicators() +{ + // + bool result = false; + + // + // Make it Enable when we need to Log Market Conditions ... + // xAU5IsTestMode = false; // IsRunningOnTestMode(); + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xAU5MaxLengthOfInputs = MathMax( + xTMMaPeriod, + xAU5NumberOfItemsPerTick); + + // + // XAMA ... + xAU5MaxLengthOfInputs = MathMax( + xAMALength, + xAU5NumberOfItemsPerTick); + xAU5MaxLengthOfInputs = MathMax( + xAMAFastEMA, + xAU5NumberOfItemsPerTick); + xAU5MaxLengthOfInputs = MathMax( + xAMASlowEMA, + xAU5NumberOfItemsPerTick); + + // + // XLH ... + xAU5MaxLengthOfInputs = MathMax( + xLHLength, + xAU5NumberOfItemsPerTick); + + // + // XTD ... + xAU5MaxLengthOfInputs = MathMax( + xTDLength, + xAU5MaxLengthOfInputs); + + // + // XFI ... + xAU5MaxLengthOfInputs = MathMax( + xFILength, + xAU5MaxLengthOfInputs); + + // + // XRSI ... + xAU5MaxLengthOfInputs = MathMax( + xRSILength, + xAU5MaxLengthOfInputs); + + // + // XOBD ... + xAU5MaxLengthOfInputs = MathMax( + xOBDLength, + xAU5MaxLengthOfInputs); + + // + // XCHLH ... + xAU5MaxLengthOfInputs = MathMax( + xCHLHLcLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHLHMcLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHLHScLength, + xAU5MaxLengthOfInputs); + + // + // XCHMA ... + xAU5MaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xAU5MaxLengthOfInputs); + + // + // Validate Indicators Inputs before Initialization ... + result = XAU5ValidateIndicatorsInputs(); + if (!result) + { + return result; + } + + // + // Validate Signallers ... + + // + // XTD ... + bool isXTDEnable = + xAU5XTDEnableSignaller && + (xAU5XTDAllowLongSignals || + xAU5XTDAllowShortSignals); + + // + // XTAM ... + bool isXTAMEnable = + xAU5XTAMEnableSignaller && + (xAU5XTAMAllowLongSignals || + xAU5XTAMAllowShortSignals); + + // + // XSI ... + bool isXSIEnable = + xAU5XSIEnableSignaller && + (xAU5XSIAllowLongSignals || + xAU5XSIAllowShortSignals); + + // + // XSTFI ... + bool isXSTFIEnable = + xAU5XSTFIEnableSignaller && + (xAU5XSTFIAllowLongSignals || + xAU5XSTFIAllowShortSignals); + + // + // XOBDLH ... + bool isXOBDLHEnable = + xAU5XOBDLHEnableSignaller && + (xAU5XOBDLHAllowLongSignals || + xAU5XOBDLHAllowShortSignals); + + // + // XCHMACC ... + bool isXCHMACCEnable = + xAU5XCHMACCEnableSignaller && + (xAU5XCHMACCAllowLongSignals || + xAU5XCHMACCAllowShortSignals); + + // + // XCHMACMX ... + bool isXCHMACMXEnable = + xAU5XCHMACMXEnableSignaller && + (xAU5XCHMACMXAllowLongSignals || + xAU5XCHMACMXAllowShortSignals); + + // + // XCHMACMN ... + bool isXCHMACMNEnable = + xAU5XCHMACMNEnableSignaller && + (xAU5XCHMACMNAllowLongSignals || + xAU5XCHMACMNAllowShortSignals); + + // + bool hasSignaller = + // + isXTDEnable || + isXTAMEnable || + isXSIEnable || + isXSTFIEnable || + isXOBDLHEnable || + isXCHMACCEnable || + isXCHMACMXEnable || + isXCHMACMNEnable + // + ; + result = hasSignaller; + if (!result) + { + // + LogMessage("XAU5 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 XAU5ReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XAMAReleaseHandlers(); + XLHReleaseHandlers(); + XTDReleaseHandlers(); + XFIReleaseHandlers(); + XTSReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XAU5HandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xAU5CalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xAU5NumberOfItemsPerTick); + XAMAReadBuffers(xAU5NumberOfItemsPerTick); + XLHReadBuffers(xAU5NumberOfItemsPerTick); + XTDReadBuffers(xAU5NumberOfItemsPerTick); + XFIReadBuffers(xAU5NumberOfItemsPerTick); + XTSReadBuffers(xAU5NumberOfItemsPerTick); + XRSIReadBuffers(xAU5NumberOfItemsPerTick); + XOBDReadBuffers(xAU5NumberOfItemsPerTick); + XCHMAReadBuffers(xAU5NumberOfItemsPerTick); + XCHLHReadBuffers(xAU5NumberOfItemsPerTick); + + // + XAU5ReadConditions(); +} + +// +// +// 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 XAU5CanOpenLongTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XAU5HasLongSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + XAU5ClearConditions(); + } + + // + 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 XAU5CanCloseLongTrade() +{ + // + 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 XAU5CanOpenShortTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XAU5HasShortSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + XAU5ClearConditions(); + } + + // + 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 XAU5CanCloseShortTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// Read All Globally Required Conditions ... +void XAU5ReadConditions() +{ + // + XAU5ClearConditions(); + + // + xAU5Conditions = XAU5GenerateMarketConditions(1); +} + +// +// Cleanup Conditions ... +void XAU5ClearConditions() +{ + // + XAU5MarketConditions mConditions = {}; + + // + xAU5Conditions = mConditions; +} + +// +// Generate Merket Conditions for Specified Bar Index ... +XAU5MarketConditions XAU5GenerateMarketConditions( + int bar_index = 1 // Specified Bar Index ... +) +{ + // + XAU5MarketConditions 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 XAU5HasLongSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XAU5XTDHasLongSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XAU5XTAMHasLongSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XAU5XSIHasLongSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XAU5XSTFIHasLongSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XAU5XOBDLHHasLongSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XAU5XCHMACCHasLongSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMACMNHasSignal = XAU5XCHMACMNHasLongSignal(); + if (isXCHMACMNHasSignal) + { + // + Add( + EnumToString(XCHMACMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMACMXHasSignal = XAU5XCHMACMXHasLongSignal(); + 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 (xAU5IsTestMode) + { + // + string message = XAU5GetConditionsString(xAU5Conditions, "\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 XAU5HasShortSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XAU5XTDHasShortSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XAU5XTAMHasShortSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XAU5XSIHasShortSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XAU5XSTFIHasShortSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XAU5XOBDLHHasShortSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XAU5XCHMACCHasShortSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMACMNHasSignal = XAU5XCHMACMNHasShortSignal(); + if (isXCHMACMNHasSignal) + { + // + Add( + EnumToString(XCHMACMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMACMXHasSignal = XAU5XCHMACMXHasShortSignal(); + 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 (xAU5IsTestMode) + { + // + string message = XAU5GetConditionsString(xAU5Conditions, "\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 XAU5DisableLongSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowLongSignals = false; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowLongSignals = false; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowLongSignals = false; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowLongSignals = false; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowLongSignals = false; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowLongSignals = false; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowLongSignals = false; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowLongSignals = false; + } +} + +// +// Enable All Signallers Longs ... +// Only if they are Configured as Enable at Settings ... +void XAU5EnableLongSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowLongSignals = + xAU5XTDAllowLongSignals + ? true + : xAU5MXTDAllowLongSignals; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowLongSignals = + xAU5XTAMAllowLongSignals + ? true + : xAU5MXTAMAllowLongSignals; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowLongSignals = + xAU5XSIAllowLongSignals + ? true + : xAU5MXSIAllowLongSignals; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowLongSignals = + xAU5XSTFIAllowLongSignals + ? true + : xAU5MXSTFIAllowLongSignals; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowLongSignals = + xAU5XOBDLHAllowLongSignals + ? true + : xAU5MXOBDLHAllowLongSignals; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowLongSignals = + xAU5XCHMACCAllowLongSignals + ? true + : xAU5MXCHMACCAllowLongSignals; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowLongSignals = + xAU5XCHMACMXAllowLongSignals + ? true + : xAU5MXCHMACMXAllowLongSignals; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowLongSignals = + xAU5XCHMACMNAllowLongSignals + ? true + : xAU5MXCHMACMNAllowLongSignals; + } +} + +// +// Disable All Signallers Shorts ... +void XEUDisableShortSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowShortSignals = false; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowShortSignals = false; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowShortSignals = false; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowShortSignals = false; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowShortSignals = false; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowShortSignals = false; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowShortSignals = false; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowShortSignals = false; + } +} + +// +// Enable All Signallers Shorts ... +// Only if they are Configured as Enable at Settings ... +void XEUEnableShortSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + xAU5MXTDAllowShortSignals = + xAU5XTDAllowShortSignals + ? true + : xAU5MXTDAllowShortSignals; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + xAU5MXTAMAllowShortSignals = + xAU5XTAMAllowShortSignals + ? true + : xAU5MXTAMAllowShortSignals; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + xAU5MXSIAllowShortSignals = + xAU5XSIAllowShortSignals + ? true + : xAU5MXSIAllowShortSignals; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + xAU5MXSTFIAllowShortSignals = + xAU5XSTFIAllowShortSignals + ? true + : xAU5MXSTFIAllowShortSignals; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + xAU5MXOBDLHAllowShortSignals = + xAU5XOBDLHAllowShortSignals + ? true + : xAU5MXOBDLHAllowShortSignals; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + xAU5MXCHMACCAllowShortSignals = + xAU5XCHMACCAllowShortSignals + ? true + : xAU5MXCHMACCAllowShortSignals; + } + + // + // XCHMAMX ... + if (xAU5MXCHMACMXEnableSignaller) + { + xAU5MXCHMACMXAllowShortSignals = + xAU5XCHMACMXAllowShortSignals + ? true + : xAU5MXCHMACMXAllowShortSignals; + } + + // + // XCHMAMN ... + if (xAU5MXCHMACMNEnableSignaller) + { + xAU5MXCHMACMNAllowShortSignals = + xAU5XCHMACMNAllowShortSignals + ? true + : xAU5MXCHMACMNAllowShortSignals; + } +} + +// +// XTD Long Signal Checking ... +bool XAU5XTDHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTDEnableSignaller || + !xAU5MXTDAllowLongSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTD Short Signal Checking ... +bool XAU5XTDHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTDEnableSignaller || + !xAU5MXTDAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTAM Long Signal Checking ... +bool XAU5XTAMHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTAMEnableSignaller || + !xAU5MXTAMAllowLongSignals) + { + 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 ... + ( + // + // Exception Cases for XCHMA Min or Max ... + !( + // + // XCHMA MAX ... + ( + // + (xAU5Conditions.isXCHMASCOverMax || + xAU5Conditions.isXCHMASCCrossedOverMax) && + (xAU5Conditions.isXCHMASCUnderMax || + xAU5Conditions.isXCHMASCCrossedUnderMax) + // + ) + // + || + // + // XCHMA MIN ... + ( + // + (xAU5Conditions.isXCHMASCOverMin || + xAU5Conditions.isXCHMASCCrossedOverMin) && + (xAU5Conditions.isXCHMASCUnderMin || + xAU5Conditions.isXCHMASCCrossedUnderMin) + // + ) + // + ) + // + && + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + ( + // !xAU5Conditions.isXCHMASCTrendsDown && + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + && + // + // MC ... + ( + // !xAU5Conditions.isXCHMAMCTrendsDown && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + ( + // !xAU5Conditions.isXCHMASCTrendsDown && + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + && + // + // LC ... + ( + // !xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + ( + // !xAU5Conditions.isXCHMAMCTrendsDown && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + && + // + // LC ... + ( + // !xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + && + // + // XCHMA Check Peaks ... + !( + // + // All Cycles Peak ... + ( + xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMALCPeak) + // + || + // + ( + // + // SC MC ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMAMCPeak) + // + || + // + // SC LC ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMALCPeak) + // + || + // + // MC LC ... + (xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMALCPeak) + // + ) + // + ) + // + && + // + // Check XCHMA Trends Powers ... + !( + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + && + // + // Check XOBD Swings ... + !xAU5Conditions.isXOBDSwingLow + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXAMABearish && + xAU5Conditions.isXTMEndBearish && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale) + // + || + // + ( + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + ( + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + || + // + (xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXAMANeutural && + xAU5Conditions.isXLHHHDecreased && + xAU5Conditions.isXTDBullUnderBear && + xAU5Conditions.isXTDSignalUnderBear) + // + || + ( + // + (xAU5Conditions.isXCHMASCTrendsDown && + xAU5Conditions.isXCHMAMCTrendsDown && + xAU5Conditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + ( + // + (xAU5Conditions.isXCHMAMCVale && + (( + // + xAU5Conditions.isXCHMASCVale + // + || + // + (xAU5Conditions.isXAMAVale && + (xAU5Conditions.isXTDBearishVale || + xAU5Conditions.isXTMStartBearish)) + // + || + // + ( + // + ((xAU5Conditions.isXCHMASCTrendsUp && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) && + (xAU5Conditions.isXCHMAMCTrendsDown && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) && + (xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ))) + // + || + // + (xAU5Conditions.isXTMBearish && + xAU5Conditions.isXAMABearish && + xAU5Conditions.isXTSCurrentMin && + xAU5Conditions.isXLHHHDecreased && + xAU5Conditions.isXFICrossedUnderZero) + // + )) + // + || + // + (xAU5Conditions.isXTSCurrentMin && + (xAU5Conditions.isXTSCurrentUnderFarest || + xAU5Conditions.isXTSCurrentCrossedUnderFarest) && + (xAU5Conditions.isXTSCurrentUnderNearest || + xAU5Conditions.isXTSCurrentCrossedUnderNearest) && + (xAU5Conditions.isXTSCurrentUnderMediest || + xAU5Conditions.isXTSCurrentCrossedUnderMediest)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTSCurrentMin && + xAU5Conditions.isXTSCurrentUnderFarest && + xAU5Conditions.isXTSCurrentUnderNearest && + xAU5Conditions.isXTSCurrentUnderMediest) + // + || + // + (xAU5Conditions.isXAMAVale && + xAU5Conditions.isXCHLHSCMCLLSame && + xAU5Conditions.isXLHLowAttachedLL) + // + || + // + ((xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCPeak) && + ( + // + (xAU5Conditions.isXCHMASCTrendsUp && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) + // + )) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXTSCurrentOverFarest && + xAU5Conditions.isXTSCurrentOverNearest && + xAU5Conditions.isXTSCurrentOverMediest) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XTAM Short Signal Checking ... +bool XAU5XTAMHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTAMEnableSignaller || + !xAU5MXTAMAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSI Long Signal Checking ... +bool XAU5XSIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSIEnableSignaller || + !xAU5MXSIAllowLongSignals) + { + 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 ... + ( + // + xAU5Conditions.isXRSICrossedOverLongEntry && + xRSIBuffer[3] < xRSILongEntryValue + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + // Exception Cases for XCHMA Min or Max ... + !( + // + // XCHMA MAX ... + ( + // + (xAU5Conditions.isXCHMASCOverMax || + xAU5Conditions.isXCHMASCCrossedOverMax) && + (xAU5Conditions.isXCHMASCUnderMax || + xAU5Conditions.isXCHMASCCrossedUnderMax) + // + ) + // + || + // + // XCHMA MIN ... + ( + // + (xAU5Conditions.isXCHMASCOverMin || + xAU5Conditions.isXCHMASCCrossedOverMin) && + (xAU5Conditions.isXCHMASCUnderMin || + xAU5Conditions.isXCHMASCCrossedUnderMin) + // + ) + // + ) + // + && + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + ( + // !xAU5Conditions.isXCHMASCTrendsDown && + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + && + // + // MC ... + ( + // !xAU5Conditions.isXCHMAMCTrendsDown && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + ( + // !xAU5Conditions.isXCHMASCTrendsDown && + (xAU5Conditions.isXCHMASCFastOverSlow || + xAU5Conditions.isXCHMASCFastCrossedOverSlow)) + // + && + // + // LC ... + ( + // !xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + ( + // !xAU5Conditions.isXCHMAMCTrendsDown && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) + // + && + // + // LC ... + ( + // !xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + && + // + // XCHMA Check Peaks ... + !( + // + // All Cycles Peak ... + ( + xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMALCPeak) + // + || + // + ( + // + // SC MC ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMAMCPeak) + // + || + // + // SC LC ... + (xAU5Conditions.isXCHMASCPeak && + xAU5Conditions.isXCHMALCPeak) + // + || + // + // MC LC ... + (xAU5Conditions.isXCHMAMCPeak && + xAU5Conditions.isXCHMALCPeak) + // + ) + // + ) + // + && + // + // Check XOBD Swings ... + !xAU5Conditions.isXOBDSwingLow + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + (xAU5Conditions.isXCHMALCPeak && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale) + // + || + // + ((xAU5Conditions.isXCHMASCTrendsUp && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) && + (xAU5Conditions.isXCHMAMCTrendsDown && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow)) && + (xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + ((xAU5Conditions.isXTMVale || + xAU5Conditions.isXTMBearish) && + xAU5Conditions.isXTSCurrentMax && + xAU5Conditions.isXLHLLDecreased && + xAU5Conditions.isXCHLHSCMCLLSame && + xAU5Conditions.isXCHLHMCLCHHSame) + // + || + // + ((xAU5Conditions.isXCHMAMCVale && + (xAU5Conditions.isXCHMAMCFastUnderSlow || + xAU5Conditions.isXCHMAMCFastCrossedUnderSlow)) && + (xAU5Conditions.isXCHMALCVale && + xAU5Conditions.isXCHMALCTrendsDown && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXTSCurrentMin && + xAU5Conditions.isXCHLHSCMCLLSame && + xAU5Conditions.isXCHLHMCLCHHSame && + xAU5Conditions.isXLHLowAttachedLL) + // + || + // + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMASCTrendsUp && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow) && + xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (( + // + ( + (xAU5Conditions.isXTMVale || + xAU5Conditions.isXTMBearish) && + (xAU5Conditions.isXAMAVale || + xAU5Conditions.isXAMABearish) && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale) + // + ) && + (xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + ((xAU5Conditions.isXCHMASCVale && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) && + (xAU5Conditions.isXCHMAMCVale && + (xAU5Conditions.isXCHMAMCFastOverSlow || + xAU5Conditions.isXCHMAMCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + ( + xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMASCTrendsUp && + (xAU5Conditions.isXCHMASCFastUnderSlow || + xAU5Conditions.isXCHMASCFastCrossedUnderSlow)) + // + || + // + ( + xAU5Conditions.isXTMVale && + xAU5Conditions.isXAMAVale && + xAU5Conditions.isXTDSignalVale && + xAU5Conditions.isXTDBullishVale && + xAU5Conditions.isXTMStartBearish && + xAU5Conditions.isXAMAStartBearish && + xAU5Conditions.isXLHLowAttachedLL) + // + || + // + (xAU5Conditions.isXTMVale && + xAU5Conditions.isXTMNeutural && + xAU5Conditions.isXTMEndBearish && + xAU5Conditions.isXLHLLDecreased && + xAU5Conditions.isXCHLHSCMCLLSame) + // + || + // + (xAU5Conditions.isXCHMASCVale && + xAU5Conditions.isXCHMAMCVale && + xAU5Conditions.isXCHMALCPeak && + (xAU5Conditions.isXCHMALCFastOverSlow || + xAU5Conditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSI Short Signal Checking ... +bool XAU5XSIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSIEnableSignaller || + !xAU5MXSIAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSTFI Long Signal Checking ... +bool XAU5XSTFIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSTFIEnableSignaller || + !xAU5MXSTFIAllowLongSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XSTFI Short Signal Checking ... +bool XAU5XSTFIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSTFIEnableSignaller || + !xAU5MXSTFIAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XOBDLH Long Signal Checking ... +bool XAU5XOBDLHHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXOBDLHEnableSignaller || + !xAU5MXOBDLHAllowLongSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XOBDLH Short Signal Checking ... +bool XAU5XOBDLHHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXOBDLHEnableSignaller || + !xAU5MXOBDLHAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACC Long Signal Checking ... +bool XAU5XCHMACCHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACCEnableSignaller || + !xAU5MXCHMACCAllowLongSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACC Short Signal Checking ... +bool XAU5XCHMACCHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACCEnableSignaller || + !xAU5MXCHMACCAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMN Long Signal Checking ... +bool XAU5XCHMACMNHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMNEnableSignaller || + !xAU5MXCHMACMNAllowLongSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMN Short Signal Checking ... +bool XAU5XCHMACMNHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMNEnableSignaller || + !xAU5MXCHMACMNAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMX Long Signal Checking ... +bool XAU5XCHMACMXHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMXEnableSignaller || + !xAU5MXCHMACMXAllowLongSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// XCHMACMX Short Signal Checking ... +bool XAU5XCHMACMXHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACMXEnableSignaller || + !xAU5MXCHMACMXAllowShortSignals) + { + 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + return result; +} + +// +// END Signal Providers ... +// + +// +// START Utilities ... +// + +// +// Converts Market Conditions to Specific String Representation ... +string XAU5GetConditionsString( + XAU5MarketConditions &condition, // Specify Conditiond + string separator = ",", // Specify Separator + bool ignoreFalses = true // Ignore False Conditions +) +{ + // + XAU5MarketConditions 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_XAU5_SIGNAL_PROVIDERS item, + ENUM_XAU5_SIGNAL_PROVIDERS &items[]) +{ + // + ArrayResize( + items, + ArraySize(items) + 1); + + // + items[ArraySize(items) - 1] = item; +} +// +// START Utilities ... +// \ No newline at end of file diff --git a/Classes/x-saherelm.class.lib.mq5 b/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 00000000..68f48471 --- /dev/null +++ b/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/Classes/x-saherelm.nn.lib.mq5 b/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 00000000..8fa40f53 --- /dev/null +++ b/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/Classes/x-saherelm.provider.lib.mq5 b/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 00000000..1dbdcd3f --- /dev/null +++ b/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/Compile-MQL.ps1 b/Compile-MQL.ps1 new file mode 100644 index 00000000..63eb9eb0 --- /dev/null +++ b/Compile-MQL.ps1 @@ -0,0 +1,47 @@ +#gets the File To Compile as an external parameter... Defaults to a Test file... +Param( $FileToCompile = "C:\Users\saherelm\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Experts\x-saherelm.ea.mq5") + +#cleans the terminal screen and sets the log file name... +Clear-Host +$LogFile = $FileToCompile + ".log" + +#before continue check if the Compile File has any spaces in it... +if ($FileToCompile.Contains(" ")) { + ""; ""; + Write-Host "ERROR! Impossible to Compile! Your Filename or Path contains SPACES!" -ForegroundColor Red; + ""; + Write-Host $FileToCompile -ForegroundColor Red; + ""; ""; + return; +} + +#first of all, kill MT Terminal (if running)... otherwise it will not see the new compiled version of the code... +Get-Process -Name terminal64 -ErrorAction SilentlyContinue | Where-Object { $_.Id -gt 0 } | Stop-Process + +#fires up the Metaeditor compiler... +& "C:\Program Files\MetaTrader 5\MetaEditor64.exe" /compile:"$FileToCompile" /log:"$LogFile" /inc:"C:\Users\saherelm\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5" | Out-Null + +#get some clean real state and tells the user what is being compiled (just the file name, no path)... +""; ""; ""; ""; "" +$JustTheFileName = Split-Path $FileToCompile -Leaf +Write-Host "Compiling........: $JustTheFileName" +"" + +#reads the log file. Eliminates the blank lines. Skip the first line because it is useless. +$Log = Get-Content -Path $LogFile | Where-Object { $_ -ne "" } | Select-Object -Skip 1 + +#Green color for successful Compilation. Otherwise (error/warning), Red! +$WhichColor = "Red" +$Log | ForEach-Object { if ($_.Contains("0 error(s), 0 warning(s)")) { $WhichColor = "Green" } } + +#runs through all the log lines... +$Log | ForEach-Object { + #ignores the ": information: error generating code" line when ME was successful + if (-Not $_.Contains("information:")) { + #common log line... just print it... + Write-Host $_ -ForegroundColor $WhichColor + } +} + +#get the MT Terminal back if all went well... +if ( $WhichColor -eq "Green") { & "C:\\Program Files\\MetaTrader 5\\MetaEditor64.exe" } \ No newline at end of file diff --git a/Documents/.gitkeep b/Documents/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Documents/Docs/MarketConditions.md b/Documents/Docs/MarketConditions.md new file mode 100644 index 00000000..bc4442f4 --- /dev/null +++ b/Documents/Docs/MarketConditions.md @@ -0,0 +1,946 @@ +# Market Conditions + +we study market and retrieve it's sense in an specific time by Capturing Market Conditions, which it is a Data Model based on Combination of Oscillators and Indicators in our Provider. + +## Market Condition Model + +```MQ5 +// +// 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; +}; +``` + +## Used Cases + +for each Strategy we have some sort of Conditions, which i try to describe it here + +```MQ5 +// +// Define a Function based on Strategy and Signal Type ... +bool XStrategyHasLongSignal() { + // + // Define a result Variable to determines there is a Signal + // on Specific Time or not ... + bool result = false; + + // + // 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 ... + ( + // + false + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + false + // + ) + // + && + // + // 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 ... + (xAU5Conditions.isXLHPriceInSignalRange && + // + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Under Signal ... + ( + // + ((xAU5Conditions.isXLHPriceUnderSignal || + xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is Over Signal ... + ( + // + ((xAU5Conditions.isXLHPriceOverSignal || + xAU5Conditions.isXLHPriceCrossedOverSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check Conditions if Price is not has clear state ... + ( + // + ((!xAU5Conditions.isXLHPriceOverSignal && + !xAU5Conditions.isXLHPriceUnderSignal && + !xAU5Conditions.isXLHPriceInSignalRange && + !xAU5Conditions.isXLHPriceCrossedOverSignal && + !xAU5Conditions.isXLHPriceCrossedUnderSignal) && + ( + // + // Next Step is to Check LL and HH Same Style ... + // + // Check if Both LL and HH Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If LL Same In Length ... + ((xAU5Conditions.isXLHLLSameInLength && + !xAU5Conditions.isXLHHHSameInLength) && + // + ( + false) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!xAU5Conditions.isXLHHHSameInLength && + !xAU5Conditions.isXLHLLSameInLength) && + // + ( + false) + // + ) + // + ) + // + ) + // + ) + // + ) + // + ; + + // + // return the result ... + return result; +} +``` + +## Common Cases + +there are many conditions which contains a combination of one or more condition and they are most commonly used. + +here i described them and document them for prevent time spending to write them in each used case ... + +### Resolve Stop Outs + +in this step just focused on Peaks and Vales; + +```MQ5 +// +// Peaks ... +// Use Trends Down ... + +// +(mConditions.isXCHMASCPeak && +(mConditions.isXCHMASCFastOverSlow || +mConditions.isXCHMASCFastCrossedOverSlow)) +// + +// +(mConditions.isXCHMAMCPeak && +(mConditions.isXCHMAMCFastOverSlow || +mConditions.isXCHMAMCFastCrossedOverSlow)) +// + +// +(mConditions.isXCHMALCPeak && +(mConditions.isXCHMALCFastOverSlow || +mConditions.isXCHMALCFastCrossedOverSlow)) + + +// +// Vales ... +// Use Trends Up ... + +// +(mConditions.isXCHMASCVale && +(mConditions.isXCHMASCFastUnderSlow || +mConditions.isXCHMASCFastCrossedUnderSlow)) +// + +// +(mConditions.isXCHMAMCVale && +(mConditions.isXCHMAMCFastUnderSlow || +mConditions.isXCHMAMCFastCrossedUnderSlow)) +// + +// +(mConditions.isXCHMALCVale && +(mConditions.isXCHMALCFastUnderSlow || +mConditions.isXCHMALCFastCrossedUnderSlow)) +``` + +```MQ5 +// +// Unders ... + +// +((mConditions.isXCHMASCFastUnderSlow || +mConditions.isXCHMASCFastCrossedUnderSlow) && +( + // + () + // + ) +// +) +// + +// +((mConditions.isXCHMAMCFastUnderSlow || +mConditions.isXCHMAMCFastCrossedUnderSlow) && +( + // + () + // + ) +// +) +// + +// +((mConditions.isXCHMALCFastUnderSlow || +mConditions.isXCHMALCFastCrossedUnderSlow) && +( + // + () + // + ) +// +) +// + + +// +// Overs ... + +// +((mConditions.isXCHMASCFastOverSlow || +mConditions.isXCHMASCFastCrossedOverSlow) && +( + // + () + // + ) +// +) +// + +// +((mConditions.isXCHMAMCFastOverSlow || +mConditions.isXCHMAMCFastCrossedOverSlow) && +( + // + () + // + ) +// +) +// + +// +((mConditions.isXCHMALCFastOverSlow || +mConditions.isXCHMALCFastCrossedOverSlow) && +( + // + () + // + ) +// +) +// +``` + +### Resolve Old Guard Attacks + +in this step complete conditions; + +### Resolve DrawDown Guard Attacks + +in this step complete conditions; + +### XCHMA Max Min Exceptions + +```MQ5 +// +// Exception Cases for XCHMA Min or Max ... +( + // + // XCHMA MAX ... + ( + // + (mConditions.isXCHMASCOverMax || + mConditions.isXCHMASCCrossedOverMax) && + (mConditions.isXCHMASCUnderMax || + mConditions.isXCHMASCCrossedUnderMax) + // + ) + // + || + // + // XCHMA MIN ... + ( + // + (mConditions.isXCHMASCOverMin || + mConditions.isXCHMASCCrossedOverMin) && + (mConditions.isXCHMASCUnderMin || + mConditions.isXCHMASCCrossedUnderMin) + // + ) +) +``` + +### XCHMA Cycles State + +#### Short Cycle + +```MQ5 +// +// Check Bullish ... +bool isXCHMASCBullish = + // + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow) + // + ; + +// +// Check Full Bullish ... +bool isXCHMASCFullBullish = + // + (isXCHMASCBullish && + !isXCHMASCTrendsDown) + // + ; +``` + +```MQ5 +// +// Check Bearish ... +bool isXCHMASCBearish = + // + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) + // + ; + +// +// Check Full Bearish ... +bool isXCHMASCFullBearish = + // + (isXCHMASCBearish && + !isXCHMASCTrendsDown) + // + ; +``` + +```MQ5 +// +// Check Not Vale and Peak ... +bool isXCHMASCNormal = + // + (!mConditions.isXCHMASCPeak && + !mConditions.isXCHMASCVale) + // + ; +``` + +#### Medium Cycle + +```MQ5 +// +// Check Bullish ... +bool isXCHMAMCBullish = + // + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow) + // + ; + +// +// Check Full Bullish ... +bool isXCHMAMCFullBullish = + // + (isXCHMAMCBullish && + !isXCHMAMCTrendsDown) + // + ; +``` + +```MQ5 +// +// Check Bearish ... +bool isXCHMAMCBearish = + // + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) + // + ; + +// +// Check Full Bearish ... +bool isXCHMAMCFullBearish = + // + (isXCHMAMCBearish && + !isXCHMAMCTrendsDown) + // + ; +``` + +```MQ5 +// +// Check Not Vale and Peak ... +bool isXCHMAMCNormal = + // + (!mConditions.isXCHMAMCPeak && + !mConditions.isXCHMAMCVale) + // + ; +``` + +#### Long Cycle + +```MQ5 +// +// Check Bullish ... +bool isXCHMALCBullish = + // + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow) + // + ; + +// +// Check Full Bullish ... +bool isXCHMALCFullBullish = + // + (isXCHMALCBullish && + !isXCHMALCTrendsDown) + // + ; +``` + +```MQ5 +// +// Check Bearish ... +bool isXCHMALCBearish = + // + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) + // + ; + +// +// Check Full Bearish ... +bool isXCHMALCFullBearish = + // + (isXCHMALCBearish && + !isXCHMALCTrendsDown) + // + ; +``` + +```MQ5 +// +// Check Not Vale and Peak ... +bool isXCHMALCNormal = + // + (!mConditions.isXCHMALCPeak && + !mConditions.isXCHMALCVale) + // + ; +``` + +### XCHMA Bullish Trend + +```MQ5 +// +// XCHMA Bullish Trend ... +bool isXCHMABullish = + // + ( + // + // All of Cycles Bullish ... + (isXCHMASCBullish && + isXCHMAMCBullish && + isXCHMALCBullish) + // + || + // + // Two of Cycles Bullish ... + ( + // + (isXCHMASCBullish && + isXCHMAMCBullish) + // + || + // + (isXCHMASCBullish && + isXCHMALCBullish) + // + || + // + (isXCHMAMCBullish && + isXCHMALCBullish) + // + ) + ) + // + ; + +// +// XCHMA Full Bullish Trend ... +bool isXCHMAFullBullish = + // + ( + // + // All of Cycles Fully Bullish ... + (isXCHMASCFullBullish && + isXCHMAMCFullBullish && + isXCHMALCFullBullish) + // + || + // + // Two Of Cycles Fully Bullish ... + ( + // + (isXCHMASCFullBullish && + isXCHMAMCFullBullish) + // + || + // + (isXCHMASCFullBullish && + isXCHMALCFullBullish) + // + || + // + (isXCHMAMCFullBullish && + isXCHMALCFullBullish) + // + ) + // + ) + // + ; +``` + +### XCHMA Bearish Trend + +```MQ5 +// +// XCHMA Bearish Trend ... +bool isXCHMABearish = + // + ( + // + // All of Cycles Bearish ... + (isXCHMASCBearish && + isXCHMAMCBearish && + isXCHMALCBearish) + // + || + // + // Two of Cycles Bearish ... + ( + // + (isXCHMASCBearish && + isXCHMAMCBearish) + // + || + // + (isXCHMASCBearish && + isXCHMALCBearish) + // + || + // + (isXCHMAMCBearish && + isXCHMALCBearish) + // + ) + ) + // + ; + +// +// XCHMA Full Bearish Trend ... +bool isXCHMAFullBearish = + // + ( + // + // All of Cycles Fully Bearish ... + (isXCHMASCFullBearish && + isXCHMAMCFullBearish && + isXCHMALCFullBearish) + // + || + // + // Two Of Cycles Fully Bearish ... + ( + // + (isXCHMASCFullBearish && + isXCHMAMCFullBearish) + // + || + // + (isXCHMASCFullBearish && + isXCHMALCFullBearish) + // + || + // + (isXCHMAMCFullBearish && + isXCHMALCFullBearish) + // + ) + // + ) + // + ; +``` diff --git a/Documents/MT Settings/x-xchlh-xeu5.set b/Documents/MT Settings/x-xchlh-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..9a5b39495a16e43990a0b8107728ed475d9b4161 GIT binary patch literal 1670 zcma)+-A=+l5QWdRiSOVO7z@fzOfL*xU{VqjOuR;`U_>DWLU?)goL!bq+m#Ta(D^+x zUw40hZgGJj7FhH94h7yY!3yU%L(ZoOwtH{sOYu(ooKbHsZsxLwj8ja(r!5BjpVObB zg*L8_#?2X9Ffu_0U4A;~^Y6;!WXS%l-98#ut(~w(pL%Xwjwa98`x{gK8eoT4PUUCv zz5(qc&RXD;_O;8JGb-bgveuZn347=rd{4A#iz|LFSTDx|V;}K>C2c9^x}*Z_SCzE2 zk=a$SYvR(L7`@UoX6M~OtLogdr&v9+PrldXv#j@tSxaiuu0yAgS=JP@;FUhHtnRVO z$ZsTz#Krb4{h{ZF+oFHltWI@JIYogD)dnpgOS`FhMQg;!oYQac#iu6C5p7MHUk#ew z{q*vj&Qj4amcD+RrB_t$U2`fv%-LjVy>*t>SJn(H<*l>q@Eo-G=K7PS2yNEVZZV=f zD_(C;#H$ZlEk&!ONzr=a6m^$Q U`SCTi715dC#obg@Z}t5C0WO~b<^TWy literal 0 HcmV?d00001 diff --git a/Documents/MT Settings/x-xchma-xeu5.set b/Documents/MT Settings/x-xchma-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..079f3fb5fe8478d2275da4bd4f5b1cafbce2f866 GIT binary patch literal 1894 zcma)7%T5A85bU#w|KKOMAS}diK#cJKrzP=>E&>sR>_P}XuU5@$vpw$e$V8Fu>Q`0I z`1|uHck(K0+2XS=nM`FOx!lT)r1&&AJ^6%v3Dnf#<}Uh4cCamF0sGu#%3$Bi z0KZcpd(yz^Tp6)MREC&H+7jcmrHh~YAexh}s~pX0*OCC#TVFbXqDN z@)_#KOgeQHTgN^5)vgzgNxz}CC#~MYL>YF`>thjG^E6_B$Tbw>X6KkZ+;ehDB~tLV zlU405jIbZoU07ja?Jv|hF8Cut`wJ0~Jm8RHV(K=5_Vb(IyDC-FY|3eM6PQ!I|2M(< z%AC3h^y;iu-8OC$H{ai3qI6!1Y5-N9uf2tSs!o-NsMDPG^P2mPN_{k&vRT!fIo11LbL%T}_6jxWRTZq7 z5wwh)>M`c&9w*Y7EtZ?n#2e37-m}B|=BLoE>;~A5w05YkMQFv-h|3$m{{b@`-v#;P Ot3Hu;_qvAOu+AUWsWFxS literal 0 HcmV?d00001 diff --git a/Documents/MT Settings/x-xlh-xeu5.set b/Documents/MT Settings/x-xlh-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..f4e89e2a683d99b5482fa0c770fa5913e4684fd5 GIT binary patch literal 126 zcmezWFNYzOA&()Qp@boW!Ir_C!H9vEfeXmaVDM$gXGj6c+Cs&07;=!r48iKG859_N ifa=nLFcWMJNH@sDM1~}w`cyPoTcABf45dJEkU9XZD;0GB literal 0 HcmV?d00001 diff --git a/Documents/MT Settings/x-xobd-xeu5.set b/Documents/MT Settings/x-xobd-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..48f059e8e1ca00f222b80bc9dd80bc02e98d1c8e GIT binary patch literal 296 zcma)&!3x4K5JcZu@E`gK1~E}22kFIwKcOg5C>2tRf3MD_r&14PVHaj+GMW8;8g8^C zUfhXnShAqw&7+`4&7{qNta=Ks)vwY-94of7_>DBVC_F(r$By;H>r~#K>-3L3_6d0T fc>U5c?Wr(LQVrP*wd`ju*cHaxsEcHJ;l}#`$3!x9 literal 0 HcmV?d00001 diff --git a/Documents/MT Settings/x-xrsi-xeu5.set b/Documents/MT Settings/x-xrsi-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..7f74a0cd803972211bd914c017750112cc9a8c77 GIT binary patch literal 772 zcmZ{iK?{OF5QX14=s)xeBC|9JPtnazMt7sINHoeI|9tgkH`+~CmW6d^_RTlXdB2tz zVS@}eTyR8NdlbtH7Dj1GcCbo2rOtq|B|TQuDm#>ze0AMeo0e zx!1I82 zI@4zJ5U>}ID}wK!)Gu6&#>Iqvit}v`rGL41JLp@C-AtR&r-LCm^&jo#y6E(u5eIEL x$=$foy+NvOhB$CL}oa{Ud@4!n`o@2Q>ITQ=>skDf8ziE literal 0 HcmV?d00001 diff --git a/Documents/MT Settings/x-xtd-xeu5.set b/Documents/MT Settings/x-xtd-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..ffe6ec5bca09f91ad058b59f4fd0a56d2815309a GIT binary patch literal 324 zcma)&!3x4a3`E~q@E`mHYq46S2l47pY;kQ1i-lG3@6|~>^-^RAOR|$pCZBgAa--ux zPeZ|;B?~TO0xwQ_NA5yYG+b3po*Apy&%&S{i?aHkrDoYs_VUE{!tvv%l&!LMQN>@Gnb?LyPvM%T*n9=-bu>AE*H literal 0 HcmV?d00001 diff --git a/Documents/MT Settings/x-xtm-xeu5.set b/Documents/MT Settings/x-xtm-xeu5.set new file mode 100644 index 0000000000000000000000000000000000000000..c4f1dad0b8f2fd4047ad70d2786e54983ba1848f GIT binary patch literal 166 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 literal 0 HcmV?d00001 diff --git a/Documents/MT Templates/x-xeu5.tpl b/Documents/MT Templates/x-xeu5.tpl new file mode 100644 index 0000000000000000000000000000000000000000..1bf1e78474199697b56254f70bbe425d891eb17c GIT binary patch literal 1834090 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

t{i<-ZDnXsi*c2`Q#eWQ@zOV|1B7p} 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%0D%()JF5P20Od#Tj`dSbsQM>cEOeEk*su`Mvy;0 zIQ}$_qTZTQ@9C^?mA!p%)n4i~=TkHFP@$kIZNG{FSUckHv$ifZry#oOKC3zBYaY-A zSE`S7)*AM@*t%BtdRxofwWC*&*Z6ys6np!Xr^~7?*v0)3;%9!l%O33LXRc4_469t& zt+M*h-&X59@5jmrJ9$f8kL<&w_KbqDT9UmkTyuXuQJrto&^h3&x3q_oY*MW|NW&@@ zb~Pupu^K6&{B5UhMZ|n#-37sip8XzFWo~gY?tx%senxZ;Cz;BlX~ek9pPeT`Yfi$( zc`~GD+$B!Z)vV(rTM8~;ui_-AMl~gzbZ&0YnXb1|Wt9uNnv?Ncp;3(a{-irj(siq} zxa{qNt2!OCCSt0Z&Cs2=3eW1jitqq?`{0UFkE$HyH@@BEl>+s{M^nG`ZVi- zQ2TL5T@PI8EUi`lu-Ap_T471C&XZ4`ex_RAz2=9JsCjzt!X?uDvT1zc`HZBa5UEq1 zFkkDzNOUr+T;VEvU5s4m*7H5U5hu|r9Z)5{S7*;b{ltAgTXR1brg0^uXq0KI9iC2& zL@iY@vP*R@^x{ei^m=rhm=&=rx$evldtIJhaWZ~qs5~dj=zBP+6KEAD)n)eRp$a={ z(79FuJCu7ICHG*biFt(`R=IdrXBf?dt{r6N>HHI;=dFn7(A;N`SP{uy7p`kgYDz@T zdz=+9VIVrisP5uqb#L3S%7tCUN!S(bd5Dvl7WZ><^yYb*IVXJ`~-NuF5|;r5brO{pqZS=8cndq^c9?x|_Mjv{CP`r;8EQI81i>;5yD#6Cq>0Bzs+a z&GXNRYBbql55YNw(EO&#KeDO|cJa;2O!4!c<&NB~ZLBKC$f_>bWh$Myb9N8U9_*;` zYwWP93wC;U%-kynyG)7i!mfI^Fy5ej_UCIxMZEaF9r7JpII-e(=Vvqz_K0zD9+AB+ zPOfy1aMiBhJZm8CWUO@KN~WuQU9(3IU)TA0sPL<=v!R=-o;|+KuHU+|JFM!$N!S%> zM(pfTA1eE-dlti97p@g2bxwEYq~;BA1l`5SUlsix_s!I=!EWwYFdOw&)t(`??G$PJw_@7x&%A6RFYVXw=ZYh20PbH@TZd)#Y+k8|Fj;;Za+ z;kx#8?V`^8a!?)HcKFu)Kh7;7I=T49@b5@tp0;|lP{mX_ebJ5;`LV~1CNPy#Y3oh? zVej*q`r+FX$0~Gu2Pvl zjFsMO52DpuUiyut_6$iBa=E?cF zic)lq?{}uEetK<>F+OV^EV!yRWsQyQ3*@uIld5)AaDJj+60@^qP6@I7vlb z`?F?4U2tWqa#lWgPM3{-y<1_;*I}>A*K5A&eCXBN6_L8sIQaNFuMd0s;7SL6)=PT+ z+4&uJ9Du899Xjmoh3lNzv6J5=&g_0%>ziL>uM5|8&L11Da})s64Anig5mjY%bAhaS zK6byl_1ek!^bH^N629f_XP`2xiQ2Hrh21Lu2tB$%kv}ub?hz-cDXX`wfUDkSkQQ${w$>lI$~TrlVtvb9`#^XaZ-1V%@vTIaTX1|IY#e9T;n?Ib>UiZ zQl5T|lW>yfA7}18oaEWoJ#(z;ft_YMbM=ERcHT`-6vR*0`FU8?1v~n_FndR2PEvW zUF==hRsG&!RTtjT1Da1V4=bI#gHP+8?y$;*U9N@(^WqK~v5=cgWAxlProKyK*z3Zz ziiLP`Rx^5gKvdE-C*frm?6UWlqRldmz9$xPuC1EY$|@IjwLddcq<)wy?k+q1Aj-`H zLlMT>2Gu|oCj#xS#w&lOe-_o^Y>GKM8DLjehq9^@c0`~nBk2S>_kqApb+wR*c_*tn zVTVOm?9ga&Zr%|IL5?_AdF)xQ?DyCz5@Jj2vmlgdYOk`9(yk(*?Crrwp&EHJy>Mrh z2X^#GD^6ln7wqVg#j4PaobF#)#X)b+W}Sb>PU)OO)GKvHLNRX5y3xVypk4IF>PWi~ zcf47IQ@m9ckyS2_t+R-#kvRi%mb*(9;S|!@VU2Z->~-N<`E$HcO0~rq0jEE+{ZMgI zR&~KnXSilYl7YQ?n)<9#FS6?S*y$a>*{MRh?N032w5#_ZWR(lMRV);Gc&+v!$baJw za?~_;)yH1zRn*!8!#bfB$3ofL2Uk3L)GPP6GOx^{p&wUu5m&g%UKg%;juBhg0*}-- zzUS0EaPnSFXPngexo2xey^9j19WheBOYG@8IuAONUR8Or%Eh}XPG&W-GG)d*w?DJB zuPG@{Gveg1*M;lapM@$)?b-`NhdXx|;beV=OIEqCt2s&UA*uqItz{D_KPT(nw(RYN zYs5<3rx8a=Kd$$?jghaDpPcu9RKA{V=n&~+Om}4;VoRka>5sb@Ss_P-gBM++Bzu~f zmfVBgYbMXK%7tAWB|$It=9qPEPi7`ssUdZOT$omTM1@E50xHI=X57I??dDW>9?Gg7 z*kvaJiPiM1Vn*)4j(L66VU$(R$L<%mjbt|JqByv^t9TD~uj$UpDi?OEI0$;u+HjE%sg)_q}PBBADK5&HN##Pu6ZmJs;HVdyQmVQgCG49W4(u|^eJjYxk1T=Xw6jZ zFJAQy(F%sd=((B7JP@A}YB5t~uM5|Tspz2jj10R@8K!#}Nxoj|Z`m}keeT|gyj-)b zYoCJ3rOQSwwI1&~7^p>z9QHn+k-xmv!wRCvMg45?BN$UAV2Xi&zJ8bV(np=~c(km0M0!nZFIpVo$#BVeF5Pd2Rty?W06& zbo(*=5TS@lh>^plf$j5=i_dECbg3U=t+U6M@#M8q99DJl!LjB{I&Vsz?7dQRGIS|N9Tf9w9tT_Fc%Ka`JqG7Pw!nkLRL%wkbV9@bSE zhC5@U{bhP5xn^{GGbdQ9&aLcq;kxD|3N4ynlea-Uj*)vf$%(8AJ6YwzuHqy*EklnD zkr+KUCzX@e6%Lg*TzI~(e{id;!4-?IT?uZd%qnX)u0)>owmn{?&v3>||9Jf7X03s$-aQK702}ogiX) zttVw~A6%Ip(!ILINtlz!N2=c$j%?c$ss+ zsKtDhy)Ilc#VEFdPweZ&tr*iC8HV{wwZq5P&)MSs3{!c!u$vVlo{opb=(!n5U-Hb$ zF(YNKi;*?1)P~AJkNJmlE144a<2v@kdCnQG*z3Zz@^sB`;`o`Ny2sb?kSePaC4Jb{ zoYdwD7(Q~69$Jq+5U~+2SZ8(F+l7?j6@@JtJ4!D zki9Nk^V}r1;{Wq*zHUj#Dx)1*lT&rN*M5y%kL|zV>ui|My>vQZeR9({t+>Kf_PRK^ z%K2g?8lJd+Rhv35)FXzH_1C*Zc#-pbQ|0TKh9?tbJNSrJ$}~}*{DY_0ak9s5pjbKf z&m&f5r*zz&PDQ`o+F(+7#@J_eLCERCG*X&qX6I%gG4gd?5b*VMkSax_jY{=Gh*0OG zmrUAYrY5CRS3lV6!gZ~Pglbe%`m+x^8NISkg&nm|q|yEUO#G;@lT}@K2X=8R%%ukH=<;<>%UE5p<8QQ)yKvlVz0)yNZ+A572+nBcpeV z@32cBqvuwdYzfr9uKSsKOO)4PtLsf* z13PM;bAlCV&0&=byV}>$no<1&u2}`d*VqQuzSVaxU%Y(!^5*69myf=WtslR9_43K_ z|Nr#z&CA!vf4@Dxa(3%JefjK&DIXtS`{wxCcek&N>i^T@&)*zhfA99EC$8XDbCS<@ z@pVp`#JxA}Z|)I8*{mQc3AKo?#3sFc$b)O;>$(|!&g=eqok+RvTZ*$jPFC1~T9noG zUZ$9ldo&T%c9pwjRUdx_y}9d)qGX~Sqvwv3OscE=BYR!AR-BCYQL&L-#TeCHoMiuG z6$^(|F6`>ut=jS0e^Zr{q37l#_a#=oPW{7YJUM2CD{qD8tXnjtAfETg+~gGMh&5a9 zXG72J77JCT7jyp&RO#EqzV2l!xK?|XkqI$+IIRZ0=6;*lSlf;{K4UdMx-afd-DoTBt?EItK*O?cs>(F7Z3)jlmK{e~lXWDd+ zuhUgpD|@ihNj^`UtbJVy^je2XdGzQZYwvYk-w%7ca1xEAZNqz|M0KBckoRzsxkg>X zJNv{nC$nw;F1crHv5ReSMWmeX;^XTujkY)c^DU3YD&3uX=qy+9Q}()Wt#S{$3bUUR zjq(kUJ$_DIQ125v_dIG&>V!a4Pm)P{aB|#`zVdat3TRPJPJaz2V^8HRfBwa-_l^=*?R~F$u&~RXA*j|jX~~-O~&N10rPUxU==a4VQ=$)&zKkNQ~kM3DxH>$t6ih%`L$6`l*)^<>ZoviA?JG%36 z{fx57ym=3H^t{)7GU+Y++QYk5EIi*T$n(C=W9f!>*mgm+VoBAPki9NkbAJ}9S$@WI zeEC_}QLU`=h^%s9S95a2!I_g;9&u)8(A2roHLBj*tZG!*62O3cZ&nogNFbJv`tV?meY>d~Ag>o8HkYsTJ+7#B|uWp5WwW;+68$!tep7bg`Z zSJ=ra7j`u#<8u-^gV%$Tu=4(9mza}ui-=4;svo-earWkJpdR@LTvb!9_$qr{xK{Zm z+eh_wg3zu+%Bo{7t6bRCz7Bfi#B2WH%~m}sav@vo^UGcru4_(eDjQcn&RZBk4qGbh zh?20^6DKR|G{cz{5obD_xf|^24Ha4C!mjdX-7psI15mAX@n`n?s_jVG>%#RloQyV9 z@-t66)Fg}?S{z@ERgW}}3%L~|KfLW&;LlNgNLMTCPI@~*D9O6#D|=nI=8P1oWNc#g zHE-vA^gWDZ{$F*=v1xQKpL;e`*l7oH);z1~(9K9r{Zv}APu&Qv>IB7{gd;?(=bjAX z8KNQJqWn0EpyKqi^^j1dmyz{+y?SU=hAZso`TDjatL&q_i>SWQ9!?KVet2lJY7QZL zUD>C`l^)SmXX5+xWxDt}J1wgj#c8h#*L7BB3K87}!A*GHNv>uPRsNAxU9cmoM|)P( zaNan{?r=53kyS42YJb+=>8vN&(diK-+2yVFUG7igJYQ*Q(<tgFVN($AeqC~a%_SeXBIyF^c*X2w%dQ#}|yswoborMmbj)hb%E<>viEI zaWjvsr@by*b506X*r#{E99_-kktaZC;PLDsYW1&ukMl*5U6Y0z&oG7RikF0X>u8M`~36cNi zDm+HcJAc&Xixds^WVxB#-3L>$Gxl6DB@1SKAwRD5PLb?&;ad55-dE4}H}=Fxaz`~M z<4OB+bLHn!-^w#E^In6qbJD}tnJv}*Htg-eNu9#Ya*tQ@(1oaHJ;Zw#b~z{U9d4Xg zwH?JtYVZ!6#8N8%kzL~aLnQ5lYkZSGQ!DQL=z{Bg=RC%>%dWxTYjz%m=idcaD#zFG z_4zS$pvvZd)CZ;x$xz*q*Xd&@wjC{ z@3Qjr^U3WlPFCCL!zvecRn}1@KA*|s8FL;f_GowJ;r%-6PUf)Jh3lG=LiIYi)eU^; zx){}6oUHB!gp-<@b;vR5VxS`)`;}xE{_$d0?N$z}T)eCOIljA>XUuj(jGo({*+^8D z!JeqH8TR(Vb*>9#XBSkfT3goo^m)wIpS}F_@b35C_S~@N>g!~mEKd5_3T^|nn60wc z#nveMTv46-z(fFYP|Vgn*#}(K^Ri);3%i<=ilEmTN7!Zg$IVIhf2#fl&l=Ul^WI-M zz7E%@zd@Co?E?C7t&j8RO%Es6IRzs_~4R%$(;(oJjzp|-nLtz*5u1C)jRLR_{ysZxF_(TU(sSL-2=iIWy&b*WE zj*;xMRcw{LE*`?H2VWhpg)3&t#Ih?*{YochbB4`8Asy zve$*{nv>uY*F{gmlZxUuU9_5&ox^Z)oor9`U_v)S+ zS1L-KeufYCs*yVtV&&t>e0AR9R`C^U@7FtBQmGwOC{chM6Yay%&7uG5jG>(E z1D90{l~pcZU*{k0nv3^5sNcQVse81>PF8in4y73>cy{43MYJb(&+f zh}6mQ>K;y?taZ<@%7tB>N7M_tZck%p{_bn97MC}#bB)|FHM@oP7V*?LkvVoOEhJ6#Q#)GjXyDZfHWR zx%x5{l{XHusmEY`)lsMy(~>!A5dm6`9iGxkp!a#eF;8hbK%GLDaX zGBfuvt*c|6w6gc}vy0Hn+qto02S9W>pyspl;hp+4WqptUe1&^H`ewP^4J^6<% z@`{tN7HfN8M}-q%hqiN`4Fwe{#Fg$Lb7PeYyQ;z&Z`6t6WWKTMj+1Dx3RiBx>BC9# zc@!mep33RZoLQ*4-m=QY$to67;mmtIC^vd9UhJxSm4;QFu#0<-#2qJgLuU(_OpB}j z_T-T|7HS3<$HFX=xMQJukn0=+YkfJU@@G(ulsLUBueRYQs`CKjGEQPu7k_2~7{x*& zdUjjl9$iRhw#p;2st0yD?;7P`w5zwzNDWujBeKecT@?$tA2vGO0k^vJC1B*Zxghsv z+1mlv58lqP=DX75vvGd*W*Ag7|Ex32{r#xVoG6@_YVL~F=bnUDFM^z^6tOMNFW5A& z-H+VL&rj^;c>;CnnATzK{XbdG_VcuQ3(@&oJYQi7?RdL!Wb7{fU)>or?Cld()dQNl z=)|cmsIvPzJU@#K=O^~ZhFrIct62|&{O_FWaN=0~##LOERW3$W*u}TW(u<+L8Z+|I ztG;{r;^otqH!q*Rd~|5B@i#tw`RvGVAHRHa{PU-m?~bpLsWm71^!W2P$JgJx{V7_U zy?J6}rQ2my5A67TV&zFja_V+Aq^f&rlwrvFJfZzQTjg`17v*#M23;~Y+W}QQBzs-B zuKk&5Qp`!BPL^Tz_%o-Vs$RIPa$#3<67(WYa_dg!(QY+K46Lgj?CpcAZqc9nm7Ltq zI^}*`@q@MQk-aWlD__ra4^t?wufw*Ald{T%UG3|1d!zma)p4eL+?=GosWg%7b>X_^ zWOiG~*q0sZ@XJFJesfcQoVwYQe?YGCXR4SUTf9^<>SfNi%xPyS#?H;i`c@@bJL2eb zmF9=HPG)?oQWsREk?NZJ{>H@psOEltVjAyKGP{bo`tJQ4?8rOSUb%N~V3m7L^yXUv zU}OiCDO6vxnI`UfD$0tH*|}Ke`#v=!?CMU2ta^UdhL3qIj^6c6Z^5p4368U5UQ zz;oj0DSKE)kZ{_pX*Pma%gdwfb3=sW7?d~tk@DIk3y{k*S^|NqD1?|k&~>z98y{uW>R**9)J4g_#J!IU*FpP?eU$!=J&_n$L^1hugH)1P9GniW!}l} zrl0u5@tN^^-+$uE+h_PKg-P_a-yc64t3NsZ`_=9Hj2>0|>GRq1UFWB9|F{16`1yZ6 zEdArnj>w9~PyGISX8n-w{PFP<*58>=tiLnQLMXgBZ2i-L`iYq={OtI%-`~(a+4xuA zKNB(S4+n-k$->v1OEQ@WPkGVA8vW*Ki=5?>Fw`oZq0XtkN{70=_oveWmj*1Xon&yL^Wn=Ljnd(rfTe$v0qzTX`@`oqCeJmB>Rs>`uP zQ1e5&UP5ZN@W0$R{Ppn^i86{J_~BQFMcPLgx?()dUmr-~``;d)A};;&&2Ii5KjWXi z=ffAr*FJyw>*KT9UHJ7|{?Xr-QdxcW%j5G|cl)1?pT+ZB{R}3~vM2xS_$M5~-u;5?5|E+oU{P`n}<4-?5zIKh&d~MDPdP?)3|NG7t zpBzm1^7!{JIpZ%ml-3e9kPT^6BmDbpd!t#sHdOso4Y@kWT<3m^c@8i3UeNugf zzdOGA4~Gh;E*RC<{nvhXJcpst&!37lD7Z%~9&sMl&7X@fyZ@Pd_eVW-|5cvc<5%xd z|Ko%@aReR3S6+`fpN=rs_s=lrs{_>;^ZTz}F~9%Xj5%MuV*VI=`2@(^qkYCbA$0#U zW{mH@y2hB=_mSC(1^oHz5$4ko!uswR!hAJH`2MR`gzvvLBg|K?2uE?5&s}kzqoVM> z|A{l+_g~HM{!6_v`dN7JzqLO_z46B*4*sRy_)ER<>%+@`du0AmZ~Tv&{&=%V#Xn}m zNGqwrzxIjFzU@CA5&hBP-`%qAcQ=c<-Q)dtq~%p5J?7>gYq1plJ;v`&)j#IHcVp>2 zwrs5a;vHdoX5t@fr*!=zqP4bH?~6XtqYC`wLBqYvDnvdeYpTj%c^Z46&pK{ayqo-N_jmMw&=;Qb58J#`2^{DV3YnSmvA3vjLL`38J z{Pw6Q=onM8+*cNVedKZGKwlhR|Mbv{e|q~>S#q!SXAOP-)vLn0|JtnZ`0DuG?p1Qs z9pba&cbq>P;dlSD$4_~zQtm%7zIXnKbyxlVnW5XqPkekH_m$81iI1O9j2qQa^u+k? z)f2m~9Ofr>|JCagyZ_q!#Q5s?&F-JVW8~*kgn9q8S~S*|LXPW+<)!<>6}y6@mt;Fo>fib zH@yGs9K-dj?tk+58IMom{uARn=bw1Zv-(S|^)70yZ;sy87k{a=?zREujfQu%4Y2yo zkJ|t`M>cOU?A{3YpGRc=yIZBg)VS7t?|z!|<)JeE-|_F4ce8B$|BsH^Dc|Ylb8Q~^mUmI|Ld&}iAud%r7H0Hr|19w=+<$c zpWnArclO@aNZG8d{>|~5(yzwmKOcVl=0{k}uGiY)8QrJ`U0eK!^N+O|MZLCJ482F0 zx2sWwtFynh_8#Ag6M5wVFV3mL*vDWi=c=n^?Z~NUaTs~>@qZoNk1uaq3#T{0Ma?80 zKYO3IPcMi*`J00|UmZ5inqjs?Pwd`~!JDfc`sBS85nJx<(cg%yxyOat2sC3<1|zU$ z{^Y$ik35(^8`&Wb5Gv>2m@#4A1}`72$Pjt#I$ghSWXC-oaLc*lLOi5H%LdPzBTD~& D&?3k; literal 0 HcmV?d00001 diff --git a/Documents/MT Templates/x-xeu5.without.xrsi.tpl b/Documents/MT Templates/x-xeu5.without.xrsi.tpl new file mode 100644 index 0000000000000000000000000000000000000000..ab887d05c3e3fc0eab51d9f718173083cf05831c GIT binary patch literal 1831778 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

nGn6IJ9hILWCNb#;Y|m!EmgSk(nP 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 z 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

?A5Vch+?CUKa~xl?%JhpLMrVRAnELH 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 z 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

  • 2B3AU%|Cb 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�y_sM*`v8*vVj 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 z%0A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 T-&J?NN48=jM3nz 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/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..d7071b48 --- /dev/null +++ b/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/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e84d762f --- /dev/null +++ b/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/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..19d3417c --- /dev/null +++ b/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/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 00000000..e6a92f65 --- /dev/null +++ b/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/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f90f15b2 --- /dev/null +++ b/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/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e6971b7a --- /dev/null +++ b/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/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..6286228b --- /dev/null +++ b/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/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 00000000..a871ed42 --- /dev/null +++ b/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/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..875eec08 --- /dev/null +++ b/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/Indicators/x-saherelm.xama.indicator.mq5 b/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/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/Indicators/x-saherelm.xchlh.oscillator.mq5 b/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 00000000..5c74787c --- /dev/null +++ b/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/Indicators/x-saherelm.xchma.oscillator.mq5 b/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 00000000..12d6c691 --- /dev/null +++ b/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/Indicators/x-saherelm.xfi.oscillator.mq5 b/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 00000000..cfd393ca --- /dev/null +++ b/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/Indicators/x-saherelm.xlh.indicator.mq5 b/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 00000000..4dfc64e2 --- /dev/null +++ b/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/Indicators/x-saherelm.xobd.indicator.mq5 b/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 00000000..4ac05cf6 --- /dev/null +++ b/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/Indicators/x-saherelm.xrsi.oscillator.mq5 b/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 00000000..5659e07d --- /dev/null +++ b/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/Indicators/x-saherelm.xtd.oscillator.mq5 b/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 00000000..5f46d187 --- /dev/null +++ b/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/Indicators/x-saherelm.xtm.indicator.mq5 b/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 00000000..eac88e0a --- /dev/null +++ b/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/Indicators/x-saherelm.xts.oscillator.mq5 b/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 00000000..46e9fbf9 --- /dev/null +++ b/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/Libraries/x-saherelm.alert.lib.mq5 b/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 00000000..10790632 --- /dev/null +++ b/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/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 00000000..290dde9b --- /dev/null +++ b/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/Libraries/x-saherelm.draw.lib.mq5 b/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 00000000..ece98c83 --- /dev/null +++ b/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/Libraries/x-saherelm.http.lib.mq5 b/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 00000000..97f7ac0a --- /dev/null +++ b/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/Libraries/x-saherelm.log.lib.mq5 b/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 00000000..70f1bda4 --- /dev/null +++ b/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/Libraries/x-saherelm.models.lib.mq5 b/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 00000000..b98ae3e8 --- /dev/null +++ b/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/MQL5.code-workspace b/MQL5.code-workspace new file mode 100644 index 00000000..876a1499 --- /dev/null +++ b/MQL5.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/Projects/.gitkeep b/Projects/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Classes/.gitkeep b/Projects/XAU5/Classes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Classes/x-saherelm.class.lib.mq5 b/Projects/XAU5/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 00000000..68f48471 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Classes/x-saherelm.nn.lib.mq5 b/Projects/XAU5/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 00000000..8fa40f53 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Classes/x-saherelm.provider.lib.mq5 b/Projects/XAU5/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 00000000..4e4497a4 --- /dev/null +++ b/Projects/XAU5/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, + // + // XSTFI ... + XSTFI, + // + // 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 XCPriver : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCPriver( + // + // 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 + // + // XSTFI ... + bool xSTFIEnableSignaller, // Enable Signaller + bool xSTFIAllowLongSignals, // Allow Long Signals + bool xSTFIAllowShortSignals, // 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; + + // + // XSTFI ... + mXSTFIEnableSignaller = xSTFIEnableSignaller; + mXSTFIAllowLongSignals = xSTFIAllowLongSignals; + mXSTFIAllowShortSignals = xSTFIAllowShortSignals; + + // + // 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 ... + ~XCPriver() {} + + // + // 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 XSTFI Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXSTFIignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXSTFIEnableSignaller) + { + return result; + } + + // + result = true; + mXSTFIEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXSTFISignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXSTFIEnableSignaller) + { + return result; + } + + // + result = true; + mXSTFIEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXSTFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + mXSTFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXSTFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXSTFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + mXSTFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXSTFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XSTFIHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowLongSignals) + { + 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 XSTFIHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowShortSignals) + { + 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 XSTFI 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; + + // + // XSTFI ... + bool mXSTFIEnableSignaller; + bool mXSTFIAllowLongSignals; + bool mXSTFIAllowShortSignals; + + // + // 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/Projects/XAU5/Documents/.gitkeep b/Projects/XAU5/Documents/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Documents/Reports/.gitkeep b/Projects/XAU5/Documents/Reports/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Documents/Settings/.gitkeep b/Projects/XAU5/Documents/Settings/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Documents/Settings/xau5.longs.vbb.set b/Projects/XAU5/Documents/Settings/xau5.longs.vbb.set new file mode 100644 index 0000000000000000000000000000000000000000..539ea87b02d6b8acd79a2da8a1f206adcb0a6073 GIT binary patch literal 7568 zcmcgwZBx@g5Z=$u_#g5E6ahg{rynYaI%5k%i~6;eP&@W*npUdgZ&#n^Hpks1ffnj@ zGHr63%Ral$?(JUk_s?rdB$JN(kW?;lJ(dyvcV!#DJ=wx}2md?r9MT<(UP1mc|9>ox zgwN09oAjY2kt>`B(3D8mXqrKD9~ya&=ZVZQJHfdlQ~ZXQJHv09KRw13^`#ik%o9C% z22B$)8bb0bmnO21r4|?XfG}6$xm}fZKUQW7|XCgI&0^iF}D%5NN3m^Co| zbF^(_{{7|+M&0Nln~Lir`1c;7e_-riSBvHobA`SSB-9sr8jf!Bdk8(u>-9A;|1(5+ zeN9|$fbRIa&a_4@XPEc*GnT3oAiz6XzU*f+o`5A}yS!_jS- zQ-yGxXHzWwpTTd6Iuy@?1~?iap5G#3IF`=g%>;;Ab83ZJ_3$|OJjKEYnff0n;ks{w z6?PiC=54+;AY~uuioXtP=-@BVz4x%P_Hm^vty;!DP`p#M9$UzPKH|fU-h&;)(0T5x zy2AB*n;(hLc2;g`(+)W^-N*XIRmo0qZ8{n|ons*b{=@5l)7(OCYsRgsJM{A$TxDjD zu*}N~%uD4H<}>f-;9~$k&xCxhw+4tzE-j1P_k~{C$nBX*tXaaGVI0G1d<5&purz~R zeMCY#ZiX0gUq=ovO-8s~g=#sd&~>+6^*p<{Gqssy^UUT~*}hYF8G2X8n&8fo6^y;7 zXc=?9tfz%%xclRZ`h;f(rn{wb0x9(|S8A|}`(+-xxn4W2l9XlY+v@1cSk}me5%aBY zz>9(LYJzhgF;g#S!LIQ|+1bKK{j$t+?0mD*5UFme0=v*M%p!{xwTel{ky_v^EAyrq z)q}KWTn<6U$Yx6P29WZ)~Ji7*;#XO=fE^500Hb)MdE6-{HKaM}`6dD^BGa_m{Z49ftsY1WaBkdc@J#x=8+xY!}yZRZT!hXt?SI0h5 z-xS;CUKibpZ}hc1GU}UFP)4I1g*PVd+^cl)q#y4SXyjWDzdMWyy_Fm}-rN;;WR@jj z>B_T`Dtx=1$lny*k*oSXR=7&$u2{<~CapMxwRX(2VPtbLtbp6Yk|AAT3%F49L?Zy#AiaJ$JO#+At-_5v~+j+AYG zH>*`3WS&@c^pRCq<-EAO5+OFTAx2zoTj)~DndPjQyi$K$Rzrl?oVHP?R^wG?#^qKq zV)I)>iOcb+yg{Y?DDPLuUN<);&kiLn(^WWexjq8Rta?W{me&e@c1*r~oVbivBW;HB m2KE%IbI#eD;G8&{;XFjz6z9!*ao*ez=gp0A?j!wQ&i?^ezdO|c literal 0 HcmV?d00001 diff --git a/Projects/XAU5/Documents/Settings/xau5.xsi.vbb.set b/Projects/XAU5/Documents/Settings/xau5.xsi.vbb.set new file mode 100644 index 0000000000000000000000000000000000000000..1194c65faaaf8f5e4d69496a4fdf476b77c15c3f GIT binary patch literal 7584 zcmcgw+iu%N5S`}&`3HVLtJscjZJ-Cmu9EAJp}IkoVkOA8w>f8r>)jVuXXZXXAA@0(f5=hO5_c()F@GhoN^ z1IGha4UPRA9hf=)e(MRNVPug_#q|;Vd)vq#8vS>bqVdF7q3uHn<%O1pqg8f~Act|i zyClYc0x$0_iTmyjay}x~Be{VuCnmD*;ZYaaZiOE)jG|@w?B8C5WTkB5Lo2rhOGk)2 zYIBYFdXI>SF_S=7&UMn=Qb$fv-tGC&L?1^wud!$4`uc_}`tiD+UyEeE1CI;nH^eRv z<%crE(W=NPLbyz$sVe!O!EcN_RGkG)a5RQLzf_3fSh|HZQy^;2sb_N4_I~hrstO}y z>Q|tI`@REKSZVB@xAE4*EbBl|{C!wQ6+cDYKE}>E!Ikc`;yKoV?46?h*hUNt;2&1> zKJ*}lu5)LV74GL%c0@wmnYk%VE9Bf%A8Q+TB`d|Fsc5Wpj)esH+vfo%xsBM?h}%_m zXy+}sN=%PXX5~k$i{%s6Gwv7QV+cEMgnaL|2Z&5AEsN~?LMyH3j!h=kC}GUdk6|{x zfOZpTnn14sJfRggfe+c&k;8iv5w5FHDQ5+;p4Y39MwdQsBg{rtUbAc17uwapZeUNz z+*MDl38kGDXw}9u?EAQvKH=G+scW%ZVV3e3C6vZana7cl;l@QX`8oF6s!Pc4D)cgb z)n}nBU;8Gk7#gdlI1k`0wSqhz8C%q2HH_3Qs~^YKR=tzwzG3nK>rWYGmPLz7$yp{H zN2-C-EU$saQX5t>GwDudocsFNKE!6w=X9Yy=Q+>j=gtjVd41T?_rNjVNw}}?O_p0? z*F2};t%*G5R2!!?bW4sS?UAf!UX}W#2~UrORp=3tXV8Lr-C%YKt(dt_QY2o{%f#aQ zALs3%bDSxQ1DoxxjO8(`We+&bpq{2U`nGAUW4^Hm=Q!RJ&*!g(dS_*y!5({kARH+Y z=gtbO4fhdq9^Vm}5tx-PG46uVOT^hD_{_#p4Z1t89R=7NIc)AcJLW9)c^>;M;zvEX zU3M$Vx$D^D_|qDpzHvUI=IT%D!y;>n(08@SJdU(?J_Z1}aeTQEh#+j;0jvR09ioKX+iCDVx>`W29 z-B09ihPudIy@?hslesJAGK)zq&R6cXu%q$oKEE>XOOE|YahJYh@=dja{SgISg0A-8 zMRk?`hL@MVTkoR?uJ_?L5q6M1&Tc(q7QuCrS&Ro0MXUzoI~=Lk{Z3Z%K*&9@8mJ`e z@XB>nGfRxBxeYO@Ww(t=Rn9F}Rm&_9s^v9AsG8LdvekOb>dLCwRg|h3&Z1Py^0mA{ z#{D4g)`(!Ywv1^%BdwRQ>|6UCs-o4XTBeI|R&%|%McEvD0gjpXE^w4*3x9PP+abf@ zXjO%9eEUe%GG2_dAI_WTEjD4D>-WVwvG&D$h_x^7TN`rU+9UU^J#z13{YvhC0$-;- AEdT%j literal 0 HcmV?d00001 diff --git a/Projects/XAU5/Experts/.gitkeep b/Projects/XAU5/Experts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Experts/x-saherelm.xau5.ea.mq5 b/Projects/XAU5/Experts/x-saherelm.xau5.ea.mq5 new file mode 100644 index 00000000..fe1bc45f --- /dev/null +++ b/Projects/XAU5/Experts/x-saherelm.xau5.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 XAU5 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" + +// +// XAU5 Signal Provider ... +#include "../Providers/x-saherelm.xau5.provider.lib.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +bool isXAU5NewHour; +bool isXAU5NewDay; +bool isXAU5NewWeek; +bool isXAU5NewMonth; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = "XAU5EA"; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Apply default Chart Style for EA ... + ApplyChartStyle(); + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize XAU5 Provider ... + if (!XAU5InitSignalProviderLibrary()) + { + 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 XAU5 Provider ... + XAU5DeinitSignalProviderLibrary(reason); + + // + // De Init XDraw Library ... + // OnDeinitDrawLibrary(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXAU5NewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXAU5NewMonth && + xAU5EnableAlerts && + xAU5EnableMonthlyAlerts; + bool canMonthlyReport = + !isFirstMonth && + canMonthlyAlert && + xAU5EnableMonthlyReports; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + // Prepare Monthly Report ... + if (canMonthlyReport) + { + // + string report = xAU5Reporter.GenerateReportString(XREPORT_MONTHLY); + + // + message = "Last Month Report:\n" + report; + } + + // + // Reset Report ... + xAU5Reporter.Reset(XREPORT_MONTHLY); + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXAU5NewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXAU5NewWeek && + xAU5EnableAlerts && + xAU5EnableWeeklyAlerts; + bool canWeeklyReport = + !isFirstWeek && + canWeeklyAlert && + xAU5EnableWeeklyReports; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + // Prepare Weekly Report ... + if (canWeeklyReport) + { + // + string report = xAU5Reporter.GenerateReportString(XREPORT_WEEKLY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xAU5Reporter.Reset(XREPORT_WEEKLY); + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXAU5NewDay = IsNewDay(); + bool canDailyAlert = + isXAU5NewDay && + xAU5EnableAlerts && + xAU5EnableDailyAlerts; + bool canDailyReport = + !isFirstDay && + canDailyAlert && + xAU5EnableDailyReports; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + // Prepare Daily Report ... + if (canDailyReport) + { + // + string report = xAU5Reporter.GenerateReportString(XREPORT_DAILY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xAU5Reporter.Reset(XREPORT_DAILY); + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXAU5NewHour = IsNewHour(); + bool canHourlyAlert = + isXAU5NewHour && + xAU5EnableAlerts && + xAU5EnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + + // + // Prevent Going Forward if user Disable it ... + if (xAU5EnableProvider) + { + // + // Handle Processing on XAU5 Signal Provider ... + XAU5SignalProviderDoControlState(); + } + + // + if (!IsNewCandle()) + { + return; + } + + // + // Prevent Going Forward if user Disable it ... + if (xAU5EnableProvider) + { + // + // Handle Processing on XAU5 Signal Provider ... + XAU5SignalProviderHandleTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + + // + // Prevent Going Forward if user Disable it ... + if (xAU5EnableProvider) + { + // + // Handle Processing Trades on XAU5 Signal Provider ... + XAU5SignalProviderHandleTrade(); + } +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + + // + // Validate XAU5 Provider Inputs ... + result = XAU5ValidateInputs(); + if (!result) + { + return false; + } + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// END Functions ... +// diff --git a/Projects/XAU5/Helpers/.gitkeep b/Projects/XAU5/Helpers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f565e415 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..d7071b48 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e84d762f --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..19d3417c --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 00000000..e6a92f65 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f90f15b2 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e6971b7a --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..6286228b --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 00000000..a871ed42 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/Projects/XAU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..875eec08 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/.gitkeep b/Projects/XAU5/Indicators/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Indicators/x-saherelm.xama.indicator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xchlh.oscillator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 00000000..5c74787c --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xchma.oscillator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 00000000..12d6c691 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xfi.oscillator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 00000000..cfd393ca --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xlh.indicator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 00000000..4dfc64e2 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xobd.indicator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 00000000..4ac05cf6 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xrsi.oscillator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 00000000..5659e07d --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xtd.oscillator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 00000000..5f46d187 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xtm.indicator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 00000000..eac88e0a --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Indicators/x-saherelm.xts.oscillator.mq5 b/Projects/XAU5/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 00000000..46e9fbf9 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Libraries/.gitkeep b/Projects/XAU5/Libraries/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Libraries/x-saherelm.alert.lib.mq5 b/Projects/XAU5/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 00000000..10790632 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Libraries/x-saherelm.common.lib.mq5 b/Projects/XAU5/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 00000000..290dde9b --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Libraries/x-saherelm.draw.lib.mq5 b/Projects/XAU5/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 00000000..ece98c83 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Libraries/x-saherelm.http.lib.mq5 b/Projects/XAU5/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 00000000..97f7ac0a --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Libraries/x-saherelm.log.lib.mq5 b/Projects/XAU5/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 00000000..70f1bda4 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Libraries/x-saherelm.models.lib.mq5 b/Projects/XAU5/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 00000000..b98ae3e8 --- /dev/null +++ b/Projects/XAU5/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/Projects/XAU5/Providers/.gitkeep b/Projects/XAU5/Providers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Providers/x-saherelm.xau5.provider.indicators.lib.mq5 b/Projects/XAU5/Providers/x-saherelm.xau5.provider.indicators.lib.mq5 new file mode 100644 index 00000000..6c9e20ab --- /dev/null +++ b/Projects/XAU5/Providers/x-saherelm.xau5.provider.indicators.lib.mq5 @@ -0,0 +1,7655 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAU5 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.xau5.provider.inputs.lib.mq5" + +// +// Include Provider Class ... +#include "../Classes/x-saherelm.provider.lib.mq5" + +// +// Signallers ... +input group "XAU5 Signallers"; + +// +// XTD ... +input group "XAU5 XTD Signaller"; +input bool xAU5XTDEnableSignaller = true; // Enable Signaller +input bool xAU5XTDAllowLongSignals = true; // Enable Long Signals +input bool xAU5XTDAllowShortSignals = true; // Enable Short Signals + +// +// XTAM ... +input group "XAU5 XTAM Signaller"; +input bool xAU5XTAMEnableSignaller = true; // Enable Signaller +input bool xAU5XTAMAllowLongSignals = true; // Enable Long Signals +input bool xAU5XTAMAllowShortSignals = true; // Enable Short Signals + +// +// XSI ... +input group "XAU5 XSI Signaller"; +input bool xAU5XSIEnableSignaller = true; // Enable Signaller +input bool xAU5XSIAllowLongSignals = true; // Enable Long Signals +input bool xAU5XSIAllowShortSignals = true; // Enable Short Signals + +// +// XSTFI ... +input group "XAU5 XSTFI Signaller"; +input bool xAU5XSTFIEnableSignaller = true; // Enable Signaller +input bool xAU5XSTFIAllowLongSignals = true; // Enable Long Signals +input bool xAU5XSTFIAllowShortSignals = true; // Enable Short Signals + +// +// XOBDLH ... +input group "XAU5 XOBDLH Signaller"; +input bool xAU5XOBDLHEnableSignaller = true; // Enable Signaller +input bool xAU5XOBDLHAllowLongSignals = true; // Enable Long Signals +input bool xAU5XOBDLHAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACC ... +input group "XAU5 XCHMACC Signaller"; +input bool xAU5XCHMACCEnableSignaller = true; // Enable Signaller +input bool xAU5XCHMACCAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMACCAllowShortSignals = true; // Enable Short Signals + +// +// XCHMAMX ... +input group "XAU5 XCHMAMX Signaller"; +input bool xAU5XCHMAMXEnableSignaller = true; // Enable Signaller +input bool xAU5XCHMAMXAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMAMXAllowShortSignals = true; // Enable Short Signals + +// +// XCHMAMN ... +input group "XAU5 XCHMAMN Signaller"; +input bool xAU5XCHMAMNEnableSignaller = true; // Enable Signaller +input bool xAU5XCHMAMNAllowLongSignals = true; // Enable Long Signals +input bool xAU5XCHMAMNAllowShortSignals = true; // Enable Short Signals + +// +bool xAU5IsTestMode = true; +int xAU5MaxLengthOfInputs = 0; +int xAU5CalculatedBars = 0; + +// +// Signaller Variables ... +// +// XTD ... +bool xAU5MXTDEnableSignaller = xAU5XTDEnableSignaller; +bool xAU5MXTDAllowLongSignals = xAU5XTDAllowLongSignals; +bool xAU5MXTDAllowShortSignals = xAU5XTDAllowShortSignals; + +// +// XTAM ... +bool xAU5MXTAMEnableSignaller = xAU5XTAMEnableSignaller; +bool xAU5MXTAMAllowLongSignals = xAU5XTAMAllowLongSignals; +bool xAU5MXTAMAllowShortSignals = xAU5XTAMAllowShortSignals; + +// +// XSI ... +bool xAU5MXSIEnableSignaller = xAU5XSIEnableSignaller; +bool xAU5MXSIAllowLongSignals = xAU5XSIAllowLongSignals; +bool xAU5MXSIAllowShortSignals = xAU5XSIAllowShortSignals; + +// +// XSTFI ... +bool xAU5MXSTFIEnableSignaller = xAU5XSTFIEnableSignaller; +bool xAU5MXSTFIAllowLongSignals = xAU5XSTFIAllowLongSignals; +bool xAU5MXSTFIAllowShortSignals = xAU5XSTFIAllowShortSignals; + +// +// XOBDLH ... +bool xAU5MXOBDLHEnableSignaller = xAU5XOBDLHEnableSignaller; +bool xAU5MXOBDLHAllowLongSignals = xAU5XOBDLHAllowLongSignals; +bool xAU5MXOBDLHAllowShortSignals = xAU5XOBDLHAllowShortSignals; + +// +// XCHMACC ... +bool xAU5MXCHMACCEnableSignaller = xAU5XCHMACCEnableSignaller; +bool xAU5MXCHMACCAllowLongSignals = xAU5XCHMACCAllowLongSignals; +bool xAU5MXCHMACCAllowShortSignals = xAU5XCHMACCAllowShortSignals; + +// +// XCHMAMX ... +bool xAU5MXCHMAMXEnableSignaller = xAU5XCHMAMXEnableSignaller; +bool xAU5MXCHMAMXAllowLongSignals = xAU5XCHMAMXAllowLongSignals; +bool xAU5MXCHMAMXAllowShortSignals = xAU5XCHMAMXAllowShortSignals; + +// +// XCHMAMN ... +bool xAU5MXCHMAMNEnableSignaller = xAU5XCHMAMNEnableSignaller; +bool xAU5MXCHMAMNAllowLongSignals = xAU5XCHMAMNAllowLongSignals; +bool xAU5MXCHMAMNAllowShortSignals = xAU5XCHMAMNAllowShortSignals; + +// +XCPriver *xAU5Provider; + +// +// Validate Indicators Inputs ... +bool XAU5ValidateIndicatorsInputs() +{ + // + 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 XCPriver Class for Use ... + xAU5Provider = new XCPriver( + // + // Commons ... + _Symbol, + _Period, + // + // Signallers ... + // + // XTD ... + xAU5MXTDEnableSignaller, + xAU5MXTDAllowLongSignals, + xAU5MXTDAllowShortSignals, + // + // XTAM ... + xAU5MXTAMEnableSignaller, + xAU5MXTAMAllowLongSignals, + xAU5MXTAMAllowShortSignals, + // + // XSI ... + xAU5MXSIEnableSignaller, + xAU5MXSIAllowLongSignals, + xAU5MXSIAllowShortSignals, + // + // XSTFI ... + xAU5MXSTFIEnableSignaller, + xAU5MXSTFIAllowLongSignals, + xAU5MXSTFIAllowShortSignals, + // + // XOBDLH ... + xAU5MXOBDLHEnableSignaller, + xAU5MXOBDLHAllowLongSignals, + xAU5MXOBDLHAllowShortSignals, + // + // XCHMACC ... + xAU5MXCHMACCEnableSignaller, + xAU5MXCHMACCAllowLongSignals, + xAU5MXCHMACCAllowShortSignals, + // + // XCHMAMX ... + xAU5MXCHMAMXEnableSignaller, + xAU5MXCHMAMXAllowLongSignals, + xAU5MXCHMAMXAllowShortSignals, + // + // XCHMAMN ... + xAU5MXCHMAMNEnableSignaller, + xAU5MXCHMAMNAllowLongSignals, + xAU5MXCHMAMNAllowShortSignals + // + ); + + // + result = true; + + // + return result; +} + +// +// Init Indicators ... +bool XAU5InitIndicators() +{ + // + bool result = false; + + // + // Make it Enable when we need to Log Market Conditions ... + // xAU5IsTestMode = false; // IsRunningOnTestMode(); + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xAU5MaxLengthOfInputs = MathMax( + xTMMaPeriod, + xAU5NumberOfItemsPerTick); + + // + // XAMA ... + xAU5MaxLengthOfInputs = MathMax( + xAMALength, + xAU5NumberOfItemsPerTick); + xAU5MaxLengthOfInputs = MathMax( + xAMAFastEMA, + xAU5NumberOfItemsPerTick); + xAU5MaxLengthOfInputs = MathMax( + xAMASlowEMA, + xAU5NumberOfItemsPerTick); + + // + // XLH ... + xAU5MaxLengthOfInputs = MathMax( + xLHLength, + xAU5NumberOfItemsPerTick); + + // + // XTD ... + xAU5MaxLengthOfInputs = MathMax( + xTDLength, + xAU5MaxLengthOfInputs); + + // + // XFI ... + xAU5MaxLengthOfInputs = MathMax( + xFILength, + xAU5MaxLengthOfInputs); + + // + // XRSI ... + xAU5MaxLengthOfInputs = MathMax( + xRSILength, + xAU5MaxLengthOfInputs); + + // + // XOBD ... + xAU5MaxLengthOfInputs = MathMax( + xOBDLength, + xAU5MaxLengthOfInputs); + + // + // XCHLH ... + xAU5MaxLengthOfInputs = MathMax( + xCHLHLcLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHLHMcLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHLHScLength, + xAU5MaxLengthOfInputs); + + // + // XCHMA ... + xAU5MaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xAU5MaxLengthOfInputs); + xAU5MaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xAU5MaxLengthOfInputs); + + // + // Validate Indicators Inputs before Initialization ... + result = XAU5ValidateIndicatorsInputs(); + if (!result) + { + return result; + } + + // + // Validate Signallers ... + + // + // XTD ... + bool isXTDEnable = + xAU5XTDEnableSignaller && + (xAU5XTDAllowLongSignals || + xAU5XTDAllowShortSignals); + + // + // XTAM ... + bool isXTAMEnable = + xAU5XTAMEnableSignaller && + (xAU5XTAMAllowLongSignals || + xAU5XTAMAllowShortSignals); + + // + // XSI ... + bool isXSIEnable = + xAU5XSIEnableSignaller && + (xAU5XSIAllowLongSignals || + xAU5XSIAllowShortSignals); + + // + // XSTFI ... + bool isXSTFIEnable = + xAU5XSTFIEnableSignaller && + (xAU5XSTFIAllowLongSignals || + xAU5XSTFIAllowShortSignals); + + // + // XOBDLH ... + bool isXOBDLHEnable = + xAU5XOBDLHEnableSignaller && + (xAU5XOBDLHAllowLongSignals || + xAU5XOBDLHAllowShortSignals); + + // + // XCHMACC ... + bool isXCHMACCEnable = + xAU5XCHMACCEnableSignaller && + (xAU5XCHMACCAllowLongSignals || + xAU5XCHMACCAllowShortSignals); + + // + // XCHMAMX ... + bool isXCHMAMXEnable = + xAU5XCHMAMXEnableSignaller && + (xAU5XCHMAMXAllowLongSignals || + xAU5XCHMAMXAllowShortSignals); + + // + // XCHMAMN ... + bool isXCHMAMNEnable = + xAU5XCHMAMNEnableSignaller && + (xAU5XCHMAMNAllowLongSignals || + xAU5XCHMAMNAllowShortSignals); + + // + bool hasSignaller = + // + isXTDEnable || + isXTAMEnable || + isXSIEnable || + isXSTFIEnable || + isXOBDLHEnable || + isXCHMACCEnable || + isXCHMAMXEnable || + isXCHMAMNEnable + // + ; + result = hasSignaller; + if (!result) + { + // + LogMessage("XAU5 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 XAU5ReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XAMAReleaseHandlers(); + XLHReleaseHandlers(); + XTDReleaseHandlers(); + XFIReleaseHandlers(); + XTSReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XAU5HandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xAU5CalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xAU5NumberOfItemsPerTick); + XAMAReadBuffers(xAU5NumberOfItemsPerTick); + XLHReadBuffers(xAU5NumberOfItemsPerTick); + XTDReadBuffers(xAU5NumberOfItemsPerTick); + XFIReadBuffers(xAU5NumberOfItemsPerTick); + XTSReadBuffers(xAU5NumberOfItemsPerTick); + XRSIReadBuffers(xAU5NumberOfItemsPerTick); + XOBDReadBuffers(xAU5NumberOfItemsPerTick); + XCHMAReadBuffers(xAU5NumberOfItemsPerTick); + XCHLHReadBuffers(xAU5NumberOfItemsPerTick); + + // + xAU5Provider.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 XAU5CanOpenLongTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XAU5HasLongSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + xAU5Provider.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 XAU5CanCloseLongTrade() +{ + // + 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 XAU5CanOpenShortTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XAU5HasShortSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + xAU5Provider.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 XAU5CanCloseShortTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// Check Market Conditions by Combination of Power of All tools for LONGs ... +bool XAU5HasLongSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XAU5XTDHasLongSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XAU5XTAMHasLongSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XAU5XSIHasLongSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XAU5XSTFIHasLongSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XAU5XOBDLHHasLongSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XAU5XCHMACCHasLongSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMAMNHasSignal = XAU5XCHMAMNHasLongSignal(); + if (isXCHMAMNHasSignal) + { + // + Add( + EnumToString(XCHMAMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMAMXHasSignal = XAU5XCHMAMXHasLongSignal(); + if (isXCHMAMXHasSignal) + { + // + Add( + EnumToString(XCHMAMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXSTFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMAMNHasSignal + // + || + // + isXCHMAMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xAU5IsTestMode) + { + // + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + string message = xAU5Provider.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 XAU5HasShortSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XAU5XTDHasShortSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XAU5XTAMHasShortSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XAU5XSIHasShortSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XAU5XSTFIHasShortSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XAU5XOBDLHHasShortSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XAU5XCHMACCHasShortSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMAMNHasSignal = XAU5XCHMAMNHasShortSignal(); + if (isXCHMAMNHasSignal) + { + // + Add( + EnumToString(XCHMAMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMAMXHasSignal = XAU5XCHMAMXHasShortSignal(); + if (isXCHMAMXHasSignal) + { + // + Add( + EnumToString(XCHMAMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXSTFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMAMNHasSignal + // + || + // + isXCHMAMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xAU5IsTestMode) + { + // + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + string message = xAU5Provider.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 XAU5DisableLongSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + // + xAU5Provider.DisbaleXTDLongs(); + xAU5MXTDAllowLongSignals = false; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + // + xAU5Provider.DisbaleXTAMLongs(); + xAU5MXTAMAllowLongSignals = false; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + // + xAU5Provider.DisbaleXSILongs(); + xAU5MXSIAllowLongSignals = false; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + // + xAU5Provider.DisbaleXSTFILongs(); + xAU5MXSTFIAllowLongSignals = false; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + // + xAU5Provider.DisbaleXOBDLHLongs(); + xAU5MXOBDLHAllowLongSignals = false; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + // + xAU5Provider.DisbaleXCHMACCLongs(); + xAU5MXCHMACCAllowLongSignals = false; + } + + // + // XCHMAMX ... + if (xAU5MXCHMAMXEnableSignaller) + { + // + xAU5Provider.DisbaleXCHMAMXLongs(); + xAU5MXCHMAMXAllowLongSignals = false; + } + + // + // XCHMAMN ... + if (xAU5MXCHMAMNEnableSignaller) + { + // + xAU5Provider.DisbaleXCHMAMNLongs(); + xAU5MXCHMAMNAllowLongSignals = false; + } +} + +// +// Enable All Signallers Longs ... +// Only if they are Configured as Enable at Settings ... +void XAU5EnableLongSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + // + xAU5MXTDAllowLongSignals = + xAU5XTDAllowLongSignals + ? true + : xAU5MXTDAllowLongSignals; + + // + if (xAU5MXTDAllowLongSignals) + { + xAU5Provider.EnableXTDLongs(); + } + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + // + xAU5MXTAMAllowLongSignals = + xAU5XTAMAllowLongSignals + ? true + : xAU5MXTAMAllowLongSignals; + + // + if (xAU5MXTAMAllowLongSignals) + { + xAU5Provider.EnableXTAMLongs(); + } + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + // + xAU5MXSIAllowLongSignals = + xAU5XSIAllowLongSignals + ? true + : xAU5MXSIAllowLongSignals; + + // + if (xAU5MXSIAllowLongSignals) + { + xAU5Provider.EnableXSILongs(); + } + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + // + xAU5MXSTFIAllowLongSignals = + xAU5XSTFIAllowLongSignals + ? true + : xAU5MXSTFIAllowLongSignals; + + // + if (xAU5MXSTFIAllowLongSignals) + { + xAU5Provider.EnableXSTFILongs(); + } + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + // + xAU5MXOBDLHAllowLongSignals = + xAU5XOBDLHAllowLongSignals + ? true + : xAU5MXOBDLHAllowLongSignals; + + // + if (xAU5MXOBDLHAllowLongSignals) + { + xAU5Provider.EnableXOBDLHLongs(); + } + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + // + xAU5MXCHMACCAllowLongSignals = + xAU5XCHMACCAllowLongSignals + ? true + : xAU5MXCHMACCAllowLongSignals; + + // + if (xAU5MXCHMACCAllowLongSignals) + { + xAU5Provider.EnableXCHMACCLongs(); + } + } + + // + // XCHMAMX ... + if (xAU5MXCHMAMXEnableSignaller) + { + // + xAU5MXCHMAMXAllowLongSignals = + xAU5XCHMAMXAllowLongSignals + ? true + : xAU5MXCHMAMXAllowLongSignals; + + // + if (xAU5MXCHMAMXAllowLongSignals) + { + xAU5Provider.EnableXCHMAMXLongs(); + } + } + + // + // XCHMAMN ... + if (xAU5MXCHMAMNEnableSignaller) + { + // + xAU5MXCHMAMNAllowLongSignals = + xAU5XCHMAMNAllowLongSignals + ? true + : xAU5MXCHMAMNAllowLongSignals; + + // + if (xAU5MXCHMAMNAllowLongSignals) + { + xAU5Provider.EnableXCHMAMNLongs(); + } + } +} + +// +// Disable All Signallers Shorts ... +void XAU5DisableShortSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + // + xAU5Provider.DisableXTDShorts(); + xAU5MXTDAllowShortSignals = false; + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + // + xAU5Provider.DisableXTAMShorts(); + xAU5MXTAMAllowShortSignals = false; + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + // + xAU5Provider.DisableXSIShorts(); + xAU5MXSIAllowShortSignals = false; + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + // + xAU5Provider.DisableXSTFIShorts(); + xAU5MXSTFIAllowShortSignals = false; + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + // + xAU5Provider.DisableXOBDLHShorts(); + xAU5MXOBDLHAllowShortSignals = false; + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + // + xAU5Provider.DisableXCHMACCShorts(); + xAU5MXCHMACCAllowShortSignals = false; + } + + // + // XCHMAMX ... + if (xAU5MXCHMAMXEnableSignaller) + { + // + xAU5Provider.DisableXCHMAMXShorts(); + xAU5MXCHMAMXAllowShortSignals = false; + } + + // + // XCHMAMN ... + if (xAU5MXCHMAMNEnableSignaller) + { + // + xAU5Provider.DisableXCHMAMNShorts(); + xAU5MXCHMAMNAllowShortSignals = false; + } +} + +// +// Enable All Signallers Shorts ... +// Only if they are Configured as Enable at Settings ... +void XAU5EnableShortSignallers() +{ + // + // XTD ... + if (xAU5MXTDEnableSignaller) + { + // + xAU5MXTDAllowShortSignals = + xAU5XTDAllowShortSignals + ? true + : xAU5MXTDAllowShortSignals; + + // + if (xAU5MXTDAllowShortSignals) + { + xAU5Provider.EnableXTDShorts(); + } + } + + // + // XTAM ... + if (xAU5MXTAMEnableSignaller) + { + // + xAU5MXTAMAllowShortSignals = + xAU5XTAMAllowShortSignals + ? true + : xAU5MXTAMAllowShortSignals; + + // + if (xAU5MXTAMAllowShortSignals) + { + xAU5Provider.EnableXTAMShorts(); + } + } + + // + // XSI ... + if (xAU5MXSIEnableSignaller) + { + // + xAU5MXSIAllowShortSignals = + xAU5XSIAllowShortSignals + ? true + : xAU5MXSIAllowShortSignals; + + // + if (xAU5MXSIAllowShortSignals) + { + xAU5Provider.EnableXSIShorts(); + } + } + + // + // XSTFI ... + if (xAU5MXSTFIEnableSignaller) + { + // + xAU5MXSTFIAllowShortSignals = + xAU5XSTFIAllowShortSignals + ? true + : xAU5MXSTFIAllowShortSignals; + + // + if (xAU5MXSTFIAllowShortSignals) + { + xAU5Provider.EnableXSTFIShorts(); + } + } + + // + // XOBDLH ... + if (xAU5MXOBDLHEnableSignaller) + { + // + xAU5MXOBDLHAllowShortSignals = + xAU5XOBDLHAllowShortSignals + ? true + : xAU5MXOBDLHAllowShortSignals; + + // + if (xAU5MXOBDLHAllowShortSignals) + { + xAU5Provider.EnableXOBDLHShorts(); + } + } + + // + // XCHMACC ... + if (xAU5MXCHMACCEnableSignaller) + { + // + xAU5MXCHMACCAllowShortSignals = + xAU5XCHMACCAllowShortSignals + ? true + : xAU5MXCHMACCAllowShortSignals; + + // + if (xAU5MXCHMACCAllowShortSignals) + { + xAU5Provider.EnableXCHMACCShorts(); + } + } + + // + // XCHMAMX ... + if (xAU5MXCHMAMXEnableSignaller) + { + // + xAU5MXCHMAMXAllowShortSignals = + xAU5XCHMAMXAllowShortSignals + ? true + : xAU5MXCHMAMXAllowShortSignals; + + // + if (xAU5MXCHMAMXAllowShortSignals) + { + xAU5Provider.EnableXCHMAMXShorts(); + } + } + + // + // XCHMAMN ... + if (xAU5MXCHMAMNEnableSignaller) + { + // + xAU5MXCHMAMNAllowShortSignals = + xAU5XCHMAMNAllowShortSignals + ? true + : xAU5MXCHMAMNAllowShortSignals; + + // + if (xAU5MXCHMAMNAllowShortSignals) + { + xAU5Provider.EnableXCHMAMNShorts(); + } + } +} + +// +// XTD Long Signal Checking ... +bool XAU5XTDHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTDEnableSignaller || + !xAU5MXTDAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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.isXCHMAMCVale && + mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + (mConditions.isXTDSignalOverBear || + mConditions.isXTDSignalCrossedOverBear)) + // + || + // + (mConditions.isXTMBullish && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXLHHHDecreased && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (( + // + (mConditions.isXAMAStartBullish && + mConditions.isXTDSignalCrossedOverBear) || + (mConditions.isXAMANeutural && + mConditions.isXAMAEndBullish) + // + ) && + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXLHLLDecreased && + (mConditions.isXTDSignalOverBear || + mConditions.isXTDSignalCrossedOverBear)) + // + || + // + (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 + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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.isXCHMALCPeak && + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMAEndBullish) + // + || + // + (mConditions.isXTSCurrentMax && + (mConditions.isXCHMALCTrendsUp || + mConditions.isXCHMALCTrendsDown) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXAMABullish && + mConditions.isXTDBearishVale) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTDBearishVale && + mConditions.isXLHLLIncreased) + // + || + // + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCVale && + ( + // + (mConditions.isXTMBullish && + mConditions.isXCHMAMCVale && + mConditions.isXTDBearishVale && + mConditions.isXAMAStartBullish) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + (mConditions.isXAMAVale && + mConditions.isXTMNeutural && + mConditions.isXTDBearishVale && + mConditions.isXAMAStartBearish) + // + || + // + (mConditions.isXCHLHMCLCLLSame && + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBearish && + mConditions.isXTDBearishVale && + mConditions.isXLHLLIncreased) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCVale || + mConditions.isXLHLLDecreased) && + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXLHLLIncreased && + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ( + // + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) && + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMANeutural && + mConditions.isXCHLHMCLCHHSame && + (mConditions.isXTDSignalOverBear || + mConditions.isXTDSignalCrossedOverBear)) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCVale && + (mConditions.isXCHMAMCPeak + // + || + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDBearishVale) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTSCurrentMax && + mConditions.isXLHLLIncreased && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + (mConditions.isXTDSignalOverBear || + mConditions.isXTDSignalCrossedOverBear)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCTrendsDown || + mConditions.isXCHMALCTrendsUp) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXAMAEndBullish && + mConditions.isXCHLHSCMCHHSame) || + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + ((mConditions.isXTSCurrentMax && + mConditions.isXTDSignalCrossedOverBear) && + ( + // + (mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXFICrossedOverZero) + // + || + // + (mConditions.isXCHLHSameHHs && + mConditions.isXLHHighAttachedHH) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCTrendsDown && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXLHLLDecreased && + mConditions.isXCHLHSCMCHHSame && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXLHHighAttachedHH && + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow))) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTSAllSame && + mConditions.isXCHLHSameHHs && + mConditions.isXLHHighAttachedHH && + mConditions.isXRSICrossedOverLongExit) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHSCMCLLSame) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXLHHighAttachedHH && + ( + // + (mConditions.isXCHLHSCMCHHSame && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTSAllSame && + mConditions.isXCHLHSameHHs && + mConditions.isXRSICrossedOverLongExit) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHLHSameLLs && + mConditions.isXTDSignalCrossedOverBear) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 XAU5XTDHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTDEnableSignaller || + !xAU5MXTDAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XTAM Long Signal Checking ... +bool XAU5XTAMHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTAMEnableSignaller || + !xAU5MXTAMAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTDBearishVale && + mConditions.isXLHLLIncreased) + // + || + // + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMAMCVale || + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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.isXTMNeutural && + mConditions.isXAMANeutural && + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXCHMAMCVale && + (mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow))) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXTMNeutural && + mConditions.isXTMEndBearish && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBearish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalUnderBear && + mConditions.isXCHLHMCLCLLSame && + mConditions.isXRSICrossedUnderShortExit) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTDBearishVale && + mConditions.isXLHLLIncreased && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + ((mConditions.isXTMVale || + mConditions.isXTMNeutural || + mConditions.isXTMEndBearish) && + (mConditions.isXAMAVale || + mConditions.isXAMANeutural || + mConditions.isXAMAEndBearish) && + mConditions.isXCHMASCVale && + mConditions.isXCHMALCPeak && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXCHLHSameHHs && + mConditions.isXTSCurrentMax && + mConditions.isXTDBearishVale && + mConditions.isXLHHighAttachedHH) + // + || + // + (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 + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XTAM Short Signal Checking ... +bool XAU5XTAMHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXTAMEnableSignaller || + !xAU5MXTAMAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSI Long Signal Checking ... +bool XAU5XSIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSIEnableSignaller || + !xAU5MXSIAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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.isXTMVale && + mConditions.isXTMBearish && + mConditions.isXAMABullish && + mConditions.isXTSCurrentMax && + mConditions.isXLHLLDecreased && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCVale && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTSCurrentUnderFarest && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCPeak) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMANeutural && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame) + // + || + // + ( + mConditions.isXCHMASCVale && + ( + // + (mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale) + // + || + // + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) + // + ) + // + ) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + || + // + (mConditions.isXCHMASCVale && + mConditions.isXCHMAMCTrendsDown && + mConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXLHHighAttachedHH && + mConditions.isXFICrossedOverZero && + (mConditions.isXCHMALCPeak && + mConditions.isXCHMALCTrendsDown && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSI Short Signal Checking ... +bool XAU5XSIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSIEnableSignaller || + !xAU5MXSIAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSTFI Long Signal Checking ... +bool XAU5XSTFIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSTFIEnableSignaller || + !xAU5MXSTFIAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.XSTFIHasLongConditions() + // + && + // + // 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.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + (mConditions.isXCHMASCVale && + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMEndBullish && + mConditions.isXTMNeutural && + mConditions.isXAMAEndBullish && + mConditions.isXAMANeutural) + // + || + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHMALCFastUnderSlow && + mConditions.isXRSICrossedOverLongExit) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTMStartBearish && + mConditions.isXAMAStartBearish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalCrossedUnderBear && + mConditions.isXLHHHIncreased && + mConditions.isXLHHHSameInLength && + mConditions.isXCHLHSCMCHHSame && + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXLHHHIncreased && + (mConditions.isXCHMALCPeak && + mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXAMAEndBearish && + mConditions.isXTMStartBullish && + (mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBullish && + mConditions.isXAMANeutural && + mConditions.isXAMAEndBullish) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTMStartBullish && + mConditions.isXAMAStartBullish) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXAMANeutural && + mConditions.isXCHLHMCLCHHSame && + mConditions.isXCHLHMCLCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXFICrossedUnderZero) + // + || + // + (mConditions.isXLHHHDecreased && + mConditions.isXLHLLDecreased && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXCHLHSameHHs && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXLHHHIncreased) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + ( + // + (mConditions.isXLHHHDecreased && + mConditions.isXTSCurrentUnderMediest) + // + || + // + (mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + (mConditions.isXCHMAMCPeak && + mConditions.isXCHMAMCTrendsUp && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXLHHighAttachedHH) + // + || + // + (mConditions.isXOBDSwingHigh && + mConditions.isXTMEndBullish && + mConditions.isXAMABullish && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear && + mConditions.isXCHLHSCMCHHSame && + mConditions.isXCHLHMCLCLLSame && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXLHHHIncreased && + mConditions.isXCHLHSCMCHHSame && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSTFI Short Signal Checking ... +bool XAU5XSTFIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXSTFIEnableSignaller || + !xAU5MXSTFIAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.XSTFIHasShortConditions() + // + && + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XOBDLH Long Signal Checking ... +bool XAU5XOBDLHHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXOBDLHEnableSignaller || + !xAU5MXOBDLHAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + XMarketConditions xMConditions2 = xAU5Provider.GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHLHSCMCLLSame) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Not Same LL or HH in Lenght ... + ((!mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTMVale && + mConditions.isXTMBearish && + mConditions.isXAMAVale && + mConditions.isXAMABearish && + mConditions.isXLHHHDecreased) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHMALCTrendsDown && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXCHLHSameLLs && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXTMVale && + mConditions.isXAMAVale && + mConditions.isXTMBearish && + mConditions.isXAMABearish && + mConditions.isXCHMASCVale && + mConditions.isXCHMAMCVale && + mConditions.isXCHMALCVale && + mConditions.isXFIUnderZero && + mConditions.isXCHLHSameLLs && + mConditions.isXTDBullUnderBear && + mConditions.isXTDSignalUnderBear) + // + ) + // + ) + // + ) + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XOBDLH Short Signal Checking ... +bool XAU5XOBDLHHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXOBDLHEnableSignaller || + !xAU5MXOBDLHAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMACC Long Signal Checking ... +bool XAU5XCHMACCHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACCEnableSignaller || + !xAU5MXCHMACCAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXAMANeutural && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // 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.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTSCurrentMax && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXAMAStartBullish && + mConditions.isXTDSignalUnderBear && + mConditions.isXFICrossedOverZero && + mConditions.isXTDBullCrossedOverBear) + // + || + // + (mConditions.isXCHLHMCLCHHSame && + (mConditions.isXCHMAMCTrendsDown && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCTrendsUp || + mConditions.isXCHMALCTrendsDown) && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTSAllSame && + mConditions.isXTSCurrentMin && + mConditions.isXTSCurrentMax) + // + || + // + (mConditions.isXCHMALCPeak && + mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXLHLLIncreased && + mConditions.isXCHLHMCLCHHSame && + (mConditions.isXCHMASCTrendsDown && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow))) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMACC Short Signal Checking ... +bool XAU5XCHMACCHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMACCEnableSignaller || + !xAU5MXCHMACCAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMN Long Signal Checking ... +bool XAU5XCHMAMNHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMAMNEnableSignaller || + !xAU5MXCHMAMNAllowLongSignals) + { + 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 = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMStartBullish && + mConditions.isXAMAEndBearish && + mConditions.isXLHLLIncreased && + (mConditions.isXCHMALCVale && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXCHMALCVale) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + ( + // + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow) + // + || + (mConditions.isXCHMAMCVale && + mConditions.isXTMEndBullish && + mConditions.isXAMAEndBullish && + mConditions.isXCHLHMCLCLLSame) + // + ) + // + ) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXLHLLIncreased && + mConditions.isXAMAStartBullish && + mConditions.isXTDSignalUnderBear && + mConditions.isXTDBullCrossedOverBear && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXAMANeutural && + mConditions.isXTMStartBullish) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXLHLLIncreased && + mConditions.isXAMAStartBullish && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMBullish && + mConditions.isXAMABullish && + mConditions.isXTDSignalVale && + mConditions.isXTDBullishVale && + mConditions.isXTDBullOverBear && + mConditions.isXTDSignalOverBear) + // + || + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXTSCurrentMax && + mConditions.isXTMStartBullish && + mConditions.isXFICrossedOverZero) + // + || + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXCHLHSCMCHHSame && + mConditions.isXTDBullUnderBear && + mConditions.isXLHHighAttachedHH && + mConditions.isXTDSignalUnderBear) + // + || + // + ((mConditions.isXCHMASCFastUnderSlow || + mConditions.isXCHMASCFastCrossedUnderSlow) && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMASCPeak && + (mConditions.isXCHMASCFastOverSlow || + mConditions.isXCHMASCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHLHMCLCLLSame && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + ((mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow) && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + || + // + (mConditions.isXCHMALCVale && + mConditions.isXCHMALCTrendsUp && + (mConditions.isXCHMALCFastUnderSlow || + mConditions.isXCHMALCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMN Short Signal Checking ... +bool XAU5XCHMAMNHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMAMNEnableSignaller || + !xAU5MXCHMAMNAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMX Long Signal Checking ... +bool XAU5XCHMAMXHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMAMXEnableSignaller || + !xAU5MXCHMAMXAllowLongSignals) + { + 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 = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + (mConditions.isXTMNeutural && + mConditions.isXTSCurrentMin && + mConditions.isXAMAEndBearish && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + || + // + (mConditions.isXTMNeutural && + mConditions.isXTMEndBullish && + (mConditions.isXTSCurrentUnderNearest || + mConditions.isXTSCurrentCrossedUnderNearest) && + (mConditions.isXCHMAMCFastUnderSlow || + mConditions.isXCHMAMCFastCrossedUnderSlow)) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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.isXTMNeutural && + mConditions.isXAMANeutural && + mConditions.isXTDBearishVale && + mConditions.isXCHLHMCLCHHSame) + // + || + // + ((mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) || + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow))) + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + (mConditions.isXTSCurrentMax && + mConditions.isXCHLHSCMCLLSame && + mConditions.isXCHLHMCLCHHSame) + // + || + // + (mConditions.isXCHMAMCPeak && + (mConditions.isXCHMAMCFastOverSlow || + mConditions.isXCHMAMCFastCrossedOverSlow)) + // + || + // + (mConditions.isXCHMALCPeak && + (mConditions.isXCHMALCFastOverSlow || + mConditions.isXCHMALCFastCrossedOverSlow)) + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMX Short Signal Checking ... +bool XAU5XCHMAMXHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xAU5MXCHMAMXEnableSignaller || + !xAU5MXCHMAMXAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xAU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xAU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// END Signal Providers ... +// diff --git a/Projects/XAU5/Providers/x-saherelm.xau5.provider.inputs.lib.mq5 b/Projects/XAU5/Providers/x-saherelm.xau5.provider.inputs.lib.mq5 new file mode 100644 index 00000000..58fdad05 --- /dev/null +++ b/Projects/XAU5/Providers/x-saherelm.xau5.provider.inputs.lib.mq5 @@ -0,0 +1,280 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAU5 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 "XAU5 Provider"; + +// +// Commonly Used Configurations ... +input group "XAU5 Common"; +// +// Provider ... +input bool xAU5EnableProvider = true; // Enable Provider +input int xAU5NumberOfItemsPerTick = 30; // Number Of items Readed In Each Tick +// +// Alerts ... +input bool xAU5EnableAlerts = true; // Enable Events Alert +input bool xAU5EnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xAU5EnableDailyAlerts = false; // Send Alert on each new Day +input bool xAU5EnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xAU5EnableMonthlyAlerts = true; // Send Alert on each new Month +// +// Reports ... +input bool xAU5EnableDailyReports = false; // Send Report on each new Day +input bool xAU5EnableWeeklyReports = false; // Send Report on each new Week +input bool xAU5EnableMonthlyReports = true; // Send Report on each new Month + +// +// Trader and Expert Specific Configurations ... +input group "XAU5 Trader"; +input int xAU5MagicNumber = 16940561; // Trader MagicNumber +input int xAU5Slippage = 10; // Trader Slippage + +// +// Trades Management Configurations ... +input group "XAU5 Trade Management"; +input bool xAU5AllowLongTrades = true; // Allow Long Trades +input bool xAU5AllowShortTrades = true; // Allow Short Trades + +// +// Risk Management Configurations ... +input group "XAU5 Risk Management"; +// +input bool xAU5UseVirtualTPSl = true; // Use Virtual TP SL +// +// Trade Count ... +input int xAU5MaxAllowedTrades = 10; // Max Allowed Trades at Same Time +input ENUM_X_CROSS_SIGNAL_METHOD xAU5CrossSignalsMethod = X_CROSS_SIGNAL_REGULAR; // Handle Cross Signals Method +// +// Max Allowed Trade Age ... +input int xAU5MaxAllowedTradeAge = 2000; // Detect Long Time Trades +input ENUM_X_GUARD_ACTIONS xAU5OldTradesAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1; // What to do with Old Trades +// +// Trade Volume Specific Configurations ... +input double xAU5StaticVolumeFactor = 0.0002; // Static Volume baesd on Balance +input ENUM_STATIC_VOLUME_METHODS xAU5StaticVolumeMethod = X_STATIC_VOLUME_BASED_ON_BALANCE; // How to Calculate Static Volume +input double xAU5VolumeMultiplier = 0; // Volume Increase Multiplier +input double xAU5ApplyVolumeMultiplierFactor = 0; // Apply Volume Multiplier Rate based on Balance +input double xAU5MaxSupportedVolumePerTradeFactor = 0; // Max Supported Volume Per Trade Factor based on Balance +input double xAU5IncreasedMaxSupportedVolumeRate = 0; // Increase Max Supported Volume based on Balance +// +// Trade Profits ... +input double xAU5MinRewardInPips = 150; // Minimum Reward Per Trade in Pips +input double xAU5RiskFreeStepInPips = 60; // Make Trades Risk Free Steps in Pips +input double xAU5RiskFreeRate = 0.6; // Volume Multiplier for Risk Free Trades +// +// Guard Riskable Money and Profits ... +input double xAU5CriticalDrawDownFactor = 0.43; // Critical Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xAU5CriticalGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5; // Specify Guard Action on Critical Drawdown +input double xAU5MaxAllowedDrawDownFactor = 0.45; // Max Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xAU5MaxAllowedGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10; // Specify Guard Action on Max Allowed Drawdown +input int xAU5GuardStopoutFiredAfterTouches = 5; // Guard Stopout all Trades if Max Allowed Drawdown touched + +// +// Account Conditions for Trading ... +input double xAU5BalanceFactorForOpenTrades = 0.5; // Minimum Balance for Open Trades +input double xAU5FreeMarginFactorForOpenTrades = 0.8; // Minimum Free Margin for Open Trades + +// +// Validate Inputs before Initialization ... +bool XAU5ValidateInputs() +{ + // + bool result = false; + + // + // Implement Other Verifications ... + + // + // Check Trading Availability ... + bool isTradeAvailable = xAU5AllowLongTrades || xAU5AllowShortTrades; + if (!isTradeAvailable) + { + LogMessage("XAU5 => Warning: Trading disabled ..."); + } + + // + // Chekc Number of reading items per tick ... + result = xAU5NumberOfItemsPerTick >= 5; + if (!result) + { + // + LogMessage("XAU5 invalid Number of items Reading Per Tick ..."); + + // + return result; + } + + // + // Check Max Allowed Trades Count ... + result = isTradeAvailable && xAU5MaxAllowedTrades >= 1; + if (!result) + { + // + LogMessage("XAU5 Number of Trades not valid ..."); + + // + return result; + } + + // + // Check Free Margin ... + result = + isTradeAvailable && + xAU5FreeMarginFactorForOpenTrades > 0 && + xAU5FreeMarginFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XAU5 Invalid Free Margin ..."); + + // + return result; + } + + // + // Check min Balance for Open Trades ... + result = + isTradeAvailable && + xAU5BalanceFactorForOpenTrades > 0 && + xAU5BalanceFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XAU5 Invalid Min Balance for Open Trades ..."); + + // + return result; + } + + // + // Check Min Reward Per Trade ... + result = xAU5MinRewardInPips > 0; + if (!result) + { + // + LogMessage("XAU5 Invalid Min Reward Per Trade ..."); + + // + return result; + } + + // + // Check Trades Volume ... + result = xAU5StaticVolumeFactor > 0; + if (!result) + { + // + LogMessage("XAU5 Invalid Static Volume ..."); + + // + return result; + } + + // + // Check Volume Multiplier ... + result = xAU5VolumeMultiplier >= 0; + if (!result) + { + // + LogMessage("XAU5 Invalid Volume Multiplier ..."); + + // + return result; + } + + // + result = + xAU5CriticalDrawDownFactor == 0 || (xAU5CriticalDrawDownFactor > 0 && + xAU5CriticalDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XAU5 Invalid Critical DrawDown Factor ..."); + + // + return result; + } + + // + result = + xAU5MaxAllowedDrawDownFactor == 0 || (xAU5MaxAllowedDrawDownFactor > 0 && + xAU5MaxAllowedDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XAU5 Invalid Max Allowed DrawDown Factor ..."); + + // + return result; + } + + // + // Check Guard Actions ... + // + result = + xAU5CriticalDrawDownFactor > 0 && + xAU5CriticalDrawDownFactor < 1 && + xAU5MaxAllowedDrawDownFactor > 0 && + xAU5MaxAllowedDrawDownFactor < 1; + if (!result) + { + // + LogMessage("XAU5 For Critical Drawdown, you have to Specify Max Drawdown also ..."); + + // + return result; + } + + // + result = xAU5CriticalDrawDownFactor > 0 && xAU5CriticalDrawDownFactor < xAU5MaxAllowedDrawDownFactor; + if (!result) + { + // + LogMessage("XAU5 Critical Drawdown must Smaller than Max Drawdown ..."); + + // + return result; + } + + // + if (xAU5CriticalDrawDownFactor > 0 && xAU5CriticalGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XAU5 IMPORTANT you Specified Critical Drawdown, but there is no any Guard Action ..."); + } + + // + if (xAU5MaxAllowedDrawDownFactor > 0 && xAU5MaxAllowedGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XAU5 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/Projects/XAU5/Providers/x-saherelm.xau5.provider.lib.mq5 b/Projects/XAU5/Providers/x-saherelm.xau5.provider.lib.mq5 new file mode 100644 index 00000000..fc252719 --- /dev/null +++ b/Projects/XAU5/Providers/x-saherelm.xau5.provider.lib.mq5 @@ -0,0 +1,1370 @@ +//////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAU5 Signal Provider Library +// -------------------------------------------------------- +// Name: XAU5SignalProvider +// Description: XAU5 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 XAU5ProviderName "XAU5" + +// +// START Inputs ... +// + +#include "x-saherelm.xau5.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 *xAU5Guard; +XCTrade *xAU5Trader; +XCReporter *xAU5Reporter; +XCCollector *xAU5Collector; +XCAccountInfo *xAU5AccountInfo; +XCVolumeManager *xAU5VolumeManager; + +// +#include "x-saherelm.xau5.provider.indicators.lib.mq5" + +// +// Controlling Variables ... +bool xAU5MEnableProvider = false; +bool xAU5MAllowLongTrades = false; +bool xAU5MAllowShortTrades = false; + +// +double xAU5Deposit = 0; +double xAU5Balance = 0; +double xAU5MinReward = 0; +double xAU5FreeMargin = 0; +double xAU5BalanceForOpenTrades = 0; +double xAU5FreeMarginForOpenTrades = 0; + +// +// Guard ... +double xAU5CriticalDrawDown = 0; +double xAU5MaxAllowedDrawDown = 0; + +// +double xAU5MaxDrawUp = 0; +double xAU5MaxDrawDown = 0; + +// +int NOT_ENOUGH_MONEY_ERROR = 4756; +const string XAU5_SUPPORT_ID = "SP"; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// Initial Library if required ... +bool XAU5InitSignalProviderLibrary() +{ + // + bool result = false; + + // + if (!xAU5EnableProvider) + { + return result; + } + + // + // Controlling Variables ... + xAU5MEnableProvider = xAU5EnableProvider; + xAU5MAllowLongTrades = xAU5AllowLongTrades; + xAU5MAllowShortTrades = xAU5AllowShortTrades; + + // + // Validate Inputs ... + result = XAU5ValidateInputs(); + if (!result) + { + return result; + } + + // + // Init Indicators ... + result = XAU5InitIndicators(); + if (!result) + { + return result; + } + + // + xAU5Reporter = new XCReporter(); + xAU5Collector = new XCCollector(); + xAU5AccountInfo = new XCAccountInfo(); + + // + // Calculate Account Deposit ... + xAU5Deposit = xAU5AccountInfo.GetInitialBalance(); + + // + // Prepare Min Reward ... + if (xAU5MinRewardInPips > 0) + { + xAU5MinReward = PipsToPrice(xAU5MinRewardInPips); + } + + // + // Calculate Min Balance for Trades ... + if (xAU5BalanceFactorForOpenTrades > 0) + { + xAU5BalanceForOpenTrades = xAU5BalanceFactorForOpenTrades * xAU5Deposit; + } + + // + // Claculate Min Free Marging for Trades ... + if (xAU5FreeMarginFactorForOpenTrades > 0) + { + xAU5FreeMarginForOpenTrades = xAU5FreeMarginFactorForOpenTrades * xAU5Deposit; + } + + // + // Calculate Init Time Critical DrawDown Value ... + if (xAU5CriticalDrawDownFactor > 0) + { + xAU5CriticalDrawDown = xAU5CriticalDrawDownFactor * xAU5Deposit; + } + + // + // Calculate Init Time Max Allowed DrawDown Value ... + if (xAU5MaxAllowedDrawDownFactor > 0) + { + xAU5MaxAllowedDrawDown = xAU5MaxAllowedDrawDownFactor * xAU5Deposit; + } + + // + // Instant Volume Manager ... + xAU5VolumeManager = new XCVolumeManager( + xAU5StaticVolumeFactor, + xAU5StaticVolumeMethod, + xAU5VolumeMultiplier, + xAU5ApplyVolumeMultiplierFactor, + xAU5MaxSupportedVolumePerTradeFactor, + xAU5IncreasedMaxSupportedVolumeRate); + + // + // Make XCTrader instance ... + xAU5Trader = new XCTrade( + XAU5ProviderName, + _Symbol, + xAU5Slippage, + xAU5MagicNumber, + xAU5UseVirtualTPSl, + xAU5MaxAllowedTrades, + xAU5FreeMarginForOpenTrades, + xAU5BalanceForOpenTrades); + + // + // Instantiate Account Guard ... + xAU5Guard = new XCGuard( + // + // Old Trades ... + xAU5MaxAllowedTradeAge, + xAU5OldTradesAction, + // + // Critical DrawDown ... + xAU5CriticalDrawDownFactor, + xAU5CriticalGuardAction, + // + // Max Allowed DrawDown ... + xAU5MaxAllowedDrawDownFactor, + xAU5MaxAllowedGuardAction, + xAU5GuardStopoutFiredAfterTouches, + // + // xAU5GuardSupportMethod + X_SUPPORT_DO_NOTHING + // + ); + + // + // Reset Calculations Buffers and Variables ... + XAU5ResetCollectors(); + + // + XAU5UpdateReports(); + + // + result = true; + + // + // Logging State ... + XAU5IssueInitializationSucceedAlert(); + + // + return result; +} + +// +// DeInitial Library if required ... +void XAU5DeinitSignalProviderLibrary(const int reason) +{ + // + // Release Handlers ... + XAU5ReleaseIndicators(); + + // + // Logging State ... + XAU5IssueDeinitializationSucceedAlert(); +} + +// +// this is a Globally Function which do all of +// checkings and positions handling ... +void XAU5SignalProviderHandleTick() +{ + // + // Check Provider is Enable or Not ... + if (!xAU5MEnableProvider) + { + return; + } + + // + XAU5SignalProviderDoControlState(); + + // + // Reading Indicator Buffers ... + XAU5HandleReadingBuffers(); + if (xAU5CalculatedBars < xAU5MaxLengthOfInputs) + { + return; + } + + // + // Handle Open Trades ... + XAU5HandleOpenTrades(); + + // + // Handle Close Trades ... + XAU5HandleCloseTrades(); + + // + // DrawDown and DrawUp ... + XAU5HandleCalculateDrawDownUp(); +} + +// +// Do Control Checks here ... +void XAU5SignalProviderDoControlState() +{ + // + // Update account Balance ... + xAU5Balance = xAU5AccountInfo.GetBalance(); + xAU5FreeMargin = xAU5AccountInfo.GetFreeMargin(); + + // + // Check Provider is Enable or Not ... + if (!xAU5MEnableProvider) + { + return; + } + + // + // Protect Account by Guarding Maximum Drawdown ... + // TODO: add Guard Result here ... + string guardMessage = ""; + XGuardHandlerResult guardHandlerResult; + bool isGuarded = xAU5Guard.Guard( + guardHandlerResult, + guardMessage, + xAU5Trader, + _Period); + if (isGuarded) + { + // + // Criticals ... + int criticalsCount = ArraySize(guardHandlerResult.criticals); + if (criticalsCount > 0) + { + // + for (int i = 0; i < criticalsCount; i++) + { + // + XSignal iSignal = guardHandlerResult.criticals[i]; + + // + XAU5OnGuard( + 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]; + + // + XAU5OnGuard( + 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]; + + // + XAU5OnGuard( + iSignal, + X_GUARDED_OLD, + guardMessage); + } + } + } + + // + // Signal Protection ... + XSignal protectSupports[]; + bool isSupported = xAU5Guard.ProtectSignals( + protectSupports, + xAU5Trader); + if (isSupported) + { + // + LogMessage("Guard do Support Trdae ..."); + } + + // + // Handling Signals ... + XTraderHandlerResult signalHandlerResult; + xAU5Trader.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]; + XAU5OnSL(iSignal); + } + } + + // + // Handle TP Reports ... + int handledTPsCount = ArraySize(signalHandlerResult.tp); + if (handledTPsCount > 0) + { + // + for (int i = 0; i < handledTPsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.tp[i]; + XAU5OnTP(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]; + XAU5OnRF(iSignal); + } + } +} + +// +// Handle Trades when OnTrade Event Hnadler Calls ... +void XAU5SignalProviderHandleTrade() +{ + // + // Check Provider Enabled ... + if (!xAU5MEnableProvider) + { + return; + } + + // + // Handle OnTrade Event ... + XOnTradeHandlerResult result = {}; + xAU5Trader.HandleOnTradeEvent( + result); + + // + // Detected TP or SL ... + if (result.hasNewDeal) + { + // + XDeal last = xAU5Trader.GetLastDeal(); + + // + if (last.reason == DEAL_REASON_SL) + { + xAU5Reporter.AddTradeSLInReports(); + } + else if (last.reason == DEAL_REASON_TP) + { + xAU5Reporter.AddTradeTPInReports(); + } + } +} + +// +// Handle Open Trades ... +void XAU5HandleOpenTrades() +{ + // + // Check Can Trade ... + bool canTrade = xAU5MAllowLongTrades || xAU5MAllowShortTrades; + if (!canTrade) + { + return; + } + + // + // Check Max Open Trades ... + int openSignals = xAU5Trader.Count(); + bool canOpenPositions = openSignals < xAU5MaxAllowedTrades; + if (!canOpenPositions) + { + return; + } + + // + // Check Signals Exists ... + XProvidedSignal longSignalInfo; + XProvidedSignal shortSignalInfo; + bool hasLongSignal = XAU5CanOpenLongTrade(longSignalInfo); + bool hasShortSignal = XAU5CanOpenShortTrade(shortSignalInfo); + if (!hasLongSignal && !hasShortSignal) + { + return; + } + + // + // Update Reports ... + XAU5UpdateReports(); + + // + // Open Long Trades ... + if ( + // + hasLongSignal && + xAU5MAllowLongTrades) + { + // + bool isOpened = XAU5OpenLongPosition(longSignalInfo); + } + + // + // Open Short Trades ... + if ( + // + hasShortSignal && + xAU5MAllowShortTrades) + { + // + bool isOpened = XAU5OpenShortPosition(shortSignalInfo); + } +} + +// +// Handle Close Trades ... +void XAU5HandleCloseTrades() +{ + // + // Force Close Long Trades ... + bool isClosedLongTrades = false; + bool canCloseLongTrades = XAU5CanCloseLongTrade(); + if (xAU5MAllowLongTrades && canCloseLongTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; + + // + XSignal closed[]; + xAU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedLongTrades = closedTradesCount > 0; + if (isClosedLongTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XAU5OnFC(iSignal); + } + } + } + + // + // Force Close Short Trades ... + bool isClosedShortTrades = false; + bool canCloseShortTrades = XAU5CanCloseShortTrade(); + if (xAU5MAllowShortTrades && canCloseShortTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; + + // + XSignal closed[]; + xAU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedShortTrades = closedTradesCount > 0; + if (isClosedShortTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XAU5OnFC(iSignal); + } + } + } +} + +// +// Open Long Position ... +bool XAU5OpenLongPosition( + 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 + xAU5MinReward; + double riskFreeRate = xAU5RiskFreeRate; + double riskFreeStep = xAU5RiskFreeStepInPips; + double volume = XAU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xAU5Trader.GenerateSignal( + X_SIGNAL_LONG, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xAU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xAU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XAU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xAU5CrossSignalsMethod != X_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xAU5Trader.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 = xAU5Trader.GetSignal(signal.ticket); + + // + XAU5OnSignal( + tSignal, + providers); + } + else + { + XAU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Open Short Position ... +bool XAU5OpenShortPosition( + 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 - xAU5MinReward; + double riskFreeRate = xAU5RiskFreeRate; + double riskFreeStep = xAU5RiskFreeStepInPips; + double volume = XAU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xAU5Trader.GenerateSignal( + X_SIGNAL_SHORT, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xAU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xAU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XAU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xAU5CrossSignalsMethod != X_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xAU5Trader.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 = xAU5Trader.GetSignal(signal.ticket); + + // + XAU5OnSignal( + tSignal, + providers); + } + else + { + XAU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Apply Cross Signal Actions ... +void XAU5HnadleCrossSignal( + XSignal &signal // Specified Signal ... +) +{ + // + // Check Cross Signal Handling Enabled ... + if (xAU5CrossSignalsMethod == X_CROSS_SIGNAL_DO_NOTHING) + { + return; + } + + // + // First We have to Change Cross Signals Comment ... + string comment = xAU5Trader.GenerateSignalComment( + signal, + true); + + // + signal.comment = comment; + + // + // If Every thing is Regular, prevent any changes here ... + if (xAU5CrossSignalsMethod == X_CROSS_SIGNAL_REGULAR) + { + return; + } + + // + // Retrieve Max in Drawdown Signal ... + XSignal maxInDDSignal = xAU5Trader.GetMaxInDrawdownSignal(); + + // + // Validate Signal ... + bool isValidSignal = + maxInDDSignal.ticket > 0 && + maxInDDSignal.symbol == signal.symbol && + IsValid(maxInDDSignal, xAU5MagicNumber); + if (!isValidSignal) + { + return; + } + + // + double volume = signal.volume; + bool isDirectional = maxInDDSignal.type == signal.type; + + // + // Prevent any changes on Regular Conditions ... + bool isRegular = + isDirectional + ? ( + // + xAU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_REGULAR || + xAU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT + // + ) + : ( + // + xAU5CrossSignalsMethod == X_CROSS_SIGNAL_INDIRECTION_REGULAR || + xAU5CrossSignalsMethod == 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 XAU5HandleCalculateDrawDownUp() +{ + // + XSignal signals[]; + xAU5Trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + double profit = 0; + double volume = 0; + XCollector collector = {}; + double maxAllowedVolume = xAU5VolumeManager.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) + { + // + xAU5MaxDrawDown = + xAU5MaxDrawDown == 0 || + xAU5MaxDrawDown > MathAbs(profit) + ? MathAbs(profit) + : xAU5MaxDrawDown; + + // + // Update Buffers ... + datetime time = iTime(_Symbol, _Period, 0); + + // + // Calculate Max Allowed Drawdown ... + // + collector.time = time; + collector.volume = volume; + collector.maxDrawDown = xAU5MaxDrawDown; + collector.maxAllowedVolume = maxAllowedVolume; + collector.minBalanceForOpenTrade = xAU5Trader.GetMinBalanceForOpenTrades(); + } + else + { + // + xAU5MaxDrawUp = + xAU5MaxDrawUp == 0 || + xAU5MaxDrawUp < profit + ? profit + : xAU5MaxDrawUp; + } + + // + // Update Collector ... + xAU5Collector.Add(collector); + + // + // Update Reports ... + xAU5Reporter.UpdateMaxDrawUpInReports(xAU5MaxDrawUp); + xAU5Reporter.UpdateMaxDrawDownInReports(xAU5MaxDrawDown); + xAU5Reporter.UpdateMaxSameTimeTradesInReports(signalsCount); +} + +// +// START Event Handlers ... +// + +// +// Runs When a Signal Successfully Executed ... +void XAU5OnSignal( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + // Issue Propper Alert ... + XAU5IssueSignalExecutionAlert( + signal, + providers); + + // + // Add Signal To Supports on Guard ... + xAU5Guard.AddSupport(signal); + + // + // Update Reports ... + xAU5Reporter.AddSignalToReports( + signal, + providers); +} + +// +// Runs when a Position Got Take Profit ... +void XAU5OnTP( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XAU5IssueTPAlert(signal); + + // + // Remove Signal From Guard Protector ... + xAU5Guard.Remove(signal.ticket); + xAU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xAU5Reporter.AddTradeTPInReports(); + XAU5UpdateReports(); +} + +// +// Runs when a Position Got Stop Loss ... +void XAU5OnSL( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XAU5IssueSLAlert(signal); + + // + // Remove Signal From Guard Protector ... + xAU5Guard.Remove(signal.ticket); + xAU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xAU5Reporter.AddTradeSLInReports(); + XAU5UpdateReports(); +} + +// +// Runs when a Position Risk Free ... +void XAU5OnRF( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XAU5IssueRFAlert(signal); + + // + // Remove Signal From Guard Protector ... + // since RiskFree Signals has SL ... + xAU5Guard.Remove(signal.ticket); + xAU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xAU5Reporter.AddTradeSLInReports(); + XAU5UpdateReports(); +} + +// +// Runs when a Position Force Closed ... +void XAU5OnFC( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XAU5IssueFCAlert(signal); + + // + // Remove Signal From Guard Protector ... + xAU5Guard.Remove(signal.ticket); + xAU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xAU5Reporter.AddTradeSLInReports(); + XAU5UpdateReports(); +} + +// +// Runs when a Position Guarded ... +void XAU5OnGuard( + 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); + + // + xAU5MEnableProvider = false; + } + + // + // Issue Propper Alert ... + XAU5IssueGuardAlert(signal, reason, isStopOut); + + // + // Update Reports ... + xAU5Reporter.AddTradeSLInReports(); + XAU5UpdateReports(); +} + +// +// END Event Handlers ... +// + +// +// END Provided Functions ... +// + +// +// START Private Functions ... +// + +// +// START Volume Baseed Functions ... +// + +// +// Calculating Volume for Tradings ... +double XAU5CalculateVolume( + 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 = xAU5Trader.Count(); + + // + double result = xAU5VolumeManager.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 XAU5UpdateReports() +{ + // + double staticVolume = xAU5VolumeManager.GetStaticVolume(); + string staticVolumeCalculationMethod = EnumToString(xAU5StaticVolumeMethod); + double maxAllowedVolume = xAU5VolumeManager.GetMaxAllowedVolume(); + double volumeIncreaseMultiplier = xAU5VolumeManager.GetVolumeMultiplier(); + double balanceGowingToApplyMultiplier = xAU5VolumeManager.GetIncreaseMultiplierBalance(); + + double balanceGrowingToIncreaseMaxAllowedVolume = xAU5VolumeManager.GetIncreaseMaxAllowedVolumeBalance(); + + // + // Update Reports Volume Info ... + xAU5Reporter.UpdateReportsVolumeInfo( + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Calculate Max Allowed Drawdown ... + double minBalanceForTradeBasedOnBalance = xAU5Trader.GetMinBalanceForOpenTrades(); + xAU5Reporter.UpdateMinBalanceForOpenTradesInReports(minBalanceForTradeBasedOnBalance); +} + +// +// Reset XAU5 Info Buffers ... +void XAU5ResetCollectors() +{ + // + // Reset Calculations Buffers and Variables ... + xAU5MaxDrawUp = 0; + xAU5MaxDrawDown = 0; + + // + xAU5Trader.Reset(); + xAU5Reporter.Reset(); + xAU5Collector.Reset(); + xAU5VolumeManager.ResetForceVolumeMultiplier(); +} + +// +// END Report/Collect and Guard Functions ... +// + +// +// START Alert Functions ... +// + +// +// Send Alert ... +void XAU5IssueAlert(string message) +{ + // + // Validate Args ... + if (StringLen(message) <= 0) + { + return; + } + + // + if (xAU5EnableAlerts) + { + SendAlert(message); + } + else + { + LogMessage(message); + } +} + +// +// Send Take Profit Alert on Specific Signal ... +void XAU5IssueTPAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xAU5Trader.GenerateSignalTPComment(signal); + + // + XAU5IssueAlert(message); +} + +// +// Send Stop Loss Alert on Specific Signal ... +void XAU5IssueSLAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xAU5Trader.GenerateSignalSLComment(signal); + + // + XAU5IssueAlert(message); +} + +// +// Send Force Close Alert on Specific Signal ... +void XAU5IssueFCAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xAU5Trader.GenerateSignalForceCloseComment(signal); + + // + XAU5IssueAlert(message); +} + +// +// Send Risk Free Alert on Specific Signal ... +void XAU5IssueRFAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xAU5Trader.GenerateSignalRFComment(signal, 0); + + // + XAU5IssueAlert(message); +} + +// +// Send Guard Alert on Specific Signal ... +void XAU5IssueGuardAlert( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason, // Specified Guard Reason + bool isStopOut = false // Specified StopOut Fired or not +) +{ + // + string message = ""; + + // + message = xAU5Guard.GenerateGuardedSignalComment( + signal, + reason); + + // + XAU5IssueAlert(message); +} + +// +// Send Initialization Succeed Alert ... +void XAU5IssueInitializationSucceedAlert() +{ + // + string message = "Initializion of (" + XAU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; + XAU5IssueAlert(message); +} + +// +// Send De Initialization Succeed Alert ... +void XAU5IssueDeinitializationSucceedAlert() +{ + // + string message = "De Initializion of (" + XAU5ProviderName + " Provider" + ") Succeeded ..."; + XAU5IssueAlert(message); +} + +// +// Send Signal Successfully Execution Alert ... +void XAU5IssueSignalExecutionAlert( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + string message = xAU5Trader.ToString(signal); + + // + string providersMsg = ToString(providers); + if (StringLen(providersMsg) > 0) + { + message += ", Providers: " + providersMsg; + } + + // + XAU5IssueAlert(message); +} + +// +// Send Signal Execution Alert ... +void XAU5IssueSignalExecutionError(int error) +{ + // + string message = GetSignalExecutionError(error); + if (StringLen(message) == 0) + { + return; + } + + // + XAU5IssueAlert(message); +} + +// +// END Alert Functions ... +// + +// +// END Private Functions ... +// diff --git a/Projects/XAU5/Settings/.gitkeep b/Projects/XAU5/Settings/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XAU5/Templates/.gitkeep b/Projects/XAU5/Templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Classes/.gitkeep b/Projects/XBTU5/Classes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Classes/x-saherelm.class.lib.mq5 b/Projects/XBTU5/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 00000000..68f48471 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Classes/x-saherelm.nn.lib.mq5 b/Projects/XBTU5/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 00000000..8fa40f53 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Classes/x-saherelm.provider.lib.mq5 b/Projects/XBTU5/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 00000000..4e4497a4 --- /dev/null +++ b/Projects/XBTU5/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, + // + // XSTFI ... + XSTFI, + // + // 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 XCPriver : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCPriver( + // + // 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 + // + // XSTFI ... + bool xSTFIEnableSignaller, // Enable Signaller + bool xSTFIAllowLongSignals, // Allow Long Signals + bool xSTFIAllowShortSignals, // 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; + + // + // XSTFI ... + mXSTFIEnableSignaller = xSTFIEnableSignaller; + mXSTFIAllowLongSignals = xSTFIAllowLongSignals; + mXSTFIAllowShortSignals = xSTFIAllowShortSignals; + + // + // 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 ... + ~XCPriver() {} + + // + // 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 XSTFI Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXSTFIignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXSTFIEnableSignaller) + { + return result; + } + + // + result = true; + mXSTFIEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXSTFISignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXSTFIEnableSignaller) + { + return result; + } + + // + result = true; + mXSTFIEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXSTFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + mXSTFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXSTFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXSTFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + mXSTFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXSTFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSTFIAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XSTFIHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowLongSignals) + { + 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 XSTFIHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSTFIEnableSignaller || + !mXSTFIAllowShortSignals) + { + 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 XSTFI 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; + + // + // XSTFI ... + bool mXSTFIEnableSignaller; + bool mXSTFIAllowLongSignals; + bool mXSTFIAllowShortSignals; + + // + // 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/Projects/XBTU5/Documents/.gitkeep b/Projects/XBTU5/Documents/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Documents/Reports/.gitkeep b/Projects/XBTU5/Documents/Reports/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Documents/Settings/.gitkeep b/Projects/XBTU5/Documents/Settings/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Experts/.gitkeep b/Projects/XBTU5/Experts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Experts/x-saherelm.xbtu5.ea.mq5 b/Projects/XBTU5/Experts/x-saherelm.xbtu5.ea.mq5 new file mode 100644 index 00000000..4e5acc15 --- /dev/null +++ b/Projects/XBTU5/Experts/x-saherelm.xbtu5.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 XBTU5 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" + +// +// XBTU5 Signal Provider ... +#include "../Providers/x-saherelm.xbtu5.provider.lib.mq5" + +// +// END Including Providers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +bool isXBTU5NewHour; +bool isXBTU5NewDay; +bool isXBTU5NewWeek; +bool isXBTU5NewMonth; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + logTag = "XBTU5EA"; + drawPrefix = logTag; + alertPrefix = logTag; + + // + // Apply default Chart Style for EA ... + ApplyChartStyle(); + + // + // Reset Timings ... + ResetTiming(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize XBTU5 Provider ... + if (!XBTU5InitSignalProviderLibrary()) + { + 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 XBTU5 Provider ... + XBTU5DeinitSignalProviderLibrary(reason); + + // + // De Init XDraw Library ... + // OnDeinitDrawLibrary(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Handle Monthly Alert ... + bool isFirstMonth = xMonth == -1; + isXBTU5NewMonth = IsNewMonth(); + bool canMonthlyAlert = + isXBTU5NewMonth && + xBTU5EnableAlerts && + xBTU5EnableMonthlyAlerts; + bool canMonthlyReport = + !isFirstMonth && + canMonthlyAlert && + xBTU5EnableMonthlyReports; + if (canMonthlyAlert) + { + // + string message = "New Month ..."; + + // + // Prepare Monthly Report ... + if (canMonthlyReport) + { + // + string report = xBTU5Reporter.GenerateReportString(XREPORT_MONTHLY); + + // + message = "Last Month Report:\n" + report; + } + + // + // Reset Report ... + xBTU5Reporter.Reset(XREPORT_MONTHLY); + + // + SendAlert(message); + } + + // + // Handle Weekly Alert ... + bool isFirstWeek = xDayOfWeek == -1; + isXBTU5NewWeek = IsNewWeek(); + bool canWeeklyAlert = + isXBTU5NewWeek && + xBTU5EnableAlerts && + xBTU5EnableWeeklyAlerts; + bool canWeeklyReport = + !isFirstWeek && + canWeeklyAlert && + xBTU5EnableWeeklyReports; + if (canWeeklyAlert) + { + // + string message = "New Week ..."; + + // + // Prepare Weekly Report ... + if (canWeeklyReport) + { + // + string report = xBTU5Reporter.GenerateReportString(XREPORT_WEEKLY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xBTU5Reporter.Reset(XREPORT_WEEKLY); + + // + SendAlert(message); + } + + // + // Handle Daily Alert ... + bool isFirstDay = xDay == -1; + isXBTU5NewDay = IsNewDay(); + bool canDailyAlert = + isXBTU5NewDay && + xBTU5EnableAlerts && + xBTU5EnableDailyAlerts; + bool canDailyReport = + !isFirstDay && + canDailyAlert && + xBTU5EnableDailyReports; + if (canDailyAlert) + { + // + string message = "New Day ..."; + + // + // Prepare Daily Report ... + if (canDailyReport) + { + // + string report = xBTU5Reporter.GenerateReportString(XREPORT_DAILY); + + // + message = "Last Week Report:\n" + report; + } + + // + // Reset Report ... + xBTU5Reporter.Reset(XREPORT_DAILY); + + // + SendAlert(message); + } + + // + // Handle Hourly Alert ... + bool isFirstHour = xHour == -1; + isXBTU5NewHour = IsNewHour(); + bool canHourlyAlert = + isXBTU5NewHour && + xBTU5EnableAlerts && + xBTU5EnableHourlyAlerts; + if (canHourlyAlert) + { + // + string message = "New Hour ..."; + + // + SendAlert(message); + } + + + // + // Prevent Going Forward if user Disable it ... + if (xBTU5EnableProvider) + { + // + // Handle Processing on XBTU5 Signal Provider ... + XBTU5SignalProviderDoControlState(); + } + + // + if (!IsNewCandle()) + { + return; + } + + // + // Prevent Going Forward if user Disable it ... + if (xBTU5EnableProvider) + { + // + // Handle Processing on XBTU5 Signal Provider ... + XBTU5SignalProviderHandleTick(); + } +} + +// +// Handle Trade Events ... +void OnTrade() +{ + + // + // Prevent Going Forward if user Disable it ... + if (xBTU5EnableProvider) + { + // + // Handle Processing Trades on XBTU5 Signal Provider ... + XBTU5SignalProviderHandleTrade(); + } +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + + // + // Validate XBTU5 Provider Inputs ... + result = XBTU5ValidateInputs(); + if (!result) + { + return false; + } + + // + // Logging State ... + string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ..."; + LogMessage(message); + + // + return result; +} + +// +// END Functions ... +// diff --git a/Projects/XBTU5/Helpers/.gitkeep b/Projects/XBTU5/Helpers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f565e415 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..d7071b48 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e84d762f --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..19d3417c --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 00000000..e6a92f65 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f90f15b2 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e6971b7a --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..6286228b --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 00000000..a871ed42 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/Projects/XBTU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..875eec08 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/.gitkeep b/Projects/XBTU5/Indicators/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Indicators/x-saherelm.xama.indicator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xchlh.oscillator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 00000000..5c74787c --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xchma.oscillator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 00000000..12d6c691 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xfi.oscillator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 00000000..cfd393ca --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xlh.indicator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 00000000..4dfc64e2 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xobd.indicator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 00000000..4ac05cf6 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xrsi.oscillator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 00000000..5659e07d --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xtd.oscillator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 00000000..5f46d187 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xtm.indicator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 00000000..eac88e0a --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Indicators/x-saherelm.xts.oscillator.mq5 b/Projects/XBTU5/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 00000000..46e9fbf9 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Libraries/.gitkeep b/Projects/XBTU5/Libraries/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Libraries/x-saherelm.alert.lib.mq5 b/Projects/XBTU5/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 00000000..10790632 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Libraries/x-saherelm.common.lib.mq5 b/Projects/XBTU5/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 00000000..290dde9b --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Libraries/x-saherelm.draw.lib.mq5 b/Projects/XBTU5/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 00000000..ece98c83 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Libraries/x-saherelm.http.lib.mq5 b/Projects/XBTU5/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 00000000..97f7ac0a --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Libraries/x-saherelm.log.lib.mq5 b/Projects/XBTU5/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 00000000..70f1bda4 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Libraries/x-saherelm.models.lib.mq5 b/Projects/XBTU5/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 00000000..b98ae3e8 --- /dev/null +++ b/Projects/XBTU5/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/Projects/XBTU5/Providers/.gitkeep b/Projects/XBTU5/Providers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.indicators.lib.mq5 b/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.indicators.lib.mq5 new file mode 100644 index 00000000..eb57263a --- /dev/null +++ b/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.indicators.lib.mq5 @@ -0,0 +1,6705 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XBTU5 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.xbtu5.provider.inputs.lib.mq5" + +// +// Include Provider Class ... +#include "../Classes/x-saherelm.provider.lib.mq5" + +// +// Signallers ... +input group "XBTU5 Signallers"; + +// +// XTD ... +input group "XBTU5 XTD Signaller"; +input bool xBTU5XTDEnableSignaller = true; // Enable Signaller +input bool xBTU5XTDAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XTDAllowShortSignals = true; // Enable Short Signals + +// +// XTAM ... +input group "XBTU5 XTAM Signaller"; +input bool xBTU5XTAMEnableSignaller = true; // Enable Signaller +input bool xBTU5XTAMAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XTAMAllowShortSignals = true; // Enable Short Signals + +// +// XSI ... +input group "XBTU5 XSI Signaller"; +input bool xBTU5XSIEnableSignaller = true; // Enable Signaller +input bool xBTU5XSIAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XSIAllowShortSignals = true; // Enable Short Signals + +// +// XSTFI ... +input group "XBTU5 XSTFI Signaller"; +input bool xBTU5XSTFIEnableSignaller = true; // Enable Signaller +input bool xBTU5XSTFIAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XSTFIAllowShortSignals = true; // Enable Short Signals + +// +// XOBDLH ... +input group "XBTU5 XOBDLH Signaller"; +input bool xBTU5XOBDLHEnableSignaller = true; // Enable Signaller +input bool xBTU5XOBDLHAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XOBDLHAllowShortSignals = true; // Enable Short Signals + +// +// XCHMACC ... +input group "XBTU5 XCHMACC Signaller"; +input bool xBTU5XCHMACCEnableSignaller = true; // Enable Signaller +input bool xBTU5XCHMACCAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XCHMACCAllowShortSignals = true; // Enable Short Signals + +// +// XCHMAMX ... +input group "XBTU5 XCHMAMX Signaller"; +input bool xBTU5XCHMAMXEnableSignaller = true; // Enable Signaller +input bool xBTU5XCHMAMXAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XCHMAMXAllowShortSignals = true; // Enable Short Signals + +// +// XCHMAMN ... +input group "XBTU5 XCHMAMN Signaller"; +input bool xBTU5XCHMAMNEnableSignaller = true; // Enable Signaller +input bool xBTU5XCHMAMNAllowLongSignals = true; // Enable Long Signals +input bool xBTU5XCHMAMNAllowShortSignals = true; // Enable Short Signals + +// +bool xBTU5IsTestMode = true; +int xBTU5MaxLengthOfInputs = 0; +int xBTU5CalculatedBars = 0; + +// +// Signaller Variables ... +// +// XTD ... +bool xBTU5MXTDEnableSignaller = xBTU5XTDEnableSignaller; +bool xBTU5MXTDAllowLongSignals = xBTU5XTDAllowLongSignals; +bool xBTU5MXTDAllowShortSignals = xBTU5XTDAllowShortSignals; + +// +// XTAM ... +bool xBTU5MXTAMEnableSignaller = xBTU5XTAMEnableSignaller; +bool xBTU5MXTAMAllowLongSignals = xBTU5XTAMAllowLongSignals; +bool xBTU5MXTAMAllowShortSignals = xBTU5XTAMAllowShortSignals; + +// +// XSI ... +bool xBTU5MXSIEnableSignaller = xBTU5XSIEnableSignaller; +bool xBTU5MXSIAllowLongSignals = xBTU5XSIAllowLongSignals; +bool xBTU5MXSIAllowShortSignals = xBTU5XSIAllowShortSignals; + +// +// XSTFI ... +bool xBTU5MXSTFIEnableSignaller = xBTU5XSTFIEnableSignaller; +bool xBTU5MXSTFIAllowLongSignals = xBTU5XSTFIAllowLongSignals; +bool xBTU5MXSTFIAllowShortSignals = xBTU5XSTFIAllowShortSignals; + +// +// XOBDLH ... +bool xBTU5MXOBDLHEnableSignaller = xBTU5XOBDLHEnableSignaller; +bool xBTU5MXOBDLHAllowLongSignals = xBTU5XOBDLHAllowLongSignals; +bool xBTU5MXOBDLHAllowShortSignals = xBTU5XOBDLHAllowShortSignals; + +// +// XCHMACC ... +bool xBTU5MXCHMACCEnableSignaller = xBTU5XCHMACCEnableSignaller; +bool xBTU5MXCHMACCAllowLongSignals = xBTU5XCHMACCAllowLongSignals; +bool xBTU5MXCHMACCAllowShortSignals = xBTU5XCHMACCAllowShortSignals; + +// +// XCHMAMX ... +bool xBTU5MXCHMAMXEnableSignaller = xBTU5XCHMAMXEnableSignaller; +bool xBTU5MXCHMAMXAllowLongSignals = xBTU5XCHMAMXAllowLongSignals; +bool xBTU5MXCHMAMXAllowShortSignals = xBTU5XCHMAMXAllowShortSignals; + +// +// XCHMAMN ... +bool xBTU5MXCHMAMNEnableSignaller = xBTU5XCHMAMNEnableSignaller; +bool xBTU5MXCHMAMNAllowLongSignals = xBTU5XCHMAMNAllowLongSignals; +bool xBTU5MXCHMAMNAllowShortSignals = xBTU5XCHMAMNAllowShortSignals; + +// +XCPriver *xBTU5Provider; + +// +// Validate Indicators Inputs ... +bool XBTU5ValidateIndicatorsInputs() +{ + // + 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 XCPriver Class for Use ... + xBTU5Provider = new XCPriver( + // + // Commons ... + _Symbol, + _Period, + // + // Signallers ... + // + // XTD ... + xBTU5MXTDEnableSignaller, + xBTU5MXTDAllowLongSignals, + xBTU5MXTDAllowShortSignals, + // + // XTAM ... + xBTU5MXTAMEnableSignaller, + xBTU5MXTAMAllowLongSignals, + xBTU5MXTAMAllowShortSignals, + // + // XSI ... + xBTU5MXSIEnableSignaller, + xBTU5MXSIAllowLongSignals, + xBTU5MXSIAllowShortSignals, + // + // XSTFI ... + xBTU5MXSTFIEnableSignaller, + xBTU5MXSTFIAllowLongSignals, + xBTU5MXSTFIAllowShortSignals, + // + // XOBDLH ... + xBTU5MXOBDLHEnableSignaller, + xBTU5MXOBDLHAllowLongSignals, + xBTU5MXOBDLHAllowShortSignals, + // + // XCHMACC ... + xBTU5MXCHMACCEnableSignaller, + xBTU5MXCHMACCAllowLongSignals, + xBTU5MXCHMACCAllowShortSignals, + // + // XCHMAMX ... + xBTU5MXCHMAMXEnableSignaller, + xBTU5MXCHMAMXAllowLongSignals, + xBTU5MXCHMAMXAllowShortSignals, + // + // XCHMAMN ... + xBTU5MXCHMAMNEnableSignaller, + xBTU5MXCHMAMNAllowLongSignals, + xBTU5MXCHMAMNAllowShortSignals + // + ); + + // + result = true; + + // + return result; +} + +// +// Init Indicators ... +bool XBTU5InitIndicators() +{ + // + bool result = false; + + // + // Make it Enable when we need to Log Market Conditions ... + // xBTU5IsTestMode = false; // IsRunningOnTestMode(); + + // + // Check and Calculate Max Length in Inputs ... + // + + // + // XTM ... + xBTU5MaxLengthOfInputs = MathMax( + xTMMaPeriod, + xBTU5NumberOfItemsPerTick); + + // + // XAMA ... + xBTU5MaxLengthOfInputs = MathMax( + xAMALength, + xBTU5NumberOfItemsPerTick); + xBTU5MaxLengthOfInputs = MathMax( + xAMAFastEMA, + xBTU5NumberOfItemsPerTick); + xBTU5MaxLengthOfInputs = MathMax( + xAMASlowEMA, + xBTU5NumberOfItemsPerTick); + + // + // XLH ... + xBTU5MaxLengthOfInputs = MathMax( + xLHLength, + xBTU5NumberOfItemsPerTick); + + // + // XTD ... + xBTU5MaxLengthOfInputs = MathMax( + xTDLength, + xBTU5MaxLengthOfInputs); + + // + // XFI ... + xBTU5MaxLengthOfInputs = MathMax( + xFILength, + xBTU5MaxLengthOfInputs); + + // + // XRSI ... + xBTU5MaxLengthOfInputs = MathMax( + xRSILength, + xBTU5MaxLengthOfInputs); + + // + // XOBD ... + xBTU5MaxLengthOfInputs = MathMax( + xOBDLength, + xBTU5MaxLengthOfInputs); + + // + // XCHLH ... + xBTU5MaxLengthOfInputs = MathMax( + xCHLHLcLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHLHMcLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHLHScLength, + xBTU5MaxLengthOfInputs); + + // + // XCHMA ... + xBTU5MaxLengthOfInputs = MathMax( + xCHMAScFastLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHMAScSlowLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHMAMcFastLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHMAMcSlowLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHMALcFastLength, + xBTU5MaxLengthOfInputs); + xBTU5MaxLengthOfInputs = MathMax( + xCHMALcSlowLength, + xBTU5MaxLengthOfInputs); + + // + // Validate Indicators Inputs before Initialization ... + result = XBTU5ValidateIndicatorsInputs(); + if (!result) + { + return result; + } + + // + // Validate Signallers ... + + // + // XTD ... + bool isXTDEnable = + xBTU5XTDEnableSignaller && + (xBTU5XTDAllowLongSignals || + xBTU5XTDAllowShortSignals); + + // + // XTAM ... + bool isXTAMEnable = + xBTU5XTAMEnableSignaller && + (xBTU5XTAMAllowLongSignals || + xBTU5XTAMAllowShortSignals); + + // + // XSI ... + bool isXSIEnable = + xBTU5XSIEnableSignaller && + (xBTU5XSIAllowLongSignals || + xBTU5XSIAllowShortSignals); + + // + // XSTFI ... + bool isXSTFIEnable = + xBTU5XSTFIEnableSignaller && + (xBTU5XSTFIAllowLongSignals || + xBTU5XSTFIAllowShortSignals); + + // + // XOBDLH ... + bool isXOBDLHEnable = + xBTU5XOBDLHEnableSignaller && + (xBTU5XOBDLHAllowLongSignals || + xBTU5XOBDLHAllowShortSignals); + + // + // XCHMACC ... + bool isXCHMACCEnable = + xBTU5XCHMACCEnableSignaller && + (xBTU5XCHMACCAllowLongSignals || + xBTU5XCHMACCAllowShortSignals); + + // + // XCHMAMX ... + bool isXCHMAMXEnable = + xBTU5XCHMAMXEnableSignaller && + (xBTU5XCHMAMXAllowLongSignals || + xBTU5XCHMAMXAllowShortSignals); + + // + // XCHMAMN ... + bool isXCHMAMNEnable = + xBTU5XCHMAMNEnableSignaller && + (xBTU5XCHMAMNAllowLongSignals || + xBTU5XCHMAMNAllowShortSignals); + + // + bool hasSignaller = + // + isXTDEnable || + isXTAMEnable || + isXSIEnable || + isXSTFIEnable || + isXOBDLHEnable || + isXCHMACCEnable || + isXCHMAMXEnable || + isXCHMAMNEnable + // + ; + result = hasSignaller; + if (!result) + { + // + LogMessage("XBTU5 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 XBTU5ReleaseIndicators() +{ + // + // Release Handlers ... + XTMReleaseHandlers(); + XAMAReleaseHandlers(); + XLHReleaseHandlers(); + XTDReleaseHandlers(); + XFIReleaseHandlers(); + XTSReleaseHandlers(); + XRSIReleaseHandlers(); + XOBDReleaseHandlers(); + XCHMAReleaseHandlers(); + XCHLHReleaseHandlers(); +} + +// +// Handle Reading Buffers ... +void XBTU5HandleReadingBuffers() +{ + // + // Reading Calculated Bars for a Simple Handler ... + xBTU5CalculatedBars = BarsCalculated(xTMHandler); + + // + // Read Indicators Buffers ... + XTMReadBuffers(xBTU5NumberOfItemsPerTick); + XAMAReadBuffers(xBTU5NumberOfItemsPerTick); + XLHReadBuffers(xBTU5NumberOfItemsPerTick); + XTDReadBuffers(xBTU5NumberOfItemsPerTick); + XFIReadBuffers(xBTU5NumberOfItemsPerTick); + XTSReadBuffers(xBTU5NumberOfItemsPerTick); + XRSIReadBuffers(xBTU5NumberOfItemsPerTick); + XOBDReadBuffers(xBTU5NumberOfItemsPerTick); + XCHMAReadBuffers(xBTU5NumberOfItemsPerTick); + XCHLHReadBuffers(xBTU5NumberOfItemsPerTick); + + // + xBTU5Provider.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 XBTU5CanOpenLongTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XBTU5HasLongSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + xBTU5Provider.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 XBTU5CanCloseLongTrade() +{ + // + 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 XBTU5CanOpenShortTrade( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + info.tp = 0; + info.sl = 0; + ArrayResize( + info.signallers, + 0); + + // + bool hasSignal = XBTU5HasShortSignal(info); + + // + result = + // + hasSignal + // + ; + + // + if (result) + { + xBTU5Provider.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 XBTU5CanCloseShortTrade() +{ + // + bool result = false; + + // + return result; +} + +// +// +// END Combination Functions ... +// +// + +// +// +// START Combination Signaling ... +// +// + +// +// Check Market Conditions by Combination of Power of All tools for LONGs ... +bool XBTU5HasLongSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XBTU5XTDHasLongSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XBTU5XTAMHasLongSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XBTU5XSIHasLongSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XBTU5XSTFIHasLongSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XBTU5XOBDLHHasLongSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XBTU5XCHMACCHasLongSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMAMNHasSignal = XBTU5XCHMAMNHasLongSignal(); + if (isXCHMAMNHasSignal) + { + // + Add( + EnumToString(XCHMAMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMAMXHasSignal = XBTU5XCHMAMXHasLongSignal(); + if (isXCHMAMXHasSignal) + { + // + Add( + EnumToString(XCHMAMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXSTFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMAMNHasSignal + // + || + // + isXCHMAMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xBTU5IsTestMode) + { + // + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + string message = xBTU5Provider.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 XBTU5HasShortSignal( + XProvidedSignal &info // Retrieve Signal Additional Info on this Object +) +{ + // + bool result = false; + + // + // XTD ... + bool isXTDHasSignal = XBTU5XTDHasShortSignal(); + if (isXTDHasSignal) + { + // + Add( + EnumToString(XTD), + info.signallers); + } + + // + // XTAM ... + bool isXTAMHasSignal = XBTU5XTAMHasShortSignal(); + if (isXTAMHasSignal) + { + // + Add( + EnumToString(XTAM), + info.signallers); + } + + // + // XSI ... + bool isXSIHasSignal = XBTU5XSIHasShortSignal(); + if (isXSIHasSignal) + { + // + Add( + EnumToString(XSI), + info.signallers); + } + + // + // XSTFI ... + bool isXSTFIHasSignal = XBTU5XSTFIHasShortSignal(); + if (isXSTFIHasSignal) + { + // + Add( + EnumToString(XSTFI), + info.signallers); + } + + // + // XOBD XLH ... + bool isXOBDLHHasSignal = XBTU5XOBDLHHasShortSignal(); + if (isXOBDLHHasSignal) + { + // + Add( + EnumToString(XOBDLH), + info.signallers); + } + + // + // XCHMA Cycles Cross ... + bool isXCHMACCHasSignal = XBTU5XCHMACCHasShortSignal(); + if (isXCHMACCHasSignal) + { + // + Add( + EnumToString(XCHMACC), + info.signallers); + } + + // + // XCHMA Cycles Min ... + bool isXCHMAMNHasSignal = XBTU5XCHMAMNHasShortSignal(); + if (isXCHMAMNHasSignal) + { + // + Add( + EnumToString(XCHMAMN), + info.signallers); + } + + // + // XCHMA Cycles Max + bool isXCHMAMXHasSignal = XBTU5XCHMAMXHasShortSignal(); + if (isXCHMAMXHasSignal) + { + // + Add( + EnumToString(XCHMAMX), + info.signallers); + } + + // + result = + // + isXTDHasSignal + // + || + // + isXTAMHasSignal + // + || + // + isXSIHasSignal + // + || + // + isXSTFIHasSignal + // + || + // + isXOBDLHHasSignal + // + || + // + isXCHMACCHasSignal + // + || + // + isXCHMAMNHasSignal + // + || + // + isXCHMAMXHasSignal + // + ; + + // + if (result) + { + // + // Only Log Signals Time Market Conditions if is in Testing Mode ... + if (xBTU5IsTestMode) + { + // + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + string message = xBTU5Provider.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 XBTU5DisableLongSignallers() +{ + // + // XTD ... + if (xBTU5MXTDEnableSignaller) + { + // + xBTU5Provider.DisbaleXTDLongs(); + xBTU5MXTDAllowLongSignals = false; + } + + // + // XTAM ... + if (xBTU5MXTAMEnableSignaller) + { + // + xBTU5Provider.DisbaleXTAMLongs(); + xBTU5MXTAMAllowLongSignals = false; + } + + // + // XSI ... + if (xBTU5MXSIEnableSignaller) + { + // + xBTU5Provider.DisbaleXSILongs(); + xBTU5MXSIAllowLongSignals = false; + } + + // + // XSTFI ... + if (xBTU5MXSTFIEnableSignaller) + { + // + xBTU5Provider.DisbaleXSTFILongs(); + xBTU5MXSTFIAllowLongSignals = false; + } + + // + // XOBDLH ... + if (xBTU5MXOBDLHEnableSignaller) + { + // + xBTU5Provider.DisbaleXOBDLHLongs(); + xBTU5MXOBDLHAllowLongSignals = false; + } + + // + // XCHMACC ... + if (xBTU5MXCHMACCEnableSignaller) + { + // + xBTU5Provider.DisbaleXCHMACCLongs(); + xBTU5MXCHMACCAllowLongSignals = false; + } + + // + // XCHMAMX ... + if (xBTU5MXCHMAMXEnableSignaller) + { + // + xBTU5Provider.DisbaleXCHMAMXLongs(); + xBTU5MXCHMAMXAllowLongSignals = false; + } + + // + // XCHMAMN ... + if (xBTU5MXCHMAMNEnableSignaller) + { + // + xBTU5Provider.DisbaleXCHMAMNLongs(); + xBTU5MXCHMAMNAllowLongSignals = false; + } +} + +// +// Enable All Signallers Longs ... +// Only if they are Configured as Enable at Settings ... +void XBTU5EnableLongSignallers() +{ + // + // XTD ... + if (xBTU5MXTDEnableSignaller) + { + // + xBTU5MXTDAllowLongSignals = + xBTU5XTDAllowLongSignals + ? true + : xBTU5MXTDAllowLongSignals; + + // + if (xBTU5MXTDAllowLongSignals) + { + xBTU5Provider.EnableXTDLongs(); + } + } + + // + // XTAM ... + if (xBTU5MXTAMEnableSignaller) + { + // + xBTU5MXTAMAllowLongSignals = + xBTU5XTAMAllowLongSignals + ? true + : xBTU5MXTAMAllowLongSignals; + + // + if (xBTU5MXTAMAllowLongSignals) + { + xBTU5Provider.EnableXTAMLongs(); + } + } + + // + // XSI ... + if (xBTU5MXSIEnableSignaller) + { + // + xBTU5MXSIAllowLongSignals = + xBTU5XSIAllowLongSignals + ? true + : xBTU5MXSIAllowLongSignals; + + // + if (xBTU5MXSIAllowLongSignals) + { + xBTU5Provider.EnableXSILongs(); + } + } + + // + // XSTFI ... + if (xBTU5MXSTFIEnableSignaller) + { + // + xBTU5MXSTFIAllowLongSignals = + xBTU5XSTFIAllowLongSignals + ? true + : xBTU5MXSTFIAllowLongSignals; + + // + if (xBTU5MXSTFIAllowLongSignals) + { + xBTU5Provider.EnableXSTFILongs(); + } + } + + // + // XOBDLH ... + if (xBTU5MXOBDLHEnableSignaller) + { + // + xBTU5MXOBDLHAllowLongSignals = + xBTU5XOBDLHAllowLongSignals + ? true + : xBTU5MXOBDLHAllowLongSignals; + + // + if (xBTU5MXOBDLHAllowLongSignals) + { + xBTU5Provider.EnableXOBDLHLongs(); + } + } + + // + // XCHMACC ... + if (xBTU5MXCHMACCEnableSignaller) + { + // + xBTU5MXCHMACCAllowLongSignals = + xBTU5XCHMACCAllowLongSignals + ? true + : xBTU5MXCHMACCAllowLongSignals; + + // + if (xBTU5MXCHMACCAllowLongSignals) + { + xBTU5Provider.EnableXCHMACCLongs(); + } + } + + // + // XCHMAMX ... + if (xBTU5MXCHMAMXEnableSignaller) + { + // + xBTU5MXCHMAMXAllowLongSignals = + xBTU5XCHMAMXAllowLongSignals + ? true + : xBTU5MXCHMAMXAllowLongSignals; + + // + if (xBTU5MXCHMAMXAllowLongSignals) + { + xBTU5Provider.EnableXCHMAMXLongs(); + } + } + + // + // XCHMAMN ... + if (xBTU5MXCHMAMNEnableSignaller) + { + // + xBTU5MXCHMAMNAllowLongSignals = + xBTU5XCHMAMNAllowLongSignals + ? true + : xBTU5MXCHMAMNAllowLongSignals; + + // + if (xBTU5MXCHMAMNAllowLongSignals) + { + xBTU5Provider.EnableXCHMAMNLongs(); + } + } +} + +// +// Disable All Signallers Shorts ... +void XBTU5DisableShortSignallers() +{ + // + // XTD ... + if (xBTU5MXTDEnableSignaller) + { + // + xBTU5Provider.DisableXTDShorts(); + xBTU5MXTDAllowShortSignals = false; + } + + // + // XTAM ... + if (xBTU5MXTAMEnableSignaller) + { + // + xBTU5Provider.DisableXTAMShorts(); + xBTU5MXTAMAllowShortSignals = false; + } + + // + // XSI ... + if (xBTU5MXSIEnableSignaller) + { + // + xBTU5Provider.DisableXSIShorts(); + xBTU5MXSIAllowShortSignals = false; + } + + // + // XSTFI ... + if (xBTU5MXSTFIEnableSignaller) + { + // + xBTU5Provider.DisableXSTFIShorts(); + xBTU5MXSTFIAllowShortSignals = false; + } + + // + // XOBDLH ... + if (xBTU5MXOBDLHEnableSignaller) + { + // + xBTU5Provider.DisableXOBDLHShorts(); + xBTU5MXOBDLHAllowShortSignals = false; + } + + // + // XCHMACC ... + if (xBTU5MXCHMACCEnableSignaller) + { + // + xBTU5Provider.DisableXCHMACCShorts(); + xBTU5MXCHMACCAllowShortSignals = false; + } + + // + // XCHMAMX ... + if (xBTU5MXCHMAMXEnableSignaller) + { + // + xBTU5Provider.DisableXCHMAMXShorts(); + xBTU5MXCHMAMXAllowShortSignals = false; + } + + // + // XCHMAMN ... + if (xBTU5MXCHMAMNEnableSignaller) + { + // + xBTU5Provider.DisableXCHMAMNShorts(); + xBTU5MXCHMAMNAllowShortSignals = false; + } +} + +// +// Enable All Signallers Shorts ... +// Only if they are Configured as Enable at Settings ... +void XBTU5EnableShortSignallers() +{ + // + // XTD ... + if (xBTU5MXTDEnableSignaller) + { + // + xBTU5MXTDAllowShortSignals = + xBTU5XTDAllowShortSignals + ? true + : xBTU5MXTDAllowShortSignals; + + // + if (xBTU5MXTDAllowShortSignals) + { + xBTU5Provider.EnableXTDShorts(); + } + } + + // + // XTAM ... + if (xBTU5MXTAMEnableSignaller) + { + // + xBTU5MXTAMAllowShortSignals = + xBTU5XTAMAllowShortSignals + ? true + : xBTU5MXTAMAllowShortSignals; + + // + if (xBTU5MXTAMAllowShortSignals) + { + xBTU5Provider.EnableXTAMShorts(); + } + } + + // + // XSI ... + if (xBTU5MXSIEnableSignaller) + { + // + xBTU5MXSIAllowShortSignals = + xBTU5XSIAllowShortSignals + ? true + : xBTU5MXSIAllowShortSignals; + + // + if (xBTU5MXSIAllowShortSignals) + { + xBTU5Provider.EnableXSIShorts(); + } + } + + // + // XSTFI ... + if (xBTU5MXSTFIEnableSignaller) + { + // + xBTU5MXSTFIAllowShortSignals = + xBTU5XSTFIAllowShortSignals + ? true + : xBTU5MXSTFIAllowShortSignals; + + // + if (xBTU5MXSTFIAllowShortSignals) + { + xBTU5Provider.EnableXSTFIShorts(); + } + } + + // + // XOBDLH ... + if (xBTU5MXOBDLHEnableSignaller) + { + // + xBTU5MXOBDLHAllowShortSignals = + xBTU5XOBDLHAllowShortSignals + ? true + : xBTU5MXOBDLHAllowShortSignals; + + // + if (xBTU5MXOBDLHAllowShortSignals) + { + xBTU5Provider.EnableXOBDLHShorts(); + } + } + + // + // XCHMACC ... + if (xBTU5MXCHMACCEnableSignaller) + { + // + xBTU5MXCHMACCAllowShortSignals = + xBTU5XCHMACCAllowShortSignals + ? true + : xBTU5MXCHMACCAllowShortSignals; + + // + if (xBTU5MXCHMACCAllowShortSignals) + { + xBTU5Provider.EnableXCHMACCShorts(); + } + } + + // + // XCHMAMX ... + if (xBTU5MXCHMAMXEnableSignaller) + { + // + xBTU5MXCHMAMXAllowShortSignals = + xBTU5XCHMAMXAllowShortSignals + ? true + : xBTU5MXCHMAMXAllowShortSignals; + + // + if (xBTU5MXCHMAMXAllowShortSignals) + { + xBTU5Provider.EnableXCHMAMXShorts(); + } + } + + // + // XCHMAMN ... + if (xBTU5MXCHMAMNEnableSignaller) + { + // + xBTU5MXCHMAMNAllowShortSignals = + xBTU5XCHMAMNAllowShortSignals + ? true + : xBTU5MXCHMAMNAllowShortSignals; + + // + if (xBTU5MXCHMAMNAllowShortSignals) + { + xBTU5Provider.EnableXCHMAMNShorts(); + } + } +} + +// +// XTD Long Signal Checking ... +bool XBTU5XTDHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXTDEnableSignaller || + !xBTU5MXTDAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 XBTU5XTDHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXTDEnableSignaller || + !xBTU5MXTDAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XTAM Long Signal Checking ... +bool XBTU5XTAMHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXTAMEnableSignaller || + !xBTU5MXTAMAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XTAM Short Signal Checking ... +bool XBTU5XTAMHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXTAMEnableSignaller || + !xBTU5MXTAMAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSI Long Signal Checking ... +bool XBTU5XSIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXSIEnableSignaller || + !xBTU5MXSIAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSI Short Signal Checking ... +bool XBTU5XSIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXSIEnableSignaller || + !xBTU5MXSIAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSTFI Long Signal Checking ... +bool XBTU5XSTFIHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXSTFIEnableSignaller || + !xBTU5MXSTFIAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.XSTFIHasLongConditions() + // + && + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XSTFI Short Signal Checking ... +bool XBTU5XSTFIHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXSTFIEnableSignaller || + !xBTU5MXSTFIAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.XSTFIHasShortConditions() + // + && + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XOBDLH Long Signal Checking ... +bool XBTU5XOBDLHHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXOBDLHEnableSignaller || + !xBTU5MXOBDLHAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + XMarketConditions xMConditions2 = xBTU5Provider.GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XOBDLH Short Signal Checking ... +bool XBTU5XOBDLHHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXOBDLHEnableSignaller || + !xBTU5MXOBDLHAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMACC Long Signal Checking ... +bool XBTU5XCHMACCHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXCHMACCEnableSignaller || + !xBTU5MXCHMACCAllowLongSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMACC Short Signal Checking ... +bool XBTU5XCHMACCHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXCHMACCEnableSignaller || + !xBTU5MXCHMACCAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMN Long Signal Checking ... +bool XBTU5XCHMAMNHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXCHMAMNEnableSignaller || + !xBTU5MXCHMAMNAllowLongSignals) + { + 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 = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMN Short Signal Checking ... +bool XBTU5XCHMAMNHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXCHMAMNEnableSignaller || + !xBTU5MXCHMAMNAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMX Long Signal Checking ... +bool XBTU5XCHMAMXHasLongSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXCHMAMXEnableSignaller || + !xBTU5MXCHMAMXAllowLongSignals) + { + 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 = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// XCHMAMX Short Signal Checking ... +bool XBTU5XCHMAMXHasShortSignal() +{ + // + bool result = false; + + // + // Validate Args ... + if (!xBTU5MXCHMAMXEnableSignaller || + !xBTU5MXCHMAMXAllowShortSignals) + { + return result; + } + + // + // Retrieve Market Condition ... + XMarketConditions mConditions = xBTU5Provider.GetLastMarketCondition(); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + xBTU5Provider.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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If HH is Same In Length ... + ((mConditions.isXLHHHSameInLength && + !mConditions.isXLHLLSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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 ... + // + // Check if Both LL and HH Same In Length ... + ((mConditions.isXLHLLSameInLength && + mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // Check If LL Same In Length ... + ((mConditions.isXLHLLSameInLength && + !mConditions.isXLHHHSameInLength) && + // + ( + // + false + // + ) + // + ) + // + || + // + // 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; +} + +// +// END Signal Providers ... +// diff --git a/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.inputs.lib.mq5 b/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.inputs.lib.mq5 new file mode 100644 index 00000000..06c1557b --- /dev/null +++ b/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.inputs.lib.mq5 @@ -0,0 +1,280 @@ +/////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XBTU5 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 "XBTU5 Provider"; + +// +// Commonly Used Configurations ... +input group "XBTU5 Common"; +// +// Provider ... +input bool xBTU5EnableProvider = true; // Enable Provider +input int xBTU5NumberOfItemsPerTick = 30; // Number Of items Readed In Each Tick +// +// Alerts ... +input bool xBTU5EnableAlerts = true; // Enable Events Alert +input bool xBTU5EnableHourlyAlerts = false; // Send Alert on each new Hour +input bool xBTU5EnableDailyAlerts = false; // Send Alert on each new Day +input bool xBTU5EnableWeeklyAlerts = false; // Send Alert on each new Week +input bool xBTU5EnableMonthlyAlerts = true; // Send Alert on each new Month +// +// Reports ... +input bool xBTU5EnableDailyReports = false; // Send Report on each new Day +input bool xBTU5EnableWeeklyReports = false; // Send Report on each new Week +input bool xBTU5EnableMonthlyReports = true; // Send Report on each new Month + +// +// Trader and Expert Specific Configurations ... +input group "XBTU5 Trader"; +input int xBTU5MagicNumber = 16940560; // Trader MagicNumber +input int xBTU5Slippage = 10; // Trader Slippage + +// +// Trades Management Configurations ... +input group "XBTU5 Trade Management"; +input bool xBTU5AllowLongTrades = true; // Allow Long Trades +input bool xBTU5AllowShortTrades = true; // Allow Short Trades + +// +// Risk Management Configurations ... +input group "XBTU5 Risk Management"; +// +input bool xBTU5UseVirtualTPSl = true; // Use Virtual TP SL +// +// Trade Count ... +input int xBTU5MaxAllowedTrades = 10; // Max Allowed Trades at Same Time +input ENUM_X_CROSS_SIGNAL_METHOD xBTU5CrossSignalsMethod = X_CROSS_SIGNAL_REGULAR; // Handle Cross Signals Method +// +// Max Allowed Trade Age ... +input int xBTU5MaxAllowedTradeAge = 2000; // Detect Long Time Trades +input ENUM_X_GUARD_ACTIONS xBTU5OldTradesAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_1; // What to do with Old Trades +// +// Trade Volume Specific Configurations ... +input double xBTU5StaticVolumeFactor = 0.0002; // Static Volume baesd on Balance +input ENUM_STATIC_VOLUME_METHODS xBTU5StaticVolumeMethod = X_STATIC_VOLUME_BASED_ON_BALANCE; // How to Calculate Static Volume +input double xBTU5VolumeMultiplier = 0; // Volume Increase Multiplier +input double xBTU5ApplyVolumeMultiplierFactor = 0; // Apply Volume Multiplier Rate based on Balance +input double xBTU5MaxSupportedVolumePerTradeFactor = 0; // Max Supported Volume Per Trade Factor based on Balance +input double xBTU5IncreasedMaxSupportedVolumeRate = 0; // Increase Max Supported Volume based on Balance +// +// Trade Profits ... +input double xBTU5MinRewardInPips = 15; // Minimum Reward Per Trade in Pips +input double xBTU5RiskFreeStepInPips = 6; // Make Trades Risk Free Steps in Pips +input double xBTU5RiskFreeRate = 0.6; // Volume Multiplier for Risk Free Trades +// +// Guard Riskable Money and Profits ... +input double xBTU5CriticalDrawDownFactor = 0.43; // Critical Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xBTU5CriticalGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_5; // Specify Guard Action on Critical Drawdown +input double xBTU5MaxAllowedDrawDownFactor = 0.45; // Max Allowed Drawdown Factor based on Balance +input ENUM_X_GUARD_ACTIONS xBTU5MaxAllowedGuardAction = X_GUARD_PARTIAL_CLOSE_MAX_IN_DD_10; // Specify Guard Action on Max Allowed Drawdown +input int xBTU5GuardStopoutFiredAfterTouches = 5; // Guard Stopout all Trades if Max Allowed Drawdown touched + +// +// Account Conditions for Trading ... +input double xBTU5BalanceFactorForOpenTrades = 0.5; // Minimum Balance for Open Trades +input double xBTU5FreeMarginFactorForOpenTrades = 0.8; // Minimum Free Margin for Open Trades + +// +// Validate Inputs before Initialization ... +bool XBTU5ValidateInputs() +{ + // + bool result = false; + + // + // Implement Other Verifications ... + + // + // Check Trading Availability ... + bool isTradeAvailable = xBTU5AllowLongTrades || xBTU5AllowShortTrades; + if (!isTradeAvailable) + { + LogMessage("XBTU5 => Warning: Trading disabled ..."); + } + + // + // Chekc Number of reading items per tick ... + result = xBTU5NumberOfItemsPerTick >= 5; + if (!result) + { + // + LogMessage("XBTU5 invalid Number of items Reading Per Tick ..."); + + // + return result; + } + + // + // Check Max Allowed Trades Count ... + result = isTradeAvailable && xBTU5MaxAllowedTrades >= 1; + if (!result) + { + // + LogMessage("XBTU5 Number of Trades not valid ..."); + + // + return result; + } + + // + // Check Free Margin ... + result = + isTradeAvailable && + xBTU5FreeMarginFactorForOpenTrades > 0 && + xBTU5FreeMarginFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XBTU5 Invalid Free Margin ..."); + + // + return result; + } + + // + // Check min Balance for Open Trades ... + result = + isTradeAvailable && + xBTU5BalanceFactorForOpenTrades > 0 && + xBTU5BalanceFactorForOpenTrades < 1; + if (!result) + { + // + LogMessage("XBTU5 Invalid Min Balance for Open Trades ..."); + + // + return result; + } + + // + // Check Min Reward Per Trade ... + result = xBTU5MinRewardInPips > 0; + if (!result) + { + // + LogMessage("XBTU5 Invalid Min Reward Per Trade ..."); + + // + return result; + } + + // + // Check Trades Volume ... + result = xBTU5StaticVolumeFactor > 0; + if (!result) + { + // + LogMessage("XBTU5 Invalid Static Volume ..."); + + // + return result; + } + + // + // Check Volume Multiplier ... + result = xBTU5VolumeMultiplier >= 0; + if (!result) + { + // + LogMessage("XBTU5 Invalid Volume Multiplier ..."); + + // + return result; + } + + // + result = + xBTU5CriticalDrawDownFactor == 0 || (xBTU5CriticalDrawDownFactor > 0 && + xBTU5CriticalDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XBTU5 Invalid Critical DrawDown Factor ..."); + + // + return result; + } + + // + result = + xBTU5MaxAllowedDrawDownFactor == 0 || (xBTU5MaxAllowedDrawDownFactor > 0 && + xBTU5MaxAllowedDrawDownFactor < 1); + if (!result) + { + // + LogMessage("XBTU5 Invalid Max Allowed DrawDown Factor ..."); + + // + return result; + } + + // + // Check Guard Actions ... + // + result = + xBTU5CriticalDrawDownFactor > 0 && + xBTU5CriticalDrawDownFactor < 1 && + xBTU5MaxAllowedDrawDownFactor > 0 && + xBTU5MaxAllowedDrawDownFactor < 1; + if (!result) + { + // + LogMessage("XBTU5 For Critical Drawdown, you have to Specify Max Drawdown also ..."); + + // + return result; + } + + // + result = xBTU5CriticalDrawDownFactor > 0 && xBTU5CriticalDrawDownFactor < xBTU5MaxAllowedDrawDownFactor; + if (!result) + { + // + LogMessage("XBTU5 Critical Drawdown must Smaller than Max Drawdown ..."); + + // + return result; + } + + // + if (xBTU5CriticalDrawDownFactor > 0 && xBTU5CriticalGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XBTU5 IMPORTANT you Specified Critical Drawdown, but there is no any Guard Action ..."); + } + + // + if (xBTU5MaxAllowedDrawDownFactor > 0 && xBTU5MaxAllowedGuardAction == X_GUARD_DO_NOTHING) + { + LogMessage("XBTU5 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/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.lib.mq5 b/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.lib.mq5 new file mode 100644 index 00000000..2c38e710 --- /dev/null +++ b/Projects/XBTU5/Providers/x-saherelm.xbtu5.provider.lib.mq5 @@ -0,0 +1,1370 @@ +//////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XBTU5 Signal Provider Library +// -------------------------------------------------------- +// Name: XBTU5SignalProvider +// Description: XBTU5 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 XBTU5ProviderName "XBTU5" + +// +// START Inputs ... +// + +#include "x-saherelm.xbtu5.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 *xBTU5Guard; +XCTrade *xBTU5Trader; +XCReporter *xBTU5Reporter; +XCCollector *xBTU5Collector; +XCAccountInfo *xBTU5AccountInfo; +XCVolumeManager *xBTU5VolumeManager; + +// +#include "x-saherelm.xbtu5.provider.indicators.lib.mq5" + +// +// Controlling Variables ... +bool xBTU5MEnableProvider = false; +bool xBTU5MAllowLongTrades = false; +bool xBTU5MAllowShortTrades = false; + +// +double xBTU5Deposit = 0; +double xBTU5Balance = 0; +double xBTU5MinReward = 0; +double xBTU5FreeMargin = 0; +double xBTU5BalanceForOpenTrades = 0; +double xBTU5FreeMarginForOpenTrades = 0; + +// +// Guard ... +double xBTU5CriticalDrawDown = 0; +double xBTU5MaxAllowedDrawDown = 0; + +// +double xBTU5MaxDrawUp = 0; +double xBTU5MaxDrawDown = 0; + +// +int NOT_ENOUGH_MONEY_ERROR = 4756; +const string XBTU5_SUPPORT_ID = "SP"; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// Initial Library if required ... +bool XBTU5InitSignalProviderLibrary() +{ + // + bool result = false; + + // + if (!xBTU5EnableProvider) + { + return result; + } + + // + // Controlling Variables ... + xBTU5MEnableProvider = xBTU5EnableProvider; + xBTU5MAllowLongTrades = xBTU5AllowLongTrades; + xBTU5MAllowShortTrades = xBTU5AllowShortTrades; + + // + // Validate Inputs ... + result = XBTU5ValidateInputs(); + if (!result) + { + return result; + } + + // + // Init Indicators ... + result = XBTU5InitIndicators(); + if (!result) + { + return result; + } + + // + xBTU5Reporter = new XCReporter(); + xBTU5Collector = new XCCollector(); + xBTU5AccountInfo = new XCAccountInfo(); + + // + // Calculate Account Deposit ... + xBTU5Deposit = xBTU5AccountInfo.GetInitialBalance(); + + // + // Prepare Min Reward ... + if (xBTU5MinRewardInPips > 0) + { + xBTU5MinReward = PipsToPrice(xBTU5MinRewardInPips); + } + + // + // Calculate Min Balance for Trades ... + if (xBTU5BalanceFactorForOpenTrades > 0) + { + xBTU5BalanceForOpenTrades = xBTU5BalanceFactorForOpenTrades * xBTU5Deposit; + } + + // + // Claculate Min Free Marging for Trades ... + if (xBTU5FreeMarginFactorForOpenTrades > 0) + { + xBTU5FreeMarginForOpenTrades = xBTU5FreeMarginFactorForOpenTrades * xBTU5Deposit; + } + + // + // Calculate Init Time Critical DrawDown Value ... + if (xBTU5CriticalDrawDownFactor > 0) + { + xBTU5CriticalDrawDown = xBTU5CriticalDrawDownFactor * xBTU5Deposit; + } + + // + // Calculate Init Time Max Allowed DrawDown Value ... + if (xBTU5MaxAllowedDrawDownFactor > 0) + { + xBTU5MaxAllowedDrawDown = xBTU5MaxAllowedDrawDownFactor * xBTU5Deposit; + } + + // + // Instant Volume Manager ... + xBTU5VolumeManager = new XCVolumeManager( + xBTU5StaticVolumeFactor, + xBTU5StaticVolumeMethod, + xBTU5VolumeMultiplier, + xBTU5ApplyVolumeMultiplierFactor, + xBTU5MaxSupportedVolumePerTradeFactor, + xBTU5IncreasedMaxSupportedVolumeRate); + + // + // Make XCTrader instance ... + xBTU5Trader = new XCTrade( + XBTU5ProviderName, + _Symbol, + xBTU5Slippage, + xBTU5MagicNumber, + xBTU5UseVirtualTPSl, + xBTU5MaxAllowedTrades, + xBTU5FreeMarginForOpenTrades, + xBTU5BalanceForOpenTrades); + + // + // Instantiate Account Guard ... + xBTU5Guard = new XCGuard( + // + // Old Trades ... + xBTU5MaxAllowedTradeAge, + xBTU5OldTradesAction, + // + // Critical DrawDown ... + xBTU5CriticalDrawDownFactor, + xBTU5CriticalGuardAction, + // + // Max Allowed DrawDown ... + xBTU5MaxAllowedDrawDownFactor, + xBTU5MaxAllowedGuardAction, + xBTU5GuardStopoutFiredAfterTouches, + // + // xBTU5GuardSupportMethod + X_SUPPORT_DO_NOTHING + // + ); + + // + // Reset Calculations Buffers and Variables ... + XBTU5ResetCollectors(); + + // + XBTU5UpdateReports(); + + // + result = true; + + // + // Logging State ... + XBTU5IssueInitializationSucceedAlert(); + + // + return result; +} + +// +// DeInitial Library if required ... +void XBTU5DeinitSignalProviderLibrary(const int reason) +{ + // + // Release Handlers ... + XBTU5ReleaseIndicators(); + + // + // Logging State ... + XBTU5IssueDeinitializationSucceedAlert(); +} + +// +// this is a Globally Function which do all of +// checkings and positions handling ... +void XBTU5SignalProviderHandleTick() +{ + // + // Check Provider is Enable or Not ... + if (!xBTU5MEnableProvider) + { + return; + } + + // + XBTU5SignalProviderDoControlState(); + + // + // Reading Indicator Buffers ... + XBTU5HandleReadingBuffers(); + if (xBTU5CalculatedBars < xBTU5MaxLengthOfInputs) + { + return; + } + + // + // Handle Open Trades ... + XBTU5HandleOpenTrades(); + + // + // Handle Close Trades ... + XBTU5HandleCloseTrades(); + + // + // DrawDown and DrawUp ... + XBTU5HandleCalculateDrawDownUp(); +} + +// +// Do Control Checks here ... +void XBTU5SignalProviderDoControlState() +{ + // + // Update account Balance ... + xBTU5Balance = xBTU5AccountInfo.GetBalance(); + xBTU5FreeMargin = xBTU5AccountInfo.GetFreeMargin(); + + // + // Check Provider is Enable or Not ... + if (!xBTU5MEnableProvider) + { + return; + } + + // + // Protect Account by Guarding Maximum Drawdown ... + // TODO: add Guard Result here ... + string guardMessage = ""; + XGuardHandlerResult guardHandlerResult; + bool isGuarded = xBTU5Guard.Guard( + guardHandlerResult, + guardMessage, + xBTU5Trader, + _Period); + if (isGuarded) + { + // + // Criticals ... + int criticalsCount = ArraySize(guardHandlerResult.criticals); + if (criticalsCount > 0) + { + // + for (int i = 0; i < criticalsCount; i++) + { + // + XSignal iSignal = guardHandlerResult.criticals[i]; + + // + XBTU5OnGuard( + 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]; + + // + XBTU5OnGuard( + 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]; + + // + XBTU5OnGuard( + iSignal, + X_GUARDED_OLD, + guardMessage); + } + } + } + + // + // Signal Protection ... + XSignal protectSupports[]; + bool isSupported = xBTU5Guard.ProtectSignals( + protectSupports, + xBTU5Trader); + if (isSupported) + { + // + LogMessage("Guard do Support Trdae ..."); + } + + // + // Handling Signals ... + XTraderHandlerResult signalHandlerResult; + xBTU5Trader.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]; + XBTU5OnSL(iSignal); + } + } + + // + // Handle TP Reports ... + int handledTPsCount = ArraySize(signalHandlerResult.tp); + if (handledTPsCount > 0) + { + // + for (int i = 0; i < handledTPsCount; i++) + { + // + XSignal iSignal = signalHandlerResult.tp[i]; + XBTU5OnTP(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]; + XBTU5OnRF(iSignal); + } + } +} + +// +// Handle Trades when OnTrade Event Hnadler Calls ... +void XBTU5SignalProviderHandleTrade() +{ + // + // Check Provider Enabled ... + if (!xBTU5MEnableProvider) + { + return; + } + + // + // Handle OnTrade Event ... + XOnTradeHandlerResult result = {}; + xBTU5Trader.HandleOnTradeEvent( + result); + + // + // Detected TP or SL ... + if (result.hasNewDeal) + { + // + XDeal last = xBTU5Trader.GetLastDeal(); + + // + if (last.reason == DEAL_REASON_SL) + { + xBTU5Reporter.AddTradeSLInReports(); + } + else if (last.reason == DEAL_REASON_TP) + { + xBTU5Reporter.AddTradeTPInReports(); + } + } +} + +// +// Handle Open Trades ... +void XBTU5HandleOpenTrades() +{ + // + // Check Can Trade ... + bool canTrade = xBTU5MAllowLongTrades || xBTU5MAllowShortTrades; + if (!canTrade) + { + return; + } + + // + // Check Max Open Trades ... + int openSignals = xBTU5Trader.Count(); + bool canOpenPositions = openSignals < xBTU5MaxAllowedTrades; + if (!canOpenPositions) + { + return; + } + + // + // Check Signals Exists ... + XProvidedSignal longSignalInfo; + XProvidedSignal shortSignalInfo; + bool hasLongSignal = XBTU5CanOpenLongTrade(longSignalInfo); + bool hasShortSignal = XBTU5CanOpenShortTrade(shortSignalInfo); + if (!hasLongSignal && !hasShortSignal) + { + return; + } + + // + // Update Reports ... + XBTU5UpdateReports(); + + // + // Open Long Trades ... + if ( + // + hasLongSignal && + xBTU5MAllowLongTrades) + { + // + bool isOpened = XBTU5OpenLongPosition(longSignalInfo); + } + + // + // Open Short Trades ... + if ( + // + hasShortSignal && + xBTU5MAllowShortTrades) + { + // + bool isOpened = XBTU5OpenShortPosition(shortSignalInfo); + } +} + +// +// Handle Close Trades ... +void XBTU5HandleCloseTrades() +{ + // + // Force Close Long Trades ... + bool isClosedLongTrades = false; + bool canCloseLongTrades = XBTU5CanCloseLongTrade(); + if (xBTU5MAllowLongTrades && canCloseLongTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_LONG; + + // + XSignal closed[]; + xBTU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedLongTrades = closedTradesCount > 0; + if (isClosedLongTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XBTU5OnFC(iSignal); + } + } + } + + // + // Force Close Short Trades ... + bool isClosedShortTrades = false; + bool canCloseShortTrades = XBTU5CanCloseShortTrade(); + if (xBTU5MAllowShortTrades && canCloseShortTrades) + { + // + ENUM_X_SIGNAL_TYPE type = X_SIGNAL_SHORT; + + // + XSignal closed[]; + xBTU5Trader.CloseSignals( + closed, + type); + + // + int closedTradesCount = ArraySize(closed); + isClosedShortTrades = closedTradesCount > 0; + if (isClosedShortTrades) + { + // + for (int i = 0; i < closedTradesCount; i++) + { + // + XSignal iSignal = closed[i]; + XBTU5OnFC(iSignal); + } + } + } +} + +// +// Open Long Position ... +bool XBTU5OpenLongPosition( + 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 + xBTU5MinReward; + double riskFreeRate = xBTU5RiskFreeRate; + double riskFreeStep = xBTU5RiskFreeStepInPips; + double volume = XBTU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xBTU5Trader.GenerateSignal( + X_SIGNAL_LONG, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xBTU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xBTU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XBTU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xBTU5CrossSignalsMethod != X_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xBTU5Trader.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 = xBTU5Trader.GetSignal(signal.ticket); + + // + XBTU5OnSignal( + tSignal, + providers); + } + else + { + XBTU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Open Short Position ... +bool XBTU5OpenShortPosition( + 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 - xBTU5MinReward; + double riskFreeRate = xBTU5RiskFreeRate; + double riskFreeStep = xBTU5RiskFreeStepInPips; + double volume = XBTU5CalculateVolume(ArraySize(info.signallers)); + + // + XSignal signal = {}; + signal = xBTU5Trader.GenerateSignal( + X_SIGNAL_SHORT, + tp, + sl, + volume, + riskFreeStep, + riskFreeRate); + bool isValidSignal = IsValid( + signal, + xBTU5MagicNumber); + if (!isValidSignal) + { + return result; + } + + // + int signalsCount = xBTU5Trader.Count(); + bool isCross = signalsCount >= 1; + if (isCross) + { + // + // Handle Cross Signals ... + XBTU5HnadleCrossSignal(signal); + } + + // + // Retrieve Can Execute Signal or not ... + bool canExecuteSignal = + !isCross + // + || + // + ( + // + isCross && + xBTU5CrossSignalsMethod != X_CROSS_SIGNAL_DO_NOTHING + // + ); + if (!canExecuteSignal) + { + return result; + } + + // + // Execute Signal ... + ENUM_EXECUTION_SIGNAL_RESULT executionResult = xBTU5Trader.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 = xBTU5Trader.GetSignal(signal.ticket); + + // + XBTU5OnSignal( + tSignal, + providers); + } + else + { + XBTU5IssueSignalExecutionError(executionResult); + } + + // + return result; +} + +// +// Apply Cross Signal Actions ... +void XBTU5HnadleCrossSignal( + XSignal &signal // Specified Signal ... +) +{ + // + // Check Cross Signal Handling Enabled ... + if (xBTU5CrossSignalsMethod == X_CROSS_SIGNAL_DO_NOTHING) + { + return; + } + + // + // First We have to Change Cross Signals Comment ... + string comment = xBTU5Trader.GenerateSignalComment( + signal, + true); + + // + signal.comment = comment; + + // + // If Every thing is Regular, prevent any changes here ... + if (xBTU5CrossSignalsMethod == X_CROSS_SIGNAL_REGULAR) + { + return; + } + + // + // Retrieve Max in Drawdown Signal ... + XSignal maxInDDSignal = xBTU5Trader.GetMaxInDrawdownSignal(); + + // + // Validate Signal ... + bool isValidSignal = + maxInDDSignal.ticket > 0 && + maxInDDSignal.symbol == signal.symbol && + IsValid(maxInDDSignal, xBTU5MagicNumber); + if (!isValidSignal) + { + return; + } + + // + double volume = signal.volume; + bool isDirectional = maxInDDSignal.type == signal.type; + + // + // Prevent any changes on Regular Conditions ... + bool isRegular = + isDirectional + ? ( + // + xBTU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_REGULAR || + xBTU5CrossSignalsMethod == X_CROSS_SIGNAL_DIRECTION_REGULAR_INDIRECTION_IMPORTANT + // + ) + : ( + // + xBTU5CrossSignalsMethod == X_CROSS_SIGNAL_INDIRECTION_REGULAR || + xBTU5CrossSignalsMethod == 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 XBTU5HandleCalculateDrawDownUp() +{ + // + XSignal signals[]; + xBTU5Trader.GetSignals(signals); + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + double profit = 0; + double volume = 0; + XCollector collector = {}; + double maxAllowedVolume = xBTU5VolumeManager.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) + { + // + xBTU5MaxDrawDown = + xBTU5MaxDrawDown == 0 || + xBTU5MaxDrawDown > MathAbs(profit) + ? MathAbs(profit) + : xBTU5MaxDrawDown; + + // + // Update Buffers ... + datetime time = iTime(_Symbol, _Period, 0); + + // + // Calculate Max Allowed Drawdown ... + // + collector.time = time; + collector.volume = volume; + collector.maxDrawDown = xBTU5MaxDrawDown; + collector.maxAllowedVolume = maxAllowedVolume; + collector.minBalanceForOpenTrade = xBTU5Trader.GetMinBalanceForOpenTrades(); + } + else + { + // + xBTU5MaxDrawUp = + xBTU5MaxDrawUp == 0 || + xBTU5MaxDrawUp < profit + ? profit + : xBTU5MaxDrawUp; + } + + // + // Update Collector ... + xBTU5Collector.Add(collector); + + // + // Update Reports ... + xBTU5Reporter.UpdateMaxDrawUpInReports(xBTU5MaxDrawUp); + xBTU5Reporter.UpdateMaxDrawDownInReports(xBTU5MaxDrawDown); + xBTU5Reporter.UpdateMaxSameTimeTradesInReports(signalsCount); +} + +// +// START Event Handlers ... +// + +// +// Runs When a Signal Successfully Executed ... +void XBTU5OnSignal( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + // Issue Propper Alert ... + XBTU5IssueSignalExecutionAlert( + signal, + providers); + + // + // Add Signal To Supports on Guard ... + xBTU5Guard.AddSupport(signal); + + // + // Update Reports ... + xBTU5Reporter.AddSignalToReports( + signal, + providers); +} + +// +// Runs when a Position Got Take Profit ... +void XBTU5OnTP( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XBTU5IssueTPAlert(signal); + + // + // Remove Signal From Guard Protector ... + xBTU5Guard.Remove(signal.ticket); + xBTU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xBTU5Reporter.AddTradeTPInReports(); + XBTU5UpdateReports(); +} + +// +// Runs when a Position Got Stop Loss ... +void XBTU5OnSL( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XBTU5IssueSLAlert(signal); + + // + // Remove Signal From Guard Protector ... + xBTU5Guard.Remove(signal.ticket); + xBTU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xBTU5Reporter.AddTradeSLInReports(); + XBTU5UpdateReports(); +} + +// +// Runs when a Position Risk Free ... +void XBTU5OnRF( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XBTU5IssueRFAlert(signal); + + // + // Remove Signal From Guard Protector ... + // since RiskFree Signals has SL ... + xBTU5Guard.Remove(signal.ticket); + xBTU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xBTU5Reporter.AddTradeSLInReports(); + XBTU5UpdateReports(); +} + +// +// Runs when a Position Force Closed ... +void XBTU5OnFC( + XSignal &signal // Specified Signal +) +{ + // + // Issue Propper Alert ... + XBTU5IssueFCAlert(signal); + + // + // Remove Signal From Guard Protector ... + xBTU5Guard.Remove(signal.ticket); + xBTU5Guard.RemoveSupport(signal.ticket); + + // + // Update Reports ... + xBTU5Reporter.AddTradeSLInReports(); + XBTU5UpdateReports(); +} + +// +// Runs when a Position Guarded ... +void XBTU5OnGuard( + 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); + + // + xBTU5MEnableProvider = false; + } + + // + // Issue Propper Alert ... + XBTU5IssueGuardAlert(signal, reason, isStopOut); + + // + // Update Reports ... + xBTU5Reporter.AddTradeSLInReports(); + XBTU5UpdateReports(); +} + +// +// END Event Handlers ... +// + +// +// END Provided Functions ... +// + +// +// START Private Functions ... +// + +// +// START Volume Baseed Functions ... +// + +// +// Calculating Volume for Tradings ... +double XBTU5CalculateVolume( + 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 = xBTU5Trader.Count(); + + // + double result = xBTU5VolumeManager.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 XBTU5UpdateReports() +{ + // + double staticVolume = xBTU5VolumeManager.GetStaticVolume(); + string staticVolumeCalculationMethod = EnumToString(xBTU5StaticVolumeMethod); + double maxAllowedVolume = xBTU5VolumeManager.GetMaxAllowedVolume(); + double volumeIncreaseMultiplier = xBTU5VolumeManager.GetVolumeMultiplier(); + double balanceGowingToApplyMultiplier = xBTU5VolumeManager.GetIncreaseMultiplierBalance(); + + double balanceGrowingToIncreaseMaxAllowedVolume = xBTU5VolumeManager.GetIncreaseMaxAllowedVolumeBalance(); + + // + // Update Reports Volume Info ... + xBTU5Reporter.UpdateReportsVolumeInfo( + staticVolume, + staticVolumeCalculationMethod, + maxAllowedVolume, + volumeIncreaseMultiplier, + balanceGowingToApplyMultiplier, + balanceGrowingToIncreaseMaxAllowedVolume); + + // + // Calculate Max Allowed Drawdown ... + double minBalanceForTradeBasedOnBalance = xBTU5Trader.GetMinBalanceForOpenTrades(); + xBTU5Reporter.UpdateMinBalanceForOpenTradesInReports(minBalanceForTradeBasedOnBalance); +} + +// +// Reset XBTU5 Info Buffers ... +void XBTU5ResetCollectors() +{ + // + // Reset Calculations Buffers and Variables ... + xBTU5MaxDrawUp = 0; + xBTU5MaxDrawDown = 0; + + // + xBTU5Trader.Reset(); + xBTU5Reporter.Reset(); + xBTU5Collector.Reset(); + xBTU5VolumeManager.ResetForceVolumeMultiplier(); +} + +// +// END Report/Collect and Guard Functions ... +// + +// +// START Alert Functions ... +// + +// +// Send Alert ... +void XBTU5IssueAlert(string message) +{ + // + // Validate Args ... + if (StringLen(message) <= 0) + { + return; + } + + // + if (xBTU5EnableAlerts) + { + SendAlert(message); + } + else + { + LogMessage(message); + } +} + +// +// Send Take Profit Alert on Specific Signal ... +void XBTU5IssueTPAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xBTU5Trader.GenerateSignalTPComment(signal); + + // + XBTU5IssueAlert(message); +} + +// +// Send Stop Loss Alert on Specific Signal ... +void XBTU5IssueSLAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xBTU5Trader.GenerateSignalSLComment(signal); + + // + XBTU5IssueAlert(message); +} + +// +// Send Force Close Alert on Specific Signal ... +void XBTU5IssueFCAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xBTU5Trader.GenerateSignalForceCloseComment(signal); + + // + XBTU5IssueAlert(message); +} + +// +// Send Risk Free Alert on Specific Signal ... +void XBTU5IssueRFAlert( + XSignal &signal // Specified Signal +) +{ + // + string message = ""; + + // + message = xBTU5Trader.GenerateSignalRFComment(signal, 0); + + // + XBTU5IssueAlert(message); +} + +// +// Send Guard Alert on Specific Signal ... +void XBTU5IssueGuardAlert( + XSignal &signal, // Specified Signal + ENUM_X_GUARD_REASONS reason, // Specified Guard Reason + bool isStopOut = false // Specified StopOut Fired or not +) +{ + // + string message = ""; + + // + message = xBTU5Guard.GenerateGuardedSignalComment( + signal, + reason); + + // + XBTU5IssueAlert(message); +} + +// +// Send Initialization Succeed Alert ... +void XBTU5IssueInitializationSucceedAlert() +{ + // + string message = "Initializion of (" + XBTU5ProviderName + " Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; + XBTU5IssueAlert(message); +} + +// +// Send De Initialization Succeed Alert ... +void XBTU5IssueDeinitializationSucceedAlert() +{ + // + string message = "De Initializion of (" + XBTU5ProviderName + " Provider" + ") Succeeded ..."; + XBTU5IssueAlert(message); +} + +// +// Send Signal Successfully Execution Alert ... +void XBTU5IssueSignalExecutionAlert( + XSignal &signal, // Specified Signal + string &providers[] // Signal Providers +) +{ + // + string message = xBTU5Trader.ToString(signal); + + // + string providersMsg = ToString(providers); + if (StringLen(providersMsg) > 0) + { + message += ", Providers: " + providersMsg; + } + + // + XBTU5IssueAlert(message); +} + +// +// Send Signal Execution Alert ... +void XBTU5IssueSignalExecutionError(int error) +{ + // + string message = GetSignalExecutionError(error); + if (StringLen(message) == 0) + { + return; + } + + // + XBTU5IssueAlert(message); +} + +// +// END Alert Functions ... +// + +// +// END Private Functions ... +// diff --git a/Projects/XBTU5/Settings/.gitkeep b/Projects/XBTU5/Settings/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XBTU5/Templates/.gitkeep b/Projects/XBTU5/Templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Classes/.gitkeep b/Projects/XEU5/Classes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Classes/x-saherelm.class.lib.mq5 b/Projects/XEU5/Classes/x-saherelm.class.lib.mq5 new file mode 100644 index 00000000..68f48471 --- /dev/null +++ b/Projects/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/Projects/XEU5/Classes/x-saherelm.nn.lib.mq5 b/Projects/XEU5/Classes/x-saherelm.nn.lib.mq5 new file mode 100644 index 00000000..8fa40f53 --- /dev/null +++ b/Projects/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/Projects/XEU5/Classes/x-saherelm.provider.lib.mq5 b/Projects/XEU5/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 00000000..1dbdcd3f --- /dev/null +++ b/Projects/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/Projects/XEU5/Documents/.gitkeep b/Projects/XEU5/Documents/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Documents/Reports/.gitkeep b/Projects/XEU5/Documents/Reports/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Documents/Settings/.gitkeep b/Projects/XEU5/Documents/Settings/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Experts/.gitkeep b/Projects/XEU5/Experts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Experts/x-saherelm.xeu5.ea.mq5 b/Projects/XEU5/Experts/x-saherelm.xeu5.ea.mq5 new file mode 100644 index 00000000..58c5bdac --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/.gitkeep b/Projects/XEU5/Helpers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xama.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f565e415 --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..d7071b48 --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e84d762f --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..19d3417c --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xlh.indicator.helper.lib.mq5 new file mode 100644 index 00000000..e6a92f65 --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xobd.indicator.helper.lib.mq5 new file mode 100644 index 00000000..f90f15b2 --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..e6971b7a --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..6286228b --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xtm.indicator.helper.lib.mq5 new file mode 100644 index 00000000..a871ed42 --- /dev/null +++ b/Projects/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/Projects/XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 b/Projects/XEU5/Helpers/x-saherelm.xts.oscillator.helper.lib.mq5 new file mode 100644 index 00000000..875eec08 --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/.gitkeep b/Projects/XEU5/Indicators/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Indicators/x-saherelm.xama.indicator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 00000000..5c74787c --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 00000000..12d6c691 --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 00000000..cfd393ca --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xlh.indicator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 00000000..4dfc64e2 --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xobd.indicator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 00000000..4ac05cf6 --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 00000000..5659e07d --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 00000000..5f46d187 --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xtm.indicator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 00000000..eac88e0a --- /dev/null +++ b/Projects/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/Projects/XEU5/Indicators/x-saherelm.xts.oscillator.mq5 b/Projects/XEU5/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 00000000..46e9fbf9 --- /dev/null +++ b/Projects/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/Projects/XEU5/Libraries/.gitkeep b/Projects/XEU5/Libraries/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Libraries/x-saherelm.alert.lib.mq5 b/Projects/XEU5/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 00000000..10790632 --- /dev/null +++ b/Projects/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/Projects/XEU5/Libraries/x-saherelm.common.lib.mq5 b/Projects/XEU5/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 00000000..290dde9b --- /dev/null +++ b/Projects/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/Projects/XEU5/Libraries/x-saherelm.draw.lib.mq5 b/Projects/XEU5/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 00000000..ece98c83 --- /dev/null +++ b/Projects/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/Projects/XEU5/Libraries/x-saherelm.http.lib.mq5 b/Projects/XEU5/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 00000000..97f7ac0a --- /dev/null +++ b/Projects/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/Projects/XEU5/Libraries/x-saherelm.log.lib.mq5 b/Projects/XEU5/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 00000000..70f1bda4 --- /dev/null +++ b/Projects/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/Projects/XEU5/Libraries/x-saherelm.models.lib.mq5 b/Projects/XEU5/Libraries/x-saherelm.models.lib.mq5 new file mode 100644 index 00000000..b98ae3e8 --- /dev/null +++ b/Projects/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/Projects/XEU5/Providers/.gitkeep b/Projects/XEU5/Providers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 b/Projects/XEU5/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 new file mode 100644 index 00000000..c077b65f --- /dev/null +++ b/Projects/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/Projects/XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 b/Projects/XEU5/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 new file mode 100644 index 00000000..03e0a509 --- /dev/null +++ b/Projects/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/Projects/XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 b/Projects/XEU5/Providers/x-saherelm.xeu5.provider.lib.mq5 new file mode 100644 index 00000000..c57de45d --- /dev/null +++ b/Projects/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/Projects/XEU5/Settings/.gitkeep b/Projects/XEU5/Settings/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Projects/XEU5/Settings/xeu5.longs.vbb.set b/Projects/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/Projects/XEU5/Settings/xeu5.vbb.set b/Projects/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/Projects/XEU5/Templates/.gitkeep b/Projects/XEU5/Templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 b/Providers/x-saherelm.xeu5.provider.indicators.lib.mq5 new file mode 100644 index 00000000..c077b65f --- /dev/null +++ b/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/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 b/Providers/x-saherelm.xeu5.provider.inputs.lib.mq5 new file mode 100644 index 00000000..03e0a509 --- /dev/null +++ b/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/Providers/x-saherelm.xeu5.provider.lib.mq5 b/Providers/x-saherelm.xeu5.provider.lib.mq5 new file mode 100644 index 00000000..c57de45d --- /dev/null +++ b/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/README.md b/README.md new file mode 100644 index 00000000..31dbde13 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# MQL5 + +this is a workspace which contains MetaTrader4 Data Folder Contents to Directly develop MQL5 using VSCode and test them. + +## Maintainer + +Hadi Khazaee asl + +[https://www.saherelm.ir](https://www.saherelm.ir) + +[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com) diff --git a/package.json b/package.json new file mode 100644 index 00000000..81edb960 --- /dev/null +++ b/package.json @@ -0,0 +1,108 @@ +{ + "name": "mql5", + "version": "1.0.0", + "description": "MQL5 Workspace", + "main": "index.js", + "scripts": { + "true": "", + "aaa": "|----------|", + "aab": "| Projects |", + "aac": "|----------|", + "rmExperts": "shx --silent rm ./Experts/* || npm run true", + "rmHelpers": "shx --silent rm ./Helpers/* || npm run true", + "rmClasses": "shx --silent rm ./Classes/* || npm run true", + "rmLibraries": "shx --silent rm ./Libraries/* || npm run true", + "rmProviders": "shx --silent rm ./Providers/* || npm run true", + "rmIndicators": "shx --silent rm ./Indicators/* || npm run true", + "bkpExperts": "shx --silent mkdir -p ./BKP/Main/Experts && shx --silent cp -r ./Experts/*.mq5 ./BKP/Main/Experts || npm run true", + "bkpHelpers": "shx --silent mkdir -p ./BKP/Main/Helpers && shx --silent cp -r ./Helpers/*.mq5 ./BKP/Main/Helpers || npm run true", + "bkpClasses": "shx --silent mkdir -p ./BKP/Main/Classes && shx --silent cp -r ./Classes/*.mq5 ./BKP/Main/Classes || npm run true", + "bkpLibraries": "shx --silent mkdir -p ./BKP/Main/Libraries && shx --silent cp -r ./Libraries/*.mq5 ./BKP/Main/Libraries || npm run true", + "bkpProviders": "shx --silent mkdir -p ./BKP/Main/Providers && shx --silent cp -r ./Providers/*.mq5 ./BKP/Main/Providers || npm run true", + "bkpIndicators": "shx --silent mkdir -p ./BKP/Main/Indicators && shx --silent cp -r ./Indicators/*.mq5 ./BKP/Main/Indicators || npm run true", + "cleanupWorkspace": "npm run rmExperts && npm run rmHelpers && npm run rmClasses && npm run rmLibraries && npm run rmProviders && npm run rmIndicators", + "backupWorkspace": "shx --silent rm -rf ./BKP/Main && npm run bkpExperts && npm run bkpHelpers && npm run bkpClasses && npm run bkpLibraries && npm run bkpProviders && npm run bkpIndicators", + "aba": "|----------|", + "abb": "| XEU5 |", + "abc": "|----------|", + "xEU5CpExperts": "shx --silent mkdir -p ./Experts && shx --silent cp -r ./Projects/XEU5/Experts/*.mq5 ./Experts || npm run true", + "xEU5CpHelpers": "shx --silent mkdir -p ./Helpers && shx --silent cp -r ./Projects/XEU5/Helpers/*.mq5 ./Helpers || npm run true", + "xEU5CpClasses": "shx --silent mkdir -p ./Classes && shx --silent cp -r ./Projects/XEU5/Classes/*.mq5 ./Classes || npm run true", + "xEU5CpProviders": "shx --silent mkdir -p ./Providers && shx --silent cp -r ./Projects/XEU5/Providers/*.mq5 ./Providers || npm run true", + "xEU5CpLibraries": "shx --silent mkdir -p ./Libraries && shx --silent cp -r ./Projects/XEU5/Libraries/*.mq5 ./Libraries || npm run true", + "xEU5CpIndicators": "shx --silent mkdir -p ./Indicators && shx --silent cp -r ./Projects/XEU5/Indicators/*.mq5 ./Indicators || npm run true", + "xEU5UpSourceExperts": "shx --silent cp -r ./Experts/*.mq5 ./Projects/XEU5/Experts || npm run true", + "xEU5UpSourceHelpers": "shx --silent cp -r ./Helpers/*.mq5 ./Projects/XEU5/Helpers || npm run true", + "xEU5UpSourceClasses": "shx --silent cp -r ./Classes/*.mq5 ./Projects/XEU5/Classes || npm run true", + "xEU5UpSourceProviders": "shx --silent cp -r ./Providers/*.mq5 ./Projects/XEU5/Providers || npm run true", + "xEU5UpSourceLibraries": "shx --silent cp -r ./Libraries/*.mq5 ./Projects/XEU5/Libraries || npm run true", + "xEU5UpSourceIndicators": "shx --silent cp -r ./Indicators/*.mq5 ./Projects/XEU5/Indicators || npm run true", + "xEU5CpWorkspace": "npm run xEU5CpExperts && npm run xEU5CpProviders && npm run xEU5CpIndicators && npm run xEU5CpLibraries && npm run xEU5CpHelpers && npm run xEU5CpClasses", + "xEU5UpSourceFromWorkspace": "npm run xEU5UpSourceExperts && npm run xEU5UpSourceProviders && npm run xEU5UpSourceIndicators && npm run xEU5UpSourceLibraries && npm run xEU5UpSourceHelpers && npm run xEU5UpSourceClasses", + "xEU5PrepareWorkspace": "npm run backupWorkspace && npm run cleanupWorkspace && npm run xEU5CpWorkspace", + "xEU5ApplyFromWorkspace": "npm run backupWorkspace && npm run xEU5UpSourceFromWorkspace", + "abd": "|----------|", + "abe": "| /XEU5 |", + "abf": "|----------|", + "aca": "|----------|", + "acb": "| XAU5 |", + "acc": "|----------|", + "xAU5CpExperts": "shx --silent mkdir -p ./Experts && shx --silent cp -r ./Projects/XAU5/Experts/*.mq5 ./Experts || npm run true", + "xAU5CpHelpers": "shx --silent mkdir -p ./Helpers && shx --silent cp -r ./Projects/XAU5/Helpers/*.mq5 ./Helpers || npm run true", + "xAU5CpClasses": "shx --silent mkdir -p ./Classes && shx --silent cp -r ./Projects/XAU5/Classes/*.mq5 ./Classes || npm run true", + "xAU5CpProviders": "shx --silent mkdir -p ./Providers && shx --silent cp -r ./Projects/XAU5/Providers/*.mq5 ./Providers || npm run true", + "xAU5CpLibraries": "shx --silent mkdir -p ./Libraries && shx --silent cp -r ./Projects/XAU5/Libraries/*.mq5 ./Libraries || npm run true", + "xAU5CpIndicators": "shx --silent mkdir -p ./Indicators && shx --silent cp -r ./Projects/XAU5/Indicators/*.mq5 ./Indicators || npm run true", + "xAU5UpSourceExperts": "shx --silent cp -r ./Experts/*.mq5 ./Projects/XAU5/Experts || npm run true", + "xAU5UpSourceHelpers": "shx --silent cp -r ./Helpers/*.mq5 ./Projects/XAU5/Helpers || npm run true", + "xAU5UpSourceClasses": "shx --silent cp -r ./Classes/*.mq5 ./Projects/XAU5/Classes || npm run true", + "xAU5UpSourceProviders": "shx --silent cp -r ./Providers/*.mq5 ./Projects/XAU5/Providers || npm run true", + "xAU5UpSourceLibraries": "shx --silent cp -r ./Libraries/*.mq5 ./Projects/XAU5/Libraries || npm run true", + "xAU5UpSourceIndicators": "shx --silent cp -r ./Indicators/*.mq5 ./Projects/XAU5/Indicators || npm run true", + "xAU5CpWorkspace": "npm run xAU5CpExperts && npm run xAU5CpProviders && npm run xAU5CpIndicators && npm run xAU5CpLibraries && npm run xAU5CpHelpers && npm run xAU5CpClasses", + "xAU5UpSourceFromWorkspace": "npm run xAU5UpSourceExperts && npm run xAU5UpSourceProviders && npm run xAU5UpSourceIndicators && npm run xAU5UpSourceLibraries && npm run xAU5UpSourceHelpers && npm run xAU5UpSourceClasses", + "xAU5PrepareWorkspace": "npm run backupWorkspace && npm run cleanupWorkspace && npm run xAU5CpWorkspace", + "xAU5ApplyFromWorkspace": "npm run backupWorkspace && npm run xAU5UpSourceFromWorkspace", + "acd": "|----------|", + "ace": "| /XAU5 |", + "acf": "|----------|", + "ada": "|-----------|", + "adb": "| XBTU5 |", + "adc": "|-----------|", + "xBTU5CpExperts": "shx --silent mkdir -p ./Experts && shx --silent cp -r ./Projects/XBTU5/Experts/*.mq5 ./Experts || npm run true", + "xBTU5CpHelpers": "shx --silent mkdir -p ./Helpers && shx --silent cp -r ./Projects/XBTU5/Helpers/*.mq5 ./Helpers || npm run true", + "xBTU5CpClasses": "shx --silent mkdir -p ./Classes && shx --silent cp -r ./Projects/XBTU5/Classes/*.mq5 ./Classes || npm run true", + "xBTU5CpProviders": "shx --silent mkdir -p ./Providers && shx --silent cp -r ./Projects/XBTU5/Providers/*.mq5 ./Providers || npm run true", + "xBTU5CpLibraries": "shx --silent mkdir -p ./Libraries && shx --silent cp -r ./Projects/XBTU5/Libraries/*.mq5 ./Libraries || npm run true", + "xBTU5CpIndicators": "shx --silent mkdir -p ./Indicators && shx --silent cp -r ./Projects/XBTU5/Indicators/*.mq5 ./Indicators || npm run true", + "xBTU5UpSourceExperts": "shx --silent cp -r ./Experts/*.mq5 ./Projects/XBTU5/Experts || npm run true", + "xBTU5UpSourceHelpers": "shx --silent cp -r ./Helpers/*.mq5 ./Projects/XBTU5/Helpers || npm run true", + "xBTU5UpSourceClasses": "shx --silent cp -r ./Classes/*.mq5 ./Projects/XBTU5/Classes || npm run true", + "xBTU5UpSourceProviders": "shx --silent cp -r ./Providers/*.mq5 ./Projects/XBTU5/Providers || npm run true", + "xBTU5UpSourceLibraries": "shx --silent cp -r ./Libraries/*.mq5 ./Projects/XBTU5/Libraries || npm run true", + "xBTU5UpSourceIndicators": "shx --silent cp -r ./Indicators/*.mq5 ./Projects/XBTU5/Indicators || npm run true", + "xBTU5CpWorkspace": "npm run xBTU5CpExperts && npm run xBTU5CpProviders && npm run xBTU5CpIndicators && npm run xBTU5CpLibraries && npm run xBTU5CpHelpers && npm run xBTU5CpClasses", + "xBTU5UpSourceFromWorkspace": "npm run xBTU5UpSourceExperts && npm run xBTU5UpSourceProviders && npm run xBTU5UpSourceIndicators && npm run xBTU5UpSourceLibraries && npm run xBTU5UpSourceHelpers && npm run xBTU5UpSourceClasses", + "xBTU5PrepareWorkspace": "npm run backupWorkspace && npm run cleanupWorkspace && npm run xBTU5CpWorkspace", + "xBTU5ApplyFromWorkspace": "npm run backupWorkspace && npm run xBTU5UpSourceFromWorkspace", + "add": "|-----------|", + "ade": "| /XBTU5 |", + "adf": "|-----------|", + "aad": "|-----------|", + "aae": "| /Projects |", + "aaf": "|-----------|" + }, + "repository": { + "type": "git", + "url": "https://pm.saherelmhub.ir/source/MQL5Data.git" + }, + "keywords": [ + "MQL5", + "ROBOT" + ], + "author": "Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)", + "license": "ISC", + "devDependencies": { + "shx": "^0.3.4" + } +} \ No newline at end of file

    r%ujQlFz8_DjL3?pJ_Vd>uB~MCuA~T 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