quantitative 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c2f8345b245cd469b234752f2fb757a1006b6a04322412acbb3fc10bd759827
4
- data.tar.gz: fa5388e69c9f82fe686424dcfd81d8795ea6814a4b2b98b0edb6a52598ffbdaf
3
+ metadata.gz: 7491465248d383f459899467e14c9bafa16376f8fe7dc2cac657fca8a9170200
4
+ data.tar.gz: 956074c17983ee22d6480a176c48b0cc15257aaca2649086eacc71a52688cb12
5
5
  SHA512:
6
- metadata.gz: bb3c3cc8db589f5051d9dcd921fc1c01292897c440cfdb72c45df568051213ddd3fad5aa27e40652aff452619eefa835dcc4675120d050c9a46bbf34e83be3cc
7
- data.tar.gz: cfcc8acf5989103a9a59b84965b3d1d3eb1f3288737afa3636f684ea5f378e10d82f4bda5e487f9a1ddcb867abd0fb82cef4048219acac6ee98bcfd412124db5
6
+ metadata.gz: 0f932bc68ca6f3e47261aaf2d19b34465b0f242bc13b5935ab55c0eea0ee736b0ea183b4bacc6a99d9beecd9a2457dd07957a639bd2d85e35f0a5584b35c2f2a
7
+ data.tar.gz: c0baa0af0133cbdd46439fc0ce8d068a583f05688371025275afe4297d0bd01a7aad90c4f3ebae98afaa1a4b28b56e43fa2aa68aaafc018bd34e22ec037d1b07
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ inherit_gem:
2
2
  relaxed-rubocop: .rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 3.0
5
+ TargetRubyVersion: 3.2
6
6
  Exclude:
7
7
  - 'spec/performance/*.rb'
8
8
 
data/Gemfile CHANGED
@@ -18,3 +18,7 @@ gem "guard-rspec", "~> 4.7"
18
18
  gem "yard", "~> 0.9"
19
19
  gem "benchmark-ips", "~> 2.9"
20
20
 
21
+ gem 'rspec-github'
22
+ gem 'simplecov'
23
+ gem 'simplecov-cobertura'
24
+
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- quantitative (0.1.7)
4
+ quantitative (0.1.8)
5
5
  oj (~> 3.10)
6
6
 
7
7
  GEM
@@ -15,6 +15,7 @@ GEM
15
15
  irb (>= 1.5.0)
16
16
  reline (>= 0.3.1)
17
17
  diff-lcs (1.5.0)
18
+ docile (1.4.0)
18
19
  ffi (1.16.3)
19
20
  formatador (1.1.0)
20
21
  guard (2.18.1)
@@ -79,6 +80,8 @@ GEM
79
80
  rspec-expectations (3.12.3)
80
81
  diff-lcs (>= 1.2.0, < 2.0)
81
82
  rspec-support (~> 3.12.0)
83
+ rspec-github (2.4.0)
84
+ rspec-core (~> 3.0)
82
85
  rspec-mocks (3.12.6)
83
86
  diff-lcs (>= 1.2.0, < 2.0)
84
87
  rspec-support (~> 3.12.0)
@@ -106,6 +109,15 @@ GEM
106
109
  rubocop-factory_bot (~> 2.22)
107
110
  ruby-progressbar (1.13.0)
108
111
  shellany (0.0.1)
112
+ simplecov (0.22.0)
113
+ docile (~> 1.1)
114
+ simplecov-html (~> 0.11)
115
+ simplecov_json_formatter (~> 0.1)
116
+ simplecov-cobertura (2.1.0)
117
+ rexml
118
+ simplecov (~> 0.19)
119
+ simplecov-html (0.12.3)
120
+ simplecov_json_formatter (0.1.4)
109
121
  stringio (3.1.0)
110
122
  thor (1.3.0)
111
123
  unicode-display_width (2.5.0)
@@ -113,6 +125,7 @@ GEM
113
125
 
114
126
  PLATFORMS
115
127
  arm64-darwin-22
128
+ x86_64-linux
116
129
 
117
130
  DEPENDENCIES
118
131
  benchmark-ips (~> 2.9)
@@ -122,8 +135,11 @@ DEPENDENCIES
122
135
  rake (~> 13.0)
123
136
  relaxed-rubocop
124
137
  rspec (~> 3.0)
138
+ rspec-github
125
139
  rubocop (~> 1.21)
126
140
  rubocop-rspec
141
+ simplecov
142
+ simplecov-cobertura
127
143
  yard (~> 0.9)
128
144
 
129
145
  BUNDLED WITH
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Quantitative
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/quantitative.svg)](https://badge.fury.io/rb/quantitative)
3
+ [![Gem Version](https://badge.fury.io/rb/quantitative.svg)](https://badge.fury.io/rb/quantitative) [![codecov](https://codecov.io/gh/mwlang/quantitative/graph/badge.svg?token=ZXMSKQZKD5)](https://codecov.io/gh/mwlang/quantitative)
4
4
 
5
5
  STATUS: ALPHA - very early stages! The framework is very much a work in progress and I am rapidly introducing new things and changing existing things around.
6
6
 
7
- Quantitative is a statistical and quantitative library for Ruby 3.x for trading stocks, cryptocurrency, and forex. It provides a number of classes and modules for working with time-series data, financial data, and other quantitative data. It is designed to be fast, efficient, and easy to use.
7
+ Quantitative is a statistical and quantitative library for Ruby 3.2+ for trading stocks, cryptocurrency, and forex. It provides a number of classes and modules for working with time-series data, financial data, and other quantitative data. It is designed to be fast, efficient, and easy to use.
8
8
 
9
9
  It has been highly optimized for fairly high-frequency trading purely in Ruby (no external numerical/statistical native extensions). The one exception is that I opted to depend on `Oj` which is a high-performant JSON parser that greatly speeds up serializing data between disk and memory. In practice, Quantitative is performant enough to trade one minute tickers on down to 30 second ticks for around 100 or so ticker symbols. Trading anything lower depends on the amount of analysis you're doing and your mileage may vary. It is possible, but you will find yourself with tradeoffs between the amount of data you can crunch and how fast you can react to live trading situations.
10
10
 
@@ -46,6 +46,18 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
46
46
 
47
47
  Bug reports and pull requests are welcome on GitHub at https://github.com/mwlang/quantitative. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/mwlang/quantitative/blob/main/CODE_OF_CONDUCT.md).
48
48
 
49
+ The Relaxed Ruby Style Guide is adopted for RuboCop.
50
+
51
+ ### Keeping Test Coverage High
52
+
53
+ TDD/BDD is fully embraced for this project. If you opt to contribute, please include tests to coverage new features and behavior tests.
54
+
55
+ RSpec is the test framework. SimpleCov is used for coverage reports.
56
+
57
+ ### Test Driven / Behavior Driven development Coverage Map:
58
+
59
+ ![Coverage Map](https://codecov.io/gh/mwlang/quantitative/graphs/sunburst.svg?token=ZXMSKQZKD5)
60
+
49
61
  ## License
50
62
 
51
63
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/lib/quant/asset.rb CHANGED
@@ -82,7 +82,7 @@ module Quant
82
82
  end
83
83
 
84
84
  def to_json(*args, full: false)
85
- Oj.dump(to_h(full: full), *args)
85
+ Oj.dump(to_h(full:), *args)
86
86
  end
87
87
  end
88
88
  end
@@ -93,7 +93,7 @@ module Quant
93
93
  end
94
94
 
95
95
  registry[klass] ||= {}
96
- registry[klass][name] = { key: key, default: default }
96
+ registry[klass][name] = { key:, default: }
97
97
  end
98
98
 
99
99
  module InstanceMethods
@@ -138,7 +138,7 @@ module Quant
138
138
  if entry[:default].is_a?(Symbol) && respond_to?(entry[:default])
139
139
  send(entry[:default])
140
140
 
141
- elsif entry[:default].is_a?(Symbol) && current_tick&.respond_to?(entry[:default])
141
+ elsif entry[:default].is_a?(Symbol) && current_tick.respond_to?(entry[:default])
142
142
  current_tick.send(entry[:default])
143
143
 
144
144
  elsif entry[:default].is_a?(Proc)
@@ -5,6 +5,7 @@ module Quant
5
5
  class Indicator
6
6
  include Enumerable
7
7
  include Mixins::Functions
8
+ include Mixins::Filters
8
9
  include Mixins::MovingAverages
9
10
  # include Mixins::HilbertTransform
10
11
  # include Mixins::SuperSmoother
@@ -44,7 +45,7 @@ module Quant
44
45
 
45
46
  def <<(tick)
46
47
  @t0 = tick
47
- @p0 = points_class.new(tick: tick, source: source)
48
+ @p0 = points_class.new(tick:, source:)
48
49
  @points[tick] = @p0
49
50
 
50
51
  @p1 = values[-2] || @p0
@@ -6,6 +6,7 @@ module Quant
6
6
  include Quant::Attributes
7
7
 
8
8
  attr_reader :tick
9
+
9
10
  attribute :source, key: "src"
10
11
  attribute :input, key: "in"
11
12
 
@@ -25,7 +25,7 @@ module Quant
25
25
  # prepared, the indicator becomes active and all ticks pushed into the series
26
26
  # are sent to the indicator for processing.
27
27
  def indicator(indicator_class)
28
- indicators[indicator_class] ||= indicator_class.new(series: series, source: source)
28
+ indicators[indicator_class] ||= indicator_class.new(series:, source:)
29
29
  end
30
30
 
31
31
  # Adds the tick to all active indicators, triggering them to compute
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Quant
4
+ module Mixins
5
+ module ButterworthFilters
6
+ def two_pole_butterworth(source, period:, previous: :bw)
7
+ raise ArgumentError, "source must be a Symbol" unless source.is_a?(Symbol)
8
+
9
+ v0 = p0.send(source)
10
+
11
+ v1 = 0.5 * (v0 + p1.send(source))
12
+ v2 = p1.send(previous)
13
+ v3 = p2.send(previous)
14
+
15
+ radians = Math.sqrt(2) * Math::PI / period
16
+ a = Math.exp(-radians)
17
+ b = 2 * a * Math.cos(radians)
18
+
19
+ c2 = b
20
+ c3 = -a**2
21
+ c1 = 1.0 - c2 - c3
22
+
23
+ (c1 * v1) + (c2 * v2) + (c3 * v3)
24
+ end
25
+
26
+ def three_pole_butterworth(source, period:, previous: :bw)
27
+ raise ArgumentError, "source must be a Symbol" unless source.is_a?(Symbol)
28
+
29
+ v0 = p0.send(source)
30
+ v1 = p1.send(previous)
31
+ v2 = p2.send(previous)
32
+ v3 = p3.send(previous)
33
+
34
+ radians = Math.sqrt(3) * Math::PI / period
35
+ a = Math.exp(-radians)
36
+ b = 2 * a * Math.cos(radians)
37
+ c = a**2
38
+
39
+ d4 = c**2
40
+ d3 = -(c + (b * c))
41
+ d2 = b + c
42
+ d1 = 1.0 - d2 - d3 - d4
43
+
44
+ (d1 * v0) + (d2 * v1) + (d3 * v2) + (d4 * v3)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -27,7 +27,7 @@ module Quant
27
27
  raise ArgumentError, "previous must be a Symbol" unless previous.is_a?(Symbol)
28
28
 
29
29
  alpha = bars_to_alpha(period)
30
- p0.send(source) * alpha + p1.send(previous) * (1.0 - alpha)
30
+ (p0.send(source) * alpha) + (p1.send(previous) * (1.0 - alpha))
31
31
  end
32
32
  alias ema exponential_moving_average
33
33
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "functions"
4
-
5
3
  module Quant
6
4
  module Mixins
7
5
  # 1. All the common filters useful for traders have a transfer response
@@ -47,55 +45,7 @@ module Quant
47
45
  # Band-stop (1+σ)/2 -2λ*(1+σ)/2 (1+σ)/2 1 -λ*(1+σ) σ
48
46
  #
49
47
  module Filters
50
- include Mixins::Functions
51
-
52
- def ema(source, prev_source, period)
53
- alpha = bars_to_alpha(period)
54
- v0 = source.is_a?(Symbol) ? p0.send(source) : source
55
- v1 = p1.send(prev_source)
56
- (v0 * alpha) + (v1 * (1 - alpha))
57
- end
58
-
59
- def band_pass(source, prev_source, period, bandwidth); end
60
-
61
- def two_pole_butterworth(source, prev_source, period)
62
- v0 = source.is_a?(Symbol) ? p0.send(source) : source
63
-
64
- v1 = 0.5 * (v0 + p1.send(source))
65
- v2 = p1.send(prev_source)
66
- v3 = p2.send(prev_source)
67
-
68
- radians = Math.sqrt(2) * Math::PI / period
69
- a = Math.exp(-radians)
70
- b = 2 * a * Math.cos(radians)
71
-
72
- c2 = b
73
- c3 = -a**2
74
- c1 = 1.0 - c2 - c3
75
-
76
- (c1 * v1) + (c2 * v2) + (c3 * v3)
77
- end
78
-
79
- def three_pole_butterworth(source, prev_source, period)
80
- v0 = source.is_a?(Symbol) ? p0.send(source) : source
81
- return v0 if p2 == p3
82
-
83
- v1 = p1.send(prev_source)
84
- v2 = p2.send(prev_source)
85
- v3 = p3.send(prev_source)
86
-
87
- radians = Math.sqrt(3) * Math::PI / period
88
- a = Math.exp(-radians)
89
- b = 2 * a * Math.cos(radians)
90
- c = a**2
91
-
92
- d4 = c**2
93
- d3 = -(c + (b * c))
94
- d2 = b + c
95
- d1 = 1.0 - d2 - d3 - d4
96
-
97
- (d1 * v0) + (d2 * v1) + (d3 * v2) + (d4 * v3)
98
- end
48
+ include Mixins::ButterworthFilters
99
49
  end
100
50
  end
101
51
  end
@@ -3,36 +3,45 @@
3
3
  module Quant
4
4
  module Mixins
5
5
  # Fisher Transforms
6
- # • Price is not a Gaussian (Bell Curve) distribution, even though many technical analysis formulas
7
- # falsely assume that it is. Bell Curve tails are missing.
8
- # If $10 stock were Gaussian, it could go up or down $20 – Standard deviation based indicators like Bollinger Bands
9
- # and zScore make the Gaussian assumption error
10
- # TheFisher Transform converts almost any probability distribution in a Gaussian-like one
11
- # Expands the distribution and creates tails
12
- # • The Inverse Fisher Transform converts almost any probability distribution into a square wave
13
- # Compresses, removes low amplitude variations
6
+ # • Price is not a Gaussian (Bell Curve) distribution, even though many
7
+ # technical analysis formulas falsely assume that it is. Bell Curve tails
8
+ # are missing.
9
+ # If $10 stock were Gaussian, it could go up or down $20
10
+ # Standard deviation based indicators like Bollinger Bands
11
+ # and zScore make the Gaussian assumption error
12
+ #
13
+ # TheFisher Transform converts almost any probability distribution
14
+ # in a Gaussian-like one
15
+ # – Expands the distribution and creates tails
16
+ #
17
+ # • The Inverse Fisher Transform converts almost any probability
18
+ # distribution into a square wave
19
+ # – Compresses, removes low amplitude variations
14
20
  module FisherTransform
15
21
  # inverse fisher transform
16
22
  # https://www.mql5.com/en/articles/303
17
- def ift(value, scale_factor = 1.0)
23
+ def inverse_fisher_transform(value, scale_factor: 1.0)
18
24
  r = (Math.exp(2.0 * scale_factor * value) - 1.0) / (Math.exp(2.0 * scale_factor * value) + 1.0)
19
25
  r.nan? ? 0.0 : r
20
26
  end
27
+ alias ift inverse_fisher_transform
21
28
 
22
- # def fisher_transform(value, max_value)
23
- # return 0.0 if max_value.zero?
24
- # x = (value / max_value).abs
25
- # r = 0.5 * Math.log((1 + x) / (1 - x))
26
- # r.nan? ? 0.0 : r
27
- # end
29
+ def relative_fisher_transform(value, max_value:)
30
+ max_value.zero? ? 0.0 : fisher_transform(value / max_value)
31
+ end
32
+ alias rft relative_fisher_transform
28
33
 
29
34
  # The absolute value passed must be < 1.0
30
35
  def fisher_transform(value)
31
- r = 0.5 * Math.log((1.0 + value) / (1.0 - value))
32
- r.nan? ? 0.0 : r
36
+ raise ArgumentError, "value (#{value}) must be between -1.0 and 1.0" unless value.abs <= 1.0
37
+
38
+ result = 0.5 * Math.log((1.0 + value) / (1.0 - value))
39
+ result.nan? ? 0.0 : result
33
40
  rescue Math::DomainError => e
34
- raise "value #{value}: #{(1 + value) / (1 - value)}, e: #{e}"
41
+ raise Math::DomainError, "#{e.message}: cannot take the Log of #{value}: #{(1 + value) / (1 - value)}"
35
42
  end
43
+ alias fisher fisher_transform
44
+ alias ft fisher_transform
36
45
  end
37
46
  end
38
47
  end
@@ -3,11 +3,11 @@
3
3
  module Quant
4
4
  module Mixins
5
5
  module HilbertTransform
6
- def hilbert_transform(source, period = p1.period)
6
+ def hilbert_transform(source, period:)
7
7
  [0.0962 * p0.send(source),
8
8
  0.5769 * p2.send(source),
9
- -0.5769 * prev(4).send(source),
10
- -0.0962 * prev(6).send(source),].sum * ((0.075 * period) + 0.54)
9
+ -0.5769 * p(4).send(source),
10
+ -0.0962 * p(6).send(source),].sum * ((0.075 * period) + 0.54)
11
11
  end
12
12
  end
13
13
  end
@@ -13,7 +13,7 @@ module Quant
13
13
  coef3 = -a1 * a1
14
14
  coef1 = 1.0 - coef2 - coef3
15
15
 
16
- v0 = (p0.send(source) + p1.send(source))/2.0
16
+ v0 = (p0.send(source) + p1.send(source)) / 2.0
17
17
  v1 = p2.send(previous)
18
18
  v2 = p3.send(previous)
19
19
  ((coef1 * v0) + (coef2 * v1) + (coef3 * v2)).to_f
@@ -17,7 +17,7 @@ module Quant
17
17
  [4.0 * p0.send(source),
18
18
  3.0 * p1.send(source),
19
19
  2.0 * p2.send(source),
20
- p3.send(source)].sum / 10.0
20
+ p3.send(source)].sum / 10.0
21
21
  end
22
22
  alias wma weighted_moving_average
23
23
 
@@ -37,7 +37,7 @@ module Quant
37
37
  4.0 * p3.send(source),
38
38
  3.0 * p(4).send(source),
39
39
  2.0 * p(5).send(source),
40
- p(6).send(source)].sum / 28.0
40
+ p(6).send(source)].sum / 28.0
41
41
  end
42
42
  alias ewma extended_weighted_moving_average
43
43
  end
@@ -176,7 +176,7 @@ module Quant
176
176
  # @param n [Integer] the number of elements to compute the Standard Deviation over.
177
177
  # @return [Float]
178
178
  def stddev(reference_value, n: size)
179
- variance(reference_value, n: n)**0.5
179
+ variance(reference_value, n:)**0.5
180
180
  end
181
181
 
182
182
  def variance(reference_value, n: size)
data/lib/quant/series.rb CHANGED
@@ -19,7 +19,7 @@ module Quant
19
19
  raise "File #{filename} does not exist" unless File.exist?(filename)
20
20
 
21
21
  ticks = File.read(filename).split("\n").map{ |line| Oj.load(line) }
22
- from_hash symbol: symbol, interval: interval, hash: ticks, serializer_class: serializer_class
22
+ from_hash symbol:, interval:, hash: ticks, serializer_class:
23
23
  end
24
24
 
25
25
  # Loads a series of ticks when the JSON string represents an array of ticks.
@@ -29,8 +29,8 @@ module Quant
29
29
  # @param json [String] The JSON string to parse into ticks.
30
30
  # @param serializer_class [Class] {Quant::Ticks::TickSerializer} class to use for the conversion.
31
31
  def self.from_json(symbol:, interval:, json:, serializer_class: nil)
32
- ticks = Oj.load(json)
33
- from_hash symbol: symbol, interval: interval, hash: ticks, serializer_class: serializer_class
32
+ hash = Oj.load(json)
33
+ from_hash symbol:, interval:, hash:, serializer_class:
34
34
  end
35
35
 
36
36
  # Loads a series of ticks where the hash must be cast to an array of {Quant::Ticks::Tick} objects.
@@ -39,15 +39,15 @@ module Quant
39
39
  # @param hash [Array<Hash>] The array of hashes to convert to {Quant::Ticks::Tick} objects.
40
40
  # @param serializer_class [Class] {Quant::Ticks::TickSerializer} class to use for the conversion.
41
41
  def self.from_hash(symbol:, interval:, hash:, serializer_class: nil)
42
- ticks = hash.map { |tick_hash| Quant::Ticks::OHLC.from(tick_hash, serializer_class: serializer_class) }
43
- from_ticks symbol: symbol, interval: interval, ticks: ticks
42
+ ticks = hash.map { |tick_hash| Quant::Ticks::OHLC.from(tick_hash, serializer_class:) }
43
+ from_ticks symbol:, interval:, ticks:
44
44
  end
45
45
 
46
46
  # Loads a series of ticks where the array represents an array of {Quant::Ticks::Tick} objects.
47
47
  def self.from_ticks(symbol:, interval:, ticks:)
48
48
  ticks = ticks.sort_by(&:close_timestamp)
49
49
 
50
- new(symbol: symbol, interval: interval).tap do |series|
50
+ new(symbol:, interval:).tap do |series|
51
51
  ticks.each { |tick| series << tick }
52
52
  end
53
53
  end
@@ -64,14 +64,14 @@ module Quant
64
64
  selected_ticks = ticks[start_iteration..stop_iteration]
65
65
  return self if selected_ticks.size == ticks.size
66
66
 
67
- self.class.from_ticks(symbol: symbol, interval: interval, ticks: selected_ticks)
67
+ self.class.from_ticks(symbol:, interval:, ticks: selected_ticks)
68
68
  end
69
69
 
70
70
  def limit(period)
71
71
  selected_ticks = ticks.select{ |tick| period.cover?(tick.close_timestamp) }
72
72
  return self if selected_ticks.size == ticks.size
73
73
 
74
- self.class.from_ticks(symbol: symbol, interval: interval, ticks: selected_ticks)
74
+ self.class.from_ticks(symbol:, interval:, ticks: selected_ticks)
75
75
  end
76
76
 
77
77
  def_delegator :@ticks, :[]
@@ -94,7 +94,7 @@ module Quant
94
94
  end
95
95
 
96
96
  def dup
97
- self.class.from_ticks(symbol: symbol, interval: interval, ticks: ticks)
97
+ self.class.from_ticks(symbol:, interval:, ticks:)
98
98
  end
99
99
 
100
100
  def inspect
@@ -3,7 +3,7 @@
3
3
  module Quant
4
4
  module Ticks
5
5
  module Serializers
6
- module OHLC
6
+ class OHLC < Tick
7
7
  # Returns a +Quant::Ticks::Tick+ from a valid JSON +String+.
8
8
  # @param json [String]
9
9
  # @param tick_class [Quant::Ticks::Tick]
@@ -13,7 +13,7 @@ module Quant
13
13
  # Quant::Ticks::Serializers::Tick.from_json(json, tick_class: Quant::Ticks::Spot)
14
14
  def self.from_json(json, tick_class:)
15
15
  hash = Oj.load(json)
16
- from(hash, tick_class: tick_class)
16
+ from(hash, tick_class:)
17
17
  end
18
18
 
19
19
  # Instantiates a tick from a +Hash+. The hash keys are expected to be the same as the serialized keys.
@@ -13,7 +13,7 @@ module Quant
13
13
  # Quant::Ticks::Serializers::Tick.from_json(json, tick_class: Quant::Ticks::Spot)
14
14
  def self.from_json(json, tick_class:)
15
15
  hash = Oj.load(json)
16
- from(hash, tick_class: tick_class)
16
+ from(hash, tick_class:)
17
17
  end
18
18
 
19
19
  # Returns a +Hash+ of the Spot tick's key properties
@@ -69,7 +69,7 @@ module Quant
69
69
  # Quant::Ticks::Serializers::Tick.from_json(json, tick_class: Quant::Ticks::Spot)
70
70
  def self.from_json(json, tick_class:)
71
71
  hash = Oj.load(json)
72
- from(hash, tick_class: tick_class)
72
+ from(hash, tick_class:)
73
73
  end
74
74
  end
75
75
  end
@@ -120,7 +120,7 @@ module Quant
120
120
  # tick.to_csv(headers: true)
121
121
  # # => "timestamp,price,volume\n2018-01-01 12:00:00 UTC,100.0,1000\n"
122
122
  def to_csv(serializer_class: default_serializer_class, headers: false)
123
- serializer_class.to_csv(self, headers: headers)
123
+ serializer_class.to_csv(self, headers:)
124
124
  end
125
125
 
126
126
  # Reflects the serializer class from the tick's class name.
@@ -72,7 +72,7 @@ module Quant
72
72
  end
73
73
 
74
74
  def to_h
75
- { start_at: start_at, end_at: end_at }
75
+ { start_at:, end_at: }
76
76
  end
77
77
  end
78
78
  end
data/lib/quant/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quant
4
- VERSION = "0.1.7"
4
+ VERSION = "0.1.8"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quantitative
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Lang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-26 00:00:00.000000000 Z
11
+ date: 2024-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -24,8 +24,8 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.10'
27
- description: Quantitative and statistical tools written for Ruby 3.x for trading and
28
- finance.
27
+ description: Quantitative and statistical tools written for Ruby 3.2+ for trading
28
+ and finance.
29
29
  email:
30
30
  - mwlang@cybrains.net
31
31
  executables: []
@@ -57,6 +57,7 @@ files:
57
57
  - lib/quant/indicators_proxy.rb
58
58
  - lib/quant/indicators_sources.rb
59
59
  - lib/quant/interval.rb
60
+ - lib/quant/mixins/butterworth_filters.rb
60
61
  - lib/quant/mixins/direction.rb
61
62
  - lib/quant/mixins/exponential_moving_average.rb
62
63
  - lib/quant/mixins/filters.rb
@@ -99,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
100
  requirements:
100
101
  - - ">="
101
102
  - !ruby/object:Gem::Version
102
- version: 3.0.0
103
+ version: '3.2'
103
104
  required_rubygems_version: !ruby/object:Gem::Requirement
104
105
  requirements:
105
106
  - - ">="
@@ -109,5 +110,6 @@ requirements: []
109
110
  rubygems_version: 3.5.6
110
111
  signing_key:
111
112
  specification_version: 4
112
- summary: Quantitative and statistical tools written for Ruby 3.x for trading and finance.
113
+ summary: Quantitative and statistical tools written for Ruby 3.2+ for trading and
114
+ finance.
113
115
  test_files: []