quantitative 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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