From e53530621c2b0c84f5cbbc1825c2d0f7f13874ef Mon Sep 17 00:00:00 2001 From: kenorb Date: Sun, 20 Jun 2021 23:24:00 +0100 Subject: [PATCH] Strategy: Adds StrategyPriceStop struct logic --- Strategy.mqh | 28 ++++++- Strategy.struct.h | 3 + Strategy.struct.pricestop.h | 147 ++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 Strategy.struct.pricestop.h diff --git a/Strategy.mqh b/Strategy.mqh index 4c0fff726..74e848e50 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -1162,8 +1162,32 @@ class Strategy : public Object { * Returns current stop loss value when _mode is ORDER_TYPE_SL * and profit take when _mode is ORDER_TYPE_TP. */ - virtual float PriceStop(ENUM_ORDER_TYPE _cmd, ENUM_ORDER_TYPE_VALUE _mode, int _method = 0, - float _level = 0.0f) = NULL; + virtual float PriceStop(ENUM_ORDER_TYPE _cmd, ENUM_ORDER_TYPE_VALUE _mode, int _method = 0, float _level = 0.0f) { + double _result = 0; + float _trade_dist = trade.GetTradeDistanceInValue(); + int _count = (int)fmax(fabs(_level), fabs(_method)); + int _direction = Order::OrderDirection(_cmd, _mode); + Chart *_chart = trade.GetChart(); + Indicator *_indi = GetIndicator(); + StrategyPriceStop _psm(_method); + _psm.SetChartParams(_chart.GetParams()); + if (Object::IsValid(_indi)) { + int _ishift = _direction > 0 ? _indi.GetHighest(_count) : _indi.GetLowest(_count); + _psm.SetIndicatorPriceValue(_indi.GetValuePrice(_ishift, 0, PRICE_CLOSE)); + /* + //IndicatorDataEntry _data[]; + if (_indi.CopyEntries(_data, 3, 0)) { + _psm.SetIndicatorDataEntry(_data); + _psm.SetIndicatorParams(_indi.GetParams()); + } + */ + _result = _psm.GetValue(_ishift, _direction, _trade_dist); + } else { + int _pshift = _direction > 0 ? _chart.GetHighest(_count) : _chart.GetLowest(_count); + _result = _psm.GetValue(_pshift, _direction, _trade_dist); + } + return (float)_result; + } /** * Gets trend strength value. diff --git a/Strategy.struct.h b/Strategy.struct.h index 27ab2d9e7..19c281dbc 100644 --- a/Strategy.struct.h +++ b/Strategy.struct.h @@ -33,6 +33,7 @@ // Includes. #include "Serializer.mqh" #include "Strategy.enum.h" +#include "Strategy.struct.pricestop.h" #include "Task.struct.h" // Forward class declaration. @@ -129,6 +130,7 @@ struct StgParams { } // Deconstructor. ~StgParams() {} + // Getters. template T Get(ENUM_STRATEGY_PARAM _param) { @@ -171,6 +173,7 @@ struct StgParams { SetUserError(ERR_INVALID_PARAMETER); return WRONG_VALUE; } + bool HasIndicator(int _id = 0) { return GetIndicator(_id) != NULL; } bool IsBoosted() { return is_boosted; } bool IsEnabled() { return is_enabled; } bool IsSuspended() { return is_suspended; } diff --git a/Strategy.struct.pricestop.h b/Strategy.struct.pricestop.h new file mode 100644 index 000000000..f018bfce9 --- /dev/null +++ b/Strategy.struct.pricestop.h @@ -0,0 +1,147 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * @file + * Includes Indicator's signal structs. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Forward declaration. +struct ChartParams; +struct IndicatorDataEntry; +struct IndicatorParams; + +// Includes. +#include "Chart.struct.h" + +/* Structure for strategy price stops. */ +struct StrategyPriceStop { + /* Define enumeration for strategy price stops. */ + enum ENUM_STRATEGY_PRICE_STOP { + STRATEGY_PRICE_STOP_NONE = 0 << 0, // (None) + STRATEGY_PRICE_STOP_INDI_PEAK = 1 << 0, // Indicator value peak. + STRATEGY_PRICE_STOP_INDI_PRICE = 1 << 1, // Indicator value. + STRATEGY_PRICE_STOP_PRICE = 1 << 2, // Price value. + STRATEGY_PRICE_STOP_PRICE_PEAK = 1 << 3, // Price value peak. + STRATEGY_PRICE_STOP_PRICE_PP = 1 << 4, // Price value of Pivot res/sup. + STRATEGY_PRICE_STOP_VALUE_ADD_PRICE_DIFF = 1 << 5, // Add price difference. + STRATEGY_PRICE_STOP_VALUE_ADD_RANGE = 1 << 6, // Add candle range to the trail value. + // STRATEGY_PRICE_STOP_INDI_CHG_PCT = 1 << 0, // Indicator value change (%). + }; + + float ivalue; // Indicator price value. + unsigned int method; // Store price stop methods (@see: ENUM_STRATEGY_PRICE_STOP). + // unsigned int mode[2]; // Indicator modes to use. + ChartParams cparams; + // IndicatorDataEntry idata[]; + // IndicatorParams iparams; + + /* Constructors */ + void StrategyPriceStop(int _method = 0, float _ivalue = 0) : method(_method), ivalue(_ivalue) {} + // Main methods. + // Calculate price stop value. + float GetValue(int _shift = 0, int _direction = -1, float _min_trade_dist = 0.0f) { + float _result = ivalue, _trail = _min_trade_dist; + BarOHLC _ohlc0 = Chart::GetOHLC(cparams.tf.GetTf(), 0, cparams.symbol); + BarOHLC _ohlc1 = Chart::GetOHLC(cparams.tf.GetTf(), _shift, cparams.symbol); + if (CheckMethod(STRATEGY_PRICE_STOP_INDI_PRICE)) { + _result = ivalue; + } + if (CheckMethod(STRATEGY_PRICE_STOP_PRICE)) { + // Use price as a base line for the stop value. + float _price; + ENUM_APPLIED_PRICE _ap = PRICE_WEIGHTED; + if (CheckMethod(STRATEGY_PRICE_STOP_PRICE_PEAK)) { + // On peak, use low or high prices instead. + _ap = _direction > 0 ? PRICE_HIGH : PRICE_LOW; + } + _price = (float)ChartStatic::iPrice(_ap, cparams.symbol, cparams.tf.GetTf(), _shift); + _result = _direction > 0 ? fmax(_price, _result) : fmin(_price, _result); + } + if (CheckMethod(STRATEGY_PRICE_STOP_PRICE_PP)) { + float _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4; + float _prices[4]; + _prices[0] = _ohlc0.GetClose(); + _prices[1] = _direction > 0 ? _ohlc0.GetHigh() : _ohlc0.GetLow(); + _prices[2] = _direction > 0 ? _ohlc1.GetHigh() : _ohlc1.GetLow(); + _prices[3] = _ohlc1.GetOpen(); + BarOHLC _ohlc_pp(_prices, _ohlc0.GetTime()); + _ohlc_pp.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); + _result = _direction > 0 ? fmax(_r1, _result) : fmin(_s1, _result); + } + if (CheckMethod(STRATEGY_PRICE_STOP_VALUE_ADD_PRICE_DIFF)) { + _trail += fabs(_ohlc0.GetPivot() - _ohlc1.GetPivot()); + } + if (CheckMethod(STRATEGY_PRICE_STOP_VALUE_ADD_RANGE)) { + _trail += _ohlc1.GetRange(); + } + _result = _result > 0 ? (_direction > 0 ? _result + _trail : _result - _trail) : 0; + return _result; + } + /* Setters */ + void SetChartParams(ChartParams &_cparams) { cparams = _cparams; } + void SetIndicatorPriceValue(float _ivalue) { ivalue = _ivalue; } + /* + void SetIndicatorDataEntry(IndicatorDataEntry &_data[]) { + int _asize = ArraySize(idata); + for (int i = 0; i < _asize; i++) { + idata[i] = _data[i]; + } + } + void SetIndicatorParams(IndicatorParams &_iparams, int _m1 = 0, int _m2 = 0) { + iparams = _iparams; + mode[0] = _m1; + mode[1] = _m2; + } + */ + /* Flag getters */ + bool CheckMethod(unsigned int _flags) { return (method & _flags) != 0; } + bool CheckMethodsXor(unsigned int _flags) { return (method ^ _flags) != 0; } + bool CheckMethodAll(unsigned int _flags) { return (method & _flags) == _flags; } + bool CheckMethodXorAll(unsigned int _flags) { return (method ^ _flags) == _flags; } + unsigned int GetMethod() { return method; } + /* Flag setters */ + void AddMethod(unsigned int _flags) { method |= _flags; } + void RemoveMethod(unsigned int _flags) { method &= ~_flags; } + void SetMethod(ENUM_STRATEGY_PRICE_STOP _flag, bool _value = true) { + if (_value) { + AddMethod(_flag); + } else { + RemoveMethod(_flag); + } + } + void SetMethod(unsigned int _flags) { method = _flags; } + /* Serializers */ + SerializerNodeType Serialize(Serializer &_s) { + int _size = sizeof(int) * 8; + for (int i = 0; i < _size; i++) { + int _value = CheckMethod(1 << i) ? 1 : 0; + _s.Pass(this, (string)(i + 1), _value, SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); + } + return SerializerNodeObject; + } +};