From 17a7270baa4e057cda0b3eb772f3be3c6f838d42 Mon Sep 17 00:00:00 2001 From: Victor Yang Date: Sun, 23 Feb 2025 12:05:30 +0800 Subject: [PATCH] Release version 0.3.0: Enhance documentation and testing infrastructure - Add auto-generated YARD documentation - Implement GitHub Actions PR Agent workflow - Add cross-platform test support (Ubuntu, macOS, Windows) - Optimize function documentation generator - Improve error handling and validation - Update development dependencies - Fix prices handling in multiple technical analysis functions - Update version across project files --- CHANGELOG.md | 16 ++++ Gemfile.lock | 2 +- lib/ta_lib_ffi.rb | 186 ++++++++++++++++++++-------------------- lib/ta_lib_ffi/doc.rb | 6 +- spec/ta_lib_ffi_spec.rb | 33 +++++-- ta_lib_ffi.gemspec | 2 +- 6 files changed, 138 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af099af..7195e38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.0] - 2025-02-23 + +### Added +- Auto-generated YARD documentation +- GitHub Actions PR Agent workflow +- Cross-platform test support (Ubuntu, macOS, Windows) + +### Changed +- Optimized function documentation generator +- Improved error handling and validation +- Updated development dependencies + +### Fixed +- Fixed prices handling in multiple technical analysis functions + ## [0.2.0] - 2025-01-21 ### Added @@ -39,5 +54,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security - N/A +[0.3.0]: https://github.com/TA-Lib/ta-lib-ruby/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/TA-Lib/ta-lib-ruby/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/TA-Lib/ta-lib-ruby/releases/tag/v0.1.0 diff --git a/Gemfile.lock b/Gemfile.lock index 5059ce9..3600fe3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - ta_lib_ffi (0.2.0) + ta_lib_ffi (0.3.0) fiddle (~> 1.1) GEM diff --git a/lib/ta_lib_ffi.rb b/lib/ta_lib_ffi.rb index cb754b2..751d1e5 100644 --- a/lib/ta_lib_ffi.rb +++ b/lib/ta_lib_ffi.rb @@ -18,7 +18,7 @@ # # @see https://ta-lib.org/ TA-Lib Official Website module TALibFFI - VERSION = "0.2.0" + VERSION = "0.3.0" if defined?(Zeitwerk) # https://github.com/fxn/zeitwerk?tab=readme-ov-file#custom-inflector @@ -797,7 +797,7 @@ class << self # @!method accbands(price_hlc, time_period: 20.0) # Acceleration Bands # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -815,7 +815,7 @@ class << self # @!method ad(price_hlcv) # Chaikin A/D Line # - # @param price_hlcv [Array, Array, Array, Array] Required price arrays: high, low, close, volume + # @param price_hlcv [Array(Array, Array, Array, Array)] Required price arrays: high, low, close, volume # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -830,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, Array, Array, Array] Required price arrays: high, low, close, volume + # @param price_hlcv [Array(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] @@ -839,7 +839,7 @@ class << self # @!method adx(price_hlc, time_period: 14.0) # Average Directional Movement Index # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -847,7 +847,7 @@ class << self # @!method adxr(price_hlc, time_period: 14.0) # Average Directional Movement Index Rating # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -865,7 +865,7 @@ class << self # @!method aroon(price_hl, time_period: 14.0) # Aroon # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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 @@ -875,7 +875,7 @@ class << self # @!method aroonosc(price_hl, time_period: 14.0) # Aroon Oscillator # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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 @@ -897,7 +897,7 @@ class << self # @!method atr(price_hlc, time_period: 14.0) # Average True Range # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -905,7 +905,7 @@ class << self # @!method avgprice(price_ohlc) # Average Price # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(Array, Array, Array, Array)] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -943,14 +943,14 @@ class << self # @!method bop(price_ohlc) # Balance Of Power # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -958,56 +958,56 @@ class << self # @!method cdl2crows(price_ohlc) # Two Crows # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1015,49 +1015,49 @@ class << self # @!method cdladvanceblock(price_ohlc) # Advance Block # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1065,35 +1065,35 @@ class << self # @!method cdldoji(price_ohlc) # Doji # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1101,7 +1101,7 @@ class << self # @!method cdleveningstar(price_ohlc, penetration: 0.3) # Evening Star # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1109,147 +1109,147 @@ class << self # @!method cdlgapsidesidewhite(price_ohlc) # Up/Down-gap side-by-side white lines # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1257,7 +1257,7 @@ class << self # @!method cdlmorningdojistar(price_ohlc, penetration: 0.3) # Morning Doji Star # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1265,7 +1265,7 @@ class << self # @!method cdlmorningstar(price_ohlc, penetration: 0.3) # Morning Star # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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 @@ -1273,119 +1273,119 @@ class << self # @!method cdlonneck(price_ohlc) # On-Neck Pattern # - # @param price_ohlc [Array, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(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, Array, Array, Array] Required price arrays: open, high, low, close + # @param price_ohlc [Array(Array, Array, Array, Array)] Required price arrays: open, high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -1446,7 +1446,7 @@ class << self # @!method dx(price_hlc, time_period: 14.0) # Directional Movement Index # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -1522,7 +1522,7 @@ class << self # @!method imi(price_oc, time_period: 14.0) # Intraday Momentum Index # - # @param price_oc [Array, Array] Required price arrays: open, close + # @param price_oc [Array(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 @@ -1671,14 +1671,14 @@ class << self # @!method medprice(price_hl) # Median Price # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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, Array, Array, Array] Required price arrays: high, low, close, volume + # @param price_hlcv [Array(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 @@ -1694,7 +1694,7 @@ class << self # @!method midprice(price_hl, time_period: 14.0) # Midpoint Price over period # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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 @@ -1738,7 +1738,7 @@ class << self # @!method minus_di(price_hlc, time_period: 14.0) # Minus Directional Indicator # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -1746,7 +1746,7 @@ class << self # @!method minus_dm(price_hl, time_period: 14.0) # Minus Directional Movement # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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 @@ -1770,7 +1770,7 @@ class << self # @!method natr(price_hlc, time_period: 14.0) # Normalized Average True Range # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -1779,14 +1779,14 @@ class << self # On Balance Volume # # @param real [Array] Input values - # @param price_v [Array] Required price arrays: volume + # @param price_v [Array(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, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 @@ -1794,7 +1794,7 @@ class << self # @!method plus_dm(price_hl, time_period: 14.0) # Plus Directional Movement # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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 @@ -1852,7 +1852,7 @@ class << self # @!method sar(price_hl, acceleration: 0.02, maximum: 0.2) # Parabolic SAR # - # @param price_hl [Array, Array] Required price arrays: high, low + # @param price_hl [Array(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] @@ -1861,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, Array] Required price arrays: high, low + # @param price_hl [Array(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) @@ -1914,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, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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) @@ -1928,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, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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) @@ -2000,7 +2000,7 @@ class << self # @!method trange(price_hlc) # True Range # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(Array, Array, Array)] Required price arrays: high, low, close # @return [Array] # @raise [TALibError] If there is an error in function execution @@ -2031,14 +2031,14 @@ class << self # @!method typprice(price_hlc) # Typical Price # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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) @@ -2057,14 +2057,14 @@ class << self # @!method wclprice(price_hlc) # Weighted Close Price # - # @param price_hlc [Array, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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, Array, Array] Required price arrays: high, low, close + # @param price_hlc [Array(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 6ea6887..e224943 100644 --- a/lib/ta_lib_ffi/doc.rb +++ b/lib/ta_lib_ffi/doc.rb @@ -71,7 +71,7 @@ def generate_function_description(func_info, inputs, opt_inputs) # rubocop:disab ] end - def generate_input_documentation(inputs) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/CyclomaticComplexity + def generate_input_documentation(inputs) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize 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) @@ -79,7 +79,7 @@ def generate_input_documentation(inputs) # rubocop:disable Metrics/MethodLength, type = case input["type"] when TALibFFI::TA_PARAM_TYPE[:TA_Input_Price] array_types = Array.new(flags.length, "Array") - array_types.join(", ").to_s + "Array(#{array_types.join(", ")})" when TALibFFI::TA_PARAM_TYPE[:TA_Input_Real] "Array" when TALibFFI::TA_PARAM_TYPE[:TA_Input_Integer] @@ -100,7 +100,7 @@ def generate_input_documentation(inputs) # rubocop:disable Metrics/MethodLength, end "Required price arrays: #{arrays.join(", ")}" else - flags.empty? ? "Input values" : flags.join(", ") + "Input values" end " # @param #{param_name} [#{type}] #{description}" diff --git a/spec/ta_lib_ffi_spec.rb b/spec/ta_lib_ffi_spec.rb index 6610e16..92eb59c 100644 --- a/spec/ta_lib_ffi_spec.rb +++ b/spec/ta_lib_ffi_spec.rb @@ -24,7 +24,7 @@ describe "Version and Initialization" do it "has a version number" do - expect(described_class::VERSION).to eq("0.2.0") + expect(described_class::VERSION).to eq("0.3.0") end it "returns a string for TA-Lib version", skip: "Not implemented under Windows" do @@ -832,9 +832,9 @@ expect(result[:upper_band].length).to eq([high_prices.length - 19, 0].max) end - it "respects specified time period", skip: "Needs implementation review" do + it "respects specified time period" do result = described_class.accbands([high_prices, low_prices, close_prices], time_period: 7) - expect(result[:upper_band].length).to eq(6) + expect(result[:upper_band].length).to eq(high_prices.length - 6) end it "returns empty arrays when period exceeds data length" do @@ -1114,18 +1114,33 @@ end end - describe "#sar", skip: "Needs implementation review" do + describe "#sar" do it_behaves_like "ta_lib_input_validation", :sar - it "calculates Parabolic SAR" do - result = described_class.sar(high_prices, low_prices) + it "calculates Parabolic SAR with default parameters" do + result = described_class.sar([high_prices, low_prices]) expect(result).to be_an(Array) - expect(result.length).to be <= high_prices.length + expect(result.length).to eq(high_prices.length - 1) end - it "handles custom acceleration and maximum parameters" do - result = described_class.sar(high_prices, low_prices, acceleration: 0.02, maximum: 0.2) + it "calculates Parabolic SAR with custom acceleration and maximum parameters" do + result = described_class.sar([high_prices, low_prices], acceleration: 0.02, maximum: 0.2) expect(result).to be_an(Array) + expect(result.length).to eq(high_prices.length - 1) + end + + it "uses default parameters when not specified" do + result1 = described_class.sar([high_prices, low_prices]) + result2 = described_class.sar([high_prices, low_prices], acceleration: 0.02, maximum: 0.2) + expect(result1).to eq(result2) + end + + it "raises error when acceleration is negative" do + expect { described_class.sar([high_prices, low_prices], acceleration: -0.02) }.to raise_error(described_class::TALibError) + end + + it "raises error when maximum is negative" do + expect { described_class.sar([high_prices, low_prices], maximum: -0.2) }.to raise_error(described_class::TALibError) end end diff --git a/ta_lib_ffi.gemspec b/ta_lib_ffi.gemspec index 0587ae8..5bee6ac 100644 --- a/ta_lib_ffi.gemspec +++ b/ta_lib_ffi.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |spec| "CHANGELOG.md", "Gemfile", "Rakefile", - "ta_lib_ffi.gemspec", + "ta_lib_ffi.gemspec" ] spec.bindir = "exe" spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }