diff --git a/README.md b/README.md index 0978eed..ab9794f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # TALibFFI ![Tests](https://github.com/TA-Lib/ta-lib-ruby/actions/workflows/main.yml/badge.svg) -![Gem Version](https://img.shields.io/gem/v/ta_lib_ffi.svg) +[![Gem Version](https://badge.fury.io/rb/ta_lib_ffi.svg?icon=si%3Arubygems)](https://badge.fury.io/rb/ta_lib_ffi) ## Introduction -TALibFFI is a Ruby binding for [TA-Lib](https://ta-lib.org/) (Technical Analysis Library) using FFI (Foreign Function Interface). It provides a comprehensive set of functions for technical analysis of financial market data. +TALibFFI is a Ruby binding for [TA-Lib](https://ta-lib.org/) (Technical Analysis Library) using FFI (Foreign Function Interface). It provides a comprehensive set of functions for technical analysis of financial market data. This gem is based on the [TA-Lib C headers](https://github.com/TA-Lib/ta-lib/blob/6a07e4ca1877c5ab4b08b81015858bfcbf2ef832/include/ta_abstract.h#L45), providing a Ruby-friendly interface to the underlying C library. ## Requirements @@ -39,7 +39,7 @@ wget https://github.com/ta-lib/ta-lib/releases/download/v0.6.4/ta-lib_0.6.4_i386 sudo dpkg -i ta-lib_0.6.4_i386.deb ``` -### Installing the Ruby Gem +### [Installing the Ruby Gem](https://rubygems.org/gems/ta_lib_ffi) Add this to your application's Gemfile: @@ -66,8 +66,20 @@ prices = [10.0, 11.0, 12.0, 11.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0] # Calculate SMA puts TALibFFI.sma(prices, time_period: 3) # => [11.0, 11.333333333333334, 11.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0] + +# Average True Range (ATR) Example +high = [82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00, 85.90, 86.58, 86.98, 88.00, 87.87] +low = [81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11, 84.03, 85.39, 85.76, 87.17, 87.01] +close = [81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29] + +# Calculate ATR with period = 5 +result = TALibFFI.atr([high, low, close], time_period: 5) +# => [1.101999999999998, 1.0495999999999992, 1.2396799999999994, 1.1617440000000012, 1.1073952000000011, ...] ``` +## Documentation +- [API Documentation](https://www.rubydoc.info/github/TA-Lib/ta-lib-ruby/main) - Detailed documentation of all available methods and classes + ## TODO - [ ] Add RDoc documentation for Ruby methods - [ ] Create detailed function examples with input/output samples diff --git a/lib/ta_lib_ffi.rb b/lib/ta_lib_ffi.rb index 911a1c5..cb754b2 100644 --- a/lib/ta_lib_ffi.rb +++ b/lib/ta_lib_ffi.rb @@ -375,7 +375,7 @@ def call_func(func_name, args) # rubocop:disable Metrics/MethodLength setup_input_parameters(params_ptr, input_arrays, func_name) setup_optional_parameters(params_ptr, options, func_name) _lookback = calculate_lookback(params_ptr) - calculate_results(params_ptr, input_arrays.first.length, func_name) + calculate_results(params_ptr, input_arrays, func_name) ensure TA_ParamHolderFree(params_ptr) end @@ -523,10 +523,17 @@ def set_optional_parameter(params_ptr, index, value, type) # Calculates function results # # @param params_ptr [Fiddle::Pointer] Parameter holder pointer - # @param input_size [Integer] Size of input data + # @param input_arrays [Array] Input data # @param func_name [String] Function name # @return [Array, Hash] Function results - def calculate_results(params_ptr, input_size, func_name) # rubocop:disable Metrics/MethodLength + def calculate_results(params_ptr, input_arrays, func_name) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize + func_info = function_info_map[func_name] + input_size = if func_info[:inputs].first["type"] == TA_PARAM_TYPE[:TA_Input_Price] + input_arrays[0][0].length + else + input_arrays[0].length + end + out_begin = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT) out_size = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT) output_arrays = setup_output_buffers(params_ptr, input_size, func_name) @@ -770,13 +777,10 @@ def define_ta_function(method_name, func_name) # @param flags [Integer] Input flags def setup_price_inputs(params_ptr, index, price_data, flags) required_flags = extract_flags(flags, :TA_InputFlags) - data_pointers = Array.new(6) { nil } - TA_FLAGS[:TA_InputFlags].keys[0..5].each_with_index do |flag, i| - data_pointers[i] = if required_flags.include?(flag) - prepare_double_array(price_data[required_flags.index(flag)]) - else - Fiddle::Pointer.malloc(0) - end + data_pointers = Array.new(6) { Fiddle::Pointer.malloc(0) } + required_flags.each_with_index do |flag, i| + flag_index = TA_FLAGS[:TA_InputFlags].keys.index(flag) + data_pointers[flag_index] = prepare_double_array(price_data[i]) if required_flags.include?(flag) end TA_SetInputParamPricePtr(params_ptr, index, *data_pointers) @@ -793,7 +797,7 @@ class << self # @!method accbands(price_hlc, time_period: 20.0) # Acceleration Bands # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 20.0) # @return [Hash] Hash containing the following arrays: # @option result [Array] :upper_band Output values @@ -811,7 +815,7 @@ class << self # @!method ad(price_hlcv) # Chaikin A/D Line # - # @param price_hlcv [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE, TA_IN_PRICE_VOLUME + # @param price_hlcv [Array, Array, Array, Array] Required price arrays: high, low, close, volume # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -826,7 +830,7 @@ class << self # @!method adosc(price_hlcv, fast_period: 3.0, slow_period: 10.0) # Chaikin A/D Oscillator # - # @param price_hlcv [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE, TA_IN_PRICE_VOLUME + # @param price_hlcv [Array, Array, Array, Array] Required price arrays: high, low, close, volume # @param fast_period [Integer] Number of period for the fast MA (default: 3.0) # @param slow_period [Integer] Number of period for the slow MA (default: 10.0) # @return [Array] @@ -835,7 +839,7 @@ class << self # @!method adx(price_hlc, time_period: 14.0) # Average Directional Movement Index # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -843,7 +847,7 @@ class << self # @!method adxr(price_hlc, time_period: 14.0) # Average Directional Movement Index Rating # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -861,7 +865,7 @@ class << self # @!method aroon(price_hl, time_period: 14.0) # Aroon # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param time_period [Integer] Number of period (default: 14.0) # @return [Hash] Hash containing the following arrays: # @option result [Array] :aroon_down Output values @@ -871,7 +875,7 @@ class << self # @!method aroonosc(price_hl, time_period: 14.0) # Aroon Oscillator # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -893,7 +897,7 @@ class << self # @!method atr(price_hlc, time_period: 14.0) # Average True Range # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -901,7 +905,7 @@ class << self # @!method avgprice(price_ohlc) # Average Price # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -939,14 +943,14 @@ class << self # @!method bop(price_ohlc) # Balance Of Power # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cci(price_hlc, time_period: 14.0) # Commodity Channel Index # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -954,56 +958,56 @@ class << self # @!method cdl2crows(price_ohlc) # Two Crows # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdl3blackcrows(price_ohlc) # Three Black Crows # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdl3inside(price_ohlc) # Three Inside Up/Down # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdl3linestrike(price_ohlc) # Three-Line Strike # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdl3outside(price_ohlc) # Three Outside Up/Down # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdl3starsinsouth(price_ohlc) # Three Stars In The South # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdl3whitesoldiers(price_ohlc) # Three Advancing White Soldiers # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlabandonedbaby(price_ohlc, penetration: 0.3) # Abandoned Baby # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.3) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1011,49 +1015,49 @@ class << self # @!method cdladvanceblock(price_ohlc) # Advance Block # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlbelthold(price_ohlc) # Belt-hold # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlbreakaway(price_ohlc) # Breakaway # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlclosingmarubozu(price_ohlc) # Closing Marubozu # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlconcealbabyswall(price_ohlc) # Concealing Baby Swallow # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlcounterattack(price_ohlc) # Counterattack # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdldarkcloudcover(price_ohlc, penetration: 0.5) # Dark Cloud Cover # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.5) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1061,35 +1065,35 @@ class << self # @!method cdldoji(price_ohlc) # Doji # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdldojistar(price_ohlc) # Doji Star # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdldragonflydoji(price_ohlc) # Dragonfly Doji # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlengulfing(price_ohlc) # Engulfing Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdleveningdojistar(price_ohlc, penetration: 0.3) # Evening Doji Star # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.3) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1097,7 +1101,7 @@ class << self # @!method cdleveningstar(price_ohlc, penetration: 0.3) # Evening Star # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.3) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1105,147 +1109,147 @@ class << self # @!method cdlgapsidesidewhite(price_ohlc) # Up/Down-gap side-by-side white lines # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlgravestonedoji(price_ohlc) # Gravestone Doji # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlhammer(price_ohlc) # Hammer # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlhangingman(price_ohlc) # Hanging Man # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlharami(price_ohlc) # Harami Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlharamicross(price_ohlc) # Harami Cross Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlhighwave(price_ohlc) # High-Wave Candle # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlhikkake(price_ohlc) # Hikkake Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlhikkakemod(price_ohlc) # Modified Hikkake Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlhomingpigeon(price_ohlc) # Homing Pigeon # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlidentical3crows(price_ohlc) # Identical Three Crows # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlinneck(price_ohlc) # In-Neck Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlinvertedhammer(price_ohlc) # Inverted Hammer # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlkicking(price_ohlc) # Kicking # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlkickingbylength(price_ohlc) # Kicking - bull/bear determined by the longer marubozu # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlladderbottom(price_ohlc) # Ladder Bottom # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdllongleggeddoji(price_ohlc) # Long Legged Doji # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdllongline(price_ohlc) # Long Line Candle # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlmarubozu(price_ohlc) # Marubozu # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlmatchinglow(price_ohlc) # Matching Low # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlmathold(price_ohlc, penetration: 0.5) # Mat Hold # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.5) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1253,7 +1257,7 @@ class << self # @!method cdlmorningdojistar(price_ohlc, penetration: 0.3) # Morning Doji Star # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.3) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1261,7 +1265,7 @@ class << self # @!method cdlmorningstar(price_ohlc, penetration: 0.3) # Morning Star # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @param penetration [Float] Percentage of penetration of a candle within another candle (default: 0.3) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1269,119 +1273,119 @@ class << self # @!method cdlonneck(price_ohlc) # On-Neck Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlpiercing(price_ohlc) # Piercing Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlrickshawman(price_ohlc) # Rickshaw Man # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlrisefall3methods(price_ohlc) # Rising/Falling Three Methods # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlseparatinglines(price_ohlc) # Separating Lines # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlshootingstar(price_ohlc) # Shooting Star # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlshortline(price_ohlc) # Short Line Candle # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlspinningtop(price_ohlc) # Spinning Top # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlstalledpattern(price_ohlc) # Stalled Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlsticksandwich(price_ohlc) # Stick Sandwich # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdltakuri(price_ohlc) # Takuri (Dragonfly Doji with very long lower shadow) # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdltasukigap(price_ohlc) # Tasuki Gap # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlthrusting(price_ohlc) # Thrusting Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdltristar(price_ohlc) # Tristar Pattern # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlunique3river(price_ohlc) # Unique 3 River # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlupsidegap2crows(price_ohlc) # Upside Gap Two Crows # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method cdlxsidegap3methods(price_ohlc) # Upside/Downside Gap Three Methods # - # @param price_ohlc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1442,7 +1446,7 @@ class << self # @!method dx(price_hlc, time_period: 14.0) # Directional Movement Index # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1518,7 +1522,7 @@ class << self # @!method imi(price_oc, time_period: 14.0) # Intraday Momentum Index # - # @param price_oc [Array] TA_IN_PRICE_OPEN, TA_IN_PRICE_CLOSE + # @param price_oc [Array, Array] Required price arrays: open, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1667,14 +1671,14 @@ class << self # @!method medprice(price_hl) # Median Price # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method mfi(price_hlcv, time_period: 14.0) # Money Flow Index # - # @param price_hlcv [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE, TA_IN_PRICE_VOLUME + # @param price_hlcv [Array, Array, Array, Array] Required price arrays: high, low, close, volume # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1690,7 +1694,7 @@ class << self # @!method midprice(price_hl, time_period: 14.0) # Midpoint Price over period # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1734,7 +1738,7 @@ class << self # @!method minus_di(price_hlc, time_period: 14.0) # Minus Directional Indicator # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1742,7 +1746,7 @@ class << self # @!method minus_dm(price_hl, time_period: 14.0) # Minus Directional Movement # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1766,7 +1770,7 @@ class << self # @!method natr(price_hlc, time_period: 14.0) # Normalized Average True Range # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1775,14 +1779,14 @@ class << self # On Balance Volume # # @param real [Array] Input values - # @param price_v [Array] TA_IN_PRICE_VOLUME + # @param price_v [Array] Required price arrays: volume # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method plus_di(price_hlc, time_period: 14.0) # Plus Directional Indicator # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1790,7 +1794,7 @@ class << self # @!method plus_dm(price_hl, time_period: 14.0) # Plus Directional Movement # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1848,7 +1852,7 @@ class << self # @!method sar(price_hl, acceleration: 0.02, maximum: 0.2) # Parabolic SAR # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param acceleration [Float] Acceleration Factor used up to the Maximum value (default: 0.02) # @param maximum [Float] Acceleration Factor Maximum value (default: 0.2) # @return [Array] @@ -1857,7 +1861,7 @@ class << self # @!method sarext(price_hl, start_value: 0.0, offset_on_reverse: 0.0, acceleration_init_long: 0.02, acceleration_long: 0.02, acceleration_max_long: 0.2, acceleration_init_short: 0.02, acceleration_short: 0.02, acceleration_max_short: 0.2) # Parabolic SAR - Extended # - # @param price_hl [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW + # @param price_hl [Array, Array] Required price arrays: high, low # @param start_value [Float] Start value and direction. 0 for Auto, >0 for Long, <0 for Short (default: 0.0) # @param offset_on_reverse [Float] Percent offset added/removed to initial stop on short/long reversal (default: 0.0) # @param acceleration_init_long [Float] Acceleration Factor initial value for the Long direction (default: 0.02) @@ -1910,7 +1914,7 @@ class << self # @!method stoch(price_hlc, fast_k_period: 5.0, slow_k_period: 3.0, slow_k_ma_type: 0.0, slow_d_period: 3.0, slow_d_ma_type: 0.0) # Stochastic # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param fast_k_period [Integer] Time period for building the Fast-K line (default: 5.0) # @param slow_k_period [Integer] Smoothing for making the Slow-K line. Usually set to 3 (default: 3.0) # @param slow_k_ma_type [Integer] Type of Moving Average for Slow-K (default: 0.0) @@ -1924,7 +1928,7 @@ class << self # @!method stochf(price_hlc, fast_k_period: 5.0, fast_d_period: 3.0, fast_d_ma_type: 0.0) # Stochastic Fast # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param fast_k_period [Integer] Time period for building the Fast-K line (default: 5.0) # @param fast_d_period [Integer] Smoothing for making the Fast-D line. Usually set to 3 (default: 3.0) # @param fast_d_ma_type [Integer] Type of Moving Average for Fast-D (default: 0.0) @@ -1996,7 +2000,7 @@ class << self # @!method trange(price_hlc) # True Range # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -2027,14 +2031,14 @@ class << self # @!method typprice(price_hlc) # Typical Price # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method ultosc(price_hlc, time_period1: 7.0, time_period2: 14.0, time_period3: 28.0) # Ultimate Oscillator # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period1 [Integer] Number of bars for 1st period. (default: 7.0) # @param time_period2 [Integer] Number of bars fro 2nd period (default: 14.0) # @param time_period3 [Integer] Number of bars for 3rd period (default: 28.0) @@ -2053,14 +2057,14 @@ class << self # @!method wclprice(price_hlc) # Weighted Close Price # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution # @!method willr(price_hlc, time_period: 14.0) # Williams' %R # - # @param price_hlc [Array] TA_IN_PRICE_HIGH, TA_IN_PRICE_LOW, TA_IN_PRICE_CLOSE + # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close # @param time_period [Integer] Number of period (default: 14.0) # @return [Array] # @raise [TALibError] If there is an error in function execution diff --git a/lib/ta_lib_ffi/doc.rb b/lib/ta_lib_ffi/doc.rb index a4e3e49..6ea6887 100644 --- a/lib/ta_lib_ffi/doc.rb +++ b/lib/ta_lib_ffi/doc.rb @@ -71,12 +71,39 @@ def generate_function_description(func_info, inputs, opt_inputs) # rubocop:disab ] end - def generate_input_documentation(inputs) - inputs.map do |input| + def generate_input_documentation(inputs) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/CyclomaticComplexity + inputs.map do |input| # rubocop:disable Metrics/BlockLength param_name = TALibFFI.normalize_parameter_name(input["paramName"].to_s) flags = TALibFFI.extract_flags(input["flags"], :TA_InputFlags) - description = flags.empty? ? "Input values" : flags.join(", ") - " # @param #{param_name} [Array] #{description}" + + type = case input["type"] + when TALibFFI::TA_PARAM_TYPE[:TA_Input_Price] + array_types = Array.new(flags.length, "Array") + array_types.join(", ").to_s + when TALibFFI::TA_PARAM_TYPE[:TA_Input_Real] + "Array" + when TALibFFI::TA_PARAM_TYPE[:TA_Input_Integer] + "Array" + end + + description = if input["type"] == TALibFFI::TA_PARAM_TYPE[:TA_Input_Price] + arrays = flags.map do |flag| + { + TA_IN_PRICE_OPEN: "open", + TA_IN_PRICE_HIGH: "high", + TA_IN_PRICE_LOW: "low", + TA_IN_PRICE_CLOSE: "close", + TA_IN_PRICE_VOLUME: "volume", + TA_IN_PRICE_OPENINTEREST: "open interest", + TA_IN_PRICE_TIMESTAMP: "timestamp" + }[flag] + end + "Required price arrays: #{arrays.join(", ")}" + else + flags.empty? ? "Input values" : flags.join(", ") + end + + " # @param #{param_name} [#{type}] #{description}" end end diff --git a/spec/ta_lib_ffi_spec.rb b/spec/ta_lib_ffi_spec.rb index 6084978..6610e16 100644 --- a/spec/ta_lib_ffi_spec.rb +++ b/spec/ta_lib_ffi_spec.rb @@ -1093,7 +1093,7 @@ it "calculates MidPrice over period" do result = described_class.midprice([high_prices, low_prices], time_period: 2) expect(result).to be_an(Array) - expect(result.length).to eq(1) + expect(result.length).to eq(high_prices.length - 1) end it "uses default time period (14) when not specified" do