Class: Quant::Series

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/quant/series.rb

Overview

Ticks belong to the first series they’re associated with always. There are no provisions for series merging their ticks to one series! Indicators will be computed against the parent series of a list of ticks, so we can safely work with subsets of a series and indicators will compute just once.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(symbol:, interval:) ⇒ Series

Returns a new instance of Series.



57
58
59
60
61
# File 'lib/quant/series.rb', line 57

def initialize(symbol:, interval:)
  @symbol = symbol
  @interval = Interval[interval]
  @ticks = []
end

Instance Attribute Details

#intervalObject (readonly)

Returns the value of attribute interval.



55
56
57
# File 'lib/quant/series.rb', line 55

def interval
  @interval
end

#symbolObject (readonly)

Returns the value of attribute symbol.



55
56
57
# File 'lib/quant/series.rb', line 55

def symbol
  @symbol
end

#ticksObject (readonly)

Returns the value of attribute ticks.



55
56
57
# File 'lib/quant/series.rb', line 55

def ticks
  @ticks
end

Class Method Details

.from_file(filename:, symbol:, interval:, serializer_class: nil) ⇒ Object

Loads a series of ticks when each line is a parsible JSON string that represents a tick. A Ticks::TickSerializer may be passed to convert the parsed JSON to Ticks::Tick object.

Parameters:

  • filename (String)

    The filename to load the ticks from.

  • symbol (String)

    The symbol of the series.

  • interval (String)

    The interval of the series.

  • serializer_class (Class) (defaults to: nil)

    Ticks::TickSerializer class to use for the conversion.



18
19
20
21
22
23
# File 'lib/quant/series.rb', line 18

def self.from_file(filename:, symbol:, interval:, serializer_class: nil)
  raise "File #{filename} does not exist" unless File.exist?(filename)

  ticks = File.read(filename).split("\n").map{ |line| Oj.load(line) }
  from_hash symbol:, interval:, hash: ticks, serializer_class:
end

.from_hash(symbol:, interval:, hash:, serializer_class: nil) ⇒ Object

Loads a series of ticks where the hash must be cast to an array of Ticks::Tick objects.

Parameters:

  • symbol (String)

    The symbol of the series.

  • interval (String)

    The interval of the series.

  • hash (Array<Hash>)

    The array of hashes to convert to Ticks::Tick objects.

  • serializer_class (Class) (defaults to: nil)

    Ticks::TickSerializer class to use for the conversion.



41
42
43
44
# File 'lib/quant/series.rb', line 41

def self.from_hash(symbol:, interval:, hash:, serializer_class: nil)
  ticks = hash.map { |tick_hash| Quant::Ticks::OHLC.from(tick_hash, serializer_class:) }
  from_ticks symbol:, interval:, ticks:
end

.from_json(symbol:, interval:, json:, serializer_class: nil) ⇒ Object

Loads a series of ticks when the JSON string represents an array of ticks. A Ticks::TickSerializer may be passed to convert the parsed JSON to Ticks::Tick object.

Parameters:

  • symbol (String)

    The symbol of the series.

  • interval (String)

    The interval of the series.

  • json (String)

    The JSON string to parse into ticks.

  • serializer_class (Class) (defaults to: nil)

    Ticks::TickSerializer class to use for the conversion.



31
32
33
34
# File 'lib/quant/series.rb', line 31

def self.from_json(symbol:, interval:, json:, serializer_class: nil)
  hash = Oj.load(json)
  from_hash symbol:, interval:, hash:, serializer_class:
end

.from_ticks(symbol:, interval:, ticks:) ⇒ Object

Loads a series of ticks where the array represents an array of Ticks::Tick objects.



47
48
49
50
51
52
53
# File 'lib/quant/series.rb', line 47

def self.from_ticks(symbol:, interval:, ticks:)
  ticks = ticks.sort_by(&:close_timestamp)

  new(symbol:, interval:).tap do |series|
    ticks.each { |tick| series << tick }
  end
end

Instance Method Details

#<<(tick) ⇒ Object



107
108
109
110
111
112
# File 'lib/quant/series.rb', line 107

def <<(tick)
  tick = Ticks::Spot.new(price: tick) if tick.is_a?(Numeric)
  indicators << tick unless tick.series?
  @ticks << tick.assign_series(self)
  self
end

#==(other) ⇒ Object



95
96
97
# File 'lib/quant/series.rb', line 95

def ==(other)
  [symbol, interval, ticks] == [other.symbol, other.interval, other.ticks]
end

#build_limited_series(selected_ticks) ⇒ Object



63
64
65
66
67
# File 'lib/quant/series.rb', line 63

def build_limited_series(selected_ticks)
  return self if selected_ticks.size == ticks.size

  self.class.from_ticks(symbol:, interval:, ticks: selected_ticks)
end

#dupObject



99
100
101
# File 'lib/quant/series.rb', line 99

def dup
  self.class.from_ticks(symbol:, interval:, ticks:)
end

#highestObject



87
88
89
# File 'lib/quant/series.rb', line 87

def highest
  ticks.max_by(&:high_price)
end

#indicatorsObject



114
115
116
# File 'lib/quant/series.rb', line 114

def indicators
  @indicators ||= IndicatorsSources.new(series: self)
end

#inspectObject



103
104
105
# File 'lib/quant/series.rb', line 103

def inspect
  "#<#{self.class.name} symbol=#{symbol} interval=#{interval} ticks=#{ticks.size}>"
end

#limit(period) ⇒ Object



74
75
76
77
# File 'lib/quant/series.rb', line 74

def limit(period)
  selected_ticks = ticks.select{ |tick| period.cover?(tick.close_timestamp) }
  build_limited_series selected_ticks
end

#limit_iterations(start_iteration, stop_iteration) ⇒ Object



69
70
71
72
# File 'lib/quant/series.rb', line 69

def limit_iterations(start_iteration, stop_iteration)
  selected_ticks = ticks[start_iteration..stop_iteration]
  build_limited_series selected_ticks
end

#lowestObject



91
92
93
# File 'lib/quant/series.rb', line 91

def lowest
  ticks.min_by(&:low_price)
end

#to_hObject



118
119
120
121
122
# File 'lib/quant/series.rb', line 118

def to_h
  { "symbol" => symbol,
    "interval" => interval.to_s,
    "ticks" => ticks.map(&:to_h) }
end

#to_json(*args) ⇒ Object



124
125
126
# File 'lib/quant/series.rb', line 124

def to_json(*args)
  Oj.dump(to_h, *args)
end