diff --git a/.github/workflows/test-indicators-special.yml b/.github/workflows/test-indicators-special.yml new file mode 100644 index 000000000..6e3cfc6e0 --- /dev/null +++ b/.github/workflows/test-indicators-special.yml @@ -0,0 +1,65 @@ +--- +name: Test Indicators (Special) + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - 'Indicator**' + - 'Indicators/Special/**' + - '.github/workflows/test-indicators-special.yml' + push: + paths: + - 'Indicator**' + - 'Indicators/Special/**' + - '.github/workflows/test-indicators-special.yml' + +jobs: + + Compile: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Compile + uses: fx31337/mql-compile-action@master + with: + init-platform: true + path: 'Indicators/Special/tests' + verbose: true + - name: Print compiled files + run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' + shell: powershell + - name: Upload artifacts (MQL4) + uses: actions/upload-artifact@v2 + with: + name: files-ex4 + path: '**/*.ex4' + - name: Upload artifacts (MQL5) + uses: actions/upload-artifact@v2 + with: + name: files-ex5 + path: '**/*.ex5' + + Indicators-Tests-MQL4: + defaults: + run: + shell: bash + working-directory: Indicators/tests + needs: Compile + runs-on: ubuntu-latest + strategy: + matrix: + test: + - Indi_Custom.test + steps: + - uses: actions/download-artifact@v2 + with: + name: files-ex4 + - name: Run ${{ matrix.test }} + uses: fx31337/mql-tester-action@master + with: + BtDays: 4-8 + BtMonths: 1 + BtYears: 2020 + TestExpert: ${{ matrix.test }} + timeout-minutes: 10 diff --git a/.github/workflows/test-tick.yml b/.github/workflows/test-tick.yml new file mode 100644 index 000000000..941fe371a --- /dev/null +++ b/.github/workflows/test-tick.yml @@ -0,0 +1,58 @@ +--- +name: Test Tick + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - 'Tick/**.h' + - '.github/workflows/test-tick.yml' + push: + paths: + - 'Tick/**.h' + - '.github/workflows/test-tick.yml' + +jobs: + + Compile: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Compile + uses: fx31337/mql-compile-action@master + with: + path: 'Tick/tests' + verbose: true + - name: Print compiled files + run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' + shell: powershell + - name: Upload artifacts (MQL4) + uses: actions/upload-artifact@v2 + with: + name: files-ex4 + path: '**/*.ex4' + - name: Upload artifacts (MQL5) + uses: actions/upload-artifact@v2 + with: + name: files-ex5 + path: '**/*.ex5' + + Tick-Tests-MQL4: + defaults: + run: + shell: bash + working-directory: Tick/tests + needs: Compile + runs-on: ubuntu-latest + strategy: + matrix: + test: + - TickManager.test + steps: + - uses: actions/download-artifact@v2 + with: + name: files-ex4 + - name: Run ${{ matrix.test }} + uses: fx31337/mql-tester-action@master + with: + Script: ${{ matrix.test }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 858887afa..ca02328a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: - name: Compile uses: fx31337/mql-compile-action@master with: - init-platform: true + mt-version: 4.0.0.1349 verbose: true - name: Print compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' @@ -89,6 +89,7 @@ jobs: BtDays: 1-8 BtMonths: 1 BtYears: 2020 + MtVersion: 4.0.0.1349 TestExpert: ${{ matrix.test }} timeout-minutes: 10 diff --git a/Action.mqh b/Action.mqh index 1e01b324d..65dc92f3b 100644 --- a/Action.mqh +++ b/Action.mqh @@ -303,6 +303,7 @@ class Action { * Returns true when the condition is met. */ bool CheckCondition(ENUM_ACTION_CONDITION _cond, DataParamEntry &_args[]) { + bool _result = false; switch (_cond) { case ACTION_COND_IS_ACTIVE: // Is active; @@ -321,8 +322,9 @@ class Action { return IsInvalid(); default: logger.Ptr().Error(StringFormat("Invalid Action condition: %s!", EnumToString(_cond), __FUNCTION_LINE__)); - return false; + break; } + return _result; } bool CheckCondition(ENUM_ACTION_CONDITION _cond) { ARRAY(DataParamEntry, _args); @@ -338,7 +340,7 @@ class Action { * Returns true when the action has been executed successfully. */ bool ExecuteAction(ENUM_ACTION_ACTION _action, DataParamEntry &_args[]) { - bool _result = true; + bool _result = false; switch (_action) { case ACTION_ACTION_DISABLE: // Disable action. @@ -360,7 +362,7 @@ class Action { return SetFlags(ACTION_ENTRY_FLAG_IS_INVALID); default: logger.Ptr().Error(StringFormat("Invalid action of action: %s!", EnumToString(_action), __FUNCTION_LINE__)); - return false; + break; } return _result; } diff --git a/Buffer/BufferTick.h b/Buffer/BufferTick.h index 70965dcfe..d3eb35dab 100644 --- a/Buffer/BufferTick.h +++ b/Buffer/BufferTick.h @@ -26,14 +26,52 @@ // Includes. #include "../BufferStruct.mqh" +#include "../Chart.enum.h" +#include "../Storage/IValueStorage.h" #include "../Tick.struct.h" +template +class BufferTickValueStorage : ValueStorage { + // Poiner to buffer to take tick from. + BufferTick *buffer_tick; + + // PRICE_ASK or PRICE_BID. + int applied_price; + + public: + /** + * Constructor. + */ + BufferTickValueStorage(BufferTick *_buffer_tick, int _applied_price) + : buffer_tick(_buffer_tick), applied_price(_applied_price) {} + + /** + * Fetches value from a given shift. Takes into consideration as-series flag. + */ + TV Fetch(int _shift) override { + Print("BufferTickValueStorage: Fetching " + (applied_price == PRICE_ASK ? "Ask" : "Bid") + " price from shift ", + _shift); + return 0; + } + + /** + * Returns number of values available to fetch (size of the values buffer). + */ + int Size() const override { return (int)buffer_tick.Size(); } +}; + /** * Class to store struct data. */ template class BufferTick : public BufferStruct> { protected: + // Ask prices ValueStorage proxy. + BufferTickValueStorage *_vs_ask; + + // Bid prices ValueStorage proxy. + BufferTickValueStorage *_vs_bid; + protected: /* Protected methods */ @@ -42,7 +80,11 @@ class BufferTick : public BufferStruct> { * * Called on constructor. */ - void Init() { SetOverflowListener(BufferTickOverflowListener, 10); } + void Init() { + _vs_ask = NULL; + _vs_bid = NULL; + SetOverflowListener(BufferTickOverflowListener, 10); + } public: /* Constructors */ @@ -51,11 +93,43 @@ class BufferTick : public BufferStruct> { * Constructor. */ BufferTick() { Init(); } - BufferTick(BufferTick& _right) { + BufferTick(BufferTick &_right) { THIS_REF = _right; Init(); } + /** + * Destructor. + */ + ~BufferTick() { + if (_vs_ask != NULL) { + delete _vs_ask; + } + if (_vs_bid != NULL) { + delete _vs_bid; + } + } + + /** + * Returns Ask prices ValueStorage proxy. + */ + BufferTickValueStorage *GetAskValueStorage() { + if (_vs_ask == NULL) { + _vs_ask = new BufferTickValueStorage(THIS_PTR, PRICE_ASK); + } + return _vs_ask; + } + + /** + * Returns Bid prices ValueStorage proxy. + */ + BufferTickValueStorage *GetBidValueStorage() { + if (_vs_bid == NULL) { + _vs_bid = new BufferTickValueStorage(THIS_PTR, PRICE_BID); + } + return _vs_bid; + } + /* Grouping methods */ /** diff --git a/Chart.enum.h b/Chart.enum.h index e7e68247c..5835ba3da 100644 --- a/Chart.enum.h +++ b/Chart.enum.h @@ -43,9 +43,14 @@ enum ENUM_APPLIED_PRICE { PRICE_MEDIAN, // Median price (H+L)/2 PRICE_TYPICAL, // Typical price, (H+L+C)/3 PRICE_WEIGHTED, // Weighted close price (H+L+C+C)/4 + FINAL_APPLIED_PRICE_ENTRY }; #endif +// Additional modes for applied price. +#define PRICE_ASK ((ENUM_APPLIED_PRICE)128) +#define PRICE_BID ((ENUM_APPLIED_PRICE)129) + // Defines enumeration for chart parameters. enum ENUM_CHART_PARAM { CHART_PARAM_NONE = 0, // None diff --git a/Chart.mqh b/Chart.mqh index a568d8ae5..c73720415 100644 --- a/Chart.mqh +++ b/Chart.mqh @@ -224,7 +224,7 @@ class Chart : public Market { * @return * Returns ChartEntry struct. */ - ChartEntry GetEntry(unsigned int _shift = 0) { + ChartEntry GetEntry(int _shift = 0) { ChartEntry _chart_entry; BarOHLC _ohlc = GetOHLC(_shift); if (_ohlc.open > 0) { diff --git a/Dict.mqh b/Dict.mqh index 3fe692a31..cd55d66ba 100644 --- a/Dict.mqh +++ b/Dict.mqh @@ -205,24 +205,30 @@ class Dict : public DictBase { * Inserts value into given array of DictSlots. */ bool InsertInto(DictSlotsRef& dictSlotsRef, const K key, V value, bool allow_resize) { - // Will resize dict if there were performance problems before. - if (allow_resize && !dictSlotsRef.IsPerformant()) { - if (!GrowUp()) { - return false; - } - } - if (_mode == DictModeUnknown) _mode = DictModeDict; else if (_mode != DictModeDict) { Alert("Warning: Dict already operates as a list, not a dictionary!"); - DebugBreak(); return false; } unsigned int position; DictSlot* keySlot = GetSlotByKey(dictSlotsRef, key, position); + if (keySlot == NULL && !IsGrowUpAllowed()) { + // Resize is prohibited. + return false; + } + + // Will resize dict if there were performance problems before. + if (allow_resize && IsGrowUpAllowed() && !dictSlotsRef.IsPerformant()) { + if (!GrowUp()) { + return false; + } + // We now have new positions of slots, so we have to take the corrent slot again. + keySlot = GetSlotByKey(dictSlotsRef, key, position); + } + if (keySlot == NULL && dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { // No DictSlotsRef.DictSlots available. if (overflow_listener != NULL) { diff --git a/DictBase.mqh b/DictBase.mqh index 534f91e8a..daeaaae7a 100644 --- a/DictBase.mqh +++ b/DictBase.mqh @@ -257,6 +257,18 @@ class DictBase { // No key found. } + /** + * Checks whether overflow listener allows dict to grow up. + */ + bool IsGrowUpAllowed() { + if (overflow_listener == NULL) { + return true; + } + + // Checking if overflow listener allows resize from current to higher number of slots. + return overflow_listener(DICT_OVERFLOW_REASON_FULL, Size(), 0); + } + /** * Moves last slot to given one to fill the hole after removing the value. */ @@ -280,6 +292,11 @@ class DictBase { */ const unsigned int Size() { return _DictSlots_ref._num_used; } + /** + * Returns number of all (reserved) DictSlots. + */ + const unsigned int ReservedSize() { return ArraySize(_DictSlots_ref.DictSlots); } + /** * Checks whether given key exists in the dictionary. */ diff --git a/DictObject.mqh b/DictObject.mqh index 4491707cb..8bcc9d412 100644 --- a/DictObject.mqh +++ b/DictObject.mqh @@ -192,24 +192,30 @@ class DictObject : public DictBase { * Inserts value into given array of DictSlots. */ bool InsertInto(DictSlotsRef& dictSlotsRef, const K key, V& value, bool allow_resize) { - // Will resize dict if there were performance problems before. - if (allow_resize && !dictSlotsRef.IsPerformant()) { - if (!GrowUp()) { - return false; - } - } - if (_mode == DictModeUnknown) _mode = DictModeDict; else if (_mode != DictModeDict) { Alert("Warning: Dict already operates as a list, not a dictionary!"); - DebugBreak(); return false; } unsigned int position; DictSlot* keySlot = GetSlotByKey(dictSlotsRef, key, position); + if (keySlot == NULL && !IsGrowUpAllowed()) { + // Resize is prohibited. + return false; + } + + // Will resize dict if there were performance problems before. + if (allow_resize && IsGrowUpAllowed() && !dictSlotsRef.IsPerformant()) { + if (!GrowUp()) { + return false; + } + // We now have new positions of slots, so we have to take the corrent slot again. + keySlot = GetSlotByKey(dictSlotsRef, key, position); + } + if (keySlot == NULL && dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { // No DictSlotsRef.DictSlots available. if (overflow_listener != NULL) { diff --git a/DictStruct.mqh b/DictStruct.mqh index b6ea1eac4..b4cb0d747 100644 --- a/DictStruct.mqh +++ b/DictStruct.mqh @@ -252,13 +252,6 @@ class DictStruct : public DictBase { * Inserts value into given array of DictSlots. */ bool InsertInto(DictSlotsRef& dictSlotsRef, const K key, V& value, bool allow_resize) { - // Will resize dict if there were performance problems before. - if (allow_resize && !dictSlotsRef.IsPerformant()) { - if (!GrowUp()) { - return false; - } - } - if (_mode == DictModeUnknown) _mode = DictModeDict; else if (_mode != DictModeDict) { @@ -269,6 +262,20 @@ class DictStruct : public DictBase { unsigned int position; DictSlot* keySlot = GetSlotByKey(dictSlotsRef, key, position); + if (keySlot == NULL && !IsGrowUpAllowed()) { + // Resize is prohibited. + return false; + } + + // Will resize dict if there were performance problems before. + if (allow_resize && IsGrowUpAllowed() && !dictSlotsRef.IsPerformant()) { + if (!GrowUp()) { + return false; + } + // We now have new positions of slots, so we have to take the corrent slot again. + keySlot = GetSlotByKey(dictSlotsRef, key, position); + } + if (keySlot == NULL && dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { // No DictSlotsRef.DictSlots available. if (overflow_listener != NULL) { diff --git a/DrawIndicator.mqh b/DrawIndicator.mqh index 7017a81eb..2888b77cf 100644 --- a/DrawIndicator.mqh +++ b/DrawIndicator.mqh @@ -32,7 +32,6 @@ // Includes. #include "DictObject.mqh" #include "Draw.mqh" -#include "Indicator.mqh" #include "Object.mqh" // Forward declaration. diff --git a/EA.enum.h b/EA.enum.h index 897138ebf..717f9b21f 100644 --- a/EA.enum.h +++ b/EA.enum.h @@ -43,11 +43,11 @@ enum ENUM_EA_DATA_STORE_TYPE { /* Defines EA data export methods. */ enum ENUM_EA_DATA_EXPORT_METHOD { - EA_DATA_EXPORT_NONE = 0 << 0, - EA_DATA_EXPORT_CSV = 1 << 0, // Export into CSV file. - EA_DATA_EXPORT_DB = 1 << 1, // Export into database table. - EA_DATA_EXPORT_JSON = 1 << 2, // Export into JSON file. - EA_DATA_EXPORT_ALL = (1 << 3) - 1, // Export in all formats. + EA_DATA_EXPORT_NONE = 0 << 0, // (None) + EA_DATA_EXPORT_CSV = 1 << 0, // CSV file + EA_DATA_EXPORT_DB = 1 << 1, // Database (SQLite) + EA_DATA_EXPORT_JSON = 1 << 2, // JSON file + EA_DATA_EXPORT_ALL = (1 << 3) - 1, // All }; /* Defines EA state flags. */ diff --git a/EA.mqh b/EA.mqh index 62cd02cb8..b3bff80f5 100644 --- a/EA.mqh +++ b/EA.mqh @@ -149,7 +149,7 @@ class EA { * @return * Returns TradeSignalEntry struct. */ - TradeSignalEntry GetStrategySignalEntry(Strategy *_strat, bool _trade_allowed = true, int _shift = -1) { + TradeSignalEntry GetStrategySignalEntry(Strategy *_strat, bool _trade_allowed = true, int _shift = 0) { // float _bf = 1.0; float _scl = _strat.Get(STRAT_PARAM_SCL); float _sol = _strat.Get(STRAT_PARAM_SOL); @@ -880,6 +880,7 @@ class EA { * Returns true when the condition is met. */ bool CheckCondition(ENUM_EA_CONDITION _cond, DataParamEntry &_args[]) { + bool _result = false; switch (_cond) { case EA_COND_IS_ACTIVE: return estate.IsActive(); @@ -906,8 +907,9 @@ class EA { return estate.IsOnQuit(); default: logger.Error(StringFormat("Invalid EA condition: %s!", EnumToString(_cond), __FUNCTION_LINE__)); - return false; + break; } + return _result; } bool CheckCondition(ENUM_EA_CONDITION _cond) { ARRAY(DataParamEntry, _args); @@ -923,7 +925,7 @@ class EA { * Returns true when the action has been executed successfully. */ bool ExecuteAction(ENUM_EA_ACTION _action, DataParamEntry &_args[]) { - bool _result = true; + bool _result = false; long arg_size = ArraySize(_args); switch (_action) { case EA_ACTION_DISABLE: diff --git a/Indicator.define.h b/Indicator.define.h index 6743cba67..ab51a433d 100644 --- a/Indicator.define.h +++ b/Indicator.define.h @@ -43,12 +43,14 @@ } \ SET_HANDLE; \ } \ - int _bars_calc = ::BarsCalculated(_handle); \ - if (GetLastError() > 0) { \ - return EMPTY_VALUE; \ - } else if (_bars_calc <= 2) { \ - SetUserError(ERR_USER_INVALID_BUFF_NUM); \ - return EMPTY_VALUE; \ + if (Terminal::IsVisualMode()) { \ + int _bars_calc = ::BarsCalculated(_handle); \ + if (GetLastError() > 0) { \ + return EMPTY_VALUE; \ + } else if (_bars_calc <= 2) { \ + SetUserError(ERR_USER_INVALID_BUFF_NUM); \ + return EMPTY_VALUE; \ + } \ } \ if (::CopyBuffer(_handle, _mode, _shift, 1, _res) < 0) { \ return ArraySize(_res) > 0 ? _res[0] : EMPTY_VALUE; \ diff --git a/Indicator.enum.h b/Indicator.enum.h index 63baad455..8bf58e7b1 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -40,96 +40,99 @@ enum ENUM_INDICATOR_ACTION { FINAL_INDICATOR_ACTION_ENTRY }; -/* Define type of indicators. */ +/* Define type of */ enum ENUM_INDICATOR_TYPE { - INDI_NONE = 0, // (None) - INDI_AC, // Accelerator Oscillator - INDI_AD, // Accumulation/Distribution - INDI_ADX, // Average Directional Index - INDI_ADXW, // ADX by Welles Wilder - INDI_ALLIGATOR, // Alligator - INDI_AMA, // Adaptive Moving Average - INDI_APPLIED_PRICE, // Applied Price over OHLC Indicator - INDI_AO, // Awesome Oscillator - INDI_ASI, // Accumulation Swing Index - INDI_ATR, // Average True Range - INDI_BANDS, // Bollinger Bands - INDI_BANDS_ON_PRICE, // Bollinger Bands (on Price) - INDI_BEARS, // Bears Power - INDI_BULLS, // Bulls Power - INDI_BWMFI, // Market Facilitation Index - INDI_BWZT, // Bill Williams' Zone Trade - INDI_CANDLE, // Candle Pattern Detector - INDI_CCI, // Commodity Channel Index - INDI_CCI_ON_PRICE, // Commodity Channel Index (CCI) (on Price) - INDI_CHAIKIN, // Chaikin Oscillator - INDI_CHAIKIN_V, // Chaikin Volatility - INDI_COLOR_BARS, // Color Bars - INDI_COLOR_CANDLES_DAILY, // Color Candles Daily - INDI_COLOR_LINE, // Color Line - INDI_CUSTOM, // Custom indicator - INDI_CUSTOM_MOVING_AVG, // Custom Moving Average - INDI_DEMA, // Double Exponential Moving Average - INDI_DEMARKER, // DeMarker - INDI_DEMO, // Demo/Dummy Indicator - INDI_DETRENDED_PRICE, // Detrended Price Oscillator - INDI_DRAWER, // Drawer (Socket-based) Indicator - INDI_ENVELOPES, // Envelopes - INDI_ENVELOPES_ON_PRICE, // Evelopes (on Price) - INDI_FORCE, // Force Index - INDI_FRACTALS, // Fractals - INDI_FRAMA, // Fractal Adaptive Moving Average - INDI_GATOR, // Gator Oscillator - INDI_HEIKENASHI, // Heiken Ashi - INDI_ICHIMOKU, // Ichimoku Kinko Hyo - INDI_KILLZONES, // Killzones - INDI_MA, // Moving Average - INDI_MACD, // MACD - INDI_MA_ON_PRICE, // Moving Average (on Price). - INDI_MARKET_FI, // Market Facilitation Index - INDI_MASS_INDEX, // Mass Index - INDI_MFI, // Money Flow Index - INDI_MOMENTUM, // Momentum - INDI_MOMENTUM_ON_PRICE, // Momentum (on Price) - INDI_OBV, // On Balance Volume - INDI_OHLC, // OHLC (Open-High-Low-Close) - INDI_OSMA, // OsMA - INDI_PATTERN, // Pattern Detector - INDI_PIVOT, // Pivot Detector - INDI_PRICE, // Price - INDI_PRICE_CHANNEL, // Price Channel - INDI_PRICE_FEEDER, // Indicator which returns prices from custom array - INDI_PRICE_VOLUME_TREND, // Price and Volume Trend - INDI_RATE_OF_CHANGE, // Rate of Change - INDI_RS, // Indi_Math-based RSI indicator. - INDI_RSI, // Relative Strength Index - INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price) - INDI_RVI, // Relative Vigor Index - INDI_SAR, // Parabolic SAR - INDI_SPECIAL_MATH, // Math operations over given indicator. - INDI_STDDEV, // Standard Deviation - INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode - INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price) - INDI_STDDEV_SMA_ON_PRICE, // Standard Deviation in SMA mode (on Price) - INDI_STOCHASTIC, // Stochastic Oscillator - INDI_SVE_BB, // SVE Bollinger Bands - INDI_TEMA, // Triple Exponential Moving Average - INDI_TF, // Timeframe - INDI_TICK, // Tick - INDI_TMA_TRUE, // Triangular Moving Average True - INDI_TRIX, // Triple Exponential Moving Averages Oscillator - INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator - INDI_VIDYA, // Variable Index Dynamic Average - INDI_VOLUMES, // Volumes - INDI_VROC, // Volume Rate of Change - INDI_WILLIAMS_AD, // Larry Williams' Accumulation/Distribution - INDI_WPR, // Williams' Percent Range - INDI_ZIGZAG, // ZigZag - INDI_ZIGZAG_COLOR, // ZigZag Color + INDI_NONE = 0, // (None) + INDI_AC, // Accelerator Oscillator + INDI_AD, // Accumulation/Distribution + INDI_ADX, // Average Directional Index + INDI_ADXW, // ADX by Welles Wilder + INDI_ALLIGATOR, // Alligator + INDI_AMA, // Adaptive Moving Average + INDI_APPLIED_PRICE, // Applied Price over OHLC Indicator + INDI_AO, // Awesome Oscillator + INDI_ASI, // Accumulation Swing Index + INDI_ATR, // Average True Range + INDI_BANDS, // Bollinger Bands + INDI_BANDS_ON_PRICE, // Bollinger Bands (on Price) + INDI_BEARS, // Bears Power + INDI_BULLS, // Bulls Power + INDI_BWMFI, // Market Facilitation Index + INDI_BWZT, // Bill Williams' Zone Trade + INDI_CANDLE, // Candle Pattern Detector + INDI_CCI, // Commodity Channel Index + INDI_CCI_ON_PRICE, // Commodity Channel Index (CCI) (on Price) + INDI_CHAIKIN, // Chaikin Oscillator + INDI_CHAIKIN_V, // Chaikin Volatility + INDI_COLOR_BARS, // Color Bars + INDI_COLOR_CANDLES_DAILY, // Color Candles Daily + INDI_COLOR_LINE, // Color Line + INDI_CUSTOM, // Custom indicator + INDI_CUSTOM_MOVING_AVG, // Custom Moving Average + INDI_DEMA, // Double Exponential Moving Average + INDI_DEMARKER, // DeMarker + INDI_DEMO, // Demo/Dummy Indicator + INDI_DETRENDED_PRICE, // Detrended Price Oscillator + INDI_DRAWER, // Drawer (Socket-based) Indicator + INDI_ENVELOPES, // Envelopes + INDI_ENVELOPES_ON_PRICE, // Evelopes (on Price) + INDI_FORCE, // Force Index + INDI_FRACTALS, // Fractals + INDI_FRAMA, // Fractal Adaptive Moving Average + INDI_GATOR, // Gator Oscillator + INDI_HEIKENASHI, // Heiken Ashi + INDI_ICHIMOKU, // Ichimoku Kinko Hyo + INDI_KILLZONES, // Killzones + INDI_MA, // Moving Average + INDI_MACD, // MACD + INDI_MA_ON_PRICE, // Moving Average (on Price). + INDI_MARKET_FI, // Market Facilitation Index + INDI_MASS_INDEX, // Mass Index + INDI_MFI, // Money Flow Index + INDI_MOMENTUM, // Momentum + INDI_MOMENTUM_ON_PRICE, // Momentum (on Price) + INDI_OBV, // On Balance Volume + INDI_OHLC, // OHLC (Open-High-Low-Close) + INDI_OSMA, // OsMA + INDI_PATTERN, // Pattern Detector + INDI_PIVOT, // Pivot Detector + INDI_PRICE, // Price + INDI_PRICE_CHANNEL, // Price Channel + INDI_PRICE_FEEDER, // Indicator which returns prices from custom array + INDI_PRICE_VOLUME_TREND, // Price and Volume Trend + INDI_RATE_OF_CHANGE, // Rate of Change + INDI_RS, // Indi_Math-based RSI + INDI_RSI, // Relative Strength Index + INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price) + INDI_RVI, // Relative Vigor Index + INDI_SAR, // Parabolic SAR + INDI_SPECIAL_MATH, // Math operations over given + INDI_STDDEV, // Standard Deviation + INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode + INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price) + INDI_STDDEV_SMA_ON_PRICE, // Standard Deviation in SMA mode (on Price) + INDI_STOCHASTIC, // Stochastic Oscillator + INDI_SVE_BB, // SVE Bollinger Bands + INDI_TEMA, // Triple Exponential Moving Average + INDI_TF, // Timeframe + INDI_TICK, // Tick + INDI_TMA_TRUE, // Triangular Moving Average True + INDI_TRIX, // Triple Exponential Moving Averages Oscillator + INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator + INDI_ULTIMATE_OSCILLATOR_ATR_FAST, // Ultimate Oscillator's ATR, Fast + INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE, // Ultimate Oscillator's ATR, Middle + INDI_ULTIMATE_OSCILLATOR_ATR_SLOW, // Ultimate Oscillator's ATR, Slow + INDI_VIDYA, // Variable Index Dynamic Average + INDI_VOLUMES, // Volumes + INDI_VROC, // Volume Rate of Change + INDI_WILLIAMS_AD, // Larry Williams' Accumulation/Distribution + INDI_WPR, // Williams' Percent Range + INDI_ZIGZAG, // ZigZag + INDI_ZIGZAG_COLOR, // ZigZag Color FINAL_INDICATOR_TYPE_ENTRY }; -/* Defines type of source data for indicator. */ +/* Defines type of source data for */ enum ENUM_IDATA_SOURCE_TYPE { IDATA_BUILTIN = 0, // Platform built-in IDATA_CHART, // Chart calculation @@ -151,7 +154,7 @@ enum ENUM_IDATA_VALUE_RANGE { IDATA_RANGE_UNKNOWN }; -// Indicator line identifiers used in ADX and ADXW indicators. +// Indicator line identifiers used in ADX and ADXW enum ENUM_INDI_ADX_LINE { #ifdef __MQL4__ LINE_MAIN_ADX = MODE_MAIN, // Base indicator line. @@ -173,7 +176,7 @@ enum ENUM_INDICATOR_INDEX { FINAL_ENUM_INDICATOR_INDEX = 3 // Should be the last one. Used to calculate the number of enum items. }; -/* Indicator line identifiers used in Envelopes and Fractals indicators. */ +/* Indicator line identifiers used in Envelopes and Fractals */ enum ENUM_LO_UP_LINE { #ifdef __MQL4__ LINE_UPPER = MODE_UPPER, // Upper line. @@ -186,7 +189,7 @@ enum ENUM_LO_UP_LINE { }; /** - * Indicator line identifiers used in MACD, RVI and Stochastic indicators. + * Indicator line identifiers used in MACD, RVI and Stochastic * * @see: * - https://docs.mql4.com/constants/indicatorconstants/lines @@ -228,3 +231,28 @@ enum INDICATOR_ENTRY_FLAGS { INDI_ENTRY_FLAG_IS_VALID = 1 << 6, INDI_ENTRY_FLAG_INSUFFICIENT_DATA = 1 << 7, // Entry has missing value for that shift and probably won't ever have. }; + +// Storage type for IndicatorBase::GetSpecificValueStorage(). +enum ENUM_INDI_VS_TYPE { + INDI_VS_TYPE_TIME, // Candle. + INDI_VS_TYPE_TICK_VOLUME, // Candle. + INDI_VS_TYPE_VOLUME, // Candle. + INDI_VS_TYPE_SPREAD, // Candle. + INDI_VS_TYPE_PRICE_OPEN, // Candle. + INDI_VS_TYPE_PRICE_HIGH, // Candle. + INDI_VS_TYPE_PRICE_LOW, // Candle. + INDI_VS_TYPE_PRICE_CLOSE, // Candle. + INDI_VS_TYPE_PRICE_MEDIAN, // Candle. + INDI_VS_TYPE_PRICE_TYPICAL, // Candle. + INDI_VS_TYPE_PRICE_WEIGHTED, // Candle. + INDI_VS_TYPE_PRICE_BID, // Tick. + INDI_VS_TYPE_PRICE_ASK, // Tick. +}; + +// Indicator flags. +enum ENUM_INDI_FLAGS { + INDI_FLAG_INDEXABLE_BY_SHIFT, // Indicator supports indexation by shift. + INDI_FLAG_INDEXABLE_BY_TIMESTAMP, // Indicator supports indexation by shift. + INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT, // Source indicator must be indexable by shift. + INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP // Source indicator must be indexable by timestamp. +}; diff --git a/Indicator.mqh b/Indicator.mqh index 389d9fc54..66560fc15 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -147,22 +147,20 @@ class Indicator : public IndicatorBase { Indicator(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) : IndicatorBase(_iparams.GetTf(), NULL) { iparams = _iparams; - SetName(_iparams.name != "" ? _iparams.name : EnumToString(iparams.itype)); if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); + iparams.SetDataSourceType(IDATA_INDICATOR); } Init(); } Indicator(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorBase(_tf) { iparams = _iparams; - SetName(_iparams.name != "" ? _iparams.name : EnumToString(iparams.itype)); Init(); } Indicator(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") : IndicatorBase(_tf) { iparams.SetIndicatorType(_itype); iparams.SetShift(_shift); - SetName(_name != "" ? _name : EnumToString(iparams.itype)); Init(); } @@ -176,14 +174,14 @@ class Indicator : public IndicatorBase { /** * Gets an indicator property flag. */ - bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = -1) { + bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = 0) { IndicatorDataEntry _entry = GetEntry(_shift >= 0 ? _shift : iparams.GetShift()); return _entry.CheckFlag(_prop); } /* Buffer methods */ - virtual string CacheKey() { return GetName(); } + virtual string CacheKey() { return GetFullName(); } /** * Initializes a cached proxy between i*OnArray() methods and OnCalculate() @@ -720,6 +718,17 @@ class Indicator : public IndicatorBase { _result = _source.Ptr(); } } + } else if (iparams.GetDataSourceType() == IDATA_INDICATOR) { + // User sets data source's mode to On-Indicator, but not set data source via SetDataSource()! + + // Requesting potential data source. + IndicatorBase* _ds = OnDataSourceRequest(); + + if (_ds != NULL) { + // Initializing with new data source. + SetDataSource(_ds); + iparams.SetDataSourceType(IDATA_INDICATOR); + } } ValidateDataSource(&this, _result); @@ -735,7 +744,17 @@ class Indicator : public IndicatorBase { /** * Whether data source is selected. */ - virtual bool HasDataSource() { return GetDataSourceRaw() != NULL || iparams.GetDataSourceId() != -1; } + virtual bool HasDataSource(bool _try_initialize = false) { + if (iparams.GetDataSourceId() != -1) { + return true; + } + + if (iparams.GetDataSourceType() == IDATA_INDICATOR && GetDataSourceRaw() == NULL && _try_initialize) { + SetDataSource(OnDataSourceRequest()); + } + + return GetDataSourceRaw() != NULL; + } /** * Gets indicator's params. @@ -773,14 +792,8 @@ class Indicator : public IndicatorBase { /** * Get name of the indicator. */ - string GetName() { return iparams.name; } - - /** - * Get full name of the indicator (with "over ..." part). - */ - string GetFullName() { - return iparams.name + "[" + IntegerToString(iparams.GetMaxModes()) + "]" + - (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); + string GetName() override { + return "(" + EnumToString(GetType()) + ")" + (iparams.name != "" ? (" " + iparams.name) : ""); } /** @@ -816,19 +829,6 @@ class Indicator : public IndicatorBase { Chart::Set(_param, _value); } - /** - * Sets indicator data source. - */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { - if (indi_src.IsSet() && indi_src.Ptr() != _indi) { - indi_src.Ptr().RemoveListener(THIS_PTR); - } - indi_src = _indi; - indi_src.Ptr().AddListener(THIS_PTR); - iparams.SetDataSource(-1, _input_mode); - indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); - } - /** * Sets name of the indicator. */ @@ -966,63 +966,7 @@ class Indicator : public IndicatorBase { return true; } - /** - * Returns shift at which the last known valid entry exists for a given - * period (or from the start, when period is not specified). - */ - /* - bool GetLastValidEntryShift(int& out_shift, int period = 0) { - out_shift = 0; - - while (true) { - if ((period != 0 && out_shift >= period) || !HasValidEntry(out_shift + 1)) - return out_shift > 0; // Current shift is always invalid. - - ++out_shift; - } - - return out_shift > 0; - }*/ - - /** - * Returns shift at which the oldest known valid entry exists for a given - * period (or from the start, when period is not specified). - */ - /* - bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int period = 0) { - bool found = false; - // Counting from previous up to previous - period. - for (out_shift = shift + 1; out_shift < shift + period + 1; ++out_shift) { - if (!HasValidEntry(out_shift)) { - --out_shift; - out_num_valid = out_shift - shift; - return found; - } else - found = true; - } - - --out_shift; - out_num_valid = out_shift - shift; - return found; - } - */ - - /** - * Checks whether indicator has valid at least given number of last entries - * (counting from given shift or 0). - */ - /* - bool HasAtLeastValidLastEntries(int period, int shift = 0) { - for (int i = 0; i < period; ++i) - if (!HasValidEntry(shift + i)) return false; - - return true; - } - */ - - // ENUM_IDATA_VALUE_RANGE GetIDataValueRange() { return iparams.idvrange; } - - virtual void OnTick() { + void OnTick() override { Chart::OnTick(); if (iparams.is_draw) { @@ -1033,6 +977,38 @@ class Indicator : public IndicatorBase { } } + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { + if (indi_src.IsSet()) { + if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT) && + !bool(_indi.GetFlags() | INDI_FLAG_INDEXABLE_BY_SHIFT)) { + Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), + ", because source indicator isn't indexable by shift!"); + DebugBreak(); + return; + } + if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP) && + !bool(_indi.GetFlags() | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) { + Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), + ", because source indicator isn't indexable by timestamp!"); + DebugBreak(); + return; + } + } + + if (indi_src.IsSet() && indi_src.Ptr() != _indi) { + indi_src.Ptr().RemoveListener(THIS_PTR); + } + indi_src = _indi; + if (_indi != NULL) { + indi_src.Ptr().AddListener(THIS_PTR); + iparams.SetDataSource(-1, _input_mode); + indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); + } + } + /* Data representation methods */ /* Virtual methods */ @@ -1087,6 +1063,19 @@ class Indicator : public IndicatorBase { return _result; } + /** + * Get full name of the indicator (with "over ..." part). + */ + string GetFullName() override { + return GetName() + "[" + IntegerToString(iparams.GetMaxModes()) + "]" + + (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); + } + + /** + * Get indicator type. + */ + ENUM_INDICATOR_TYPE GetType() override { return iparams.itype; } + /** * Update indicator. */ @@ -1163,140 +1152,20 @@ class Indicator : public IndicatorBase { * This method allows user to modify the struct entry before it's added to cache. * This method is called on GetEntry() right after values are set. */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _index = -1) { + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { _entry.AddFlags(_entry.GetDataTypeFlags(iparams.GetDataValueType())); }; - - /* Defines MQL backward compatible methods */ - - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, DUMMY); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, int _mode, - int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, int _mode, - int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, - int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, K _k, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, K _k, L _l, M _m, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k - COMMA _l COMMA _m); -#endif + /** + * Returns the indicator's entry value for the given shift and mode. + * + * @see: DataParamEntry. + * + * @return + * Returns DataParamEntry struct filled with a single value. + */ + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) override { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + return GetEntry(_ishift)[_mode]; } }; diff --git a/Indicator.struct.h b/Indicator.struct.h index 782ab22c9..4479aeea4 100644 --- a/Indicator.struct.h +++ b/Indicator.struct.h @@ -437,7 +437,7 @@ struct IndicatorParams { idstype(_idstype), idvrange(IDATA_RANGE_UNKNOWN), indi_data_source_id(-1), - indi_data_source_mode(0), + indi_data_source_mode(-1), itype(_itype), is_draw(false), indi_color(clrNONE), @@ -454,7 +454,7 @@ struct IndicatorParams { idstype(_idstype), idvrange(IDATA_RANGE_UNKNOWN), indi_data_source_id(-1), - indi_data_source_mode(0), + indi_data_source_mode(-1), is_draw(false), indi_color(clrNONE), draw_window(0) { diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 34dbc37c6..c0ff4637a 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -31,16 +31,28 @@ // Includes. #include "../Buffer/BufferCandle.h" -#include "../IndicatorBase.h" +#include "../Indicator.mqh" +#include "../Candle.struct.h" + +// Indicator modes. +enum ENUM_INDI_CANDLE_MODE { + INDI_CANDLE_MODE_PRICE_OPEN, + INDI_CANDLE_MODE_PRICE_HIGH, + INDI_CANDLE_MODE_PRICE_LOW, + INDI_CANDLE_MODE_PRICE_CLOSE, + INDI_CANDLE_MODE_SPREAD, + INDI_CANDLE_MODE_TICK_VOLUME, + INDI_CANDLE_MODE_VOLUME, + FINAL_INDI_CANDLE_MODE_ENTRY, +}; /** * Class to deal with candle indicators. */ template -class IndicatorCandle : public IndicatorBase { +class IndicatorCandle : public Indicator { protected: BufferCandle icdata; - TS icparams; protected: /* Protected methods */ @@ -51,9 +63,11 @@ class IndicatorCandle : public IndicatorBase { * Called on constructor. */ void Init() { + // Along with indexing by shift, we can also index via timestamp! + flags |= INDI_FLAG_INDEXABLE_BY_TIMESTAMP; icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); - icparams.SetMaxModes(4); + iparams.SetMaxModes(4); } public: @@ -62,16 +76,13 @@ class IndicatorCandle : public IndicatorBase { /** * Class constructor. */ - IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { - icparams = _icparams; - if (_indi_src != NULL) { - SetDataSource(_indi_src, _indi_mode); - } + IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_icparams, _indi_src, _indi_mode) { Init(); } - IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, int _shift = 0, string _name = "") { - icparams.SetIndicatorType(_itype); - icparams.SetShift(_shift); + IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) { Init(); } @@ -87,42 +98,39 @@ class IndicatorCandle : public IndicatorBase { */ IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); - unsigned int _ishift = _index >= 0 ? _index : icparams.GetShift(); + unsigned int _ishift = _index >= 0 ? _index : iparams.GetShift(); long _candle_time = CalcCandleTimestamp(GetBarTime(_ishift)); - CandleOCTOHLC _candle = icdata.GetByKey(_candle_time); + long _curr_candle_time; + CandleOCTOHLC _candle; + + // Trying current and older shifts. + if (icdata.Size() > 0) { + int i = 0; + while (true) { + _curr_candle_time = CalcCandleTimestamp(GetBarTime(i++)); + + if (_curr_candle_time < icdata.GetMin()) { + // There is no older entries. + break; + } + + _candle = icdata.GetByKey(_curr_candle_time); + + if (_candle.IsValid()) { + break; + } + } + } if (!_candle.IsValid()) { - Print(GetFullName(), ": Missing candle at shift ", _index, " (", TimeToString(_candle_time), ")"); - } else { - Print(GetFullName(), ": Retrieving candle at shift ", _index, " (", TimeToString(_candle_time), ")"); + // Giving up. + DebugBreak(); + Print(GetFullName(), ": Missing candle after thorough search at shift ", _index, " (", TimeToString(_candle_time), "). Lowest timestamp in history is ", icdata.GetMin()); } return CandleToEntry(_candle_time, _candle); } - /** - * Alters indicator's struct value. - * - * This method allows user to modify the struct entry before it's added to cache. - * This method is called on GetEntry() right after values are set. - */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { - _entry.AddFlags(_entry.GetDataTypeFlags(icparams.GetDataValueType())); - }; - - /** - * Returns the indicator's entry value for the given shift and mode. - * - * @see: DataParamEntry. - * - * @return - * Returns DataParamEntry struct filled with a single value. - */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { - int _ishift = _shift >= 0 ? _shift : icparams.GetShift(); - return GetEntry(_ishift)[_mode]; - } - /** * Function should return true if resize can be made, or false to overwrite current slot. */ @@ -169,8 +177,10 @@ class IndicatorCandle : public IndicatorBase { void UpdateCandle(long _tick_timestamp, double _price) { long _candle_timestamp = CalcCandleTimestamp(_tick_timestamp); +#ifdef __debug_verbose__ Print("Updating candle for ", GetFullName(), " at candle ", TimeToString(_candle_timestamp), " from tick at ", TimeToString(_tick_timestamp)); +#endif CandleOCTOHLC _candle(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp); if (icdata.KeyExists(_candle_timestamp)) { @@ -179,35 +189,66 @@ class IndicatorCandle : public IndicatorBase { _candle.Update(_tick_timestamp, _price); } - icdata.Set(_candle_timestamp, _candle); + icdata.Add(_candle, _candle_timestamp); } /** * Calculates candle's timestamp from tick's timestamp. */ long CalcCandleTimestamp(long _tick_timestamp) { - return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle()); + return _tick_timestamp - _tick_timestamp % (iparams.GetSecsPerCandle()); } /** * Called when data source emits new entry (historic or future one). */ - virtual void OnDataSourceEntry(IndicatorDataEntry& entry) { + void OnDataSourceEntry(IndicatorDataEntry& entry) override { // Updating candle from bid price. UpdateCandle(entry.timestamp, entry[1]); }; /** - * Sets indicator data source. + * Returns value storage of given kind. + */ + IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_OPEN: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_OPEN); + case INDI_VS_TYPE_PRICE_HIGH: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_HIGH); + case INDI_VS_TYPE_PRICE_LOW: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_LOW); + case INDI_VS_TYPE_PRICE_CLOSE: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_CLOSE); + case INDI_VS_TYPE_SPREAD: + return GetValueStorage(INDI_CANDLE_MODE_SPREAD); + case INDI_VS_TYPE_TICK_VOLUME: + return GetValueStorage(INDI_CANDLE_MODE_TICK_VOLUME); + case INDI_VS_TYPE_VOLUME: + return GetValueStorage(INDI_CANDLE_MODE_VOLUME); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { - if (indi_src.IsSet() && indi_src.Ptr() != _indi) { - indi_src.Ptr().RemoveListener(THIS_PTR); + bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + switch (_type) { + case INDI_VS_TYPE_PRICE_OPEN: + case INDI_VS_TYPE_PRICE_HIGH: + case INDI_VS_TYPE_PRICE_LOW: + case INDI_VS_TYPE_PRICE_CLOSE: + case INDI_VS_TYPE_SPREAD: + case INDI_VS_TYPE_TICK_VOLUME: + case INDI_VS_TYPE_VOLUME: + return true; + default: + // Trying in parent class. + return Indicator::HasSpecificValueStorage(_type); } - indi_src = _indi; - indi_src.Ptr().AddListener(THIS_PTR); - icparams.SetDataSource(-1, _input_mode); - indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); } string CandlesToString() { @@ -220,91 +261,6 @@ class IndicatorCandle : public IndicatorBase { } /* Virtual methods */ - - /** - * Checks if indicator entry is valid. - * - * @return - * Returns true if entry is valid (has valid values), otherwise false. - */ - virtual bool IsValidEntry(IndicatorDataEntry& _entry) { - bool _result = true; - _result &= _entry.timestamp > 0; - _result &= _entry.GetSize() > 0; - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_REAL)) { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { - _result &= !_entry.HasValue(DBL_MAX); - _result &= !_entry.HasValue(NULL); - } else { - _result &= !_entry.HasValue(FLT_MAX); - _result &= !_entry.HasValue(NULL); - } - } else { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_UNSIGNED)) { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { - _result &= !_entry.HasValue(ULONG_MAX); - _result &= !_entry.HasValue(NULL); - } else { - _result &= !_entry.HasValue(UINT_MAX); - _result &= !_entry.HasValue(NULL); - } - } else { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { - _result &= !_entry.HasValue(LONG_MAX); - _result &= !_entry.HasValue(NULL); - } else { - _result &= !_entry.HasValue(INT_MAX); - _result &= !_entry.HasValue(NULL); - } - } - } - return _result; - } - - /** - * Get full name of the indicator (with "over ..." part). - */ - string GetFullName() override { - return GetName() + "[" + IntegerToString(icparams.GetMaxModes()) + "]" + - (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); - } - - /** - * Whether data source is selected. - */ - bool HasDataSource() override { return GetDataSourceRaw() != NULL || icparams.GetDataSourceId() != -1; } - - /** - * Returns currently selected data source doing validation. - */ - IndicatorBase* GetDataSource() override { - IndicatorBase* _result = NULL; - - if (GetDataSourceRaw() != NULL) { - _result = GetDataSourceRaw(); - } else if (icparams.GetDataSourceId() != -1) { - int _source_id = icparams.GetDataSourceId(); - - if (indicators.KeyExists(_source_id)) { - _result = indicators[_source_id].Ptr(); - } else { - Ref _source = FetchDataSource((ENUM_INDICATOR_TYPE)_source_id); - - if (!_source.IsSet()) { - Alert(GetName(), " has no built-in source indicator ", _source_id); - DebugBreak(); - } else { - indicators.Set(_source_id, _source); - - _result = _source.Ptr(); - } - } - } - - ValidateDataSource(&this, _result); - - return _result; - } }; #endif diff --git a/Indicator/IndicatorCandleSource.h b/Indicator/IndicatorCandleSource.h new file mode 100644 index 000000000..2d721fb8a --- /dev/null +++ b/Indicator/IndicatorCandleSource.h @@ -0,0 +1,108 @@ +//+------------------------------------------------------------------+ +//| 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 . + * + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../Indicator.mqh" +#include "tests/classes/IndicatorTfDummy.h" +#include "tests/classes/IndicatorTickReal.h" + +/** + * Indicator to be used with IndicatorCandle as a data source. + */ +template +class IndicatorCandleSource : public Indicator { + public: + /** + * Class constructor. + */ + IndicatorCandleSource(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_iparams, _indi_src, _indi_mode) {} + IndicatorCandleSource(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(_iparams, _tf) {} + IndicatorCandleSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) {} + + /** + * Class deconstructor. + */ + ~IndicatorCandleSource() {} + + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { + if (_indi == NULL) { + // Just deselecting data source. + Indicator::SetDataSource(_indi, _input_mode); + return; + } + + // We can only use data sources which supports all possible modes from IndicatorCandle. + bool _result = true; + + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_SPREAD); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_TICK_VOLUME); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_VOLUME); + + if (!_result) { + Alert("Passed indicator ", _indi.GetFullName(), " does not define all required specific data storages!"); + DebugBreak(); + } + + Indicator::SetDataSource(_indi, _input_mode); + } + + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) override { + // @todo Make use of this method. + return true; + } + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + IndicatorBase* OnDataSourceRequest() override { + // Defaulting to real platform ticks. + IndicatorBase* _indi_tick = + new IndicatorTickReal(GetSymbol(), GetTf(), "Ticker for Tf on IndicatorCandleSource-based indicator"); + + // Tf will work on real platform ticks. + IndicatorBase* _indi_tf = new IndicatorTfDummy(GetTf()); + _indi_tf.SetDataSource(_indi_tick); + + // Indicator will work on Tf, which will receive real platform ticks. + return _indi_tf; + } +}; diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h index 21350c445..84fe4b7c0 100644 --- a/Indicator/IndicatorTf.h +++ b/Indicator/IndicatorTf.h @@ -56,7 +56,7 @@ class IndicatorTf : public IndicatorCandle { * Class constructor with timeframe enum. */ IndicatorTf(uint _spc) { - icparams.SetSecsPerCandle(_spc); + iparams.SetSecsPerCandle(_spc); Init(); } @@ -64,7 +64,7 @@ class IndicatorTf : public IndicatorCandle { * Class constructor with timeframe enum. */ IndicatorTf(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { - icparams.SetSecsPerCandle(ChartTf::TfToSeconds(_tf)); + iparams.SetSecsPerCandle(ChartTf::TfToSeconds(_tf)); Init(); } @@ -72,7 +72,7 @@ class IndicatorTf : public IndicatorCandle { * Class constructor with timeframe index. */ IndicatorTf(ENUM_TIMEFRAMES_INDEX _tfi = 0) { - icparams.SetSecsPerCandle(ChartTf::TfToSeconds(ChartTf::IndexToTf(_tfi))); + iparams.SetSecsPerCandle(ChartTf::TfToSeconds(ChartTf::IndexToTf(_tfi))); Init(); } diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 4cf53be6b..e654dde70 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -31,13 +31,20 @@ // Includes. #include "../Buffer/BufferTick.h" -#include "../IndicatorBase.h" +#include "../Indicator.mqh" + +// Indicator modes. +enum ENUM_INDI_TICK_MODE { + INDI_TICK_MODE_PRICE_ASK, + INDI_TICK_MODE_PRICE_BID, + FINAL_INDI_TICK_MODE_ENTRY, +}; /** * Class to deal with tick indicators. */ template -class IndicatorTick : public IndicatorBase { +class IndicatorTick : public Indicator { protected: BufferTick itdata; TS itparams; @@ -51,6 +58,11 @@ class IndicatorTick : public IndicatorBase { * Called on constructor. */ void Init() { + // We can't index by shift. + flags &= ~INDI_FLAG_INDEXABLE_BY_SHIFT; + // We can only index via timestamp. + flags |= INDI_FLAG_INDEXABLE_BY_TIMESTAMP; + itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); itdata.SetOverflowListener(IndicatorTickOverflowListener, 10); // Ask and Bid price. @@ -63,20 +75,47 @@ class IndicatorTick : public IndicatorBase { /** * Class constructor. */ - IndicatorTick(const TS& _itparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { + IndicatorTick(const TS& _itparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_itparams, _indi_src, _indi_mode) { itparams = _itparams; if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); } Init(); } - IndicatorTick(ENUM_INDICATOR_TYPE _itype, string _symbol, int _shift = 0, string _name = "") { - itparams.SetIndicatorType(_itype); - itparams.SetShift(_shift); + IndicatorTick(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) { Init(); } - /* Virtual method implementations */ + /** + * Returns value storage of given kind. + */ + IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + return (IValueStorage*)itdata.GetAskValueStorage(); + case INDI_VS_TYPE_PRICE_BID: + return (IValueStorage*)itdata.GetBidValueStorage(); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. + */ + virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + case INDI_VS_TYPE_PRICE_BID: + return true; + } + + return Indicator::HasSpecificValueStorage(_type); + } /** * Sends historic entries to listening indicators. May be overriden. @@ -145,7 +184,7 @@ class IndicatorTick : public IndicatorBase { * @return * Returns DataParamEntry struct filled with a single value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : itparams.GetShift(); return GetEntry(_ishift)[_mode]; } @@ -165,7 +204,7 @@ class IndicatorTick : public IndicatorBase { /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) { indi_src = _indi; itparams.SetDataSource(-1, _input_mode); } diff --git a/Indicator/IndicatorTickOrCandleSource.h b/Indicator/IndicatorTickOrCandleSource.h new file mode 100644 index 000000000..45fce1acd --- /dev/null +++ b/Indicator/IndicatorTickOrCandleSource.h @@ -0,0 +1,99 @@ +//+------------------------------------------------------------------+ +//| 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 . + * + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../Indicator.mqh" +#include "tests/classes/IndicatorTfDummy.h" +#include "tests/classes/IndicatorTickReal.h" + +/** + * Indicator to be used with IndicatorTick or IndicatorCandle as a data source. + * + * In order it to work with + */ +template +class IndicatorTickOrCandleSource : public Indicator { + public: + /** + * Class constructor. + */ + IndicatorTickOrCandleSource(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_iparams, _indi_src, _indi_mode) {} + IndicatorTickOrCandleSource(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(_iparams, _tf) {} + IndicatorTickOrCandleSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) {} + + /** + * Class deconstructor. + */ + ~IndicatorTickOrCandleSource() {} + + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) override { + // @todo Make use of this method. + return true; + } + + /** + * Called when data source emits new entry (historic or future one). + */ + void OnDataSourceEntry(IndicatorDataEntry& entry) override{ + // We do nothing. + }; + + /** + * Creates default, tick based indicator for given applied price. + */ + IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) override { + // Returning real candle indicator. Thus way we can use SetAppliedPrice() and select Ask or Bid price. + IndicatorBase* _indi; + + switch (_applied_price) { + case PRICE_ASK: + case PRICE_BID: + case PRICE_OPEN: + case PRICE_HIGH: + case PRICE_LOW: + case PRICE_CLOSE: + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + // @todo ASK/BID should return Tick indicator. Other APs should return Candle-over-Tick indicator. + _indi = new IndicatorTfDummy(GetTf()); + _indi.SetDataSource(new IndicatorTickReal(GetTf())); + return _indi; + } + + Print("Passed wrong value for applied price for ", GetFullName(), " indicator!"); + DebugBreak(); + return NULL; + } +}; diff --git a/Indicator/IndicatorTickSource.h b/Indicator/IndicatorTickSource.h new file mode 100644 index 000000000..6e1734f4c --- /dev/null +++ b/Indicator/IndicatorTickSource.h @@ -0,0 +1,119 @@ +//+------------------------------------------------------------------+ +//| 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 . + * + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../Indicator.mqh" + +/** + * Indicator to be used with IndicatorTick as a data source. + */ +template +class IndicatorTickSource : public Indicator { + public: + /** + * Class constructor. + */ + IndicatorTickSource(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_iparams, _indi_src, _indi_mode) {} + IndicatorTickSource(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(_iparams, _tf) {} + IndicatorTickSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) {} + + /** + * Class deconstructor. + */ + ~IndicatorTickSource() {} + + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { + if (_indi == NULL) { + // Just deselecting data source. + Indicator::SetDataSource(_indi, _input_mode); + return; + } + + // We can only use data sources which supports all possible modes from IndicatorTick. + bool _result = true; + + if (_input_mode == -1) { + // Source mode which acts as an applied price wasn't selected, so we have to ensure that source is a Tick + // indicator. Valid only if implements bid or ask price. + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_BID) || + _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_ASK); + } else { + // Applied price selected. We will select source indicator only if it provides price buffer for given applied + // price. + switch (_input_mode) { + case PRICE_OPEN: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + break; + case PRICE_HIGH: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + break; + case PRICE_LOW: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + break; + case PRICE_CLOSE: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + break; + case PRICE_MEDIAN: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_MEDIAN); + break; + case PRICE_TYPICAL: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_TYPICAL); + break; + case PRICE_WEIGHTED: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_WEIGHTED); + break; + default: + Alert("Invalid input mode ", _input_mode, " for indicator ", _indi.GetFullName(), + ". Must be one one PRICE_(OPEN|HIGH|LOW|CLOSE|MEDIAN|TYPICAL|WEIGHTED)!"); + DebugBreak(); + } + } + + if (!_result) { + Alert("Passed indicator ", _indi.GetFullName(), + " does not provide required data storage(s)! Mode selected: ", _input_mode); + DebugBreak(); + } + + Indicator::SetDataSource(_indi, _input_mode); + } + + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) override { + // @todo Make use of this method. + return true; + } +}; diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 739855fae..c9cb9d86f 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -48,7 +48,7 @@ Ref indi_ama_orig_sim; * Implements OnInit(). */ int OnInit() { - indicators.Add(indi_tick = new IndicatorTickReal(_Symbol)); + indicators.Add(indi_tick = new IndicatorTickReal(PERIOD_CURRENT)); // 1-second candles. // indicators.Add(indi_tf = new IndicatorTfDummy(1)); @@ -107,6 +107,6 @@ void OnTick() { */ void OnDeinit(const int reason) { // Printing all grouped candles. - // Print(indi_tf.Ptr().GetName(), "'s all candles:"); - // Print(indi_tf.Ptr().CandlesToString()); + Print(indi_tf_orig_sim.Ptr().GetName(), "'s all candles:"); + Print(indi_tf_orig_sim.Ptr().CandlesToString()); } diff --git a/Indicator/tests/IndicatorTick.test.mq5 b/Indicator/tests/IndicatorTick.test.mq5 index 9b9a082e3..67400dc41 100644 --- a/Indicator/tests/IndicatorTick.test.mq5 +++ b/Indicator/tests/IndicatorTick.test.mq5 @@ -26,50 +26,13 @@ // Includes. #include "../../Test.mqh" -#include "../IndicatorTick.h" - -// Structs. -struct IndicatorTickDummyParams : IndicatorParams { - IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} -}; - -/** - * Tick indicator is an indicator that provides per-tick information. - * When asked to return data via GetEntry() it could fetch data from pre-made - * tick history or generate tick on-the-fly from remote source and save it in - * the history. - * - * Note that indicators could provide data also for future shifts, so shift=-10 - * is perfectly valid for them when doing GetEntry()/GetValue(). - * - * Tick indicator may become a data source for Candle indicator. In this - * scenario, when trying to fetch candle for a given shift, tick indicator is - * asked for ticks in a given timespan. E.g., Candle indicator may work in a 5s - * timespans, so when fetching candle with shift now+1, Tick indicator will be - * asked for ticks between now+5s and now+10s. - *rmf - * In order to fetch consecutive candles, you have to call - * IndicatorCandle::NextMaybe() to check whether new candle is ready to be - * processed. If yes, then new candle will be at index 0. - * - * if (indi_candle.NextMaybe()) { - * double _open = indi_candle.Open(0); // Shift 0 = current candle. - * double _close = indi_candle.Close(0); // Shift 0 = current candle. - * } - */ -class IndicatorTickDummy : public IndicatorTick { - public: - IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } -}; +#include "classes/IndicatorTickDummy.h" /** * Implements OnInit(). */ int OnInit() { - IndicatorTickDummy _indi_tick(_Symbol); + IndicatorTickDummy _indi_tick(PERIOD_CURRENT); long _time = 1; for (double _price = 0.1; _price <= 2.0; _price += 0.1) { MqlTick _tick; diff --git a/Indicator/tests/classes/IndicatorTfDummy.h b/Indicator/tests/classes/IndicatorTfDummy.h index 7bd57829e..6680f07e0 100644 --- a/Indicator/tests/classes/IndicatorTfDummy.h +++ b/Indicator/tests/classes/IndicatorTfDummy.h @@ -29,6 +29,9 @@ #pragma once #endif +// Includes. +#include "../../IndicatorTf.h" + // Params for dummy candle-based indicator. struct IndicatorTfDummyParams : IndicatorTfParams { IndicatorTfDummyParams(uint _spc = 60) : IndicatorTfParams(_spc) {} @@ -43,7 +46,7 @@ class IndicatorTfDummy : public IndicatorTf { IndicatorTfDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTf(_tf) {} IndicatorTfDummy(ENUM_TIMEFRAMES_INDEX _tfi = 0) : IndicatorTf(_tfi) {} - string GetName() override { return "IndicatorTfDummy(" + IntegerToString(icparams.spc) + ")"; } + string GetName() override { return "IndicatorTfDummy(" + IntegerToString(iparams.spc) + ")"; } void OnDataSourceEntry(IndicatorDataEntry& entry) override { // When overriding OnDataSourceEntry() we have to remember to call parent @@ -51,7 +54,9 @@ class IndicatorTfDummy : public IndicatorTf { // create/update matching candle. IndicatorTf::OnDataSourceEntry(entry); +#ifdef __debug_indicator__ Print(GetFullName(), " got new tick at ", entry.timestamp, " (" + TimeToString(entry.timestamp) + "): ", entry.ToString()); +#endif } }; diff --git a/Indicator/tests/classes/IndicatorTickDummy.h b/Indicator/tests/classes/IndicatorTickDummy.h index 355659ff9..683025176 100644 --- a/Indicator/tests/classes/IndicatorTickDummy.h +++ b/Indicator/tests/classes/IndicatorTickDummy.h @@ -1,3 +1,38 @@ +//+------------------------------------------------------------------+ +//| 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 + * Dummy candle-based indicator. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../../../Tick.struct.h" +#include "../../IndicatorTick.h" + // Params for dummy tick-based indicator. struct IndicatorTickDummyParams : IndicatorParams { IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 2, TYPE_DOUBLE) {} @@ -6,10 +41,8 @@ struct IndicatorTickDummyParams : IndicatorParams { // Dummy tick-based indicator. class IndicatorTickDummy : public IndicatorTick { public: - IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } + IndicatorTickDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} string GetName() override { return "IndicatorTickDummy"; } @@ -17,13 +50,22 @@ class IndicatorTickDummy : public IndicatorTick(1.0f, 1.01f))); - EmitEntry(TickToEntry(1500, TickAB(1.5f, 1.51f))); - EmitEntry(TickToEntry(2000, TickAB(2.0f, 2.01f))); - EmitEntry(TickToEntry(3000, TickAB(3.0f, 3.01f))); - EmitEntry(TickToEntry(4000, TickAB(4.0f, 4.01f))); - EmitEntry(TickToEntry(4100, TickAB(4.1f, 4.11f))); - EmitEntry(TickToEntry(4200, TickAB(4.2f, 4.21f))); - EmitEntry(TickToEntry(4800, TickAB(4.8f, 4.81f))); + TickAB _t1(1.0f, 1.01f); + TickAB _t2(1.5f, 1.51f); + TickAB _t3(2.0f, 2.01f); + TickAB _t4(3.0f, 3.01f); + TickAB _t5(4.0f, 4.01f); + TickAB _t6(4.1f, 4.11f); + TickAB _t7(4.2f, 4.21f); + TickAB _t8(4.8f, 4.81f); + + EmitEntry(TickToEntry(1000, _t1)); + EmitEntry(TickToEntry(1500, _t2)); + EmitEntry(TickToEntry(2000, _t3)); + EmitEntry(TickToEntry(3000, _t4)); + EmitEntry(TickToEntry(4000, _t5)); + EmitEntry(TickToEntry(4100, _t6)); + EmitEntry(TickToEntry(4200, _t7)); + EmitEntry(TickToEntry(4800, _t8)); }; }; diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index 668ddc1bf..977c5cc48 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -41,22 +41,24 @@ struct IndicatorTickRealParams : IndicatorParams { // Real tick-based indicator. class IndicatorTickReal : public IndicatorTick { public: - IndicatorTickReal(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } + IndicatorTickReal(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} string GetName() override { return "IndicatorTickReal"; } void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { // Feeding base indicator with historic entries of this indicator. +#ifdef __debug__ Print(GetFullName(), " became a data source for ", _base_indi.GetFullName()); +#endif #ifndef __MQL4__ int _ticks_to_emit = 1000; +#ifdef __debug_verbose__ Print(_base_indi.GetFullName(), " will be now filled with ", _ticks_to_emit, " historical entries generated by " + GetFullName()); +#endif static MqlTick _ticks[]; ArrayResize(_ticks, 0); @@ -74,6 +76,9 @@ class IndicatorTickReal : public IndicatorTick } } + // Clearing possible error 4004. + ResetLastError(); + for (int i = 0; i < _num_copied; ++i) { TickAB _tick(_ticks[i].ask, _ticks[i].bid); // We can't call EmitEntry() here, as tick would go to multiple sources at the same time! @@ -94,7 +99,10 @@ class IndicatorTickReal : public IndicatorTick // Copying only the last tick. int _num_copied = CopyTicks(GetSymbol(), _ticks, COPY_TICKS_INFO, 0, 1); +#ifdef __debug_verbose__ Print("TickReal: ", TimeToString(_ticks[0].time), " = ", _ticks[0].bid); +#endif + double _ask = _ticks[0].ask; double _bid = _ticks[0].bid; long _time = _ticks[0].time; diff --git a/IndicatorBase.h b/IndicatorBase.h index a5c35282f..4feceb40d 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -71,6 +71,8 @@ class IndicatorBase : public Chart { int indi_src_mode; // Mode of source indicator IndicatorCalculateCache cache; ARRAY(WeakRef, listeners); // List of indicators that listens for events from this one. + long last_tick_time; // Time of the last Tick() call. + int flags; // Flags such as INDI_FLAG_INDEXABLE_BY_SHIFT. public: /* Indicator enumerations */ @@ -91,18 +93,24 @@ class IndicatorBase : public Chart { * Class constructor. */ IndicatorBase(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = NULL) : indi_src(NULL), Chart(_tf, _symbol) { + // By default, indicator is indexable only by shift and data source must be also indexable by shift. + flags = INDI_FLAG_INDEXABLE_BY_SHIFT | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT; calc_start_bar = 0; is_fed = false; indi_src = NULL; + last_tick_time = 0; } /** * Class constructor. */ IndicatorBase(ENUM_TIMEFRAMES_INDEX _tfi, string _symbol = NULL) : Chart(_tfi, _symbol) { + // By default, indicator is indexable only by shift and data source must be also indexable by shift. + flags = INDI_FLAG_INDEXABLE_BY_SHIFT | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT; calc_start_bar = 0; is_fed = false; indi_src = NULL; + last_tick_time = 0; } /** @@ -121,11 +129,32 @@ class IndicatorBase : public Chart { /* Operator overloading methods */ /** - * Access indicator entry data using [] operator. + * Access indicator entry data using [] operator via shift. */ - // IndicatorDataEntry operator[](datetime _dt) { return GetEntry(_dt); } - IndicatorDataEntry operator[](int _index) { return GetEntry(_index); } - IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry(_index); } + IndicatorDataEntry operator[](int _index) { + if (!bool(flags | INDI_FLAG_INDEXABLE_BY_SHIFT)) { + Print(GetFullName(), " is not indexable by shift!"); + DebugBreak(); + IndicatorDataEntry _default; + return _default; + } + return GetEntry(_index); + } + + /** + * Access indicator entry data using [] operator via datetime. + */ + IndicatorDataEntry operator[](datetime _dt) { + if (!bool(flags | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) { + Print(GetFullName(), " is not indexable by timestamp!"); + DebugBreak(); + IndicatorDataEntry _default; + return _default; + } + return GetEntry(_dt); + } + + IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry((int)_index); } /* Buffer methods */ @@ -275,8 +304,54 @@ class IndicatorBase : public Chart { */ IndicatorBase* GetDataSourceRaw() { return indi_src.Ptr(); } + /** + * Returns given data source type. Used by i*OnIndicator methods if indicator's Calculate() uses other indicators. + */ + IndicatorBase* GetDataSource(ENUM_INDICATOR_TYPE _type) { + IndicatorBase* _result = NULL; + if (indicators.KeyExists((int)_type)) { + _result = indicators[(int)_type].Ptr(); + } else { + Ref _indi = FetchDataSource(_type); + if (!_indi.IsSet()) { + Alert(GetFullName(), " does not define required indicator type ", EnumToString(_type), " for symbol ", + GetSymbol(), ", and timeframe ", GetTf(), "!"); + DebugBreak(); + } else { + indicators.Set((int)_type, _indi); + _result = _indi.Ptr(); + } + } + return _result; + } + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + virtual IndicatorBase* OnDataSourceRequest() { + Print("In order to use IDATA_INDICATOR mode for indicator ", GetFullName(), + " without explicitly selecting an indicator, ", GetFullName(), + " must override OnDataSourceRequest() method and return new instance of data source to be used by default."); + DebugBreak(); + return NULL; + } + + /** + * Creates default, tick based indicator for given applied price. + */ + virtual IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) { + DebugBreak(); + return NULL; + } + /* Getters */ + /** + * Returns indicator's flags. + */ + int GetFlags() { return flags; } + /** * Returns buffers' cache. */ @@ -308,7 +383,7 @@ class IndicatorBase : public Chart { /** * Whether data source is selected. */ - virtual bool HasDataSource() { return false; } + virtual bool HasDataSource(bool _try_initialize = false) { return false; } /** * Returns currently selected data source doing validation. @@ -330,7 +405,7 @@ class IndicatorBase : public Chart { /** * Get name of the indicator. */ - virtual string GetName() { return ""; } + virtual string GetName() { return EnumToString(GetType()); } /** * Get full name of the indicator (with "over ..." part). @@ -371,7 +446,7 @@ class IndicatorBase : public Chart { /** * Sets indicator data source. */ - virtual void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) = NULL; + virtual void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) = NULL; /** * Sets data source's input mode. @@ -423,6 +498,72 @@ class IndicatorBase : public Chart { return value_storages[_mode]; } + /** + * Returns value storage of given kind. + */ + virtual IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + Print("Error: ", GetFullName(), " indicator has no storage type ", EnumToString(_type), "!"); + DebugBreak(); + return NULL; + } + + virtual IValueStorage* GetSpecificAppliedPriceValueStorage(ENUM_APPLIED_PRICE _ap) { + switch (_ap) { + case PRICE_ASK: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_ASK); + case PRICE_BID: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_BID); + case PRICE_OPEN: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + case PRICE_HIGH: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + case PRICE_LOW: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + case PRICE_CLOSE: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + default: + Print("Error: Invalid applied price " + EnumToString(_ap) + + ", only PRICE_(OPEN|HIGH|LOW|CLOSE) are currently supported by " + "IndicatorBase::GetSpecificAppliedPriceValueStorage()!"); + DebugBreak(); + return NULL; + } + } + + virtual bool HasSpecificAppliedPriceValueStorage(ENUM_APPLIED_PRICE _ap) { + switch (_ap) { + case PRICE_ASK: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_ASK); + case PRICE_BID: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_BID); + case PRICE_OPEN: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + case PRICE_HIGH: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + case PRICE_LOW: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + case PRICE_CLOSE: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + default: + Print("Error: Invalid applied price " + EnumToString(_ap) + + ", only PRICE_(OPEN|HIGH|LOW|CLOSE) are currently supported by " + "IndicatorBase::HasSpecificAppliedPriceValueStorage()!"); + DebugBreak(); + return false; + } + } + + /** + * Checks whether indicator support given value storage type. + */ + virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { return false; } + template T GetValue(int _mode = 0, int _index = 0) { T _out; @@ -468,6 +609,31 @@ class IndicatorBase : public Chart { return _result; } + void Tick() { + long _current_time = TimeCurrent(); + + if (last_tick_time == _current_time) { + // We've already ticked. + return; + } + + last_tick_time = _current_time; + + // Checking and potentially initializing new data source. + if (HasDataSource(true) != NULL) { + // Ticking data source if not yet ticked. + GetDataSource().Tick(); + } + + // Also ticking all used indicators if they've not yet ticked. + for (DictStructIterator> iter = indicators.Begin(); iter.IsValid(); ++iter) { + iter.Value().Ptr().Tick(); + } + + // Overridable OnTick() method. + OnTick(); + } + virtual void OnTick() {} /* Data representation methods */ @@ -477,7 +643,19 @@ class IndicatorBase : public Chart { /** * Returns the indicator's struct value. */ - virtual IndicatorDataEntry GetEntry(int _index = -1) = NULL; + virtual IndicatorDataEntry GetEntry(int _index = 0) = NULL; + + /** + * Returns the indicator's struct value. + */ + virtual IndicatorDataEntry GetEntry(datetime _dt) { + Print(GetFullName(), + " must implement IndicatorDataEntry IndicatorBase::GetEntry(datetime _dt) in order to use GetEntry(datetime " + "_dt) or _indi[datetime] subscript operator!"); + DebugBreak(); + IndicatorDataEntry _default; + return _default; + } /** * Alters indicator's struct value. @@ -492,7 +670,7 @@ class IndicatorBase : public Chart { /** * Returns the indicator's entry value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _index = -1) = NULL; + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) = NULL; /** * Sends entry to listening indicators. @@ -520,10 +698,19 @@ class IndicatorBase : public Chart { */ virtual void OnBecomeDataSourceFor(IndicatorBase* _base_indi){}; + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + virtual bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) { + _reason = "Indicator " + GetName() + " does not implement OnValidateDataSource()"; + return false; + } + /** * Returns indicator value for a given shift and mode. */ - // virtual double GetValue(int _shift = -1, int _mode = 0) = NULL; + // virtual double GetValue(int _shift = 0, int _mode = 0) = NULL; /** * Checks whether indicator has a valid value for a given shift. @@ -605,6 +792,138 @@ class IndicatorBase : public Chart { * Gets indicator's time-frame. */ ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); } + + /* Defines MQL backward compatible methods */ + + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, DUMMY); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, int _mode, + int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, int _mode, + int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, + int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, K _k, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, K _k, L _l, M _m, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k + COMMA _l COMMA _m); +#endif + } }; /** diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index d24d3eeb9..3171251f7 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -23,7 +23,7 @@ // Includes. #include "../../Bar.struct.h" #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Pattern.struct.h" #include "../../Serializer.mqh" #include "../Price/Indi_Price.mqh" @@ -47,13 +47,14 @@ struct CandleParams : IndicatorParams { /** * Implements Candle Pattern Detector. */ -class Indi_Candle : public Indicator { +class Indi_Candle : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Candle(CandleParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Candle(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CANDLE, _tf, _shift){}; + Indi_Candle(CandleParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Candle(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CANDLE, _tf, _shift){}; /** * Alters indicator's struct value. @@ -66,7 +67,7 @@ class Indi_Candle : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[1]; diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index 62e1b1a60..dc5bdc958 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -23,7 +23,7 @@ // Includes. #include "../../Bar.struct.h" #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Pattern.struct.h" #include "../../Serializer.mqh" #include "../Price/Indi_Price.mqh" @@ -46,18 +46,19 @@ struct IndiPatternParams : IndicatorParams { /** * Implements Pattern Detector. */ -class Indi_Pattern : public Indicator { +class Indi_Pattern : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Pattern(IndiPatternParams& _p, IndicatorBase* _indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Pattern(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PATTERN, _tf, _shift){}; + Indi_Pattern(IndiPatternParams& _p, IndicatorBase* _indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Pattern(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PATTERN, _tf, _shift){}; /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int i; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[8]; @@ -112,7 +113,7 @@ class Indi_Pattern : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = 0) { _entry.SetFlag(INDI_ENTRY_FLAG_IS_BITWISE, true); Indicator::GetEntryAlter(_entry); } diff --git a/Indicators/Indi_AC.mqh b/Indicators/Indi_AC.mqh index be9fe709b..c53eeffc1 100644 --- a/Indicators/Indi_AC.mqh +++ b/Indicators/Indi_AC.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -39,6 +39,11 @@ struct IndiACParams : IndicatorParams { SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Accelerator"); shift = _shift; + switch (idstype) { + case IDATA_ICUSTOM: + SetMaxModes(2); + break; + } }; IndiACParams(IndiACParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; @@ -49,13 +54,13 @@ struct IndiACParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_AC : public Indicator { +class Indi_AC : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AC(IndiACParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AC, _tf, _shift){}; + Indi_AC(IndiACParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AC, _tf, _shift){}; /** * Returns the indicator value. @@ -100,7 +105,7 @@ class Indi_AC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { IndicatorDataEntryValue _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_AD.mqh b/Indicators/Indi_AD.mqh index 51ea677cf..c91a29f1f 100644 --- a/Indicators/Indi_AD.mqh +++ b/Indicators/Indi_AD.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -48,13 +48,13 @@ struct IndiADParams : IndicatorParams { /** * Implements the Accumulation/Distribution indicator. */ -class Indi_AD : public Indicator { +class Indi_AD : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AD(IndiADParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AD, _tf, _shift) { + Indi_AD(IndiADParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AD, _tf, _shift) { iparams.SetTf(_tf); }; @@ -101,7 +101,7 @@ class Indi_AD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_ADX.mqh b/Indicators/Indi_ADX.mqh index 752805800..0301eec6e 100644 --- a/Indicators/Indi_ADX.mqh +++ b/Indicators/Indi_ADX.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Price/Indi_Price.mqh" #ifndef __MQL4__ @@ -61,13 +61,13 @@ struct IndiADXParams : IndicatorParams { /** * Implements the Average Directional Movement Index indicator. */ -class Indi_ADX : public Indicator { +class Indi_ADX : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ADX(IndiADXParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_ADX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ADX, _tf, _shift) {} + Indi_ADX(IndiADXParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ADX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ADX, _tf, _shift) {} /** * Returns the indicator value. @@ -115,7 +115,7 @@ class Indi_ADX : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_ADXW.mqh b/Indicators/Indi_ADXW.mqh index efd22ce2e..dc199dae2 100644 --- a/Indicators/Indi_ADXW.mqh +++ b/Indicators/Indi_ADXW.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "../Storage/ValueStorage.spread.h" @@ -55,13 +55,14 @@ struct IndiADXWParams : IndiADXParams { /** * Implements the Average Directional Movement Index indicator by Welles Wilder. */ -class Indi_ADXW : public Indicator { +class Indi_ADXW : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ADXW(IndiADXWParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_ADXW(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ADXW, _tf, _shift){}; + Indi_ADXW(IndiADXWParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ADXW(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ADXW, _tf, _shift){}; /** * Built-in version of ADX Wilder. @@ -102,6 +103,16 @@ class Indi_ADXW : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ADX Wilder. + */ + static double iADXWilderOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_ADXW_ON_" + _indi.GetFullName(), _period)); + return iADXWilderOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _mode, _shift, _cache); + } + /** * OnCalculate() method for ADXW indicator. */ @@ -215,7 +226,7 @@ class Indi_ADXW : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -227,6 +238,10 @@ class Indi_ADXW : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_ADXW::iADXWilderOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod() /*]*/, _mode, + _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 861d08cda..e72de2fdc 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -22,7 +22,8 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" +#include "../Indicator/tests/classes/IndicatorTfDummy.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "Price/Indi_Price.mqh" @@ -36,14 +37,15 @@ struct IndiAMAParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructor. IndiAMAParams(int _period = 10, int _fast_period = 2, int _slow_period = 30, int _ama_shift = 0, - ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL, int _shift = 0) + ENUM_APPLIED_PRICE _ap = PRICE_OPEN, int _shift = 0) : period(_period), fast_period(_fast_period), slow_period(_slow_period), ama_shift(_ama_shift), - applied_price(_ap), - IndicatorParams(INDI_AMA, 1, TYPE_DOUBLE) { + applied_price(_ap) { SetDataValueRange(IDATA_RANGE_PRICE); + // Defaulting to on-indicator mode (will use real ticks from platform via IndicatorTickReal). + SetDataSourceMode(IDATA_INDICATOR); SetShift(_shift); switch (idstype) { case IDATA_ICUSTOM: @@ -56,19 +58,22 @@ struct IndiAMAParams : IndicatorParams { IndiAMAParams(IndiAMAParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; tf = _tf; - }; + } }; /** * Implements the AMA indicator. */ -class Indi_AMA : public Indicator { +class Indi_AMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AMA, _tf, _shift){}; + Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL, int _indi_mode = 0) + : IndicatorTickOrCandleSource(_p, _indi_src, _indi_mode) { + iparams.SetIndicatorType(INDI_AMA); + }; + Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AMA, _tf, _shift){}; /** * Built-in version of AMA. @@ -82,26 +87,12 @@ class Indi_AMA : public Indicator { #else INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT( _symbol, _tf, _ap, - Util::MakeKey("INDI_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); + Util::MakeKey("Indi_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, _mode, _shift, _cache); #endif } - /** - * On-indicator version of AMA. - */ - static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, - int _fast_ema_period, int _slow_ema_period, int _ama_shift, ENUM_APPLIED_PRICE _ap, - int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { - INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( - _indi, _symbol, _tf, _ap, - Util::MakeKey("INDI_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, - (int)_ap)); - return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, - _ama_shift, _mode, _shift, _cache); - } - /** * Calculates AMA on the array of values. */ @@ -124,6 +115,20 @@ class Indi_AMA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of AMA. + */ + static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, + int _fast_ema_period, int _slow_ema_period, int _ama_shift, ENUM_APPLIED_PRICE _ap, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC( + _indi, _symbol, _tf, _ap, + Util::MakeKey("Indi_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, + (int)_ap)); + return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, + _ama_shift, _mode, _shift, _cache); + } + /** * OnInit() method for AMA indicator. */ @@ -172,6 +177,10 @@ class Indi_AMA : public Indicator { CalculateInit(InpPeriodAMA, InpFastPeriodEMA, InpSlowPeriodEMA, InpShiftAMA, ExtFastSC, ExtSlowSC, ExtPeriodAMA, ExtSlowPeriodEMA, ExtFastPeriodEMA); + for (int x = prev_calculated; x < rates_total; ++x) { + Print("price[", x, "] = ", price[x].Get(), ", O = ", iOpen(Symbol(), PERIOD_CURRENT, Bars(Symbol(), PERIOD_CURRENT) - x - 1)); + } + int i; // Check for rates count. if (rates_total < ExtPeriodAMA + begin) return (0); @@ -213,7 +222,7 @@ class Indi_AMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -237,6 +246,20 @@ class Indi_AMA : public Indicator { return _value; } + /** + * Called when data source emits new entry (historic or future one). + */ + void OnDataSourceEntry(IndicatorDataEntry &entry) override { + // Just to be able to make a breakpoint here. + int x = 4; + }; + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + virtual IndicatorBase *OnDataSourceRequest() { return DataSourceRequestReturnDefault(GetAppliedPrice()); } + /* Getters */ /** diff --git a/Indicators/Indi_AO.mqh b/Indicators/Indi_AO.mqh index a88552202..c2f9e6d35 100644 --- a/Indicators/Indi_AO.mqh +++ b/Indicators/Indi_AO.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,13 +51,13 @@ struct IndiAOParams : IndicatorParams { /** * Implements the Awesome oscillator. */ -class Indi_AO : public Indicator { +class Indi_AO : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AO(IndiAOParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AO, _tf, _shift){}; + Indi_AO(IndiAOParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AO, _tf, _shift){}; /** * Returns the indicator value. @@ -103,7 +103,7 @@ class Indi_AO : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_ASI.mqh b/Indicators/Indi_ASI.mqh index 2e0cf341b..cccfc3a2a 100644 --- a/Indicators/Indi_ASI.mqh +++ b/Indicators/Indi_ASI.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -46,13 +46,13 @@ struct IndiASIParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_ASI : public Indicator { +class Indi_ASI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ASI(IndiASIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_ASI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ASI, _tf, _shift){}; + Indi_ASI(IndiASIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ASI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ASI, _tf, _shift){}; /** * Built-in version of ASI. @@ -84,6 +84,16 @@ class Indi_ASI : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ASI. + */ + static double iASIOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, double _mpc, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_ASI_ON_" + _indi.GetFullName(), _mpc)); + return iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mpc, _mode, _shift, _cache); + } + /** * OnInit() method for ASI indicator. */ @@ -155,7 +165,7 @@ class Indi_ASI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -168,8 +178,11 @@ class Indi_ASI : public Indicator { Util::MakeKey("Indi_ASI", GetMaximumPriceChanging())); _value = iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, GetMaximumPriceChanging(), _mode, _ishift, _cache); + } break; + case IDATA_INDICATOR: + _value = Indi_ASI::iASIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetMaximumPriceChanging() /*]*/, + _mode, _ishift, THIS_PTR); break; - } default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ATR.mqh b/Indicators/Indi_ATR.mqh index c74f1edd6..3a6328447 100644 --- a/Indicators/Indi_ATR.mqh +++ b/Indicators/Indi_ATR.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -52,13 +52,13 @@ struct IndiATRParams : IndicatorParams { * * Note: It doesn't give independent signals. It is used to define volatility (trend strength). */ -class Indi_ATR : public Indicator { +class Indi_ATR : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ATR(IndiATRParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_ATR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ATR, _tf, _shift){}; + Indi_ATR(IndiATRParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ATR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ATR, _tf, _shift){}; /** * Returns the indicator value. @@ -103,7 +103,7 @@ class Indi_ATR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Alligator.mqh b/Indicators/Indi_Alligator.mqh index 62b552df7..ff8fe357d 100644 --- a/Indicators/Indi_Alligator.mqh +++ b/Indicators/Indi_Alligator.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -95,14 +95,15 @@ struct IndiAlligatorParams : IndicatorParams { /** * Implements the Alligator indicator. */ -class Indi_Alligator : public Indicator { +class Indi_Alligator : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_Alligator(IndiAlligatorParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Alligator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ADX, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Alligator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ADX, _tf, _shift){}; /** * Returns the indicator value. @@ -162,7 +163,7 @@ class Indi_Alligator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); #ifdef __MQL4__ diff --git a/Indicators/Indi_AppliedPrice.mqh b/Indicators/Indi_AppliedPrice.mqh index 379596331..28d43b785 100644 --- a/Indicators/Indi_AppliedPrice.mqh +++ b/Indicators/Indi_AppliedPrice.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "OHLC/Indi_OHLC.mqh" // Structs. @@ -44,7 +44,7 @@ struct IndiAppliedPriceParams : IndicatorParams { /** * Implements the "Applied Price over OHCL Indicator" indicator, e.g. over Indi_Price. */ -class Indi_AppliedPrice : public Indicator { +class Indi_AppliedPrice : public IndicatorTickOrCandleSource { protected: void OnInit() { if (!indi_src.IsSet()) { @@ -58,10 +58,11 @@ class Indi_AppliedPrice : public Indicator { * Class constructor. */ Indi_AppliedPrice(IndiAppliedPriceParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) { + : IndicatorTickOrCandleSource(_p, _indi_src) { OnInit(); }; - Indi_AppliedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE, _tf, _shift) { + Indi_AppliedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift) { OnInit(); }; @@ -74,7 +75,7 @@ class Indi_AppliedPrice : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_BWMFI.mqh b/Indicators/Indi_BWMFI.mqh index cc8b55e08..50d44420d 100644 --- a/Indicators/Indi_BWMFI.mqh +++ b/Indicators/Indi_BWMFI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -62,14 +62,14 @@ struct IndiBWIndiMFIParams : IndicatorParams { /** * Implements the Market Facilitation Index by Bill Williams indicator. */ -class Indi_BWMFI : public Indicator { +class Indi_BWMFI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_BWMFI(IndiBWIndiMFIParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_BWMFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BWMFI, _tf, _shift) {} + Indi_BWMFI(IndiBWIndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BWMFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BWMFI, _tf, _shift) {} /** * Returns the indicator value. @@ -114,9 +114,11 @@ class Indi_BWMFI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = BWMFI_BUFFER, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = BWMFI_BUFFER, int _shift = 0) { + int _ishift = iparams.GetShift() + _shift; + double _value = EMPTY_VALUE; - int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; @@ -136,7 +138,7 @@ class Indi_BWMFI : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // @see: https://en.wikipedia.org/wiki/Market_facilitation_index diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index 65d7cb881..5699beba3 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTf.h" #include "../Storage/ValueStorage.all.h" #include "Indi_AC.mqh" #include "Indi_AO.mqh" @@ -40,11 +40,15 @@ enum ENUM_INDI_BWZT_MODE { // Structs. struct IndiBWZTParams : IndicatorParams { + Ref indi_ac; + Ref indi_ao; unsigned int period; unsigned int second_period; unsigned int sum_period; // Struct constructor. IndiBWZTParams(int _shift = 0) : IndicatorParams(INDI_BWZT, FINAL_INDI_BWZT_MODE_ENTRY, TYPE_DOUBLE) { + indi_ac = NULL; + indi_ao = NULL; SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\BW-ZoneTrade"); shift = _shift; @@ -58,13 +62,14 @@ struct IndiBWZTParams : IndicatorParams { /** * Implements the Bill Williams' Zone Trade. */ -class Indi_BWZT : public Indicator { +class Indi_BWZT : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_BWZT(IndiBWZTParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_BWZT(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BWZT, _tf, _shift){}; + Indi_BWZT(IndiBWZTParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_BWZT(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BWZT, _tf, _shift){}; /** * Built-in version of BWZT. @@ -102,6 +107,34 @@ class Indi_BWZT : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of BWZT. + */ + static double iBWZTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode, int _shift, + IndicatorBase *_obj) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_BWZT_ON_" + _indi.GetFullName())); + + Indi_AC *_indi_ac = _obj.GetDataSource(INDI_AC); + Indi_AO *_indi_ao = _obj.GetDataSource(INDI_AO); + + return iBWZTOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache, _indi_ac, _indi_ao); + } + + /** + * Provides built-in indicators whose can be used as data source. + */ + virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + switch (_id) { + case INDI_AC: + return iparams.indi_ac.Ptr(); + case INDI_AO: + return iparams.indi_ao.Ptr(); + } + + return NULL; + } + /** * OnCalculate() method for BWZT indicator. */ @@ -172,7 +205,7 @@ class Indi_BWZT : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -182,6 +215,9 @@ class Indi_BWZT : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_BWZT::iBWZTOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_Bands.mqh b/Indicators/Indi_Bands.mqh index 0ff6a92e1..09e36401e 100644 --- a/Indicators/Indi_Bands.mqh +++ b/Indicators/Indi_Bands.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_CCI.mqh" #include "Indi_Envelopes.mqh" #include "Indi_MA.mqh" @@ -86,14 +86,14 @@ struct IndiBandsParams : IndicatorParams { /** * Implements the Bollinger Bands® indicator. */ -class Indi_Bands : public Indicator { +class Indi_Bands : public IndicatorTickSource { public: /** * Class constructor. */ Indi_Bands(IndiBandsParams &_p, IndicatorBase *_indi_src = NULL, int _mode = 0) - : Indicator(_p, _indi_src, _mode) {} - Indi_Bands(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BANDS, _tf, _shift) {} + : IndicatorTickSource(_p, _indi_src, _mode) {} + Indi_Bands(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_BANDS, _tf, _shift) {} /** * Returns the indicator value. @@ -239,7 +239,7 @@ class Indi_Bands : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = BAND_BASE, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = BAND_BASE, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_BearsPower.mqh b/Indicators/Indi_BearsPower.mqh index 1b9721606..dae950d35 100644 --- a/Indicators/Indi_BearsPower.mqh +++ b/Indicators/Indi_BearsPower.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,14 +51,15 @@ struct IndiBearsPowerParams : IndicatorParams { /** * Implements the Bears Power indicator. */ -class Indi_BearsPower : public Indicator { +class Indi_BearsPower : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_BearsPower(IndiBearsPowerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_BearsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BEARS, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BearsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BEARS, _tf, _shift) {} /** * Returns the indicator value. @@ -104,7 +105,7 @@ class Indi_BearsPower : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_BullsPower.mqh b/Indicators/Indi_BullsPower.mqh index 1741f8da7..520ef6ccb 100644 --- a/Indicators/Indi_BullsPower.mqh +++ b/Indicators/Indi_BullsPower.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,14 +51,15 @@ struct IndiBullsPowerParams : IndicatorParams { /** * Implements the Bulls Power indicator. */ -class Indi_BullsPower : public Indicator { +class Indi_BullsPower : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_BullsPower(IndiBullsPowerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_BullsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BULLS, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BullsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BULLS, _tf, _shift) {} /** * Returns the indicator value. @@ -104,7 +105,7 @@ class Indi_BullsPower : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_CCI.mqh b/Indicators/Indi_CCI.mqh index c32d4c191..4e34df025 100644 --- a/Indicators/Indi_CCI.mqh +++ b/Indicators/Indi_CCI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickSource.h" #include "Indi_MA.mqh" #include "Indi_PriceFeeder.mqh" #include "Price/Indi_Price.mqh" @@ -58,13 +58,13 @@ struct IndiCCIParams : IndicatorParams { /** * Implements the Commodity Channel Index indicator. */ -class Indi_CCI : public Indicator { +class Indi_CCI : public IndicatorTickSource { public: /** * Class constructor. */ - Indi_CCI(IndiCCIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_CCI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CCI, _tf, _shift) {} + Indi_CCI(IndiCCIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_CCI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_CCI, _tf, _shift) {} /** * Returns the indicator value. @@ -145,7 +145,7 @@ class Indi_CCI : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; switch (iparams.idstype) { diff --git a/Indicators/Indi_CHO.mqh b/Indicators/Indi_CHO.mqh index 1cf24699e..5366e2651 100644 --- a/Indicators/Indi_CHO.mqh +++ b/Indicators/Indi_CHO.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "../Util.h" #include "Indi_MA.mqh" @@ -54,13 +54,14 @@ struct IndiCHOParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_CHO : public Indicator { +class Indi_CHO : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_CHO(IndiCHOParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_CHO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CHAIKIN, _tf, _shift){}; + Indi_CHO(IndiCHOParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_CHO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CHAIKIN, _tf, _shift){}; /** * Built-in version of Chaikin Oscillator. @@ -73,7 +74,7 @@ class Indi_CHO : public Indicator { _mode, _shift); #else INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG( - _symbol, _tf, Util::MakeKey("INDI_CHO", _fast_ma_period, _slow_ma_period, (int)_ma_method, (int)_av)); + _symbol, _tf, Util::MakeKey("Indi_CHO", _fast_ma_period, _slow_ma_period, (int)_ma_method, (int)_av)); return iChaikinOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_ma_period, _slow_ma_period, _ma_method, _av, _mode, _shift, _cache); #endif @@ -102,6 +103,20 @@ class Indi_CHO : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Chaikin Oscillator. + */ + static double iChaikinOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _fast_ma_period, + int _slow_ma_period, ENUM_MA_METHOD _ma_method, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_CHO_ON_" + _indi.GetFullName(), _fast_ma_period, _slow_ma_period, (int)_ma_method, + (int)_av)); + return iChaikinOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_ma_period, _slow_ma_period, _ma_method, _av, + _mode, _shift, _cache); + } + /** * OnCalculate() method for Chaikin Oscillator indicator. */ @@ -166,7 +181,7 @@ class Indi_CHO : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -178,6 +193,10 @@ class Indi_CHO : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetFastMA(), GetSlowMA(), GetSmoothMethod(), GetInputVolume() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_CHO::iChaikinOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetFastMA(), GetSlowMA(), + GetSmoothMethod(), GetInputVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_CHV.mqh b/Indicators/Indi_CHV.mqh index d3f97fd42..145a03f59 100644 --- a/Indicators/Indi_CHV.mqh +++ b/Indicators/Indi_CHV.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "../Util.h" #include "Indi_MA.mqh" @@ -55,13 +55,14 @@ struct IndiCHVParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_CHV : public Indicator { +class Indi_CHV : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_CHV(IndiCHVParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_CHV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CHAIKIN_V, _tf, _shift){}; + Indi_CHV(IndiCHVParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_CHV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CHAIKIN_V, _tf, _shift){}; /** * Built-in version of Chaikin Volatility. @@ -99,6 +100,19 @@ class Indi_CHV : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Chaikin Volatility. + */ + static double iCHVOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _smooth_period, + int _chv_period, ENUM_CHV_SMOOTH_METHOD _smooth_method, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_CHV_ON_" + _indi.GetFullName(), _smooth_period, _chv_period, _smooth_method)); + return iCHVOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _smooth_period, _chv_period, _smooth_method, _mode, + _shift, _cache); + } + /** * OnInit() method for Chaikin Volatility indicator. */ @@ -162,7 +176,7 @@ class Indi_CHV : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -174,6 +188,10 @@ class Indi_CHV : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetSmoothPeriod(), GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_CHV::iCHVOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetSmoothPeriod(), + GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ColorBars.mqh b/Indicators/Indi_ColorBars.mqh index f89773c19..7927d1fe2 100644 --- a/Indicators/Indi_ColorBars.mqh +++ b/Indicators/Indi_ColorBars.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -42,21 +42,22 @@ struct IndiColorBarsParams : IndicatorParams { /** * Implements Color Bars */ -class Indi_ColorBars : public Indicator { +class Indi_ColorBars : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ColorBars(IndiColorBarsParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_ColorBars(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_COLOR_BARS, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ColorBars(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_COLOR_BARS, _tf, _shift){}; /** * "Built-in" version of Color Bars. */ static double iColorBars(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { - INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_ColorCandlesDaily"); + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_ColorBars"); return iColorBarsOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); } @@ -82,6 +83,16 @@ class Indi_ColorBars : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Color Bars. + */ + static double iColorBarsOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_ColorBars_ON_" + _indi.GetFullName())); + return iColorBarsOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Color Bars indicator. */ @@ -113,7 +124,7 @@ class Indi_ColorBars : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -123,6 +134,9 @@ class Indi_ColorBars : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_ColorBars::iColorBarsOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_ColorCandlesDaily.mqh b/Indicators/Indi_ColorCandlesDaily.mqh index b8c4b851c..9348b8095 100644 --- a/Indicators/Indi_ColorCandlesDaily.mqh +++ b/Indicators/Indi_ColorCandlesDaily.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -42,15 +42,15 @@ struct IndiColorCandlesDailyParams : IndicatorParams { /** * Implements Color Bars */ -class Indi_ColorCandlesDaily : public Indicator { +class Indi_ColorCandlesDaily : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ColorCandlesDaily(IndiColorCandlesDailyParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_ColorCandlesDaily(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_COLOR_CANDLES_DAILY, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_COLOR_CANDLES_DAILY, _tf, _shift){}; /** * "Built-in" version of Color Candles Daily. @@ -82,6 +82,16 @@ class Indi_ColorCandlesDaily : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Color Candles Daily. + */ + static double iCCDOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_ColorCandlesDaily_ON_" + _indi.GetFullName())); + return iCCDOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Color Candles Daily indicator. */ @@ -110,7 +120,7 @@ class Indi_ColorCandlesDaily : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -120,6 +130,10 @@ class Indi_ColorCandlesDaily : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = + Indi_ColorCandlesDaily::iCCDOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ColorLine.mqh b/Indicators/Indi_ColorLine.mqh index d3dd60ed7..64adcf9dc 100644 --- a/Indicators/Indi_ColorLine.mqh +++ b/Indicators/Indi_ColorLine.mqh @@ -22,14 +22,16 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_MA.mqh" // Structs. struct IndiColorLineParams : IndicatorParams { + IndicatorBase *indi_ma; // Struct constructor. IndiColorLineParams(int _shift = 0) : IndicatorParams(INDI_COLOR_LINE, 2, TYPE_DOUBLE) { + indi_ma = NULL; SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\ColorLine"); shift = _shift; @@ -43,14 +45,15 @@ struct IndiColorLineParams : IndicatorParams { /** * Implements Color Bars */ -class Indi_ColorLine : public Indicator { +class Indi_ColorLine : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ColorLine(IndiColorLineParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_ColorLine(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_COLOR_LINE, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ColorLine(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_COLOR_LINE, _tf, _shift){}; /** * "Built-in" version of Color Line. @@ -86,6 +89,30 @@ class Indi_ColorLine : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Color Line. + */ + static double iColorLineOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_ColorLine_ON_" + _indi.GetFullName())); + + Indi_MA *_indi_ma = _obj.GetDataSource(INDI_MA); + + return iColorLineOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache, _indi_ma); + } + + /** + * Provides built-in indicators whose can be used as data source. + */ + virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + switch (_id) { + case INDI_MA: + return iparams.indi_ma; + } + return NULL; + } + /** * OnCalculate() method for Color Line indicator. */ @@ -172,7 +199,7 @@ class Indi_ColorLine : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -182,6 +209,9 @@ class Indi_ColorLine : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_ColorLine::iColorLineOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_CustomMovingAverage.mqh b/Indicators/Indi_CustomMovingAverage.mqh index 7d83ee7dc..e172c2b69 100644 --- a/Indicators/Indi_CustomMovingAverage.mqh +++ b/Indicators/Indi_CustomMovingAverage.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" // Structs. struct IndiCustomMovingAverageParams : IndicatorParams { @@ -32,7 +32,7 @@ struct IndiCustomMovingAverageParams : IndicatorParams { // Struct constructor. IndiCustomMovingAverageParams(int _smooth_period = 13, int _smooth_shift = 0, ENUM_MA_METHOD _smooth_method = MODE_SMMA, int _shift = 0) - : IndicatorParams(INDI_CUSTOM_MOVING_AVG, 3, TYPE_DOUBLE) { + : IndicatorParams(INDI_CUSTOM_MOVING_AVG, 1, TYPE_DOUBLE) { SetDataValueRange(IDATA_RANGE_MIXED); SetDataSourceType(IDATA_ICUSTOM); #ifdef __MQL5__ @@ -54,20 +54,20 @@ struct IndiCustomMovingAverageParams : IndicatorParams { /** * Implements the Custom Moving Average indicator. */ -class Indi_CustomMovingAverage : public Indicator { +class Indi_CustomMovingAverage : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_CustomMovingAverage(IndiCustomMovingAverageParams& _p, IndicatorBase* _indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_CustomMovingAverage(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_CUSTOM_MOVING_AVG, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_CUSTOM_MOVING_AVG, _tf, _shift){}; /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_DEMA.mqh b/Indicators/Indi_DEMA.mqh index 420034607..bf5a19ebd 100644 --- a/Indicators/Indi_DEMA.mqh +++ b/Indicators/Indi_DEMA.mqh @@ -27,7 +27,7 @@ // Includes. #include "../Dict.mqh" #include "../DictObject.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Refs.mqh" #include "../Storage/Objects.h" #include "../Storage/ValueStorage.h" @@ -63,13 +63,14 @@ struct IndiDEIndiMAParams : IndicatorParams { /** * Implements the Moving Average indicator. */ -class Indi_DEMA : public Indicator { +class Indi_DEMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_DEMA(IndiDEIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_DEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DEMA, _tf, _shift) {} + Indi_DEMA(IndiDEIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_DEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DEMA, _tf, _shift) {} /** * Updates the indicator value. @@ -108,44 +109,54 @@ class Indi_DEMA : public Indicator { #else Indi_Price *_indi_price = Indi_Price::GetCached(_symbol, _applied_price, _tf, _shift); // Note that _applied_price and Indi_Price mode indices are compatible. - return Indi_DEMA::iDEMAOnIndicator(_indi_price.GetCache(), _indi_price, 0, _period, _ma_shift, _shift); + return Indi_DEMA::iDEMAOnIndicatorSlow(_indi_price.GetCache(), _indi_price, 0, _period, _ma_shift, _shift); #endif } - static double iDEMAOnIndicator(IndicatorCalculateCache *cache, IndicatorBase *_indi, int indi_mode, - unsigned int ma_period, unsigned int ma_shift, int shift) { + static double iDEMAOnIndicatorSlow(IndicatorCalculateCache *cache, IndicatorBase *_indi, int indi_mode, + unsigned int ma_period, unsigned int ma_shift, int shift) { return iDEMAOnArray(_indi.GetValueStorage(indi_mode), 0, ma_period, ma_shift, shift, cache); } - static double iDEMAOnArray(ValueStorage &price, int total, unsigned int ma_period, unsigned int ma_shift, - int shift, IndicatorCalculateCache *cache = NULL, bool recalculate = false) { - if (cache == NULL) { + static double iDEMAOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, unsigned int _ma_period, unsigned int _ma_shift, + int _mode, int _shift, IndicatorCalculateCache *_cache = NULL, + bool _recalculate = false) { + if (_cache == NULL) { Print("iDEMAOnArray() cannot yet work without cache object!"); DebugBreak(); return 0.0f; } - cache.SetPriceBuffer(price); + _cache.SetPriceBuffer(_price); - if (!cache.HasBuffers()) { - cache.AddBuffer>(3); // 3 buffers. + if (!_cache.HasBuffers()) { + _cache.AddBuffer>(3); // 3 buffers. } - if (recalculate) { + if (_recalculate) { // We don't want to continue calculations, but to recalculate previous one. - cache.ResetPrevCalculated(); + _cache.ResetPrevCalculated(); } - cache.SetPrevCalculated(Indi_DEMA::Calculate(cache.GetTotal(), cache.GetPrevCalculated(), 0, cache.GetPriceBuffer(), - ma_period, cache.GetBuffer(0), cache.GetBuffer(1), - cache.GetBuffer(2))); + _cache.SetPrevCalculated(Indi_DEMA::Calculate(INDICATOR_CALCULATE_GET_PARAMS_SHORT, _cache.GetBuffer(0), + _cache.GetBuffer(1), _cache.GetBuffer(2), + _ma_period)); - return cache.GetTailValue(0, ma_shift + shift); + return _cache.GetTailValue(0, _ma_shift + _shift); } - static int Calculate(const int rates_total, const int prev_calculated, const int begin, ValueStorage &price, - int InpPeriodEMA, ValueStorage &DemaBuffer, ValueStorage &Ema, - ValueStorage &EmaOfEma) { + /** + * On-indicator version of DEMA. + */ + static double iDEMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, int _ma_shift, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, (int)_ap, Util::MakeKey("Indi_CHV_ON_" + _indi.GetFullName(), _period, _ma_shift)); + return iDEMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _ma_shift, _mode, _shift, _cache); + } + + static int Calculate(INDICATOR_CALCULATE_METHOD_PARAMS_SHORT, ValueStorage &DemaBuffer, + ValueStorage &Ema, ValueStorage &EmaOfEma, int InpPeriodEMA) { if (rates_total < 2 * InpPeriodEMA - 2) return (0); int start; @@ -166,7 +177,7 @@ class Indi_DEMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); @@ -175,8 +186,8 @@ class Indi_DEMA : public Indicator { // We're getting DEMA from Price indicator. istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetAppliedPrice(), _ishift, _mode, - GetPointer(this)); + _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetMAShift(), GetAppliedPrice() /*]*/, + _ishift, _mode, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; @@ -185,8 +196,8 @@ class Indi_DEMA : public Indicator { break; case IDATA_INDICATOR: // Calculating DEMA value from specified indicator. - _value = Indi_DEMA::iDEMAOnIndicator(GetCache(), GetDataSource(), GetDataSourceMode(), GetPeriod(), - GetMAShift(), _ishift); + _value = Indi_DEMA::iDEMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetMAShift(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); break; } return _value; diff --git a/Indicators/Indi_DeMarker.mqh b/Indicators/Indi_DeMarker.mqh index 98524dcdb..dbff0f090 100644 --- a/Indicators/Indi_DeMarker.mqh +++ b/Indicators/Indi_DeMarker.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -50,14 +50,14 @@ struct IndiDeMarkerParams : IndicatorParams { /** * Implements the DeMarker indicator. */ -class Indi_DeMarker : public Indicator { +class Indi_DeMarker : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_DeMarker(IndiDeMarkerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_DeMarker(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DEMARKER, _tf, _shift) {} + Indi_DeMarker(IndiDeMarkerParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_DeMarker(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DEMARKER, _tf, _shift) {} /** * Returns the indicator value. @@ -102,7 +102,7 @@ class Indi_DeMarker : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Demo.mqh b/Indicators/Indi_Demo.mqh index a5bf323d5..9fd756862 100644 --- a/Indicators/Indi_Demo.mqh +++ b/Indicators/Indi_Demo.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Price/Indi_Price.mqh" /** @@ -53,13 +53,14 @@ struct IndiDemoParams : IndicatorParams { /** * Demo/Dummy Indicator. */ -class Indi_Demo : public Indicator { +class Indi_Demo : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Demo(IndiDemoParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Demo(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DEMO, _tf, _shift){}; + Indi_Demo(IndiDemoParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Demo(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DEMO, _tf, _shift){}; /** * Returns the indicator value. @@ -72,7 +73,7 @@ class Indi_Demo : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = Indi_Demo::iDemo(GetSymbol(), GetTf(), _ishift, THIS_PTR); if (iparams.is_draw) { diff --git a/Indicators/Indi_DetrendedPrice.mqh b/Indicators/Indi_DetrendedPrice.mqh index b8c4fe1cd..3f78bdddd 100644 --- a/Indicators/Indi_DetrendedPrice.mqh +++ b/Indicators/Indi_DetrendedPrice.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" #include "Indi_MA.mqh" @@ -48,15 +48,15 @@ struct IndiDetrendedPriceParams : IndicatorParams { /** * Implements Detrended Price Oscillator. */ -class Indi_DetrendedPrice : public Indicator { +class Indi_DetrendedPrice : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_DetrendedPrice(IndiDetrendedPriceParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_DetrendedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_DETRENDED_PRICE, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_DETRENDED_PRICE, _tf, _shift){}; /** * Built-in version of AMA. @@ -65,14 +65,14 @@ class Indi_DetrendedPrice : public Indicator { int _shift = 0, IndicatorBase *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT(_symbol, _tf, _ap, Util::MakeKey("Indi_DPO", _period, (int)_ap)); - return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _mode, _shift, _cache); + return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _ap, _mode, _shift, _cache); } /** * Calculates DPO on the array of values. */ - static double iDPOOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, int _period, int _mode, int _shift, - IndicatorCalculateCache *_cache, bool _recalculate = false) { + static double iDPOOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, int _period, ENUM_APPLIED_PRICE _ap, int _mode, + int _shift, IndicatorCalculateCache *_cache, bool _recalculate = false) { _cache.SetPriceBuffer(_price); if (!_cache.HasBuffers()) { @@ -89,6 +89,16 @@ class Indi_DetrendedPrice : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of DPO. + */ + static double iDPOOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_DPO_ON_" + _indi.GetFullName(), _period, (int)_ap)); + return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _ap, _mode, _shift, _cache); + } + /** * OnCalculate() method for DPO indicator. */ @@ -116,7 +126,7 @@ class Indi_DetrendedPrice : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -128,6 +138,10 @@ class Indi_DetrendedPrice : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_DetrendedPrice::iDPOOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Drawer.mqh b/Indicators/Indi_Drawer.mqh index 2fc3c2593..8825e447e 100644 --- a/Indicators/Indi_Drawer.mqh +++ b/Indicators/Indi_Drawer.mqh @@ -26,7 +26,7 @@ struct IndicatorParams; // Includes. #include "../Action.mqh" #include "../DictStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Redis.mqh" #include "Indi_Drawer.struct.h" #include "Price/Indi_Price.mqh" @@ -34,7 +34,7 @@ struct IndicatorParams; /** * Implements the Relative Strength Index indicator. */ -class Indi_Drawer : public Indicator { +class Indi_Drawer : public IndicatorTickOrCandleSource { Redis redis; public: @@ -42,10 +42,11 @@ class Indi_Drawer : public Indicator { * Class constructor. */ Indi_Drawer(const IndiDrawerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src), redis(true) { + : IndicatorTickOrCandleSource(_p, _indi_src), redis(true) { Init(); } - Indi_Drawer(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DRAWER, _tf, _shift), redis(true) { + Indi_Drawer(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DRAWER, _tf, _shift), redis(true) { Init(); } @@ -172,7 +173,7 @@ class Indi_Drawer : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Envelopes.mqh b/Indicators/Indi_Envelopes.mqh index 4761ab8ce..c9ac3d055 100644 --- a/Indicators/Indi_Envelopes.mqh +++ b/Indicators/Indi_Envelopes.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/Singleton.h" #include "Indi_MA.mqh" #include "Indi_PriceFeeder.mqh" @@ -76,14 +76,15 @@ struct IndiEnvelopesParams : IndicatorParams { /** * Implements the Envelopes indicator. */ -class Indi_Envelopes : public Indicator { +class Indi_Envelopes : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_Envelopes(IndiEnvelopesParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Envelopes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ENVELOPES, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Envelopes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ENVELOPES, _tf, _shift) {} /** * Returns the indicator value. @@ -197,7 +198,7 @@ class Indi_Envelopes : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -225,7 +226,7 @@ class Indi_Envelopes : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // The LINE_MAIN only exists in MQL4 for Envelopes. diff --git a/Indicators/Indi_Force.mqh b/Indicators/Indi_Force.mqh index 9e047338b..3c6f6e408 100644 --- a/Indicators/Indi_Force.mqh +++ b/Indicators/Indi_Force.mqh @@ -32,7 +32,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -65,14 +65,15 @@ struct IndiForceParams : IndicatorParams { /** * Implements the Force Index indicator. */ -class Indi_Force : public Indicator { +class Indi_Force : public IndicatorTickOrCandleSource { protected: public: /** * Class constructor. */ - Indi_Force(IndiForceParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Force(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_FORCE, _tf, _shift) {} + Indi_Force(IndiForceParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Force(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_FORCE, _tf, _shift) {} /** * Returns the indicator value. @@ -117,7 +118,7 @@ class Indi_Force : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index 7640170c0..a0c69a60c 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -50,14 +50,14 @@ struct IndiFrAIndiMAParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_FrAMA : public Indicator { +class Indi_FrAMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_FrAMA(IndiFrAIndiMAParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_FrAMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_FRAMA, _tf, _shift){}; + Indi_FrAMA(IndiFrAIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_FrAMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_FRAMA, _tf, _shift){}; /** * Built-in version of FrAMA. @@ -69,15 +69,15 @@ class Indi_FrAMA : public Indicator { #else INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, Util::MakeKey("Indi_FrAMA", _ma_period, _ma_shift, (int)_ap)); - return iFrAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _ma_period, _ma_shift, _mode, _shift, _ap, _cache); + return iFrAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _ma_period, _ma_shift, _ap, _mode, _shift, _cache); #endif } /** * Calculates FrAMA on the array of values. */ - static double iFrAMAOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _ma_period, int _ma_shift, int _mode, int _shift, - ENUM_APPLIED_PRICE _ap, IndicatorCalculateCache *_cache, + static double iFrAMAOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _ma_period, int _ma_shift, ENUM_APPLIED_PRICE _ap, + int _mode, int _shift, IndicatorCalculateCache *_cache, bool _recalculate = false) { _cache.SetPriceBuffer(_open, _high, _low, _close); @@ -95,6 +95,17 @@ class Indi_FrAMA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of FrAMA. + */ + static double iFrAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_AMA_ON_" + _indi.GetFullName(), _ma_period, _ma_shift, (int)_ap)); + return iFrAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _ma_period, _ma_shift, _ap, _mode, _shift, _cache); + } + static int Calculate(INDICATOR_CALCULATE_METHOD_PARAMS_LONG, ValueStorage &FrAmaBuffer, int InpPeriodFrAMA, int InpShift, ENUM_APPLIED_PRICE InpAppliedPrice) { if (rates_total < 2 * InpPeriodFrAMA) return (0); @@ -134,7 +145,7 @@ class Indi_FrAMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -146,6 +157,10 @@ class Indi_FrAMA : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetFRAMAShift() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_FrAMA::iFrAMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetFRAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Fractals.mqh b/Indicators/Indi_Fractals.mqh index 49d395311..86d7a37fd 100644 --- a/Indicators/Indi_Fractals.mqh +++ b/Indicators/Indi_Fractals.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -48,14 +48,14 @@ struct IndiFractalsParams : IndicatorParams { /** * Implements the Fractals indicator. */ -class Indi_Fractals : public Indicator { +class Indi_Fractals : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Fractals(IndiFractalsParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Fractals(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_FRACTALS, _tf, _shift) {} + Indi_Fractals(IndiFractalsParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Fractals(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_FRACTALS, _tf, _shift) {} /** * Returns the indicator value. @@ -102,7 +102,7 @@ class Indi_Fractals : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -122,7 +122,7 @@ class Indi_Fractals : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // In MT4 line identifiers starts from 1, so populating also at 0. diff --git a/Indicators/Indi_Gator.mqh b/Indicators/Indi_Gator.mqh index 9dca4b882..ff8803c1b 100644 --- a/Indicators/Indi_Gator.mqh +++ b/Indicators/Indi_Gator.mqh @@ -28,7 +28,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -103,13 +103,14 @@ struct IndiGatorParams : IndicatorParams { /** * Implements the Gator oscillator. */ -class Indi_Gator : public Indicator { +class Indi_Gator : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Gator(IndiGatorParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Gator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_GATOR, _tf, _shift) {} + Indi_Gator(IndiGatorParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Gator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_GATOR, _tf, _shift) {} /** * Returns the indicator value. @@ -169,7 +170,7 @@ class Indi_Gator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -196,7 +197,7 @@ class Indi_Gator : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // @todo: Can we calculate upper and lower histogram color in MT4? diff --git a/Indicators/Indi_HeikenAshi.mqh b/Indicators/Indi_HeikenAshi.mqh index 789478852..5c2da1599 100644 --- a/Indicators/Indi_HeikenAshi.mqh +++ b/Indicators/Indi_HeikenAshi.mqh @@ -28,7 +28,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Enums. @@ -68,14 +68,15 @@ struct IndiHeikenAshiParams : IndicatorParams { /** * Implements the Heiken-Ashi indicator. */ -class Indi_HeikenAshi : public Indicator { +class Indi_HeikenAshi : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_HeikenAshi(IndiHeikenAshiParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_HeikenAshi(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_HEIKENASHI, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_HeikenAshi(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_HEIKENASHI, _tf, _shift) {} /** * Returns value for iHeikenAshi indicator. @@ -157,6 +158,16 @@ class Indi_HeikenAshi : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Heiken Ashi. + */ + static double iHeikenAshiOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_HeikenAshi_ON_" + _indi.GetFullName())); + return iHeikenAshiOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Mass Index indicator. */ @@ -195,7 +206,7 @@ class Indi_HeikenAshi : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = HA_OPEN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = HA_OPEN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -227,6 +238,10 @@ class Indi_HeikenAshi : public Indicator { _value = Indi_HeikenAshi::iCustomLegacyHeikenAshi(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift, THIS_PTR); break; + case IDATA_INDICATOR: + _value = + Indi_HeikenAshi::iHeikenAshiOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Ichimoku.mqh b/Indicators/Indi_Ichimoku.mqh index 0f381d8d5..a207e884d 100644 --- a/Indicators/Indi_Ichimoku.mqh +++ b/Indicators/Indi_Ichimoku.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -86,14 +86,14 @@ struct IndiIchimokuParams : IndicatorParams { /** * Implements the Ichimoku Kinko Hyo indicator. */ -class Indi_Ichimoku : public Indicator { +class Indi_Ichimoku : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Ichimoku(IndiIchimokuParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Ichimoku(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ICHIMOKU, _tf, _shift) {} + Indi_Ichimoku(IndiIchimokuParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Ichimoku(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ICHIMOKU, _tf, _shift) {} /** * Returns the indicator value. @@ -142,7 +142,7 @@ class Indi_Ichimoku : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -164,7 +164,7 @@ class Indi_Ichimoku : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // In MQL4 value of LINE_TENKANSEN is 1 (not 0 as in MQL5), diff --git a/Indicators/Indi_Killzones.mqh b/Indicators/Indi_Killzones.mqh index 70016b6db..5fc584d03 100644 --- a/Indicators/Indi_Killzones.mqh +++ b/Indicators/Indi_Killzones.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Market.struct.h" // Defines enumerations. @@ -91,7 +91,7 @@ struct Indi_Killzones_Time : MarketTimeForex { /** * Implements Pivot Detector. */ -class Indi_Killzones : public Indicator { +class Indi_Killzones : public IndicatorTickOrCandleSource { protected: Indi_Killzones_Time ikt; @@ -100,13 +100,14 @@ class Indi_Killzones : public Indicator { * Class constructor. */ Indi_Killzones(IndiKillzonesParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Killzones(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_KILLZONES, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Killzones(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_KILLZONES, _tf, _shift) {} /** * Returns the indicator's value. */ - IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { float _value = FLT_MAX; int _index = (int)_mode / 2; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); diff --git a/Indicators/Indi_MA.mqh b/Indicators/Indi_MA.mqh index d8ec96e68..0408622ef 100644 --- a/Indicators/Indi_MA.mqh +++ b/Indicators/Indi_MA.mqh @@ -27,7 +27,7 @@ // Includes. #include "../Dict.mqh" #include "../DictObject.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickSource.h" #include "../Refs.mqh" #include "../Storage/Singleton.h" #include "../Storage/ValueStorage.h" @@ -74,13 +74,13 @@ struct IndiMAParams : IndicatorParams { /** * Implements the Moving Average indicator. */ -class Indi_MA : public Indicator { +class Indi_MA : public IndicatorTickSource { public: /** * Class constructor. */ - Indi_MA(IndiMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_MA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MA, _tf, _shift) {} + Indi_MA(IndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_MA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_MA, _tf, _shift) {} /** * Returns the indicator value. @@ -261,23 +261,23 @@ class Indi_MA : public Indicator { * Calculates Simple Moving Average (SMA). The same as in "Example Moving Average" indicator. */ static void CalculateSimpleMA(int rates_total, int prev_calculated, int begin, ValueStorage &price, - ValueStorage &ExtLineBuffer, int InpMAPeriod) { + ValueStorage &ExtLineBuffer, int _ma_period) { int i, start; // First calculation or number of bars was changed. if (prev_calculated == 0) { - start = InpMAPeriod + begin; + start = _ma_period + begin; // Set empty value for first start bars. for (i = 0; i < start - 1; i++) ExtLineBuffer[i] = 0.0; // Calculate first visible value. double first_value = 0; for (i = begin; i < start; i++) first_value += price[i].Get(); - first_value /= InpMAPeriod; + first_value /= _ma_period; ExtLineBuffer[start - 1] = first_value; } else start = prev_calculated - 1; // Main loop. for (i = start; i < rates_total && !IsStopped(); i++) { - ExtLineBuffer[i] = ExtLineBuffer[i - 1] + (price[i] - price[i - InpMAPeriod]) / InpMAPeriod; + ExtLineBuffer[i] = ExtLineBuffer[i - 1] + (price[i] - price[i - _ma_period]) / _ma_period; } } @@ -285,12 +285,12 @@ class Indi_MA : public Indicator { * Calculates Exponential Moving Average (EMA). The same as in "Example Moving Average" indicator. */ static void CalculateEMA(int rates_total, int prev_calculated, int begin, ValueStorage &price, - ValueStorage &ExtLineBuffer, int InpMAPeriod) { + ValueStorage &ExtLineBuffer, int _ma_period) { int i, limit; - double SmoothFactor = 2.0 / (1.0 + InpMAPeriod); + double SmoothFactor = 2.0 / (1.0 + _ma_period); // First calculation or number of bars was changed. if (prev_calculated == 0) { - limit = InpMAPeriod + begin; + limit = _ma_period + begin; ExtLineBuffer[begin] = price[begin]; for (i = begin + 1; i < limit; i++) { ExtLineBuffer[i] = price[i] * SmoothFactor + ExtLineBuffer[i - 1] * (1.0 - SmoothFactor); @@ -307,14 +307,14 @@ class Indi_MA : public Indicator { * Calculates Linearly Weighted Moving Average (LWMA). The same as in "Example Moving Average" indicator. */ static void CalculateLWMA(int rates_total, int prev_calculated, int begin, ValueStorage &price, - ValueStorage &ExtLineBuffer, int InpMAPeriod) { + ValueStorage &ExtLineBuffer, int _ma_period) { int i, limit; static int weightsum; double sum; // First calculation or number of bars was changed. if (prev_calculated == 0) { weightsum = 0; - limit = InpMAPeriod + begin; + limit = _ma_period + begin; // Set empty value for first limit bars. for (i = 0; i < limit; i++) ExtLineBuffer[i] = 0.0; // Calculate first visible value. @@ -331,7 +331,7 @@ class Indi_MA : public Indicator { // Main loop. for (i = limit; i < rates_total && !IsStopped(); i++) { sum = 0; - for (int j = 0; j < InpMAPeriod; j++) sum += (InpMAPeriod - j) * price[i - j].Get(); + for (int j = 0; j < _ma_period; j++) sum += (_ma_period - j) * price[i - j].Get(); ExtLineBuffer[i] = sum / weightsum; } //--- @@ -341,23 +341,23 @@ class Indi_MA : public Indicator { * Calculates Smoothed Moving Average (SMMA). The same as in "Example Moving Average" indicator. */ static void CalculateSmoothedMA(int rates_total, int prev_calculated, int begin, ValueStorage &price, - ValueStorage &ExtLineBuffer, int InpMAPeriod) { + ValueStorage &ExtLineBuffer, int _ma_period) { int i, limit; // First calculation or number of bars was changed. if (prev_calculated == 0) { - limit = InpMAPeriod + begin; + limit = _ma_period + begin; // Set empty value for first limit bars. for (i = 0; i < limit - 1; i++) ExtLineBuffer[i] = 0.0; // Calculate first visible value. double firstValue = 0; for (i = begin; i < limit; i++) firstValue += price[i].Get(); - firstValue /= InpMAPeriod; + firstValue /= _ma_period; ExtLineBuffer[limit - 1] = firstValue; } else limit = prev_calculated - 1; // Main loop. for (i = limit; i < rates_total && !IsStopped(); i++) - ExtLineBuffer[i] = (ExtLineBuffer[i - 1] * (InpMAPeriod - 1) + price[i].Get()) / InpMAPeriod; + ExtLineBuffer[i] = (ExtLineBuffer[i - 1] * (_ma_period - 1) + price[i].Get()) / _ma_period; //--- } @@ -576,9 +576,9 @@ class Indi_MA : public Indicator { * Calculates Moving Average. The same as in "Example Moving Average" indicator. */ static int Calculate(const int rates_total, const int prev_calculated, const int begin, ValueStorage &price, - ValueStorage &ExtLineBuffer, int InpMAMethod, int InpMAPeriod) { + ValueStorage &ExtLineBuffer, int _ma_method, int _ma_period) { // Check for bars count. - if (rates_total < InpMAPeriod - 1 + begin) { + if (rates_total < _ma_period - 1 + begin) { // Not enough bars for calculation. return (0); } @@ -588,18 +588,18 @@ class Indi_MA : public Indicator { } // Calculation. - switch (InpMAMethod) { + switch (_ma_method) { case MODE_EMA: - CalculateEMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, InpMAPeriod); + CalculateEMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, _ma_period); break; case MODE_LWMA: - CalculateLWMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, InpMAPeriod); + CalculateLWMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, _ma_period); break; case MODE_SMMA: - CalculateSmoothedMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, InpMAPeriod); + CalculateSmoothedMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, _ma_period); break; case MODE_SMA: - CalculateSimpleMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, InpMAPeriod); + CalculateSimpleMA(rates_total, prev_calculated, begin, price, ExtLineBuffer, _ma_period); break; } // Return value of prev_calculated for next call. @@ -627,7 +627,7 @@ class Indi_MA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -665,6 +665,35 @@ class Indi_MA : public Indicator { return _ptr; } + /** + * Returns value storage of given kind. + */ + IValueStorage *GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + case INDI_VS_TYPE_PRICE_BID: + // We're returning the same buffer for ask and bid price, as target indicator probably won't bother. + return GetValueStorage(0); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. + */ + bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + case INDI_VS_TYPE_PRICE_BID: + return true; + default: + // Trying in parent class. + return Indicator::HasSpecificValueStorage(_type); + } + } + /* Getters */ /** diff --git a/Indicators/Indi_MACD.mqh b/Indicators/Indi_MACD.mqh index 64570f79b..2470e2ead 100644 --- a/Indicators/Indi_MACD.mqh +++ b/Indicators/Indi_MACD.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -59,13 +59,14 @@ struct IndiMACDParams : IndicatorParams { /** * Implements the Moving Averages Convergence/Divergence indicator. */ -class Indi_MACD : public Indicator { +class Indi_MACD : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_MACD(IndiMACDParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_MACD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MACD, _tf, _shift) {} + Indi_MACD(IndiMACDParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_MACD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_MACD, _tf, _shift) {} /** * Returns the indicator value. @@ -114,7 +115,7 @@ class Indi_MACD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_MFI.mqh b/Indicators/Indi_MFI.mqh index 902d6d08b..0427138c0 100644 --- a/Indicators/Indi_MFI.mqh +++ b/Indicators/Indi_MFI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,13 +51,13 @@ struct IndiMFIParams : IndicatorParams { /** * Implements the Money Flow Index indicator. */ -class Indi_MFI : public Indicator { +class Indi_MFI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_MFI(IndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_MFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MFI, _tf, _shift) {} + Indi_MFI(IndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_MFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_MFI, _tf, _shift) {} /** * Calculates the Money Flow Index indicator and returns its value. @@ -111,7 +111,7 @@ class Indi_MFI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_MassIndex.mqh b/Indicators/Indi_MassIndex.mqh index 817b81cd8..b541f236e 100644 --- a/Indicators/Indi_MassIndex.mqh +++ b/Indicators/Indi_MassIndex.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_MA.mqh" @@ -50,14 +50,15 @@ struct IndiMassIndexParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_MassIndex : public Indicator { +class Indi_MassIndex : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_MassIndex(IndiMassIndexParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_MassIndex(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MASS_INDEX, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_MassIndex(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_MASS_INDEX, _tf, _shift){}; /** * Built-in version of Mass Index. @@ -92,6 +93,19 @@ class Indi_MassIndex : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Mass Index. + */ + static double iMIOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _second_period, int _sum_period, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_MassIndex_ON_" + _indi.GetFullName(), _period, _second_period, _sum_period)); + return iMIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _second_period, _sum_period, _mode, _shift, + _cache); + } + /** * OnCalculate() method for Mass Index indicator. */ @@ -153,7 +167,7 @@ class Indi_MassIndex : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -165,6 +179,10 @@ class Indi_MassIndex : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_MassIndex::iMIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_Momentum.mqh b/Indicators/Indi_Momentum.mqh index 5f4266dd0..327588ed2 100644 --- a/Indicators/Indi_Momentum.mqh +++ b/Indicators/Indi_Momentum.mqh @@ -30,7 +30,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_PriceFeeder.mqh" #ifndef __MQL4__ @@ -61,14 +61,14 @@ struct IndiMomentumParams : IndicatorParams { /** * Implements the Momentum indicator. */ -class Indi_Momentum : public Indicator { +class Indi_Momentum : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Momentum(IndiMomentumParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Momentum(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MOMENTUM, _tf, _shift) {} + Indi_Momentum(IndiMomentumParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Momentum(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_MOMENTUM, _tf, _shift) {} /** * Returns the indicator value. @@ -141,7 +141,7 @@ class Indi_Momentum : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_OBV.mqh b/Indicators/Indi_OBV.mqh index cefa485e9..86c6eb44a 100644 --- a/Indicators/Indi_OBV.mqh +++ b/Indicators/Indi_OBV.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -62,13 +62,13 @@ struct IndiOBVParams : IndicatorParams { /** * Implements the On Balance Volume indicator. */ -class Indi_OBV : public Indicator { +class Indi_OBV : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_OBV(IndiOBVParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_OBV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_OBV, _tf, _shift) {} + Indi_OBV(IndiOBVParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_OBV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_OBV, _tf, _shift) {} /** * Returns the indicator value. @@ -118,7 +118,7 @@ class Indi_OBV : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_OsMA.mqh b/Indicators/Indi_OsMA.mqh index ac0a608a7..7a27cf939 100644 --- a/Indicators/Indi_OsMA.mqh +++ b/Indicators/Indi_OsMA.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -58,13 +58,14 @@ struct IndiOsMAParams : IndicatorParams { /** * Implements the Moving Average of Oscillator indicator. */ -class Indi_OsMA : public Indicator { +class Indi_OsMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_OsMA(IndiOsMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_OsMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_OSMA, _tf, _shift) {} + Indi_OsMA(IndiOsMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_OsMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_OSMA, _tf, _shift) {} /** * Returns the indicator value. @@ -111,7 +112,7 @@ class Indi_OsMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; switch (iparams.idstype) { diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index 50e776a7d..75a737974 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -44,13 +44,14 @@ struct IndiPivotParams : IndicatorParams { /** * Implements Pivot Detector. */ -class Indi_Pivot : public Indicator { +class Indi_Pivot : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Pivot(IndiPivotParams& _p, IndicatorBase* _indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Pivot(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PIVOT, _tf, _shift) { + Indi_Pivot(IndiPivotParams& _p, IndicatorBase* _indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Pivot(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PIVOT, _tf, _shift) { iparams.tf = _tf; }; @@ -62,7 +63,7 @@ class Indi_Pivot : public Indicator { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - virtual IndicatorDataEntry GetEntry(int _shift = -1) { + virtual IndicatorDataEntry GetEntry(int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); long _bar_time = GetBarTime(_ishift); IndicatorDataEntry _entry = idata.GetByKey(_bar_time); @@ -100,7 +101,7 @@ class Indi_Pivot : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); return GetEntry(_ishift)[_mode]; } diff --git a/Indicators/Indi_PriceChannel.mqh b/Indicators/Indi_PriceChannel.mqh index 0afc2392e..97fbe41d2 100644 --- a/Indicators/Indi_PriceChannel.mqh +++ b/Indicators/Indi_PriceChannel.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_ZigZag.mqh" // Structs. @@ -43,17 +43,17 @@ struct IndiPriceChannelParams : IndicatorParams { }; /** - * Implements the Bill Williams' Accelerator/Decelerator oscillator. + * Implements Price Channel indicator. */ -class Indi_PriceChannel : public Indicator { +class Indi_PriceChannel : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_PriceChannel(IndiPriceChannelParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_PriceChannel(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_PRICE_CHANNEL, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_PRICE_CHANNEL, _tf, _shift){}; /** * Returns value for Price Channel indicator. @@ -86,6 +86,16 @@ class Indi_PriceChannel : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Price Channel. + */ + static double iPriceChannelOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_PriceChannel_ON_" + _indi.GetFullName(), _period)); + return iPriceChannelOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _mode, _shift, _cache); + } + /** * OnCalculate() method for Price Channel indicator. */ @@ -106,7 +116,7 @@ class Indi_PriceChannel : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -117,6 +127,10 @@ class Indi_PriceChannel : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_PriceChannel::iPriceChannelOnIndicator(GetDataSource(), GetSymbol(), GetTf(), + /*[*/ GetPeriod() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_PriceFeeder.mqh b/Indicators/Indi_PriceFeeder.mqh index c1d286d88..9dfc075ea 100644 --- a/Indicators/Indi_PriceFeeder.mqh +++ b/Indicators/Indi_PriceFeeder.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" // Structs. struct IndiPriceFeederParams : IndicatorParams { @@ -53,17 +53,18 @@ struct IndiPriceFeederParams : IndicatorParams { /** * Price Indicator. */ -class Indi_PriceFeeder : public Indicator { +class Indi_PriceFeeder : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_PriceFeeder(IndiPriceFeederParams& _p, IndicatorBase* _indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_PriceFeeder(const double& _price_data[], int _total = 0) : Indicator(INDI_PRICE_FEEDER) { + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_PriceFeeder(const double& _price_data[], int _total = 0) : IndicatorTickOrCandleSource(INDI_PRICE_FEEDER) { ArrayCopy(iparams.price_data, _price_data); }; - Indi_PriceFeeder(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE_FEEDER, _tf, _shift) {} + Indi_PriceFeeder(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE_FEEDER, _tf, _shift) {} void SetPrices(const double& _price_data[], int _total = 0) { iparams = IndiPriceFeederParams(_price_data, _total); } @@ -75,7 +76,7 @@ class Indi_PriceFeeder : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int data_size = ArraySize(iparams.price_data); int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); diff --git a/Indicators/Indi_PriceVolumeTrend.mqh b/Indicators/Indi_PriceVolumeTrend.mqh index 17505eff1..9f4899142 100644 --- a/Indicators/Indi_PriceVolumeTrend.mqh +++ b/Indicators/Indi_PriceVolumeTrend.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -45,15 +45,15 @@ struct IndiPriceVolumeTrendParams : IndicatorParams { /** * Implements the Price Volume Trend indicator. */ -class Indi_PriceVolumeTrend : public Indicator { +class Indi_PriceVolumeTrend : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_PriceVolumeTrend(IndiPriceVolumeTrendParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_PriceVolumeTrend(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_PRICE_VOLUME_TREND, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_PRICE_VOLUME_TREND, _tf, _shift){}; /** * Built-in version of Price Volume Trend. @@ -85,6 +85,16 @@ class Indi_PriceVolumeTrend : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Price Volume Trend. + */ + static double iPVTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_PVT_ON_" + _indi.GetFullName(), (int)_av)); + return iPVTOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _av, _mode, _shift, _cache); + } + /** * OnCalculate() method for Price Volume Trend indicator. */ @@ -121,7 +131,7 @@ class Indi_PriceVolumeTrend : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -133,6 +143,10 @@ class Indi_PriceVolumeTrend : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetAppliedVolume() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_PriceVolumeTrend::iPVTOnIndicator(GetDataSource(), GetSymbol(), GetTf(), + /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_RS.mqh b/Indicators/Indi_RS.mqh index 51c03ed8d..ef81af539 100644 --- a/Indicators/Indi_RS.mqh +++ b/Indicators/Indi_RS.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "OHLC/Indi_OHLC.mqh" #include "Special/Indi_Math.mqh" @@ -46,15 +46,17 @@ struct IndiRSParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_RS : public Indicator { +class Indi_RS : public IndicatorTickOrCandleSource { DictStruct> imath; public: /** * Class constructor. */ - Indi_RS(IndiRSParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) { Init(); }; - Indi_RS(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_RS, _tf, _shift) { Init(); }; + Indi_RS(IndiRSParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) { Init(); }; + Indi_RS(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RS, _tf, _shift) { + Init(); + }; void Init() { if (iparams.GetDataSourceType() == IDATA_MATH) { @@ -78,7 +80,7 @@ class Indi_RS : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_MATH: diff --git a/Indicators/Indi_RSI.mqh b/Indicators/Indi_RSI.mqh index 41b7339a9..e8b725b7d 100644 --- a/Indicators/Indi_RSI.mqh +++ b/Indicators/Indi_RSI.mqh @@ -22,7 +22,7 @@ // Includes. #include "../DictStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_Bands.mqh" #include "Indi_CCI.mqh" #include "Indi_Envelopes.mqh" @@ -89,15 +89,15 @@ struct RSIGainLossData { /** * Implements the Relative Strength Index indicator. */ -class Indi_RSI : public Indicator { +class Indi_RSI : public IndicatorTickOrCandleSource { DictStruct aux_data; public: /** * Class constructor. */ - Indi_RSI(IndiRSIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_RSI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_RSI, _tf, _shift) {} + Indi_RSI(IndiRSIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_RSI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RSI, _tf, _shift) {} /** * Returns the indicator value. @@ -289,7 +289,7 @@ class Indi_RSI : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; double _res[]; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); diff --git a/Indicators/Indi_RVI.mqh b/Indicators/Indi_RVI.mqh index 18402acad..24c2ac436 100644 --- a/Indicators/Indi_RVI.mqh +++ b/Indicators/Indi_RVI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -50,13 +50,13 @@ struct IndiRVIParams : IndicatorParams { /** * Implements the Relative Vigor Index indicator. */ -class Indi_RVI : public Indicator { +class Indi_RVI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_RVI(const IndiRVIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_RVI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_RVI, _tf, _shift) {} + Indi_RVI(const IndiRVIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_RVI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RVI, _tf, _shift) {} /** * Returns the indicator value. @@ -103,7 +103,7 @@ class Indi_RVI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_RateOfChange.mqh b/Indicators/Indi_RateOfChange.mqh index 076f4798a..2f0d5b061 100644 --- a/Indicators/Indi_RateOfChange.mqh +++ b/Indicators/Indi_RateOfChange.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" // Structs. @@ -47,15 +47,15 @@ struct IndiRateOfChangeParams : IndicatorParams { /** * Implements the Rate of Change indicator. */ -class Indi_RateOfChange : public Indicator { +class Indi_RateOfChange : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_RateOfChange(IndiRateOfChangeParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_RateOfChange(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_RATE_OF_CHANGE, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_RATE_OF_CHANGE, _tf, _shift){}; /** * Built-in version of Rate of Change. @@ -88,6 +88,16 @@ class Indi_RateOfChange : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Rate of Change. + */ + static double iROCOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_RateOfChange_ON_" + _indi.GetFullName(), _period, (int)_ap)); + return iROCOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _mode, _shift, _cache); + } + /** * OnCalculate() method for Rate of Change indicator. */ @@ -110,7 +120,7 @@ class Indi_RateOfChange : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -122,6 +132,10 @@ class Indi_RateOfChange : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_RateOfChange::iROCOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_SAR.mqh b/Indicators/Indi_SAR.mqh index 2381c9cf3..6f17f2b73 100644 --- a/Indicators/Indi_SAR.mqh +++ b/Indicators/Indi_SAR.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,13 +51,13 @@ struct IndiSARParams : IndicatorParams { /** * Implements the Parabolic Stop and Reverse system indicator. */ -class Indi_SAR : public Indicator { +class Indi_SAR : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_SAR(IndiSARParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_SAR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_SAR, _tf, _shift) {} + Indi_SAR(IndiSARParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_SAR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_SAR, _tf, _shift) {} /** * Returns the indicator value. @@ -102,7 +102,7 @@ class Indi_SAR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_StdDev.mqh b/Indicators/Indi_StdDev.mqh index 4ef932b03..7a6305b77 100644 --- a/Indicators/Indi_StdDev.mqh +++ b/Indicators/Indi_StdDev.mqh @@ -28,7 +28,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickSource.h" #include "../Storage/ObjectsCache.h" #include "Indi_MA.mqh" #include "Indi_PriceFeeder.mqh" @@ -73,13 +73,13 @@ struct IndiStdDevParams : IndicatorParams { /** * Implements the Standard Deviation indicator. */ -class Indi_StdDev : public Indicator { +class Indi_StdDev : public IndicatorTickSource { public: /** * Class constructor. */ - Indi_StdDev(IndiStdDevParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_StdDev(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_STDDEV, _tf, _shift) {} + Indi_StdDev(IndiStdDevParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_StdDev(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_STDDEV, _tf, _shift) {} /** * Calculates the Standard Deviation indicator and returns its value. @@ -226,7 +226,7 @@ class Indi_StdDev : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Stochastic.mqh b/Indicators/Indi_Stochastic.mqh index d60246205..453208b27 100644 --- a/Indicators/Indi_Stochastic.mqh +++ b/Indicators/Indi_Stochastic.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -62,13 +62,14 @@ struct IndiStochParams : IndicatorParams { /** * Implements the Stochastic Oscillator. */ -class Indi_Stochastic : public Indicator { +class Indi_Stochastic : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Stochastic(IndiStochParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Stochastic(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_STOCHASTIC, _tf, _shift) {} + Indi_Stochastic(IndiStochParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Stochastic(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_STOCHASTIC, _tf, _shift) {} /** * Calculates the Stochastic Oscillator and returns its value. @@ -119,7 +120,7 @@ class Indi_Stochastic : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_TEMA.mqh b/Indicators/Indi_TEMA.mqh index 3cc9e949b..5954a9804 100644 --- a/Indicators/Indi_TEMA.mqh +++ b/Indicators/Indi_TEMA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" #include "Indi_MA.mqh" @@ -50,13 +50,14 @@ struct IndiTEMAParams : IndicatorParams { /** * Implements the Triple Exponential Moving Average indicator. */ -class Indi_TEMA : public Indicator { +class Indi_TEMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_TEMA(IndiTEMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_TEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_TEMA, _tf, _shift){}; + Indi_TEMA(IndiTEMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_TEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_TEMA, _tf, _shift){}; /** * Built-in version of TEMA. @@ -94,6 +95,18 @@ class Indi_TEMA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of TEMA. + */ + static double iTEMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, + Util::MakeKey("Indi_TEMA_ON_" + _indi.GetFullName(), _ma_period, _ma_shift, (int)_ap)); + return iTEMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ma_period, _ma_shift, _mode, _shift, _cache); + } + /** * OnCalculate() method for TEMA indicator. * @@ -126,7 +139,7 @@ class Indi_TEMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -138,6 +151,10 @@ class Indi_TEMA : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetTEMAShift() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_TEMA::iTEMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetTEMAShift(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_TRIX.mqh b/Indicators/Indi_TRIX.mqh index a8086bd27..86caabb0d 100644 --- a/Indicators/Indi_TRIX.mqh +++ b/Indicators/Indi_TRIX.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" #include "Indi_MA.mqh" @@ -49,13 +49,14 @@ struct IndiTRIXParams : IndicatorParams { /** * Implements the Triple Exponential Average indicator. */ -class Indi_TRIX : public Indicator { +class Indi_TRIX : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_TRIX(IndiTRIXParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_TRIX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_TRIX, _tf, _shift){}; + Indi_TRIX(IndiTRIXParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_TRIX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_TRIX, _tf, _shift){}; /** * Built-in version of TriX. @@ -93,6 +94,16 @@ class Indi_TRIX : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of TriX. + */ + static double iTriXOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_TriX_ON_" + _indi.GetFullName(), _ma_period, (int)_ap)); + return iTriXOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ma_period, _mode, _shift, _cache); + } + /** * OnCalculate() method for TriX indicator. */ @@ -127,7 +138,7 @@ class Indi_TRIX : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -139,6 +150,10 @@ class Indi_TRIX : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_TRIX::iTriXOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_UltimateOscillator.mqh b/Indicators/Indi_UltimateOscillator.mqh index 7788bd77b..98a7f9e1f 100644 --- a/Indicators/Indi_UltimateOscillator.mqh +++ b/Indicators/Indi_UltimateOscillator.mqh @@ -22,13 +22,16 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_ATR.mqh" #include "Indi_MA.mqh" // Structs. struct IndiUltimateOscillatorParams : IndicatorParams { + Ref indi_atr_fast; + Ref indi_atr_middle; + Ref indi_atr_slow; int fast_period; int middle_period; int slow_period; @@ -59,15 +62,15 @@ struct IndiUltimateOscillatorParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_UltimateOscillator : public Indicator { +class Indi_UltimateOscillator : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_UltimateOscillator(IndiUltimateOscillatorParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_UltimateOscillator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_ULTIMATE_OSCILLATOR, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_ULTIMATE_OSCILLATOR, _tf, _shift){}; /** * Built-in version of Ultimate Oscillator. @@ -113,6 +116,41 @@ class Indi_UltimateOscillator : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Ultimate Oscillator. + */ + static double iUOOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _fast_period, + int _middle_period, int _slow_period, int _fast_k, int _middle_k, int _slow_k, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_UltimateOscillator_ON_" + _indi.GetFullName(), _fast_period, _middle_period, _slow_period, + _fast_k, _middle_k, _slow_k)); + + // @fixit This won't work! Find a way to differentiate ATRs. + Indi_ATR *_indi_atr_fast = (Indi_ATR *)_indi.GetDataSource(INDI_ULTIMATE_OSCILLATOR_ATR_FAST); + Indi_ATR *_indi_atr_middle = (Indi_ATR *)_indi.GetDataSource(INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE); + Indi_ATR *_indi_atr_slow = (Indi_ATR *)_indi.GetDataSource(INDI_ULTIMATE_OSCILLATOR_ATR_SLOW); + + return iUOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_period, _middle_period, _slow_period, _fast_k, + _middle_k, _slow_k, _mode, _shift, _cache, _indi_atr_fast, _indi_atr_middle, _indi_atr_slow); + } + + /** + * Provides built-in indicators whose can be used as data source. + */ + IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + switch (_id) { + case INDI_ULTIMATE_OSCILLATOR_ATR_FAST: + return iparams.indi_atr_fast.Ptr(); + case INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE: + return iparams.indi_atr_middle.Ptr(); + case INDI_ULTIMATE_OSCILLATOR_ATR_SLOW: + return iparams.indi_atr_slow.Ptr(); + } + return NULL; + } + /** * OnCalculate() method for Ultimate Oscillator. */ @@ -209,7 +247,7 @@ class Indi_UltimateOscillator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -225,6 +263,11 @@ class Indi_UltimateOscillator : public Indicator { /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_UltimateOscillator::iUOOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetFastPeriod(), + GetMiddlePeriod(), GetSlowPeriod(), GetFastK(), GetMiddleK(), + GetSlowK() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_VIDYA.mqh b/Indicators/Indi_VIDYA.mqh index a5647974c..4e98a6254 100644 --- a/Indicators/Indi_VIDYA.mqh +++ b/Indicators/Indi_VIDYA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" // Structs. @@ -53,13 +53,14 @@ struct IndiVIDYAParams : IndicatorParams { /** * Implements the Variable Index Dynamic Average indicator. */ -class Indi_VIDYA : public Indicator { +class Indi_VIDYA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_VIDYA(IndiVIDYAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_VIDYA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VIDYA, _tf, _shift){}; + Indi_VIDYA(IndiVIDYAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_VIDYA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VIDYA, _tf, _shift){}; /** * Built-in version of iVIDyA. @@ -98,6 +99,19 @@ class Indi_VIDYA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of VIDya indicator. + */ + static double iVIDyAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _cmo_period, + int _ema_period, int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, + Util::MakeKey("Indi_VIDYA_ON_" + _indi.GetFullName(), _cmo_period, _ema_period, _ma_shift, (int)_ap)); + return iVIDyAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _cmo_period, _ema_period, _ma_shift, _mode, _shift, + _cache); + } + /** * OnCalculate() method for VIDyA indicator. * @@ -147,7 +161,7 @@ class Indi_VIDYA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -162,6 +176,11 @@ class Indi_VIDYA : public Indicator { /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = + Indi_VIDYA::iVIDyAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetCMOPeriod(), GetMAPeriod(), + GetVIDYAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_VROC.mqh b/Indicators/Indi_VROC.mqh index 2170fa831..cacf2861c 100644 --- a/Indicators/Indi_VROC.mqh +++ b/Indicators/Indi_VROC.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -47,13 +47,14 @@ struct IndiVROCParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_VROC : public Indicator { +class Indi_VROC : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_VROC(IndiVROCParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_VROC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VROC, _tf, _shift){}; + Indi_VROC(IndiVROCParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_VROC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VROC, _tf, _shift){}; /** * Built-in version of VROC. @@ -65,7 +66,7 @@ class Indi_VROC : public Indicator { } /** - * Calculates AMVROC on the array of values. + * Calculates VROC on the array of values. */ static double iVROCOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _period, ENUM_APPLIED_VOLUME _av, int _mode, int _shift, IndicatorCalculateCache *_cache, bool _recalculate = false) { @@ -85,6 +86,16 @@ class Indi_VROC : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of VROC indicator. + */ + static double iVROCOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_VOLUME _av, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_VROC_ON_" + _indi.GetFullName(), _period, (int)_av)); + return iVROCOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _av, _mode, _shift, _cache); + } + /** * OnCalculate() method for VROC indicator. */ @@ -130,7 +141,7 @@ class Indi_VROC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -142,6 +153,10 @@ class Indi_VROC : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_VROC::iVROCOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Volumes.mqh b/Indicators/Indi_Volumes.mqh index 786f9fbbe..c46671424 100644 --- a/Indicators/Indi_Volumes.mqh +++ b/Indicators/Indi_Volumes.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -44,15 +44,16 @@ struct IndiVolumesParams : IndicatorParams { }; /** - * Implements the Bill Williams' Accelerator/Decelerator oscillator. + * Implements the Volumes indicator. */ -class Indi_Volumes : public Indicator { +class Indi_Volumes : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Volumes(IndiVolumesParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Volumes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VOLUMES, _tf, _shift){}; + Indi_Volumes(IndiVolumesParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Volumes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VOLUMES, _tf, _shift){}; /** * Built-in version of Volumes. @@ -84,6 +85,16 @@ class Indi_Volumes : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Volumes indicator. + */ + static double iVolumesOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_Volumes_ON_" + _indi.GetFullName(), (int)_av)); + return iVolumesOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _av, _mode, _shift, _cache); + } + /** * OnCalculate() method for Volumes indicator. */ @@ -124,7 +135,7 @@ class Indi_Volumes : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -135,6 +146,10 @@ class Indi_Volumes : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_Volumes::iVolumesOnIndicator(GetDataSource(), GetSymbol(), GetTf(), + /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_WPR.mqh b/Indicators/Indi_WPR.mqh index 8dcc258aa..98c59474c 100644 --- a/Indicators/Indi_WPR.mqh +++ b/Indicators/Indi_WPR.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -50,13 +50,13 @@ struct IndiWPRParams : IndicatorParams { /** * Implements the Larry Williams' Percent Range. */ -class Indi_WPR : public Indicator { +class Indi_WPR : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_WPR(IndiWPRParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_WPR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_WPR, _tf, _shift) {} + Indi_WPR(IndiWPRParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_WPR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_WPR, _tf, _shift) {} /** * Calculates the Larry Williams' Percent Range and returns its value. @@ -101,7 +101,7 @@ class Indi_WPR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_WilliamsAD.mqh b/Indicators/Indi_WilliamsAD.mqh index 754cff808..7e2bf94e4 100644 --- a/Indicators/Indi_WilliamsAD.mqh +++ b/Indicators/Indi_WilliamsAD.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -42,14 +42,15 @@ struct IndiWilliamsADParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_WilliamsAD : public Indicator { +class Indi_WilliamsAD : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_WilliamsAD(IndiWilliamsADParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_WilliamsAD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_WILLIAMS_AD, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_WilliamsAD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_WILLIAMS_AD, _tf, _shift){}; /** * Built-in version of Williams' AD. @@ -80,6 +81,16 @@ class Indi_WilliamsAD : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Williams' AD. + */ + static double iWADOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_WilliamsAD_ON_" + _indi.GetFullName())); + return iWADOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Williams' AD indicator. */ @@ -124,7 +135,7 @@ class Indi_WilliamsAD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -134,6 +145,9 @@ class Indi_WilliamsAD : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_WilliamsAD::iWADOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ZigZag.mqh b/Indicators/Indi_ZigZag.mqh index 94fa26e33..4803a45e6 100644 --- a/Indicators/Indi_ZigZag.mqh +++ b/Indicators/Indi_ZigZag.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Enums. @@ -58,13 +58,14 @@ enum EnSearchMode { /** * Implements ZigZag indicator. */ -class Indi_ZigZag : public Indicator { +class Indi_ZigZag : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ZigZag(IndiZigZagParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_ZigZag(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ZIGZAG, _tf, _shift) {} + Indi_ZigZag(IndiZigZagParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ZigZag(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ZIGZAG, _tf, _shift) {} /** * Returns value for ZigZag indicator. @@ -135,6 +136,18 @@ class Indi_ZigZag : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ZigZag indicator. + */ + static double iZigZagOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _depth, + int _deviation, int _backstep, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_ZigZag_ON_" + _indi.GetFullName(), _depth, _deviation, _backstep)); + return iZigZagOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _depth, _deviation, _backstep, _mode, _shift, + _cache); + } + /** * OnCalculate() method for ZigZag indicator. */ @@ -334,18 +347,23 @@ class Indi_ZigZag : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ZigZag::iZigZag(GetSymbol(), GetTf(), GetDepth(), GetDeviation(), GetBackstep(), + _value = Indi_ZigZag::iZigZag(GetSymbol(), GetTf(), /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_ZigZag::iCustomZigZag(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), GetDepth(), - GetDeviation(), GetBackstep(), (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); + _value = + Indi_ZigZag::iCustomZigZag(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetDepth(), + GetDeviation(), GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); + break; + case IDATA_INDICATOR: + _value = Indi_ZigZag::iZigZagOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetDepth(), + GetDeviation(), GetBackstep() /*]*/, _mode, _ishift, THIS_PTR); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ZigZagColor.mqh b/Indicators/Indi_ZigZagColor.mqh index 26489fd8f..6e8cf6d9a 100644 --- a/Indicators/Indi_ZigZagColor.mqh +++ b/Indicators/Indi_ZigZagColor.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_ZigZag.mqh" @@ -52,14 +52,15 @@ struct IndiZigZagColorParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_ZigZagColor : public Indicator { +class Indi_ZigZagColor : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ZigZagColor(IndiZigZagColorParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_ZigZagColor(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VROC, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ZigZagColor(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VROC, _tf, _shift){}; /** * Returns value for ZigZag Color indicator. @@ -96,6 +97,19 @@ class Indi_ZigZagColor : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ZigZag indicator. + */ + static double iZigZagColorOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _depth, + int _deviation, int _backstep, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_ZigZagColor_ON_" + _indi.GetFullName(), _depth, _deviation, _backstep)); + return iZigZagColorOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _depth, _deviation, _backstep, _mode, _shift, + _cache); + } + /** * OnCalculate() method for ZigZag Color indicator. */ @@ -268,18 +282,23 @@ class Indi_ZigZagColor : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ZigZagColor::iZigZagColor(GetSymbol(), GetTf(), GetDepth(), GetDeviation(), GetBackstep(), - (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); + _value = Indi_ZigZagColor::iZigZagColor(GetSymbol(), GetTf(), /*[*/ GetDepth(), GetDeviation(), + GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = + Indi_ZigZagColor::iZigZagColorOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetDepth(), + GetDeviation(), GetBackstep() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/OHLC/Indi_OHLC.mqh b/Indicators/OHLC/Indi_OHLC.mqh index 7d7d26d93..c7f9cc25c 100644 --- a/Indicators/OHLC/Indi_OHLC.mqh +++ b/Indicators/OHLC/Indi_OHLC.mqh @@ -22,7 +22,7 @@ // Includes. #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Storage/Objects.h" // Enums. @@ -49,18 +49,19 @@ struct IndiOHLCParams : IndicatorParams { /** * OHLC Indicator. */ -class Indi_OHLC : public Indicator { +class Indi_OHLC : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_OHLC(IndiOHLCParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_OHLC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE, _tf, _shift){}; + Indi_OHLC(IndiOHLCParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_OHLC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift){}; /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); ENUM_APPLIED_PRICE _ap = PRICE_OPEN; switch (_mode) { diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index 74cd43db8..b0cbcc6d3 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -22,7 +22,7 @@ // Includes. #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Storage/Objects.h" // Structs. @@ -46,13 +46,14 @@ struct PriceIndiParams : IndicatorParams { /** * Price Indicator. */ -class Indi_Price : public Indicator { +class Indi_Price : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Price(PriceIndiParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Price(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE, _tf, _shift){}; + Indi_Price(PriceIndiParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Price(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift){}; /** * Checks whether indicator has a valid value for a given shift. @@ -62,7 +63,7 @@ class Indi_Price : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); return ChartStatic::iPrice(iparams.GetAppliedPrice(), GetSymbol(), GetTf(), _ishift); } @@ -86,4 +87,54 @@ class Indi_Price : public Indicator { } return _indi_price; } + + /** + * Returns value storage of given kind. + */ + IValueStorage *GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + // Returning Price indicator which provides applied price in the only buffer #0. + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: // Tick. + case INDI_VS_TYPE_PRICE_BID: // Tick. + return GetCached(GetSymbol(), iparams.GetAppliedPrice(), GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_OPEN: // Candle. + return GetCached(GetSymbol(), PRICE_OPEN, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_HIGH: // Candle. + return GetCached(GetSymbol(), PRICE_HIGH, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_LOW: // Candle. + return GetCached(GetSymbol(), PRICE_LOW, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_CLOSE: // Candle. + return GetCached(GetSymbol(), PRICE_CLOSE, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_MEDIAN: // Candle. + return GetCached(GetSymbol(), PRICE_MEDIAN, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_TYPICAL: // Candle. + return GetCached(GetSymbol(), PRICE_TYPICAL, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_WEIGHTED: // Candle. + return GetCached(GetSymbol(), PRICE_WEIGHTED, GetTf(), iparams.GetShift()).GetValueStorage(0); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. + */ + bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: // Tick. + case INDI_VS_TYPE_PRICE_BID: // Tick. + case INDI_VS_TYPE_PRICE_OPEN: // Candle. + case INDI_VS_TYPE_PRICE_HIGH: // Candle. + case INDI_VS_TYPE_PRICE_LOW: // Candle. + case INDI_VS_TYPE_PRICE_CLOSE: // Candle. + case INDI_VS_TYPE_PRICE_MEDIAN: // Candle. + case INDI_VS_TYPE_PRICE_TYPICAL: // Candle. + case INDI_VS_TYPE_PRICE_WEIGHTED: // Candle. + return true; + default: + // Trying in parent class. + return Indicator::HasSpecificValueStorage(_type); + } + } }; diff --git a/Indicators/Special/Indi_Custom.mqh b/Indicators/Special/Indi_Custom.mqh new file mode 100644 index 000000000..d35236289 --- /dev/null +++ b/Indicators/Special/Indi_Custom.mqh @@ -0,0 +1,118 @@ +//+------------------------------------------------------------------+ +//| Copyright 2016-2022, 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 . + * + */ + +// Prevents processing the same indicator file twice. +#ifndef INDI_CUSTOM_MQH +#define INDI_CUSTOM_MQH + +// Defines +#ifndef INDI_CUSTOM_PATH +#ifdef __MQL4__ +#define INDI_CUSTOM_PATH "RSI" +#else +#define INDI_CUSTOM_PATH "Examples\\RSI" +#endif +#endif + +// Includes. +#include "../../Indicator.mqh" + +// Structs. + +// Defines struct to store indicator parameter values. +struct IndiCustomParams : public IndicatorParams { + DataParamEntry iargs[]; + // Struct constructors. + IndiCustomParams(string _filepath = INDI_CUSTOM_PATH, int _shift = 0) : IndicatorParams(INDI_CUSTOM, 1, TYPE_DOUBLE) { + custom_indi_name = _filepath; + SetDataSourceType(IDATA_ICUSTOM); + } + IndiCustomParams(IndiCustomParams &_params, ENUM_TIMEFRAMES _tf) { + THIS_REF = _params; + tf = _tf; + } + // Getters. + DataParamEntry GetParam(int _index) const { return iargs[_index - 1]; } + int GetParamsSize() const { return ArraySize(iargs); } + // Setters. + void AddParam(DataParamEntry &_entry) { + int _size = GetParamsSize(); + ArrayResize(iargs, _size + 1); + iargs[_size] = _entry; + } + void SetParam(DataParamEntry &_entry, int _index) { + if (_index >= GetParamsSize()) { + ArrayResize(iargs, _index + 1); + } + iargs[_index + 1] = _entry; + } + void SetParams(DataParamEntry &_entries[]) { + for (int i = 0; i < ArraySize(_entries); i++) { + iargs[i] = _entries[i]; + } + } +}; + +/** + * Implements indicator class. + */ +class Indi_Custom : public Indicator { + public: + /** + * Class constructor. + */ + Indi_Custom(IndiCustomParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} + Indi_Custom(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(INDI_CUSTOM, _tf){}; + + /** + * Returns the indicator's value. + */ + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + switch (iparams.idstype) { + case IDATA_ICUSTOM: + switch (iparams.GetParamsSize()) { + case 0: + _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), + iparams.custom_indi_name, _mode, _ishift); + break; + case 1: + _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), + iparams.custom_indi_name, iparams.GetParam(1).ToValue(), _mode, _ishift); + break; + case 2: + _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), + iparams.custom_indi_name, iparams.GetParam(1).ToValue(), + iparams.GetParam(2).ToValue(), _mode, _ishift); + break; + } + break; + default: + SetUserError(ERR_INVALID_PARAMETER); + _value = EMPTY_VALUE; + break; + } + return _value; + } +}; + +#endif // INDI_CUSTOM_MQH diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index 5b13f1227..098b4fc3f 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -22,7 +22,7 @@ // Includes. #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Math.enum.h" enum ENUM_MATH_OP_MODE { MATH_OP_MODE_BUILTIN, MATH_OP_MODE_CUSTOM_FUNCTION }; @@ -82,18 +82,19 @@ struct IndiMathParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_Math : public Indicator { +class Indi_Math : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Math(IndiMathParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Math(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_SPECIAL_MATH, _tf, _shift){}; + Indi_Math(IndiMathParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Math(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_SPECIAL_MATH, _tf, _shift){}; /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Special/indicators.h b/Indicators/Special/indicators.h index bf31bc5e3..a99faecca 100644 --- a/Indicators/Special/indicators.h +++ b/Indicators/Special/indicators.h @@ -26,4 +26,5 @@ */ // Special indicators. +#include "Indi_Custom.mqh" #include "Indi_Math.mqh" diff --git a/Indicators/Special/tests/Indi_Custom.test.mq4 b/Indicators/Special/tests/Indi_Custom.test.mq4 new file mode 100644 index 000000000..bb3fffd61 --- /dev/null +++ b/Indicators/Special/tests/Indi_Custom.test.mq4 @@ -0,0 +1,27 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 + * Test functionality of Indi_Custom indicator class. + */ + +#include "Indi_Custom.test.mq5" diff --git a/Indicators/Special/tests/Indi_Custom.test.mq5 b/Indicators/Special/tests/Indi_Custom.test.mq5 new file mode 100644 index 000000000..9806b1ef0 --- /dev/null +++ b/Indicators/Special/tests/Indi_Custom.test.mq5 @@ -0,0 +1,65 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 . + */ + +// Includes. +#include "../../../Test.mqh" +#include "../Indi_Custom.mqh" + +/** + * @file + * Test functionality of Indi_Custom indicator class. + */ + +Indi_Custom indi(PERIOD_CURRENT); + +/** + * Implements Init event handler. + */ +int OnInit() { + bool _result = true; + assertTrueOrFail(indi.IsValid(), "Error on IsValid!"); + // assertTrueOrFail(indi.IsValidEntry(), "Error on IsValidEntry!"); + // Overrides indicator params. + DataParamEntry _iparam_rsi_period = 12; + IndiCustomParams _iparams(INDI_CUSTOM_PATH); + _iparams.AddParam(_iparam_rsi_period); + indi.SetParams(_iparams); + return (_result && _LastError == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED); +} + +/** + * Implements Tick event handler. + */ +void OnTick() { + static MqlTick _tick_last; + MqlTick _tick_new = SymbolInfoStatic::GetTick(_Symbol); + if (_tick_new.time % 60 < _tick_last.time % 60) { + // Process ticks each minute. + if (_tick_new.time % 3600 < _tick_last.time % 3600) { + // Print indicator values every hour. + Print(indi.ToString()); + if (indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { + assertTrueOrExit(indi.GetEntry().IsValid(), "Invalid entry!"); + } + } + } + _tick_last = _tick_new; +} diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index db392ce69..9f03835b9 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -54,7 +54,8 @@ class Indi_TickMt : public IndicatorTick { */ Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTick(_p, _indi_src){}; - Indi_TickMt(string _symbol, int _shift = 0) : IndicatorTick(INDI_TICK, _symbol, _shift){}; + Indi_TickMt(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} /** * Returns the indicator's value. @@ -86,7 +87,7 @@ class Indi_TickMt : public IndicatorTick { * This method allows user to modify the struct entry before it's added to cache. * This method is called on GetEntry() right after values are set. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { IndicatorTick::GetEntryAlter(_entry, _shift); _entry.timestamp = _entry.timestamp > 0 ? _entry.timestamp : tick.time; }; diff --git a/Indicators/Tick/tests/Indi_TickMt.test.mq5 b/Indicators/Tick/tests/Indi_TickMt.test.mq5 index 428552d78..e77d1ee23 100644 --- a/Indicators/Tick/tests/Indi_TickMt.test.mq5 +++ b/Indicators/Tick/tests/Indi_TickMt.test.mq5 @@ -28,7 +28,7 @@ * Test functionality of Indi_TickMt indicator class. */ -Indi_TickMt indi(_Symbol); +Indi_TickMt indi(PERIOD_CURRENT); /** * Implements Init event handler. diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index 6fa64909a..3b019ba0e 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -91,6 +91,30 @@ enum ENUM_IPEAK { IPEAK_LOWEST, IPEAK_HIGHEST }; ValueStorage *_price = INDI.GetValueStorage(APPLIED_PRICE); \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) +#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC(INDI, SYMBOL, TF, APPLIED_PRICE, KEY) \ + ValueStorage *_price; \ + if (_indi.HasSpecificAppliedPriceValueStorage(APPLIED_PRICE)) { \ + _price = INDI.GetSpecificAppliedPriceValueStorage(APPLIED_PRICE); \ + } else { \ + Print("Source indicator ", INDI.GetFullName(), \ + " cannot be used as it doesn't provide a single buffer to be used by target indicator! You may try to set " \ + "applied price/data source mode and try again."); \ + DebugBreak(); \ + } \ + \ + INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) + +#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(INDI, SYMBOL, TF, KEY) \ + ValueStorage *_time = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_TIME); \ + ValueStorage *_tick_volume = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_TICK_VOLUME); \ + ValueStorage *_volume = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_VOLUME); \ + ValueStorage *_spread = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_SPREAD); \ + ValueStorage *_price_open = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); \ + ValueStorage *_price_high = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); \ + ValueStorage *_price_low = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); \ + ValueStorage *_price_close = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); \ + INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) + #define INDICATOR_CALCULATE_POPULATED_PARAMS_LONG \ _time, _price_open, _price_high, _price_low, _price_close, _tick_volume, _volume, _spread diff --git a/Strategy.mqh b/Strategy.mqh index a062b368d..01b01c475 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -682,7 +682,7 @@ class Strategy : public Object { * Returns true when the condition is met. */ bool CheckCondition(ENUM_STRATEGY_CONDITION _cond, DataParamEntry &_args[]) { - bool _result = true; + bool _result = false; long arg_size = ArraySize(_args); long _arg1l = ArraySize(_args) > 0 ? DataParamEntry::ToInteger(_args[0]) : WRONG_VALUE; long _arg2l = ArraySize(_args) > 1 ? DataParamEntry::ToInteger(_args[1]) : WRONG_VALUE; @@ -716,8 +716,9 @@ class Strategy : public Object { return _result; default: GetLogger().Error(StringFormat("Invalid EA condition: %s!", EnumToString(_cond), __FUNCTION_LINE__)); - return false; + break; } + return _result; } bool CheckCondition(ENUM_STRATEGY_CONDITION _cond, long _arg1) { ARRAY(DataParamEntry, _args); @@ -749,7 +750,7 @@ class Strategy : public Object { * Returns true when the action has been executed successfully. */ bool ExecuteAction(ENUM_STRATEGY_ACTION _action, DataParamEntry &_args[]) { - bool _result = true; + bool _result = false; double arg1d = EMPTY_VALUE; double arg2d = EMPTY_VALUE; double arg3d = EMPTY_VALUE; @@ -811,7 +812,7 @@ class Strategy : public Object { return true; default: GetLogger().Error(StringFormat("Invalid Strategy action: %s!", EnumToString(_action), __FUNCTION_LINE__)); - return false; + break; } return _result; } diff --git a/Tick/TickManager.h b/Tick/TickManager.h new file mode 100644 index 000000000..befa1d4a9 --- /dev/null +++ b/Tick/TickManager.h @@ -0,0 +1,94 @@ +//+------------------------------------------------------------------+ +//| 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 + * Implements TickManager class. + */ + +// Includes. +#include "../BufferStruct.mqh" +#include "TickManager.h" +//#include "TickManager.struct.h" + +/** + * Class to store and manage tick data. + */ +class TickManager : public BufferStruct { + protected: + /* Protected methods */ + + /** + * Init code (called on constructor). + */ + void Init() { + AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); + SetOverflowListener(TickManagerOverflowListener, 10); + } + + public: + /** + * Default class constructor. + */ + TickManager() { Init(); } + + /** + * Class constructor with parameters. + */ + // TickManager(TickManagerParams &_params) : params(_params) { Init(); } + + /* Getters */ + + /** + * Gets a property value. + */ + // template + // T Get(STRUCT_ENUM(TickManagerParams, ENUM_TSM_PARAMS_PROP) _prop) + // { return params.Get(_prop); } + + /* Setters */ + + /** + * Sets a property value. + */ + // template + // void Set(STRUCT_ENUM(TickManagerParams, ENUM_TSM_PARAMS_PROP) _prop, T _value) + // { params.Set(_prop, _value); } + + /* Other methods */ + + /** + * Function should return true if resize can be made, or false to overwrite current slot. + */ + static bool TickManagerOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { + switch (_reason) { + case DICT_OVERFLOW_REASON_FULL: + // We allow resize if dictionary size is less than 86400 slots. + return _size < 86400; + case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: + default: + // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. + break; + } + return false; + } +}; diff --git a/Tick/tests/TickManager.test.mq4 b/Tick/tests/TickManager.test.mq4 new file mode 100644 index 000000000..0956d46bf --- /dev/null +++ b/Tick/tests/TickManager.test.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| 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 + * Test functionality of TickManager class. + */ + +// Includes. +#include "TickManager.test.mq5" diff --git a/Tick/tests/TickManager.test.mq5 b/Tick/tests/TickManager.test.mq5 new file mode 100644 index 000000000..a2b36637a --- /dev/null +++ b/Tick/tests/TickManager.test.mq5 @@ -0,0 +1,53 @@ +//+------------------------------------------------------------------+ +//| 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 + * Test functionality of TickManager class. + */ + +// Includes. +#include "../../Test.mqh" +#include "../TickManager.h" + +TickManager tm; + +/** + * Implements OnInit(). + */ +int OnInit() { + bool _result = true; + // ... + return _result && GetLastError() == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED; +} + +/** + * Implements Tick event handler. + */ +void OnTick() { + MqlTick tick; + ::SymbolInfoTick(_Symbol, tick); + tm.Add(tick, tick.time); + if (tick.time % 3600 == 0) { + PrintFormat("Ticks: %d (reserved %d); Memory %d/%d", tm.Size(), tm.ReservedSize(), + ::TerminalInfoInteger(TERMINAL_MEMORY_USED), ::TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)); + } +} diff --git a/Trade.mqh b/Trade.mqh index 254f6bbff..c5664cf32 100644 --- a/Trade.mqh +++ b/Trade.mqh @@ -1729,7 +1729,7 @@ HistorySelect(0, TimeCurrent()); // Select history for access. * Returns true when the condition is met. */ bool CheckCondition(ENUM_TRADE_CONDITION _cond, DataParamEntry &_args[]) { - bool _result = true; + bool _result = false; long _arg1l = ArraySize(_args) > 0 ? DataParamEntry::ToInteger(_args[0]) : WRONG_VALUE; long _arg2l = ArraySize(_args) > 1 ? DataParamEntry::ToInteger(_args[1]) : WRONG_VALUE; Ref _oquery_ref; @@ -1798,7 +1798,6 @@ HistorySelect(0, TimeCurrent()); // Select history for access. // case TRADE_ORDER_CONDS_IN_TREND_NOT: default: logger.Error(StringFormat("Invalid trade condition: %s!", EnumToString(_cond), __FUNCTION_LINE__)); - _result = false; break; } return _result; @@ -1827,7 +1826,7 @@ HistorySelect(0, TimeCurrent()); // Select history for access. * Returns true when the condition is met. */ bool ExecuteAction(ENUM_TRADE_ACTION _action, DataParamEntry &_args[]) { - bool _result = true; + bool _result = false; Ref _oquery_ref; if (Get(TRADE_STATE_ORDERS_ACTIVE)) { _oquery_ref = OrderQuery::GetInstance(orders_active); @@ -1852,21 +1851,21 @@ HistorySelect(0, TimeCurrent()); // Select history for access. break; case TRADE_ACTION_ORDER_CLOSE_MOST_LOSS: if (Get(TRADE_STATE_ORDERS_ACTIVE) && orders_active.Size() > 0) { - _result &= _oquery_ref.Ptr() - .FindByPropViaOp(ORDER_PROP_PROFIT, - STRUCT_ENUM(OrderQuery, ORDER_QUERY_OP_LT)) - .Ptr() - .OrderClose(ORDER_REASON_CLOSED_BY_ACTION); + _result = _oquery_ref.Ptr() + .FindByPropViaOp(ORDER_PROP_PROFIT, + STRUCT_ENUM(OrderQuery, ORDER_QUERY_OP_LT)) + .Ptr() + .OrderClose(ORDER_REASON_CLOSED_BY_ACTION); RefreshActiveOrders(true, true); } break; case TRADE_ACTION_ORDER_CLOSE_MOST_PROFIT: if (Get(TRADE_STATE_ORDERS_ACTIVE) && orders_active.Size() > 0) { - _result &= _oquery_ref.Ptr() - .FindByPropViaOp(ORDER_PROP_PROFIT, - STRUCT_ENUM(OrderQuery, ORDER_QUERY_OP_GT)) - .Ptr() - .OrderClose(ORDER_REASON_CLOSED_BY_ACTION); + _result = _oquery_ref.Ptr() + .FindByPropViaOp(ORDER_PROP_PROFIT, + STRUCT_ENUM(OrderQuery, ORDER_QUERY_OP_GT)) + .Ptr() + .OrderClose(ORDER_REASON_CLOSED_BY_ACTION); RefreshActiveOrders(true, true); } break; @@ -1874,33 +1873,33 @@ HistorySelect(0, TimeCurrent()); // Select history for access. return RequestSend(GetTradeOpenRequest((ENUM_ORDER_TYPE)_args[0].integer_value)); case TRADE_ACTION_ORDERS_CLOSE_ALL: if (Get(TRADE_STATE_ORDERS_ACTIVE)) { - _result &= OrdersCloseAll(ORDER_REASON_CLOSED_BY_ACTION) >= 0; + _result = OrdersCloseAll(ORDER_REASON_CLOSED_BY_ACTION) >= 0; RefreshActiveOrders(true); } break; case TRADE_ACTION_ORDERS_CLOSE_IN_PROFIT: if (Get(TRADE_STATE_ORDERS_ACTIVE)) { - _result &= OrdersCloseViaProp( - ORDER_PROP_PROFIT_PIPS, (int)chart.Ptr().GetSpreadInPips(), MATH_COND_GT, - ORDER_REASON_CLOSED_BY_ACTION) >= 0; + _result = OrdersCloseViaProp( + ORDER_PROP_PROFIT_PIPS, (int)chart.Ptr().GetSpreadInPips(), MATH_COND_GT, + ORDER_REASON_CLOSED_BY_ACTION) >= 0; RefreshActiveOrders(true); } break; case TRADE_ACTION_ORDERS_CLOSE_IN_TREND: if (Get(TRADE_STATE_ORDERS_ACTIVE)) { - _result &= OrdersCloseViaCmd(GetTrendOp(0), ORDER_REASON_CLOSED_BY_ACTION) >= 0; + _result = OrdersCloseViaCmd(GetTrendOp(0), ORDER_REASON_CLOSED_BY_ACTION) >= 0; RefreshActiveOrders(true); } break; case TRADE_ACTION_ORDERS_CLOSE_IN_TREND_NOT: if (Get(TRADE_STATE_ORDERS_ACTIVE)) { - _result &= OrdersCloseViaCmd(Order::NegateOrderType(GetTrendOp(0)), ORDER_REASON_CLOSED_BY_ACTION) >= 0; + _result = OrdersCloseViaCmd(Order::NegateOrderType(GetTrendOp(0)), ORDER_REASON_CLOSED_BY_ACTION) >= 0; RefreshActiveOrders(true); } break; case TRADE_ACTION_ORDERS_CLOSE_BY_TYPE: if (Get(TRADE_STATE_ORDERS_ACTIVE)) { - _result &= OrdersCloseViaCmd((ENUM_ORDER_TYPE)_args[0].integer_value, ORDER_REASON_CLOSED_BY_ACTION) >= 0; + _result = OrdersCloseViaCmd((ENUM_ORDER_TYPE)_args[0].integer_value, ORDER_REASON_CLOSED_BY_ACTION) >= 0; RefreshActiveOrders(true); } break; @@ -1911,7 +1910,7 @@ HistorySelect(0, TimeCurrent()); // Select history for access. _oquery_ref.Ptr() .FindPropBySum( _order_types1, ORDER_PROP_PROFIT, ORDER_TYPE); - _result &= + _result = OrdersCloseViaCmd(Order::NegateOrderType(_order_type_profitable), ORDER_REASON_CLOSED_BY_ACTION) >= 0; } break; @@ -1922,7 +1921,7 @@ HistorySelect(0, TimeCurrent()); // Select history for access. _oquery_ref.Ptr() .FindPropBySum( _order_types2, ORDER_PROP_PROFIT, ORDER_TYPE); - _result &= OrdersCloseViaCmd(_order_type_profitable2, ORDER_REASON_CLOSED_BY_ACTION) >= 0; + _result = OrdersCloseViaCmd(_order_type_profitable2, ORDER_REASON_CLOSED_BY_ACTION) >= 0; } break; case TRADE_ACTION_ORDERS_LIMIT_SET: diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 60a416e0c..22bb10ada 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -25,7 +25,8 @@ */ // Defines. -//#define __debug__ // Enables debug. +// #define __debug__ // Enables debug. +// #define __debug_verbose__ // Forward declaration. struct DataParamEntry; @@ -83,6 +84,11 @@ int OnInit() { void OnTick() { chart.OnTick(); + // All indicators should execute its OnTick() method for every platform tick. + for (DictStructIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { + iter.Value().Ptr().Tick(); + } + if (chart.IsNewBar()) { bar_processed++; if (indis.Size() == 0) { @@ -104,6 +110,7 @@ void OnTick() { IndicatorBase* _indi = iter.Value().Ptr(); _indi.OnTick(); IndicatorDataEntry _entry(_indi.GetEntry()); + if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { if (_entry.IsValid()) { PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); @@ -321,7 +328,7 @@ bool InitIndicators() { stddev_params_on_ma_sma.SetDraw(true, 1); Ref indi_stddev_on_ma_sma = new Indi_StdDev(stddev_params_on_ma_sma); - indi_stddev_on_ma_sma.Ptr().SetDataSource(indi_ma_sma_for_stddev.Ptr(), 0); + indi_stddev_on_ma_sma.Ptr().SetDataSource(indi_ma_sma_for_stddev.Ptr()); indis.Push(indi_stddev_on_ma_sma.Ptr()); // Standard Deviation (StdDev) in SMA mode over Price. @@ -409,7 +416,18 @@ bool InitIndicators() { // AMA. IndiAMAParams ama_params(); - indis.Push(new Indi_AMA(ama_params)); + // Will use Candle indicator by default. However, in that case we need to specifiy applied price (excluding ASK and + // BID). + ama_params.SetDataSourceType(IDATA_INDICATOR); + Indi_AMA* _indi_ama = new Indi_AMA(ama_params); + _indi_ama.SetAppliedPrice(PRICE_OPEN); + indis.Push(_indi_ama); + + // Original AMA. + IndiAMAParams ama_params_orig(); + ama_params_orig.SetName("Original AMA to compare"); + ama_params_orig.SetDataSourceType(IDATA_BUILTIN); + indis.Push(new Indi_AMA(ama_params_orig)); // Chaikin Oscillator. IndiCHOParams cho_params(); @@ -533,7 +551,7 @@ bool InitIndicators() { } // Push white-listed indicators here. - whitelisted_indis.Push(_indi_test); + // whitelisted_indis.Push(_indi_test); return GetLastError() == ERR_NO_ERROR; }