quantitative 0.1.3 → 0.1.5

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.
@@ -2,12 +2,12 @@
2
2
 
3
3
  module Quant
4
4
  module Ticks
5
- # +Tick+ is the abstract ancestor for all Ticks and holds the logic for interacting with series and indicators.
5
+ # {Quant::Ticks::Tick} is the abstract ancestor for all Ticks and holds the logic for interacting with series and indicators.
6
6
  # The public interface is devoid of properties around price, volume, and timestamp, etc. Descendant classes
7
7
  # are responsible for defining the properties and how they are represented.
8
8
  #
9
- # The +Tick+ class is designed to be immutable and is intended to be used as a value object. This means that
10
- # once a +Tick+ is created, it cannot be changed. This is important for the integrity of the series and
9
+ # The {Quant::Ticks::Tick} class is designed to be immutable and is intended to be used as a value object. This means that
10
+ # once a {Quant::Ticks::Tick} is created, it cannot be changed. This is important for the integrity of the series and
11
11
  # indicators that depend on the ticks within the series.
12
12
  #
13
13
  # When a tick is added to a series, it is locked into the series and ownership cannot be changed. This is important
@@ -17,7 +17,7 @@ module Quant
17
17
  #
18
18
  # Ticks can be serialized to and from Ruby Hash, JSON strings, and CSV strings.
19
19
  class Tick
20
- # Returns a +Tick+ from a Ruby +Hash+. The default serializer is used to generate the +Tick+.
20
+ # Returns a {Quant::Ticks::Tick} from a Ruby +Hash+. The default serializer is used to generate the {Quant::Ticks::Tick}.
21
21
  # @param hash [Hash]
22
22
  # @param serializer_class [Class] The serializer class to use for the conversion.
23
23
  # @return [Quant::Ticks::Tick]
@@ -25,11 +25,12 @@ module Quant
25
25
  # hash = { "timestamp" => "2018-01-01 12:00:00 UTC", "price" => 100.0, "volume" => 1000 }
26
26
  # Quant::Ticks::Tick.from(hash)
27
27
  # # => #<Quant::Ticks::Spot:0x00007f9e3b8b3e08 @timestamp=2018-01-01 12:00:00 UTC, @price=100.0, @volume=1000>
28
- def self.from(hash, serializer_class: default_serializer_class)
28
+ def self.from(hash, serializer_class: nil)
29
+ serializer_class ||= default_serializer_class
29
30
  serializer_class.from(hash, tick_class: self)
30
31
  end
31
32
 
32
- # Returns a +Tick+ from a JSON string. The default serializer is used to generate the +Tick+.
33
+ # Returns a {Quant::Ticks::Tick} from a JSON string. The default serializer is used to generate the {Quant::Ticks::Tick}.
33
34
  # @param json [String]
34
35
  # @param serializer_class [Class] The serializer class to use for the conversion.
35
36
  # @return [Quant::Ticks::Tick]
@@ -41,21 +42,33 @@ module Quant
41
42
  serializer_class.from_json(json, tick_class: self)
42
43
  end
43
44
 
44
- attr_reader :series
45
+ attr_reader :series, :indicators
45
46
 
46
47
  def initialize
47
48
  # Set the series by appending to the series or calling #assign_series method
48
49
  @series = nil
50
+ @interval = nil
51
+ @indicators = {}
52
+ end
53
+
54
+ def interval
55
+ @series&.interval || Interval[nil]
49
56
  end
50
57
 
51
58
  # Ticks always belong to the first series they're assigned so we can easily spin off
52
59
  # sub-sets or new series with the same ticks while allowing each series to have
53
60
  # its own state and full control over the ticks within its series
54
61
  def assign_series(new_series)
55
- assign_series!(new_series) if @series.nil?
62
+ assign_series!(new_series) unless series?
56
63
  self
57
64
  end
58
65
 
66
+ # Returns true if the tick is assigned to a series. The first series a tick is assigned
67
+ # to is the series against which the indicators compute.
68
+ def series?
69
+ !!@series
70
+ end
71
+
59
72
  # Ticks always belong to the first series they're assigned so we can easily spin off
60
73
  # sub-sets or new series with the same ticks. However, if you need to reassign the
61
74
  # series, you can use this method to force the change of series ownership.
@@ -63,7 +76,7 @@ module Quant
63
76
  # The series interval is also assigned to the tick if it is not already set.
64
77
  def assign_series!(new_series)
65
78
  @series = new_series
66
- @interval = new_series.interval if @interval.nil?
79
+ @interval ||= new_series.interval
67
80
  self
68
81
  end
69
82
 
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.3"
4
+ VERSION = "0.1.5"
5
5
  end
data/lib/quantitative.rb CHANGED
@@ -12,6 +12,6 @@ quant_folder = File.join(lib_folder, "quant")
12
12
  Dir.glob(File.join(quant_folder, "*.rb")).each { |fn| require fn }
13
13
 
14
14
  # require sub-folders and their sub-folders
15
- %w(refinements ticks).each do |sub_folder|
15
+ %w(refinements mixins settings ticks indicators).each do |sub_folder|
16
16
  Dir.glob(File.join(quant_folder, sub_folder, "**/*.rb")).each { |fn| require fn }
17
- end
17
+ 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.3
4
+ version: 0.1.5
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-15 00:00:00.000000000 Z
11
+ date: 2024-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -44,7 +44,18 @@ files:
44
44
  - LICENSE
45
45
  - README.md
46
46
  - Rakefile
47
+ - lib/quant/asset.rb
48
+ - lib/quant/asset_class.rb
49
+ - lib/quant/attributes.rb
50
+ - lib/quant/config.rb
47
51
  - lib/quant/errors.rb
52
+ - lib/quant/indicators.rb
53
+ - lib/quant/indicators/indicator.rb
54
+ - lib/quant/indicators/indicator_point.rb
55
+ - lib/quant/indicators/ma.rb
56
+ - lib/quant/indicators/ping.rb
57
+ - lib/quant/indicators_proxy.rb
58
+ - lib/quant/indicators_sources.rb
48
59
  - lib/quant/interval.rb
49
60
  - lib/quant/mixins/direction.rb
50
61
  - lib/quant/mixins/filters.rb
@@ -56,9 +67,9 @@ files:
56
67
  - lib/quant/mixins/trig.rb
57
68
  - lib/quant/mixins/weighted_average.rb
58
69
  - lib/quant/refinements/array.rb
59
- - lib/quant/security.rb
60
- - lib/quant/security_class.rb
61
70
  - lib/quant/series.rb
71
+ - lib/quant/settings.rb
72
+ - lib/quant/settings/indicators.rb
62
73
  - lib/quant/ticks/ohlc.rb
63
74
  - lib/quant/ticks/serializers/ohlc.rb
64
75
  - lib/quant/ticks/serializers/spot.rb
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "security_class"
4
-
5
- module Quant
6
- # A +Security+ is a representation of a financial instrument such as a stock, option, future, or currency.
7
- # It is used to represent the instrument that is being traded, analyzed, or managed.
8
- # @example
9
- # security = Quant::Security.new(symbol: "AAPL", name: "Apple Inc.", security_class: :stock, exchange: "NASDAQ")
10
- # security.symbol # => "AAPL"
11
- # security.name # => "Apple Inc."
12
- # security.stock? # => true
13
- # security.option? # => false
14
- # security.future? # => false
15
- # security.currency? # => false
16
- # security.exchange # => "NASDAQ"
17
- # security.to_h # => { "s" => "AAPL", "n" => "Apple Inc.", "sc" => "stock", "x" => "NASDAQ" }
18
- class Security
19
- attr_reader :symbol, :name, :security_class, :id, :exchange, :source, :meta, :created_at, :updated_at
20
-
21
- def initialize(
22
- symbol:,
23
- name: nil,
24
- id: nil,
25
- active: true,
26
- tradeable: true,
27
- exchange: nil,
28
- source: nil,
29
- security_class: nil,
30
- created_at: Quant.current_time,
31
- updated_at: Quant.current_time,
32
- meta: {}
33
- )
34
- raise ArgumentError, "symbol is required" unless symbol
35
-
36
- @symbol = symbol.to_s.upcase
37
- @name = name
38
- @id = id
39
- @tradeable = tradeable
40
- @active = active
41
- @exchange = exchange
42
- @source = source
43
- @security_class = SecurityClass.new(security_class)
44
- @created_at = created_at
45
- @updated_at = updated_at
46
- @meta = meta
47
- end
48
-
49
- def active?
50
- !!@active
51
- end
52
-
53
- def tradeable?
54
- !!@tradeable
55
- end
56
-
57
- SecurityClass::CLASSES.each do |class_name|
58
- define_method("#{class_name}?") do
59
- security_class == class_name
60
- end
61
- end
62
-
63
- def to_h(full: false)
64
- return { "s" => symbol } unless full
65
-
66
- { "s" => symbol,
67
- "n" => name,
68
- "id" => id,
69
- "t" => tradeable?,
70
- "a" => active?,
71
- "x" => exchange,
72
- "sc" => security_class.to_s,
73
- "src" => source.to_s }
74
- end
75
-
76
- def to_json(*args, full: false)
77
- Oj.dump(to_h(full: full), *args)
78
- end
79
- end
80
- end