Class: Cotcube::Level::EOD_Stencil
- Inherits:
-
Object
- Object
- Cotcube::Level::EOD_Stencil
- Defined in:
- lib/cotcube-level/eod_stencil.rb
Instance Attribute Summary collapse
-
#base ⇒ Object
Returns the value of attribute base.
-
#interval ⇒ Object
readonly
Returns the value of attribute interval.
Class Method Summary collapse
-
.provide_raw_stencil(type:, interval: :daily, version: nil, timezone: Cotcube::Helpers::CHICAGO) ⇒ Object
Class method that loads the (latest) obligatory stencil for given interval and type.
Instance Method Summary collapse
- #apply(to:) ⇒ Object
- #dup ⇒ Object
- #index(offset = 0) ⇒ Object
-
#initialize(range: nil, interval:, swap_type:, date: nil, debug: false, version: nil, timezone: Cotcube::Helpers::CHICAGO, stencil: nil, warnings: true) ⇒ EOD_Stencil
constructor
A new instance of EOD_Stencil.
- #use(with:, sym:, zero: nil, grace: -2)) ⇒ Object
- #zero ⇒ Object
Constructor Details
#initialize(range: nil, interval:, swap_type:, date: nil, debug: false, version: nil, timezone: Cotcube::Helpers::CHICAGO, stencil: nil, warnings: true) ⇒ EOD_Stencil
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/cotcube-level/eod_stencil.rb', line 42 def initialize( range: nil, # used to shrink the stencil size, accepts String or Date interval:, swap_type:, date: nil, debug: false, version: nil, # when referring to a specicic version of the stencil timezone: Cotcube::Helpers::CHICAGO, stencil: nil, # instead of preparing, use this one if set warnings: true # be more quiet ) @debug = debug @interval = interval == :continuous ? :daily : interval @swap_type = swap_type @warnings = warnings step = case @interval when :hours, :hour; 1.hour when :quarters, :quarter; 15.minutes else; 1.day end case @interval when :day, :days, :daily, :dailies, :synth, :synthetic #, :week, :weeks, :month, :months unless range.nil? starter = range.begin.is_a?(String) ? timezone.parse(range.begin) : range.begin ender = range. end.is_a?(String) ? timezone.parse(range. end) : range. end end stencil_type = case swap_type when :rth :full when :rthc :rtc else swap_type end # TODO: Check / warn / raise whether stencil (if provided) is a proper data type raise ArgumentError, "EOD_Stencil should be nil or Array" unless [NilClass, Array].include? stencil.class raise ArgumentError, "Each stencil members should contain at least :datetime and :x" unless stencil.nil? or stencil.map{|x| ([:datetime, :x] - x.keys).empty? and [ActiveSupport::TimeWithZone, Day].include?( x[:datetime] ) and x[:x].is_a?(Integer)}.reduce(:&) base = stencil || EOD_Stencil.provide_raw_stencil(type: stencil_type, interval: :daily, version: version, timezone: timezone) # fast rewind to previous trading day date = timezone.parse(date) unless [NilClass, Date, ActiveSupport::TimeWithZone].include? date.class @date = date || Date.today best_match = base.select{|x| x[:datetime].to_date <= @date}.last[:datetime] @date = best_match offset = base.map{|x| x[:datetime]}.index(@date) # apply offset to stencil, so zero will match today (or what was provided as 'date') @base = base.map. each_with_index{|d,i| d[:x] = (offset - i).freeze; d } # if range was given, shrink stencil to specified range @base.select!{|d| (d[:datetime] >= starter and d[:datetime] <= ender) } unless range.nil? else raise RuntimeError, "'interval: #{interval}' was provided, what does not match anything this tool can handle (currently :days, :dailies, :synthetic)." end end |
Instance Attribute Details
#base ⇒ Object
Returns the value of attribute base.
7 8 9 |
# File 'lib/cotcube-level/eod_stencil.rb', line 7 def base @base end |
#interval ⇒ Object (readonly)
Returns the value of attribute interval.
8 9 10 |
# File 'lib/cotcube-level/eod_stencil.rb', line 8 def interval @interval end |
Class Method Details
.provide_raw_stencil(type:, interval: :daily, version: nil, timezone: Cotcube::Helpers::CHICAGO) ⇒ Object
Class method that loads the (latest) obligatory stencil for given interval and type. These raw stencils are located in /var/cotcube/level/stencils
Current daily stencils contain dates from 2020-01-01 to 2023-12-31
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/cotcube-level/eod_stencil.rb', line 16 def self.provide_raw_stencil(type:, interval: :daily, version: nil, timezone: Cotcube::Helpers::CHICAGO) loading = lambda do |typ| file_base = "/var/cotcube/level/stencils/stencil_#{interval.to_s}_#{typ.to_s}.csv_" if Dir["#{file_base}?*"].empty? raise ArgumentError, "Could not find any stencil matching interval #{interval} and type #{typ}. Check #{file_base} manually!" end if version.nil? # use latest available version if not given file = Dir["#{file_base}?*"].sort.last else file = "#{file_base}#{version}" unless File.exist? file raise ArgumentError, "Cannot open stencil from non-existant file #{file}." end end CSV.read(file).map{|x| { datetime: timezone.parse(x.first).freeze, x: x.last.to_i.freeze } } end unless const_defined? :RAW_STENCILS const_set :RAW_STENCILS, { daily: { full: loading.call( :full).freeze, rtc: loading.call( :rtc).freeze }.freeze }.freeze end RAW_STENCILS[interval][type].map{|x| x.dup} end |
Instance Method Details
#apply(to:) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/cotcube-level/eod_stencil.rb', line 122 def apply(to: ) offset = 0 @base.each_index do |i| begin offset += 1 while to[i+offset][:datetime].to_date < @base[i][:datetime].to_date rescue # appending to << @base[i] next end if to[i+offset][:datetime].to_date > @base[i][:datetime].to_date # skipping offset -= 1 next end # merging to[i+offset][:x] = @base[i][:x] end # finally remove all bars that do not belong to the stencil (i.e. holidays) to.reject!{|x| x[:x].nil? } end |
#dup ⇒ Object
103 104 105 106 107 108 109 110 111 |
# File 'lib/cotcube-level/eod_stencil.rb', line 103 def dup EOD_Stencil.new( debug: @debug, interval: @interval, swap_type: @swap_type, date: @date, stencil: @base.map{|x| x.dup} ) end |
#index(offset = 0) ⇒ Object
117 118 119 120 |
# File 'lib/cotcube-level/eod_stencil.rb', line 117 def index(offset = 0) @index ||= @base.index{|b| b[:x].zero? } @base[@index + offset] end |
#use(with:, sym:, zero: nil, grace: -2)) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/cotcube-level/eod_stencil.rb', line 144 def use(with:, sym:, zero: nil, grace: -2) # todo: validate with (check if vslid swap # sym (check keys) # zero (ohlc with x.zero?) # side ( upper or lower) swap = with.dup high = swap[:side] == :upper ohlc = high ? :high : :low start = base.find{|x| swap[:datetime] == x[:datetime]} swap[:current_change] = (swap[:tpi] * start[:x]).round(8) swap[:current_value] = swap[:members].last[ ohlc ] + swap[:current_change] * sym[:ticksize] unless zero.nil? swap[:current_diff] = (swap[:current_value] - zero[ohlc]) * (high ? 1 : -1 ) swap[:current_dist] = (swap[:current_diff] / sym[:ticksize]).to_i swap[:exceeded] = zero[:datetime] if swap[:current_dist] < grace end swap end |
#zero ⇒ Object
113 114 115 |
# File 'lib/cotcube-level/eod_stencil.rb', line 113 def zero index(0) end |