ta_lib_ffi 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -3
- data/README.md +18 -5
- data/Rakefile +12 -0
- data/lib/ta_lib_ffi/doc.rb +138 -0
- data/lib/ta_lib_ffi.rb +1465 -44
- data/ta_lib_ffi.gemspec +7 -5
- metadata +36 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92ebfb652f8812db1420b8e8722f9df5e32850da14ca18c3df847dde134518b4
|
4
|
+
data.tar.gz: cbdeb52af3442827979b03523b58b6bcbf84484ec8fbd7a5a7265d5218401ce6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c07c6bb3ed6337582246a299df71eacf041f1c562180eea98d7f044cad285b971f7c56ebd8e949d73e303bce25dd1b2d1627e5add1dc9eb494a78f0effd901ae
|
7
|
+
data.tar.gz: 90d78b4fee669a0a5cd8f4d4f90501002bfd2006ef16af5541c7416f5dcfe5f6abf1d831059b302528df5eb7b328b595fe582048d16e8d301d1b3d3de92352f3
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.3.0] - 2025-02-23
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- Auto-generated YARD documentation
|
12
|
+
- GitHub Actions PR Agent workflow
|
13
|
+
- Cross-platform test support (Ubuntu, macOS, Windows)
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
- Optimized function documentation generator
|
17
|
+
- Improved error handling and validation
|
18
|
+
- Updated development dependencies
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
- Fixed prices handling in multiple technical analysis functions
|
22
|
+
|
8
23
|
## [0.2.0] - 2025-01-21
|
9
24
|
|
10
25
|
### Added
|
@@ -15,7 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
15
30
|
- Renamed main file from `lib/ta_lib.rb` to `lib/ta_lib_ffi.rb`
|
16
31
|
- Updated require statements in specs and gemspec
|
17
32
|
|
18
|
-
## [0.1.0] -
|
33
|
+
## [0.1.0] - 2025-01-21
|
19
34
|
|
20
35
|
### Added
|
21
36
|
- Initial release of ta_lib_ffi
|
@@ -39,5 +54,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
39
54
|
### Security
|
40
55
|
- N/A
|
41
56
|
|
42
|
-
[0.
|
43
|
-
[0.
|
57
|
+
[0.3.0]: https://github.com/TA-Lib/ta-lib-ruby/compare/v0.2.0...v0.3.0
|
58
|
+
[0.2.0]: https://github.com/TA-Lib/ta-lib-ruby/compare/v0.1.0...v0.2.0
|
59
|
+
[0.1.0]: https://github.com/TA-Lib/ta-lib-ruby/releases/tag/v0.1.0
|
data/README.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# TALibFFI
|
2
2
|
|
3
|
-

|
4
|
+
[](https://badge.fury.io/rb/ta_lib_ffi)
|
4
5
|
|
5
6
|
## Introduction
|
6
7
|
|
7
|
-
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.
|
8
|
+
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.
|
8
9
|
|
9
10
|
## Requirements
|
10
11
|
|
11
|
-
- Ruby >= 3.
|
12
|
+
- Ruby >= 3.1.0
|
12
13
|
- TA-Lib >= 0.6.4
|
13
14
|
|
14
15
|
## Installation
|
@@ -38,7 +39,7 @@ wget https://github.com/ta-lib/ta-lib/releases/download/v0.6.4/ta-lib_0.6.4_i386
|
|
38
39
|
sudo dpkg -i ta-lib_0.6.4_i386.deb
|
39
40
|
```
|
40
41
|
|
41
|
-
### Installing the Ruby Gem
|
42
|
+
### [Installing the Ruby Gem](https://rubygems.org/gems/ta_lib_ffi)
|
42
43
|
|
43
44
|
Add this to your application's Gemfile:
|
44
45
|
|
@@ -65,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]
|
|
65
66
|
# Calculate SMA
|
66
67
|
puts TALibFFI.sma(prices, time_period: 3)
|
67
68
|
# => [11.0, 11.333333333333334, 11.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0]
|
69
|
+
|
70
|
+
# Average True Range (ATR) Example
|
71
|
+
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]
|
72
|
+
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]
|
73
|
+
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]
|
74
|
+
|
75
|
+
# Calculate ATR with period = 5
|
76
|
+
result = TALibFFI.atr([high, low, close], time_period: 5)
|
77
|
+
# => [1.101999999999998, 1.0495999999999992, 1.2396799999999994, 1.1617440000000012, 1.1073952000000011, ...]
|
68
78
|
```
|
69
79
|
|
80
|
+
## Documentation
|
81
|
+
- [API Documentation](https://www.rubydoc.info/github/TA-Lib/ta-lib-ruby/main) - Detailed documentation of all available methods and classes
|
82
|
+
|
70
83
|
## TODO
|
71
84
|
- [ ] Add RDoc documentation for Ruby methods
|
72
85
|
- [ ] Create detailed function examples with input/output samples
|
@@ -83,7 +96,7 @@ puts TALibFFI.sma(prices, time_period: 3)
|
|
83
96
|
|
84
97
|
## Contributing
|
85
98
|
|
86
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
99
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/TA-Lib/ta-lib-ruby
|
87
100
|
|
88
101
|
## License
|
89
102
|
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
|
+
require "yard"
|
5
6
|
|
6
7
|
RSpec::Core::RakeTask.new(:spec)
|
7
8
|
|
@@ -10,3 +11,14 @@ require "rubocop/rake_task"
|
|
10
11
|
RuboCop::RakeTask.new
|
11
12
|
|
12
13
|
task default: %i[spec rubocop]
|
14
|
+
|
15
|
+
YARD::Rake::YardocTask.new do |t|
|
16
|
+
require_relative "lib/ta_lib_ffi"
|
17
|
+
require_relative "lib/ta_lib_ffi/doc"
|
18
|
+
TALibFFI::Doc.insert
|
19
|
+
|
20
|
+
t.files = ["lib/**/*.rb"]
|
21
|
+
t.options = ["--exclude", "lib/ta_lib_ffi/doc.rb"]
|
22
|
+
t.stats_options = ["--list-undoc"]
|
23
|
+
# t.after = -> { TALibFFI::Doc.remove }
|
24
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TALibFFI
|
4
|
+
# Generates documentation for a TA-Lib function
|
5
|
+
#
|
6
|
+
# This module provides methods to generate documentation for TA-Lib functions.
|
7
|
+
# It includes methods to collect input, optional input, and output information,
|
8
|
+
# and to generate documentation for each function.
|
9
|
+
module Doc
|
10
|
+
module_function
|
11
|
+
|
12
|
+
def insert
|
13
|
+
puts "Inserting documentation"
|
14
|
+
file_path = File.expand_path("../ta_lib_ffi.rb", __dir__)
|
15
|
+
content = File.read(file_path)
|
16
|
+
|
17
|
+
new_content = content.sub(
|
18
|
+
/### GENERATED DOCUMENTATION START ###.*### GENERATED DOCUMENTATION END ###/m,
|
19
|
+
"### GENERATED DOCUMENTATION START ###\n#{generate}\n ### GENERATED DOCUMENTATION END ###"
|
20
|
+
)
|
21
|
+
|
22
|
+
File.write(file_path, new_content)
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove
|
26
|
+
puts "Removing documentation"
|
27
|
+
file_path = File.expand_path("../ta_lib_ffi.rb", __dir__)
|
28
|
+
content = File.read(file_path)
|
29
|
+
|
30
|
+
new_content = content.sub(
|
31
|
+
/### GENERATED DOCUMENTATION START ###.*### GENERATED DOCUMENTATION END ###/m,
|
32
|
+
"### GENERATED DOCUMENTATION START ###\n ### GENERATED DOCUMENTATION END ###"
|
33
|
+
)
|
34
|
+
|
35
|
+
File.write(file_path, new_content)
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate
|
39
|
+
docs = []
|
40
|
+
TALibFFI.function_info_map.each_value do |h|
|
41
|
+
docs << generate_function_documentation(h[:info], h[:inputs], h[:opt_inputs], h[:outputs])
|
42
|
+
end
|
43
|
+
docs.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_function_documentation(func_info, inputs, opt_inputs, outputs)
|
47
|
+
[
|
48
|
+
generate_function_description(func_info, inputs, opt_inputs),
|
49
|
+
generate_input_documentation(inputs),
|
50
|
+
generate_optional_input_documentation(opt_inputs),
|
51
|
+
generate_output_documentation(outputs),
|
52
|
+
generate_error_documentation
|
53
|
+
].flatten.compact.join("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_function_description(func_info, inputs, opt_inputs) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
57
|
+
args = []
|
58
|
+
inputs.map do |input|
|
59
|
+
args << TALibFFI.normalize_parameter_name(input["paramName"].to_s)
|
60
|
+
end
|
61
|
+
|
62
|
+
opt_inputs.map do |opt_input|
|
63
|
+
param_name = TALibFFI.normalize_parameter_name(opt_input["paramName"].to_s)
|
64
|
+
args << "#{param_name}: #{opt_input["defaultValue"]}"
|
65
|
+
end
|
66
|
+
|
67
|
+
[
|
68
|
+
" # @!method #{func_info["name"].to_s.downcase}(#{args.join(", ")})",
|
69
|
+
" # #{func_info["hint"].to_s.strip}",
|
70
|
+
" #"
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def generate_input_documentation(inputs) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
75
|
+
inputs.map do |input| # rubocop:disable Metrics/BlockLength
|
76
|
+
param_name = TALibFFI.normalize_parameter_name(input["paramName"].to_s)
|
77
|
+
flags = TALibFFI.extract_flags(input["flags"], :TA_InputFlags)
|
78
|
+
|
79
|
+
type = case input["type"]
|
80
|
+
when TALibFFI::TA_PARAM_TYPE[:TA_Input_Price]
|
81
|
+
array_types = Array.new(flags.length, "Array<Float>")
|
82
|
+
"Array(#{array_types.join(", ")})"
|
83
|
+
when TALibFFI::TA_PARAM_TYPE[:TA_Input_Real]
|
84
|
+
"Array<Float>"
|
85
|
+
when TALibFFI::TA_PARAM_TYPE[:TA_Input_Integer]
|
86
|
+
"Array<Integer>"
|
87
|
+
end
|
88
|
+
|
89
|
+
description = if input["type"] == TALibFFI::TA_PARAM_TYPE[:TA_Input_Price]
|
90
|
+
arrays = flags.map do |flag|
|
91
|
+
{
|
92
|
+
TA_IN_PRICE_OPEN: "open",
|
93
|
+
TA_IN_PRICE_HIGH: "high",
|
94
|
+
TA_IN_PRICE_LOW: "low",
|
95
|
+
TA_IN_PRICE_CLOSE: "close",
|
96
|
+
TA_IN_PRICE_VOLUME: "volume",
|
97
|
+
TA_IN_PRICE_OPENINTEREST: "open interest",
|
98
|
+
TA_IN_PRICE_TIMESTAMP: "timestamp"
|
99
|
+
}[flag]
|
100
|
+
end
|
101
|
+
"Required price arrays: #{arrays.join(", ")}"
|
102
|
+
else
|
103
|
+
"Input values"
|
104
|
+
end
|
105
|
+
|
106
|
+
" # @param #{param_name} [#{type}] #{description}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def generate_optional_input_documentation(opt_inputs)
|
111
|
+
opt_inputs.map do |opt_input|
|
112
|
+
param_name = TALibFFI.normalize_parameter_name(opt_input["paramName"].to_s)
|
113
|
+
type = opt_input["type"] == TALibFFI::TA_PARAM_TYPE[:TA_OptInput_RealRange] ? "Float" : "Integer"
|
114
|
+
" # @param #{param_name} [#{type}] #{opt_input["hint"]} (default: #{opt_input["defaultValue"]})"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def generate_output_documentation(outputs) # rubocop:disable Metrics/MethodLength
|
119
|
+
if outputs.length == 1
|
120
|
+
type = outputs.first["type"] == TALibFFI::TA_PARAM_TYPE[:TA_Output_Real] ? "Float" : "Integer"
|
121
|
+
[" # @return [Array<#{type}>]"]
|
122
|
+
else
|
123
|
+
[
|
124
|
+
" # @return [Hash] Hash containing the following arrays:",
|
125
|
+
*outputs.map do |output|
|
126
|
+
param_name = TALibFFI.normalize_parameter_name(output["paramName"].to_s)
|
127
|
+
type = output["type"] == TALibFFI::TA_PARAM_TYPE[:TA_Output_Real] ? "Float" : "Integer"
|
128
|
+
" # @option result [Array<#{type}>] :#{param_name} Output values"
|
129
|
+
end
|
130
|
+
]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def generate_error_documentation
|
135
|
+
" # @raise [TALibError] If there is an error in function execution\n"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|