diff --git a/.github/workflows/backtest.yml b/.github/workflows/backtest.yml index f4a48be..cd3b446 100644 --- a/.github/workflows/backtest.yml +++ b/.github/workflows/backtest.yml @@ -35,14 +35,14 @@ jobs: include: . init-platform: true mt-version: 5.0.0.2361 - path: Stg_MA.mq4 + path: Stg_MA_Breakout.mq4 verbose: true - name: Compile for MQL5 uses: fx31337/mql-compile-action@master with: include: . mt-version: 5.0.0.2515 - path: Stg_MA.mq5 + path: Stg_MA_Breakout.mq5 verbose: true - name: List compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' @@ -73,7 +73,7 @@ jobs: OptFormatBrief: true OptFormatJson: true OptVerbose: true - TestExpert: "Stg_MA" + TestExpert: "Stg_MA_Breakout" TestPeriod: M1 TestReportName: Report-${{ matrix.year }}-${{ matrix.month }} - name: Upload results diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index d1f4a4e..242ecbb 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -37,14 +37,14 @@ jobs: include: . init-platform: true mt-version: 5.0.0.2361 - path: Stg_MA.mq4 + path: Stg_MA_Breakout.mq4 verbose: true - name: Compile for MQL5 uses: fx31337/mql-compile-action@master with: include: . mt-version: 5.0.0.2515 - path: Stg_MA.mq5 + path: Stg_MA_Breakout.mq5 verbose: true - name: List compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' diff --git a/README.md b/README.md index eb3c488..f72d837 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Strategy MA +# Strategy MA Breakout [![Status][gha-image-check-master]][gha-link-check-master] [![Status][gha-image-compile-master]][gha-link-compile-master] @@ -7,19 +7,12 @@ [![License][license-image]][license-link] [![Edit][gh-edit-badge]][gh-edit-link] -Strategy based on the moving average price indicators. +Strategy based on the moving average price indicators implementing breakout signal. ## Dependencies | Tag | Framework | |:--------:|:---------:| -| v1.000 | v2.000 | -| v1.001 | v2.001 | -| ... | ... | -| v1.010 | v2.010 | -| v1.011 | v2.011.1 | -| v1.012 | v2.012.1 | -| v1.013 | v2.013 | | v2.000 | v3.000.1 | @@ -28,12 +21,12 @@ Strategy based on the moving average price indicators. [gh-discuss-link]: https://github.com/EA31337/EA31337-Strategies/discussions [gh-edit-badge]: https://img.shields.io/badge/GitHub-edit-purple.svg?logo=github -[gh-edit-link]: https://github.dev/EA31337/Strategy-MA +[gh-edit-link]: https://github.dev/EA31337/Strategy-MA_Breakout -[gha-link-check-master]: https://github.com/EA31337/Strategy-MA/actions?query=workflow:Check+branch%3Amaster -[gha-image-check-master]: https://github.com/EA31337/Strategy-MA/workflows/Check/badge.svg?branch=master -[gha-link-compile-master]: https://github.com/EA31337/Strategy-MA/actions?query=workflow:Compile+branch%3Amaster -[gha-image-compile-master]: https://github.com/EA31337/Strategy-MA/workflows/Compile/badge.svg?branch=master +[gha-link-check-master]: https://github.com/EA31337/Strategy-MA_Breakout/actions?query=workflow:Check+branch%3Amaster +[gha-image-check-master]: https://github.com/EA31337/Strategy-MA_Breakout/workflows/Check/badge.svg?branch=master +[gha-link-compile-master]: https://github.com/EA31337/Strategy-MA_Breakout/actions?query=workflow:Compile+branch%3Amaster +[gha-image-compile-master]: https://github.com/EA31337/Strategy-MA_Breakout/workflows/Compile/badge.svg?branch=master [tg-channel-image]: https://img.shields.io/badge/Telegram-join-0088CC.svg?logo=telegram [tg-channel-link]: https://t.me/EA31337 diff --git a/Stg_MA.mqh b/Stg_MA.mqh deleted file mode 100644 index a3262c0..0000000 --- a/Stg_MA.mqh +++ /dev/null @@ -1,264 +0,0 @@ -/** - * @file - * Implements MA strategy based the moving average price indicators. - */ - -enum ENUM_STG_MA_TYPE { - STG_MA_TYPE_0_NONE = 0, // (None) - STG_MA_TYPE_AMA, // AMA: Adaptive Moving Average - STG_MA_TYPE_DEMA, // DEMA: Double Exponential Moving Average - STG_MA_TYPE_FRAMA, // FrAMA: Fractal Adaptive Moving Average - STG_MA_TYPE_ICHIMOKU, // Ichimoku - STG_MA_TYPE_MA, // MA: Moving Average - STG_MA_TYPE_PRICE_CHANNEL, // Price Channel - STG_MA_TYPE_SAR, // SAR: Parabolic Stop and Reverse - STG_MA_TYPE_TEMA, // TEMA: Triple Exponential Moving Average - STG_MA_TYPE_VIDYA, // VIDYA: Variable Index Dynamic Average -}; - -// User params. -INPUT_GROUP("MA strategy: main strategy params"); -INPUT ENUM_STG_MA_TYPE MA_Type = STG_MA_TYPE_MA; // Indicator MA type -INPUT_GROUP("MA strategy: strategy params"); -INPUT float MA_LotSize = 0; // Lot size -INPUT int MA_SignalOpenMethod = 1; // Signal open method (-127-127) -INPUT float MA_SignalOpenLevel = 0.2f; // Signal open level -INPUT int MA_SignalOpenFilterMethod = 32; // Signal open filter method -INPUT int MA_SignalOpenFilterTime = 3; // Signal open filter time -INPUT int MA_SignalOpenBoostMethod = 0; // Signal open boost method -INPUT int MA_SignalCloseMethod = 1; // Signal close method (-127-127) -INPUT int MA_SignalCloseFilter = 0; // Signal close filter (-127-127) -INPUT float MA_SignalCloseLevel = 0.0f; // Signal close level -INPUT int MA_PriceStopMethod = 1; // Price stop method (0-127) -INPUT float MA_PriceStopLevel = 2; // Price stop level -INPUT int MA_TickFilterMethod = 32; // Tick filter method -INPUT float MA_MaxSpread = 4.0; // Max spread to trade (pips) -INPUT short MA_Shift = 0; // Shift -INPUT float MA_OrderCloseLoss = 80; // Order close loss -INPUT float MA_OrderCloseProfit = 80; // Order close profit -INPUT int MA_OrderCloseTime = -30; // Order close time in mins (>0) or bars (<0) -INPUT_GROUP("MA strategy: AMA indicator params"); -INPUT int MA_Indi_AMA_InpPeriodAMA = 20; // AMA period -INPUT int MA_Indi_AMA_InpFastPeriodEMA = 4; // Fast EMA period -INPUT int MA_Indi_AMA_InpSlowPeriodEMA = 30; // Slow EMA period -INPUT int MA_Indi_AMA_InpShiftAMA = 4; // AMA shift -INPUT int MA_Indi_AMA_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_AMA_SourceType = IDATA_BUILTIN; // Source type -INPUT_GROUP("MA strategy: DEMA indicator params"); -INPUT int MA_Indi_DEMA_Period = 25; // Period -INPUT int MA_Indi_DEMA_MA_Shift = 6; // MA Shift -INPUT ENUM_APPLIED_PRICE MA_Indi_DEMA_Applied_Price = PRICE_TYPICAL; // Applied Price -INPUT int MA_Indi_DEMA_Shift = 0; // DEMA Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_DEMA_SourceType = IDATA_BUILTIN; // Source type -INPUT_GROUP("MA strategy: FrAMA indicator params"); -INPUT int MA_Indi_FrAMA_Period = 10; // Period -INPUT ENUM_APPLIED_PRICE MA_Indi_FrAMA_Applied_Price = PRICE_MEDIAN; // Applied Price -INPUT int MA_Indi_FrAMA_MA_Shift = 0; // MA Shift -INPUT int MA_Indi_FrAMA_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_FrAMA_SourceType = IDATA_BUILTIN; // Source type -INPUT_GROUP("MA strategy: Ichimoku indicator params"); -// INPUT ENUM_ICHIMOKU_LINE MA_Indi_Ichimoku_MA_Line = LINE_TENKANSEN; // Ichimoku line for MA -INPUT int MA_Indi_Ichimoku_Period_Tenkan_Sen = 30; // Period Tenkan Sen -INPUT int MA_Indi_Ichimoku_Period_Kijun_Sen = 10; // Period Kijun Sen -INPUT int MA_Indi_Ichimoku_Period_Senkou_Span_B = 30; // Period Senkou Span B -INPUT int MA_Indi_Ichimoku_Shift = 1; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_Ichimoku_SourceType = IDATA_BUILTIN; // Source type -INPUT_GROUP("MA strategy: MA indicator params"); -INPUT int MA_Indi_MA_Period = 26; // Period -INPUT int MA_Indi_MA_MA_Shift = 0; // MA Shift -INPUT ENUM_MA_METHOD MA_Indi_MA_Method = MODE_LWMA; // MA Method -INPUT ENUM_APPLIED_PRICE MA_Indi_MA_Applied_Price = PRICE_WEIGHTED; // Applied Price -INPUT int MA_Indi_MA_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_MA_SourceType = IDATA_BUILTIN; // Source type -INPUT_GROUP("MA strategy: Price Channel indicator params"); -INPUT int MA_Indi_PriceChannel_Period = 26; // Period -INPUT int MA_Indi_PriceChannel_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_PriceChannel_SourceType = IDATA_ICUSTOM; // Source type -INPUT_GROUP("MA strategy: SAR indicator params"); -INPUT float MA_Indi_SAR_Step = 0.04f; // Step -INPUT float MA_Indi_SAR_Maximum_Stop = 0.4f; // Maximum stop -INPUT int MA_Indi_SAR_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_SAR_SourceType = IDATA_ICUSTOM; // Source type -INPUT_GROUP("MA strategy: TEMA indicator params"); -INPUT int MA_Indi_TEMA_Period = 10; // Period -INPUT int MA_Indi_TEMA_MA_Shift = 0; // MA Shift -INPUT ENUM_APPLIED_PRICE MA_Indi_TEMA_Applied_Price = PRICE_WEIGHTED; // Applied Price -INPUT int MA_Indi_TEMA_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_TEMA_SourceType = IDATA_BUILTIN; // Source type -INPUT_GROUP("MA strategy: VIDYA indicator params"); -INPUT int MA_Indi_VIDYA_Period = 30; // Period -INPUT int MA_Indi_VIDYA_MA_Period = 20; // MA Period -INPUT int MA_Indi_VIDYA_MA_Shift = 1; // MA Shift -INPUT ENUM_APPLIED_PRICE MA_Indi_VIDYA_Applied_Price = PRICE_WEIGHTED; // Applied Price -INPUT int MA_Indi_VIDYA_Shift = 0; // Shift -INPUT ENUM_IDATA_SOURCE_TYPE MA_Indi_VIDYA_SourceType = IDATA_BUILTIN; // Source type - -// Structs. - -// Defines struct with default user strategy values. -struct Stg_MA_Params_Defaults : StgParams { - Stg_MA_Params_Defaults() - : StgParams(::MA_SignalOpenMethod, ::MA_SignalOpenFilterMethod, ::MA_SignalOpenLevel, ::MA_SignalOpenBoostMethod, - ::MA_SignalCloseMethod, ::MA_SignalCloseFilter, ::MA_SignalCloseLevel, ::MA_PriceStopMethod, - ::MA_PriceStopLevel, ::MA_TickFilterMethod, ::MA_MaxSpread, ::MA_Shift) { - Set(STRAT_PARAM_LS, MA_LotSize); - Set(STRAT_PARAM_OCL, MA_OrderCloseLoss); - Set(STRAT_PARAM_OCP, MA_OrderCloseProfit); - Set(STRAT_PARAM_OCT, MA_OrderCloseTime); - Set(STRAT_PARAM_SOFT, MA_SignalOpenFilterTime); - } -}; - -class Stg_MA : public Strategy { - public: - Stg_MA(StgParams &_sparams, TradeParams &_tparams, ChartParams &_cparams, string _name = "") - : Strategy(_sparams, _tparams, _cparams, _name) {} - - static Stg_MA *Init(ENUM_TIMEFRAMES _tf = NULL, EA *_ea = NULL) { - // Initialize strategy initial values. - Stg_MA_Params_Defaults stg_ma_defaults; - StgParams _stg_params(stg_ma_defaults); - // Initialize Strategy instance. - ChartParams _cparams(_tf, _Symbol); - TradeParams _tparams; - Strategy *_strat = new Stg_MA(_stg_params, _tparams, _cparams, "MA"); - return _strat; - } - - /** - * Event on strategy's init. - */ - void OnInit() { - // Initialize indicators. - switch (MA_Type) { - case STG_MA_TYPE_AMA: // AMA - { - IndiAMAParams _indi_params(::MA_Indi_AMA_InpPeriodAMA, ::MA_Indi_AMA_InpFastPeriodEMA, - ::MA_Indi_AMA_InpSlowPeriodEMA, ::MA_Indi_AMA_InpShiftAMA, PRICE_TYPICAL, - ::MA_Indi_AMA_Shift); - _indi_params.SetDataSourceType(::MA_Indi_AMA_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_AMA(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_DEMA: // DEMA - { - IndiDEIndiMAParams _indi_params(::MA_Indi_DEMA_Period, ::MA_Indi_DEMA_MA_Shift, ::MA_Indi_DEMA_Applied_Price, - ::MA_Indi_DEMA_Shift); - _indi_params.SetDataSourceType(::MA_Indi_DEMA_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_DEMA(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_FRAMA: // FrAMA - { - IndiFrAIndiMAParams _indi_params(::MA_Indi_FrAMA_Period, ::MA_Indi_FrAMA_MA_Shift, - ::MA_Indi_FrAMA_Applied_Price, ::MA_Indi_FrAMA_Shift); - _indi_params.SetDataSourceType(::MA_Indi_FrAMA_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_FrAMA(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_ICHIMOKU: // Ichimoku - { - IndiIchimokuParams _indi_params(::MA_Indi_Ichimoku_Period_Tenkan_Sen, ::MA_Indi_Ichimoku_Period_Kijun_Sen, - ::MA_Indi_Ichimoku_Period_Senkou_Span_B, ::MA_Indi_Ichimoku_Shift); - _indi_params.SetDataSourceType(::MA_Indi_Ichimoku_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_Ichimoku(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_MA: // MA - { - IndiMAParams _indi_params(::MA_Indi_MA_Period, ::MA_Indi_MA_MA_Shift, ::MA_Indi_MA_Method, - ::MA_Indi_MA_Applied_Price, ::MA_Indi_MA_Shift); - _indi_params.SetDataSourceType(::MA_Indi_MA_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_MA(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_PRICE_CHANNEL: // Price Channel - { - IndiPriceChannelParams _indi_params(::MA_Indi_PriceChannel_Period, ::MA_Indi_PriceChannel_Shift); - _indi_params.SetDataSourceType(::MA_Indi_PriceChannel_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_PriceChannel(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_SAR: // SAR - { - IndiSARParams _indi_params(::MA_Indi_SAR_Step, ::MA_Indi_SAR_Maximum_Stop, ::MA_Indi_SAR_Shift); - _indi_params.SetDataSourceType(::MA_Indi_SAR_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_SAR(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_TEMA: // TEMA - { - IndiTEMAParams _indi_params(::MA_Indi_TEMA_Period, ::MA_Indi_TEMA_MA_Shift, ::MA_Indi_TEMA_Applied_Price, - ::MA_Indi_TEMA_Shift); - _indi_params.SetDataSourceType(::MA_Indi_TEMA_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_TEMA(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_VIDYA: // VIDYA - { - IndiVIDYAParams _indi_params(::MA_Indi_VIDYA_Period, ::MA_Indi_VIDYA_MA_Period, ::MA_Indi_VIDYA_MA_Shift, - ::MA_Indi_VIDYA_Applied_Price, ::MA_Indi_VIDYA_Shift); - _indi_params.SetDataSourceType(::MA_Indi_VIDYA_SourceType); - _indi_params.SetTf(Get(STRAT_PARAM_TF)); - SetIndicator(new Indi_VIDYA(_indi_params), ::MA_Type); - break; - } - case STG_MA_TYPE_0_NONE: // (None) - default: - break; - } - } - - /** - * Check strategy's opening signal. - */ - bool SignalOpen(ENUM_ORDER_TYPE _cmd, int _method = 0, float _level = 0.0f, int _shift = 0) { - Chart *_chart = trade.GetChart(); - IndicatorBase *_indi = GetIndicator(::MA_Type); - uint _ishift = _shift; // @todo: _indi.GetShift(); - // bool _result = _indi.GetFlag(INDI_ENTRY_FLAG_IS_VALID, _shift); // @fixme - bool _result = true; - if (!_result) { - // Returns false when indicator data is not valid. - return false; - } - float _level_pips = (float)(_level * _chart.GetPipSize()); - switch (_cmd) { - case ORDER_TYPE_BUY: - _result &= _indi[_shift][0] >= _chart.GetOpen(_ishift) + _level_pips; - _result &= - _indi[_shift + 1][0] < _chart.GetOpen(_ishift + 1) || _indi[_shift + 2][0] < _chart.GetOpen(_ishift + 2); - _result &= _indi.IsIncreasing(1, 0, _shift); - if (_result && _method != 0) { - if (METHOD(_method, 0)) _result &= _indi.IsIncreasing(1, 0, _shift + 1); - if (METHOD(_method, 1)) _result &= _indi.IsIncreasing(4, 0, _shift + 3); - if (METHOD(_method, 2)) - _result &= fmax4(_indi[_shift][0], _indi[_shift + 1][0], _indi[_shift + 2][0], _indi[_shift + 3][0]) == - _indi[_shift][0]; - } - break; - case ORDER_TYPE_SELL: - _result &= _indi[_shift][0] <= _chart.GetOpen(_ishift) - _level_pips; - _result &= - _indi[_shift + 1][0] > _chart.GetOpen(_ishift + 1) || _indi[_shift + 2][0] > _chart.GetOpen(_ishift + 2); - _result &= _indi.IsDecreasing(1, 0, _shift); - if (_result && _method != 0) { - if (METHOD(_method, 0)) _result &= _indi.IsDecreasing(1, 0, _shift + 1); - if (METHOD(_method, 1)) _result &= _indi.IsDecreasing(4, 0, _shift + 3); - if (METHOD(_method, 2)) - _result &= fmin4(_indi[_shift][0], _indi[_shift + 1][0], _indi[_shift + 2][0], _indi[_shift + 3][0]) == - _indi[_shift][0]; - } - break; - } - return _result; - } -}; diff --git a/Stg_MA.mq4 b/Stg_MA_Breakout.mq4 similarity index 85% rename from Stg_MA.mq4 rename to Stg_MA_Breakout.mq4 index b7fb5b3..b5a0787 100644 --- a/Stg_MA.mq4 +++ b/Stg_MA_Breakout.mq4 @@ -6,8 +6,8 @@ /** * @file - * Implements MA strategy. + * Implements MA Breakout strategy. */ // Includes the main code. -#include "Stg_MA.mq5" +#include "Stg_MA_Breakout.mq5" diff --git a/Stg_MA.mq5 b/Stg_MA_Breakout.mq5 similarity index 90% rename from Stg_MA.mq5 rename to Stg_MA_Breakout.mq5 index 29e13e5..4f51ba9 100644 --- a/Stg_MA.mq5 +++ b/Stg_MA_Breakout.mq5 @@ -27,13 +27,13 @@ input ENUM_LOG_LEVEL Log_Level = V_INFO; // Log level. input bool Info_On_Chart = true; // Display info on chart. // Includes strategy. -#include "Stg_MA.mqh" +#include "Stg_MA_Breakout.mqh" // Defines. -#define ea_name "Strategy MA" +#define ea_name "Strategy MA Breakout" #define ea_version "2.000" -#define ea_desc "Strategy based on the moving average price indicators." -#define ea_link "https://github.com/EA31337/Strategy-MA" +#define ea_desc "Strategy based on the moving average price indicators implementing breakout signal." +#define ea_link "https://github.com/EA31337/Strategy-MA_Breakout" #define ea_author "EA31337 Ltd" // Properties. @@ -59,7 +59,7 @@ int OnInit() { bool _result = true; EAParams ea_params(__FILE__, Log_Level); ea = new EA(ea_params); - _result &= ea.StrategyAdd(Active_Tfs); + _result &= ea.StrategyAdd(Active_Tfs); return (_result ? INIT_SUCCEEDED : INIT_FAILED); } diff --git a/Stg_MA_Breakout.mqh b/Stg_MA_Breakout.mqh new file mode 100644 index 0000000..59b75b5 --- /dev/null +++ b/Stg_MA_Breakout.mqh @@ -0,0 +1,277 @@ +/** + * @file + * Implements strategy based on the moving average price indicators implementing breakout signal. + */ + +enum ENUM_STG_MA_BREAKOUT_TYPE { + STG_MA_BREAKOUT_TYPE_0_NONE = 0, // (None) + STG_MA_BREAKOUT_TYPE_AMA, // AMA: Adaptive Moving Average + STG_MA_BREAKOUT_TYPE_DEMA, // DEMA: Double Exponential Moving Average + STG_MA_BREAKOUT_TYPE_FRAMA, // FrAMA: Fractal Adaptive Moving Average + STG_MA_BREAKOUT_TYPE_ICHIMOKU, // Ichimoku + STG_MA_BREAKOUT_TYPE_MA, // MA: Moving Average + STG_MA_BREAKOUT_TYPE_PRICE_CHANNEL, // Price Channel + STG_MA_BREAKOUT_TYPE_SAR, // SAR: Parabolic Stop and Reverse + STG_MA_BREAKOUT_TYPE_TEMA, // TEMA: Triple Exponential Moving Average + STG_MA_BREAKOUT_TYPE_VIDYA, // VIDYA: Variable Index Dynamic Average +}; + +// User params. +INPUT_GROUP("MA Breakout strategy: main strategy params"); +INPUT ENUM_STG_MA_BREAKOUT_TYPE MA_Breakout_Type = STG_MA_BREAKOUT_TYPE_ICHIMOKU; // Indicator MA type +INPUT_GROUP("MA Breakout strategy: strategy params"); +INPUT float MA_Breakout_LotSize = 0; // Lot size +INPUT int MA_Breakout_SignalOpenMethod = 0; // Signal open method (-127-127) +INPUT float MA_Breakout_SignalOpenLevel = 1.0f; // Signal open level +INPUT int MA_Breakout_SignalOpenFilterMethod = 32; // Signal open filter method +INPUT int MA_Breakout_SignalOpenFilterTime = 3; // Signal open filter time +INPUT int MA_Breakout_SignalOpenBoostMethod = 0; // Signal open boost method +INPUT int MA_Breakout_SignalCloseMethod = 0; // Signal close method (-127-127) +INPUT int MA_Breakout_SignalCloseFilter = 0; // Signal close filter (-127-127) +INPUT float MA_Breakout_SignalCloseLevel = 1.0f; // Signal close level +INPUT int MA_Breakout_PriceStopMethod = 1; // Price stop method (0-127) +INPUT float MA_Breakout_PriceStopLevel = 2; // Price stop level +INPUT int MA_Breakout_TickFilterMethod = 32; // Tick filter method +INPUT float MA_Breakout_MaxSpread = 4.0; // Max spread to trade (pips) +INPUT short MA_Breakout_Shift = 0; // Shift +INPUT float MA_Breakout_OrderCloseLoss = 80; // Order close loss +INPUT float MA_Breakout_OrderCloseProfit = 80; // Order close profit +INPUT int MA_Breakout_OrderCloseTime = -30; // Order close time in mins (>0) or bars (<0) +INPUT_GROUP("MA Breakout strategy: AMA indicator params"); +INPUT int MA_Breakout_Indi_AMA_InpPeriodAMA = 20; // AMA period +INPUT int MA_Breakout_Indi_AMA_InpFastPeriodEMA = 4; // Fast EMA period +INPUT int MA_Breakout_Indi_AMA_InpSlowPeriodEMA = 30; // Slow EMA period +INPUT int MA_Breakout_Indi_AMA_InpShiftAMA = 4; // AMA Breakout shift +INPUT int MA_Breakout_Indi_AMA_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_AMA_SourceType = IDATA_BUILTIN; // Source type +INPUT_GROUP("MA Breakout strategy: DEMA indicator params"); +INPUT int MA_Breakout_Indi_DEMA_Period = 25; // Period +INPUT int MA_Breakout_Indi_DEMA_MA_Shift = 6; // MA Shift +INPUT ENUM_APPLIED_PRICE MA_Breakout_Indi_DEMA_Applied_Price = PRICE_TYPICAL; // Applied Price +INPUT int MA_Breakout_Indi_DEMA_Shift = 0; // DEMA Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_DEMA_SourceType = IDATA_BUILTIN; // Source type +INPUT_GROUP("MA Breakout strategy: FrAMA indicator params"); +INPUT int MA_Breakout_Indi_FrAMA_Period = 10; // Period +INPUT ENUM_APPLIED_PRICE MA_Breakout_Indi_FrAMA_Applied_Price = PRICE_MEDIAN; // Applied Price +INPUT int MA_Breakout_Indi_FrAMA_MA_Shift = 0; // MA Shift +INPUT int MA_Breakout_Indi_FrAMA_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_FrAMA_SourceType = IDATA_BUILTIN; // Source type +INPUT_GROUP("MA Breakout strategy: Ichimoku indicator params"); +// INPUT ENUM_ICHIMOKU_LINE MA_Breakout_Indi_Ichimoku_MA_Line = LINE_TENKANSEN; // Ichimoku line for MA +INPUT int MA_Breakout_Indi_Ichimoku_Period_Tenkan_Sen = 30; // Period Tenkan Sen +INPUT int MA_Breakout_Indi_Ichimoku_Period_Kijun_Sen = 10; // Period Kijun Sen +INPUT int MA_Breakout_Indi_Ichimoku_Period_Senkou_Span_B = 30; // Period Senkou Span B +INPUT int MA_Breakout_Indi_Ichimoku_Shift = 1; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_Ichimoku_SourceType = IDATA_BUILTIN; // Source type +INPUT_GROUP("MA Breakout strategy: MA indicator params"); +INPUT int MA_Breakout_Indi_MA_Period = 26; // Period +INPUT int MA_Breakout_Indi_MA_MA_Shift = 0; // MA Shift +INPUT ENUM_MA_METHOD MA_Breakout_Indi_MA_Method = MODE_LWMA; // MA Method +INPUT ENUM_APPLIED_PRICE MA_Breakout_Indi_MA_Applied_Price = PRICE_WEIGHTED; // Applied Price +INPUT int MA_Breakout_Indi_MA_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_MA_SourceType = IDATA_BUILTIN; // Source type +INPUT_GROUP("MA Breakout strategy: Price Channel indicator params"); +INPUT int MA_Breakout_Indi_PriceChannel_Period = 26; // Period +INPUT int MA_Breakout_Indi_PriceChannel_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_PriceChannel_SourceType = IDATA_ICUSTOM; // Source type +INPUT_GROUP("MA Breakout strategy: SAR indicator params"); +INPUT float MA_Breakout_Indi_SAR_Step = 0.04f; // Step +INPUT float MA_Breakout_Indi_SAR_Maximum_Stop = 0.4f; // Maximum stop +INPUT int MA_Breakout_Indi_SAR_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_SAR_SourceType = IDATA_ICUSTOM; // Source type +INPUT_GROUP("MA Breakout strategy: TEMA indicator params"); +INPUT int MA_Breakout_Indi_TEMA_Period = 10; // Period +INPUT int MA_Breakout_Indi_TEMA_MA_Shift = 0; // MA Shift +INPUT ENUM_APPLIED_PRICE MA_Breakout_Indi_TEMA_Applied_Price = PRICE_WEIGHTED; // Applied Price +INPUT int MA_Breakout_Indi_TEMA_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_TEMA_SourceType = IDATA_BUILTIN; // Source type +INPUT_GROUP("MA Breakout strategy: VIDYA indicator params"); +INPUT int MA_Breakout_Indi_VIDYA_Period = 30; // Period +INPUT int MA_Breakout_Indi_VIDYA_MA_Period = 20; // MA Period +INPUT int MA_Breakout_Indi_VIDYA_MA_Shift = 1; // MA Shift +INPUT ENUM_APPLIED_PRICE MA_Breakout_Indi_VIDYA_Applied_Price = PRICE_WEIGHTED; // Applied Price +INPUT int MA_Breakout_Indi_VIDYA_Shift = 0; // Shift +INPUT ENUM_IDATA_SOURCE_TYPE MA_Breakout_Indi_VIDYA_SourceType = IDATA_BUILTIN; // Source type + +// Structs. + +// Defines struct with default user strategy values. +struct Stg_MA_Breakout_Params_Defaults : StgParams { + Stg_MA_Breakout_Params_Defaults() + : StgParams(::MA_Breakout_SignalOpenMethod, ::MA_Breakout_SignalOpenFilterMethod, ::MA_Breakout_SignalOpenLevel, + ::MA_Breakout_SignalOpenBoostMethod, ::MA_Breakout_SignalCloseMethod, ::MA_Breakout_SignalCloseFilter, + ::MA_Breakout_SignalCloseLevel, ::MA_Breakout_PriceStopMethod, ::MA_Breakout_PriceStopLevel, + ::MA_Breakout_TickFilterMethod, ::MA_Breakout_MaxSpread, ::MA_Breakout_Shift) { + Set(STRAT_PARAM_LS, MA_Breakout_LotSize); + Set(STRAT_PARAM_OCL, MA_Breakout_OrderCloseLoss); + Set(STRAT_PARAM_OCP, MA_Breakout_OrderCloseProfit); + Set(STRAT_PARAM_OCT, MA_Breakout_OrderCloseTime); + Set(STRAT_PARAM_SOFT, MA_Breakout_SignalOpenFilterTime); + } +}; + +class Stg_MA_Breakout : public Strategy { + public: + Stg_MA_Breakout(StgParams &_sparams, TradeParams &_tparams, ChartParams &_cparams, string _name = "") + : Strategy(_sparams, _tparams, _cparams, _name) {} + + static Stg_MA_Breakout *Init(ENUM_TIMEFRAMES _tf = NULL, EA *_ea = NULL) { + // Initialize strategy initial values. + Stg_MA_Breakout_Params_Defaults stg_ma_defaults; + StgParams _stg_params(stg_ma_defaults); + // Initialize Strategy instance. + ChartParams _cparams(_tf, _Symbol); + TradeParams _tparams; + Strategy *_strat = new Stg_MA_Breakout(_stg_params, _tparams, _cparams, "MA"); + return _strat; + } + + /** + * Event on strategy's init. + */ + void OnInit() { + // Initialize indicators. + switch (::MA_Breakout_Type) { + case STG_MA_BREAKOUT_TYPE_AMA: // AMA + { + IndiAMAParams _indi_params(::MA_Breakout_Indi_AMA_InpPeriodAMA, ::MA_Breakout_Indi_AMA_InpFastPeriodEMA, + ::MA_Breakout_Indi_AMA_InpSlowPeriodEMA, ::MA_Breakout_Indi_AMA_InpShiftAMA, + PRICE_TYPICAL, ::MA_Breakout_Indi_AMA_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_AMA_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_AMA(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_DEMA: // DEMA + { + IndiDEIndiMAParams _indi_params(::MA_Breakout_Indi_DEMA_Period, ::MA_Breakout_Indi_DEMA_MA_Shift, + ::MA_Breakout_Indi_DEMA_Applied_Price, ::MA_Breakout_Indi_DEMA_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_DEMA_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_DEMA(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_FRAMA: // FrAMA + { + IndiFrAIndiMAParams _indi_params(::MA_Breakout_Indi_FrAMA_Period, ::MA_Breakout_Indi_FrAMA_MA_Shift, + ::MA_Breakout_Indi_FrAMA_Applied_Price, ::MA_Breakout_Indi_FrAMA_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_FrAMA_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_FrAMA(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_ICHIMOKU: // Ichimoku + { + IndiIchimokuParams _indi_params( + ::MA_Breakout_Indi_Ichimoku_Period_Tenkan_Sen, ::MA_Breakout_Indi_Ichimoku_Period_Kijun_Sen, + ::MA_Breakout_Indi_Ichimoku_Period_Senkou_Span_B, ::MA_Breakout_Indi_Ichimoku_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_Ichimoku_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_Ichimoku(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_MA: // MA + { + IndiMAParams _indi_params(::MA_Breakout_Indi_MA_Period, ::MA_Breakout_Indi_MA_MA_Shift, + ::MA_Breakout_Indi_MA_Method, ::MA_Breakout_Indi_MA_Applied_Price, + ::MA_Breakout_Indi_MA_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_MA_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_MA(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_PRICE_CHANNEL: // Price Channel + { + IndiPriceChannelParams _indi_params(::MA_Breakout_Indi_PriceChannel_Period, + ::MA_Breakout_Indi_PriceChannel_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_PriceChannel_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_PriceChannel(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_SAR: // SAR + { + IndiSARParams _indi_params(::MA_Breakout_Indi_SAR_Step, ::MA_Breakout_Indi_SAR_Maximum_Stop, + ::MA_Breakout_Indi_SAR_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_SAR_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_SAR(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_TEMA: // TEMA + { + IndiTEMAParams _indi_params(::MA_Breakout_Indi_TEMA_Period, ::MA_Breakout_Indi_TEMA_MA_Shift, + ::MA_Breakout_Indi_TEMA_Applied_Price, ::MA_Breakout_Indi_TEMA_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_TEMA_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_TEMA(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_VIDYA: // VIDYA + { + IndiVIDYAParams _indi_params(::MA_Breakout_Indi_VIDYA_Period, ::MA_Breakout_Indi_VIDYA_MA_Period, + ::MA_Breakout_Indi_VIDYA_MA_Shift, ::MA_Breakout_Indi_VIDYA_Applied_Price, + ::MA_Breakout_Indi_VIDYA_Shift); + _indi_params.SetDataSourceType(::MA_Breakout_Indi_VIDYA_SourceType); + _indi_params.SetTf(Get(STRAT_PARAM_TF)); + SetIndicator(new Indi_VIDYA(_indi_params), ::MA_Breakout_Type); + break; + } + case STG_MA_BREAKOUT_TYPE_0_NONE: // (None) + default: + break; + } + } + + /** + * Check strategy's opening signal. + */ + bool SignalOpen(ENUM_ORDER_TYPE _cmd, int _method = 0, float _level = 0.0f, int _shift = 0) { + Chart *_chart = trade.GetChart(); + IndicatorBase *_indi = GetIndicator(::MA_Breakout_Type); + uint _ishift = _shift; // @todo: _indi.GetShift(); + // bool _result = _indi.GetFlag(INDI_ENTRY_FLAG_IS_VALID, _shift); // @fixme + bool _result = true; + if (!_result) { + // Returns false when indicator data is not valid. + return false; + } + float _level_pips = (float)(_level * _chart.GetPipSize()); + double _value1 = _indi[_ishift][0]; + ChartEntry _ohlc_candle0 = _chart.GetEntry(0); + ChartEntry _ohlc_candle1 = _chart.GetEntry(1); + ChartEntry _ohlc_d1_0 = _chart.GetEntry(PERIOD_D1, _shift, _chart.GetSymbol()); + ChartEntry _ohlc_d1_1 = _chart.GetEntry(PERIOD_D1, _shift + 1, _chart.GetSymbol()); + double _range_candle = _ohlc_candle0.bar.ohlc.GetRange() + _ohlc_candle1.bar.ohlc.GetRange(); + double _range_d1 = _ohlc_d1_0.bar.ohlc.GetRange() + _ohlc_d1_1.bar.ohlc.GetRange(); + // double _tf_in_h = ChartTf::TfToHours(_chart.Get(CHART_PARAM_TF)); // @fixme: It returns 0.0? + double _range_pc = + (100 / _range_d1) * _range_candle / ChartTf::TfToMinutes(_chart.Get(CHART_PARAM_TF)); + _result &= _range_pc > _level; + _result &= (_chart.GetLow(_ishift) < _indi[_shift][0] && _chart.GetHigh(_ishift) > _indi[_shift][0]) || + (_chart.GetLow(_ishift + 1) < _indi[_shift][0] && _chart.GetHigh(_ishift + 1) > _indi[_shift][0]); + switch (_cmd) { + case ORDER_TYPE_BUY: + _result &= _ohlc_candle0.bar.ohlc.IsBull() || _ohlc_candle1.bar.ohlc.IsBull(); + if (_result && _method != 0) { + if (METHOD(_method, 0)) _result &= _indi.IsIncreasing(1, 0, _shift); + if (METHOD(_method, 1)) _result &= _indi.IsIncreasing(4, 0, _shift + 3); + if (METHOD(_method, 2)) + _result &= fmax4(_indi[_shift][0], _indi[_shift + 1][0], _indi[_shift + 2][0], _indi[_shift + 3][0]) == + _indi[_shift][0]; + } + break; + case ORDER_TYPE_SELL: + _result &= _ohlc_candle0.bar.ohlc.IsBear() || _ohlc_candle1.bar.ohlc.IsBear(); + if (_result && _method != 0) { + if (METHOD(_method, 0)) _result &= _indi.IsDecreasing(1, 0, _shift); + if (METHOD(_method, 1)) _result &= _indi.IsDecreasing(4, 0, _shift + 3); + if (METHOD(_method, 2)) + _result &= fmin4(_indi[_shift][0], _indi[_shift + 1][0], _indi[_shift + 2][0], _indi[_shift + 3][0]) == + _indi[_shift][0]; + } + break; + } + return _result; + } +}; diff --git a/Stg_MA.mqproj b/Stg_MA_Breakout.mqproj similarity index 87% rename from Stg_MA.mqproj rename to Stg_MA_Breakout.mqproj index 486d5dc..2b50749 100644 --- a/Stg_MA.mqproj +++ b/Stg_MA_Breakout.mqproj @@ -2,7 +2,7 @@ "platform" :"mt5", "program_type":"expert", "copyright" :"Copyright 2016-2023, EA31337 Ltd", - "link" :"https:\/\/github.com\/EA31337\/Strategy-MA", + "link" :"https:\/\/github.com\/EA31337\/Strategy-MA_Breakout", "version" :"2.000", "description" :"Strategy based on the moving average price indicators.", "optimize" :"0", @@ -15,7 +15,7 @@ "files": [ { - "path":"Stg_MA.mq5", + "path":"Stg_MA_Breakout.mq5", "compile":true, "relative_to_project":true }, @@ -215,7 +215,7 @@ "relative_to_project":false }, { - "path":"Stg_MA.mqh", + "path":"Stg_MA_Breakout.mqh", "compile":false, "relative_to_project":true }, @@ -708,6 +708,91 @@ "path":"MQL5\\Include\\EA31337-classes\\Storage\\Singleton.h", "compile":false, "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_AMA.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ValueStorage.price.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ObjectsCache.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Price\\Indi_Price.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_DEMA.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_FractalAdaptiveMA.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ValueStorage.all.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ValueStorage.spread.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ValueStorage.tick_volume.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ValueStorage.time.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Storage\\ValueStorage.volume.h", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_Ichimoku.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_PriceChannel.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_ZigZag.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_SAR.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_TEMA.mqh", + "compile":false, + "relative_to_project":false + }, + { + "path":"MQL5\\Include\\EA31337-classes\\Indicators\\Indi_VIDYA.mqh", + "compile":false, + "relative_to_project":false } ] -} +} \ No newline at end of file