cotcube-level 0.3.3 → 0.3.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a349cee7bdea128658af11ee026dcc2ff995d711c930c5ee188396b1cca045a
4
- data.tar.gz: edc2b404b579336d585efeba20b12d8e2572ae3242a939aa060c286b405eee4e
3
+ metadata.gz: '04184473172dd9ffd09c49a16bf6c2a724eb5cbef3f0f3d5423c44dea55f530f'
4
+ data.tar.gz: 75d1363041e3767a2f79c277a0d945fd830c1521df481194d8162c36b36044f2
5
5
  SHA512:
6
- metadata.gz: e395bcc4db6052b95b08a1daad0d3ed1b344f533aa779d257de64ba205daf23ccc40853e284ff55dace36c8d3e4e6053e2694a37cee75def861c29e8cab28efe
7
- data.tar.gz: c6e059bd6dfbac4a4a4e3da069ff557f9ebecf46596983f056c78c6675447f6a3cd3eedde2b0ad2f48f9552c1e5bc01ba3fc2057a5f81f4129db3360d501ce50
6
+ metadata.gz: 70875d4dd83cb114b62456866b7c8ddaaa9753890442b06d71d770bb6408994cadcf3a5cd12704d658e049ed2aba0cd14bdbf79ce9d25e462ff9453c785a5142
7
+ data.tar.gz: 34aa4547dab7a3b13c896db860bcb23d36c432a0c3480cadf2e8a542351316d92cbe10a321ff8b20da236556312da27e8bb53ac6f65a1d885b48ccbe270c41ef
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.3.4 (October 06, 2021)
2
+ - intraday_stencil: major rework resp. rebuild ... now beta-ready
3
+ - helpers: preparing puts_swap and get_jsonl_name to work intraday
4
+ - puts_swap: changed output scheme to provide exceedance as NOTE
5
+
1
6
  ## 0.3.3 (October 05, 2021)
2
7
  - helpers::load_swaps: added :exceed to allow 1(sic) swap to be exceeded while loading
3
8
  - tritangulate: added :manual for feature of manual swap creation with base of 2 members
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.3
1
+ 0.3.4
@@ -42,10 +42,13 @@ module Cotcube
42
42
  # notice: add this to output as well
43
43
  def puts_swap(swap, format: , short: true, notice: nil, hash: 3)
44
44
  return if swap[:empty]
45
- daily = %i[ continuous daily ].include?(swap[:interval].to_sym)
46
- datetime_format = daily ? '%Y-%m-%d' : '%Y-%m-%d %H:%M'
45
+ daily = %i[ continuous daily ].include?(swap[:interval].to_sym) rescue false
46
+ datetime_format = daily ? '%Y-%m-%d' : '%Y-%m-%d %I:%M %p'
47
47
  high = swap[:side] == :high
48
48
  ohlc = high ? :high : :low
49
+ if notice.nil? and swap[:exceeded]
50
+ notice = "exceeded #{swap[:exceeded].strftime(datetime_format)}"
51
+ end
49
52
  if short
50
53
  puts (hash ? "#{swap[:digest][...hash]} ".colorize(:light_white) : '') +
51
54
  "S: #{swap[:side]
@@ -56,8 +59,7 @@ module Cotcube
56
59
  } F: #{ format format, swap[:members].last[ ohlc ]
57
60
  } S: #{ swap[:members].first[:datetime].strftime(datetime_format)
58
61
  } - #{ swap[:members].last[:datetime].strftime(datetime_format)
59
- }#{ format('%20s', (swap[:exceeded] ? " XXX: #{swap[:exceeded].strftime(datetime_format)}" : ''))
60
- }#{" NOTE: #{notice}" unless notice.nil?}".colorize(swap[:color] || :white )
62
+ }#{" NOTE: #{notice}" unless notice.nil?}".colorize(swap[:color] || :white )
61
63
  else
62
64
  puts "side: #{swap[:side] }\tlen: #{swap[:length]} \trating: #{swap[:rating]}".colorize(swap[:color] || :white )
63
65
  puts "diff: #{swap[:ticks]}\tdif: #{swap[:diff].round(7)}\tdepth: #{swap[:depth]}".colorize(swap[:color] || :white )
@@ -70,7 +72,7 @@ module Cotcube
70
72
  # create a standardized name for the cache files
71
73
  # and, on-the-fly, create these files plus their directory
72
74
  def get_jsonl_name(interval:, swap_type:, contract:, sym: nil)
73
- raise "Interval #{interval } is not supported, please choose from #{INTERVALS}" unless INTERVALS.include? interval
75
+ raise "Interval #{interval } is not supported, please choose from #{INTERVALS}" unless INTERVALS.include?(interval) || interval.is_a?(Integer)
74
76
  raise "Swaptype #{swap_type} is not supported, please choose from #{SWAPTYPES}" unless SWAPTYPES.include? swap_type
75
77
  sym ||= Cotcube::Helpers.get_id_set(contract: contract)
76
78
  root = '/var/cotcube/level'
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Cotcube
2
4
  module Level
3
- # TODO: Missing documentation of shiftsets, swap_types and stencil_types
5
+
4
6
  class Intraday_Stencil
5
7
 
6
- GLOBAL_SOW = { 'CT' => '0000-1700' }
7
- GLOBAL_EOW = { 'CT' => '1700-0000' }
8
- GLOBAL_EOD = { 'CT' => '1600-1700' }
9
8
 
9
+ # Class method that loads the (latest) shiftset for given asset
10
+ # These raw stencils are located in /var/cotcube/level/stencils/shiftsets.csv
11
+ #
10
12
 
11
13
  def self.shiftset(asset:, sym: nil)
12
14
  shiftset_file = '/var/cotcube/level/stencils/shiftsets.csv'
@@ -18,45 +20,53 @@ module Cotcube
18
20
  sym ||= Cotcube::Helpers.get_id_set(symbol: asset)
19
21
  current_set = shiftsets.find{|s| s[:symbols] =~ /#{sym[:type]}/ }
20
22
  return current_set.tap{|s| headers.map{|h| s[h] = nil if s[h] == '---------' }; s[:rth5] ||= s[:rth]; s[:mpost5] ||= s[:mpost] } unless current_set.nil?
21
- raise "Cannot get shiftset for #{sym[:type]}: #{asset}, please prepare #{shiftset_file} before!"
23
+ raise "Cannot get shiftset for #{sym[:type]}: #{asset}, please prepare #{shiftset_file} before!"
22
24
  end
23
25
 
24
26
  attr_reader :base, :shiftset, :timezone, :datetime, :zero, :index
25
27
 
26
- # asset: the asset the stencil will be applied to--or :full, if default stencil is desired
27
- # datetime: the datetime that will become 'zero'.
28
- # it will be calculated to the beginning of the previous interval
29
- # it must match the timezone of the asset
30
- # interval: the interval as minutes
31
- # weeks: the amount of weeks before the beginning of the current week
32
- # future: the amount of weeks after the beginning of the current week
33
- def initialize(asset:, sym: nil, datetime:, interval:, weeks:, future: 1, debug: false, type:, base: )
34
- @shiftset = Intraday_Stencils.shiftset(asset: asset)
35
- @timezone = TIMEZONES[@shiftset[:tz]]
36
- @debug = debug
28
+
29
+
30
+ def initialize(
31
+ asset:,
32
+ interval: 30.minutes,
33
+ swap_type: :full,
34
+ datetime: nil,
35
+ debug: false,
36
+ weeks: 6,
37
+ future: 2,
38
+ version: nil, # when referring to a specicic version of the stencil
39
+ stencil: nil, # instead of preparing, use this one if set
40
+ warnings: true # be more quiet
41
+ )
42
+ @shiftset = Intraday_Stencil.shiftset(asset: asset)
43
+ @timezone = Cotcube::Level::TIMEZONES[@shiftset[:tz]]
44
+ @debug = debug
45
+ @interval = interval
46
+ @swap_type = swap_type
47
+ @warnings = warnings
48
+ datetime ||= DateTime.now
37
49
  datetime = @timezone.at(datetime.to_i) unless datetime.is_a? ActiveSupport::TimeWithZone
38
- # slight flaw, as datetime does not carry the actuall timezone information but just the abbr. timezone name (like CDT or CEST)
39
- raise "Zone mismatch: Timezone of asset is #{@timezone.now.zone} but datetime given is #{dateime.zone}" unless @timezone.now.zone == datetime.zone
40
50
  @datetime = datetime.beginning_of_day
41
51
  @datetime += interval while @datetime <= datetime - interval
42
- @datetime -= interval
52
+ @datetime -= interval
53
+
43
54
  const = "RAW_INTRA_STENCIL_#{@shiftset[:nr]}_#{interval.in_minutes.to_i}".to_sym
44
55
  if Object.const_defined? const
45
56
  @base = (Object.const_get const).map{|z| z.dup}
46
57
  else
47
-
48
58
  start_time = lambda {|x| @shiftset[x].split('-').first rescue '' }
49
59
  start_hours = lambda {|x| @shiftset[x].split('-').first[ 0.. 1].to_i.send(:hours) rescue 0 }
50
60
  start_minutes = lambda {|x| @shiftset[x].split('-').first[-2..-1].to_i.send(:minutes) rescue 0 }
51
61
  end_time = lambda {|x| @shiftset[x].split('-').last rescue '' }
52
62
  end_hours = lambda {|x| @shiftset[x].split('-').last [ 0.. 1].to_i.send(:hours) rescue 0 }
53
- end_minutes = lambda {|x| @shiftset[x].split('-').last [-2..-1].to_i.send(:minutes) rescue 0 }
63
+ end_minutes = lambda {|x| @shiftset[x].split('-').last [-2..-1].to_i.send(:minutes) rescue 0 }
54
64
 
55
- runner = (@datetime -
65
+ runner = (@datetime -
56
66
  weeks * 7.days).beginning_of_week(:sunday)
57
67
  tm_runner = lambda { runner.strftime('%H%M') }
58
- @base = []
59
- (weeks+future).times do
68
+ @base = []
69
+ (weeks+future).times do
60
70
  while tm_runner.call < GLOBAL_SOW[@shiftset[:tz]].split('-').last
61
71
  # if daylight is switched, this phase will be shorter or longer
62
72
  @base << { datetime: runner, type: :sow }
@@ -81,10 +91,10 @@ module Cotcube
81
91
  yet_rth = true
82
92
  end
83
93
  end
84
- while ((sophase > eophase) ? (tm_runner.call >= sophase or tm_runner.call < eophase) : (tm_runner.call < eophase))
94
+ while ((sophase > eophase) ? (tm_runner.call >= sophase or tm_runner.call < eophase) : (tm_runner.call < eophase))
85
95
  current = { datetime: runner, type: phase }
86
96
  if phase == :rth and not yet_rth
87
- current[:block] = true
97
+ current[:block] = true
88
98
  yet_rth = true
89
99
  end
90
100
  @base << current
@@ -100,80 +110,104 @@ module Cotcube
100
110
  while runner < end_of_week
101
111
  @base << { datetime: runner, type: :eow }
102
112
  runner += interval
103
- end
113
+ end
104
114
  end
105
115
  Object.const_set(const, @base.map{|z| z.dup})
106
116
  end
107
- self.apply to: base, type: type
108
- @index = @base.index{|x| x[:datetime] == @datetime }
109
- @index -= 1 while %i[sow sod mpre mpost eod eow].include? @base[@index][:type]
117
+
118
+ case swap_type
119
+ when :full
120
+ @base.select!{|x| %i[ pre rth post ].include?(x[:type]) }
121
+ when :rth
122
+ @base.select!{|x| x[:type] == :rth }
123
+ # to.map{ |x| [:high, :low, :volume].map{|z| x[z] = nil} if x[:block] }
124
+ when :flow
125
+ @base.reject!{|x| %i[ meow postmm postmm5 ].include?(x[:type]) }
126
+ @base.
127
+ map{ |x|
128
+ [:high, :low, :volume].map{|z| x[z] = nil} unless x[:type] == :rth
129
+ # [:high, :low, :volume].map{|z| x[z] = nil} if x[:block]
130
+ }
131
+ when :run
132
+ @base.select!{|x| %i[ premarket rth postmarket ].include? x[:type]}
133
+ else
134
+ raise ArgumentError, "Unknown stencil/swap type '#{type}'"
135
+ end
136
+ @base.map!{|z| z.dup}
137
+
138
+ @index = @base.index{|x| x[:datetime] == @datetime }
139
+ @index -= 1 while %i[sow sod mpre mpost eod eow].include? @base[@index][:type]
110
140
  @datetime = @base[@index][:datetime]
111
141
  @zero = @base[@index]
112
- counter = 0
142
+ counter = 0
113
143
  while @base[@index - counter] and @index - counter >= 0
114
144
  @base[@index - counter][:x] = counter
115
145
  counter += 1
116
146
  end
117
- counter = 0
147
+ counter = 0
118
148
  while @base[@index + counter] and @index + counter < @base.length
119
149
  @base[@index + counter][:x] = -counter
120
150
  counter += 1
121
151
  end
122
- @base.select!{|z| z[:x] <= 0 or z[:high]}
123
152
  end
124
153
 
125
- def apply!(to:, type:)
126
- apply(to: to, type: type, force: true)
154
+ =begin
155
+ def dup
156
+ Intraday_Stencil.new(
157
+ debug: @debug,
158
+ interval: @interval,
159
+ swap_type: @swap_type,
160
+ datetime: @datetime,
161
+ stencil: @base.map{|x| x.dup}
162
+ )
163
+ end
164
+ =end
165
+
166
+ def zero
167
+ @zero ||= @base.find{|b| b[:x].zero? }
127
168
  end
128
169
 
129
- # :force will apply values to each bar regardless of existing ones
130
- def apply(to:, type:, force: false, debug: false)
170
+ def apply(to: )
131
171
  offset = 0
132
- to.each_index do |i|
172
+ @base.each_index do |i|
133
173
  begin
134
- offset += 1 while @base[i+offset][:datetime] < to[i][:datetime]
135
- puts "#{i}\t#{offset}\t#{@base[i+offset][:datetime]} < #{to[i][:datetime]}" if debug
174
+ offset += 1 while to[i+offset][:datetime] < @base[i][:datetime]
136
175
  rescue
137
176
  # appending
138
- puts "appending #{i}\t#{offset}\t#{@base[i+offset][:datetime]} < #{to[i][:datetime]}" if debug
139
- @base << to[i]
177
+ to << @base[i]
140
178
  next
141
179
  end
142
- if @base[i+offset][:datetime] > to[i][:datetime]
180
+ if to[i+offset][:datetime] > @base[i][:datetime]
143
181
  # skipping
144
- puts "skipping #{i}\t#{offset}\t#{@base[i+offset][:datetime]} < #{to[i][:datetime]}" if debug
145
182
  offset -= 1
146
183
  next
147
184
  end
148
185
  # merging
149
- j = i + offset
150
- @base[j]=@base[j].merge(to[i]) if force or (@base[j][:high].nil? and @base[j][:low].nil?)
151
- puts "MERGED:\t#{i}\t#{offset}\t#{@base[j]}" if debug
186
+ to[i+offset][:x] = @base[i][:x]
187
+ to[i+offset][:type] = @base[i][:type]
152
188
  end
153
189
  # finally remove all bars that do not belong to the stencil (i.e. holidays)
154
- case type
155
- when :full
156
- @base.select!{|x| %i[ pre rth post ].include?(x[:type]) }
157
- when :rth
158
- @base.select!{|x| x[:type] == :rth }
159
- # to.map{ |x| [:high, :low, :volume].map{|z| x[z] = nil} if x[:block] }
160
- when :flow
161
- @base.reject!{|x| %i[ meow postmm postmm5 ].include?(x[:type]) }
162
- @base.
163
- map{ |x|
164
- [:high, :low, :volume].map{|z| x[z] = nil} unless x[:type] == :rth
165
- # [:high, :low, :volume].map{|z| x[z] = nil} if x[:block]
166
- }
167
- when :run
168
- @base.select!{|x| %i[ premarket rth postmarket ].include? x[:type]}
169
- else
170
- raise ArgumentError, "Unknown stencil/swap type '#{type}'"
171
- end
172
- @base.map!{|z| z.dup}
190
+ to.reject!{|x| x[:x].nil? }
173
191
  end
174
192
 
193
+ def use(with:, sym:, zero:, grace: -2)
194
+ # todo: validate with (check if vslid swap
195
+ # sym (check keys)
196
+ # zero (ohlc with x.zero?)
197
+ # side ( upper or lower)
198
+ swap = with.dup
199
+ high = swap[:side] == :upper
200
+ ohlc = high ? :high : :low
201
+ start = base.find{|x| swap[:datetime] == x[:datetime]}
202
+ swap[:current_change] = (swap[:tpi] * start[:x]).round(8)
203
+ swap[:current_value] = swap[:members].last[ ohlc ] + swap[:current_change] * sym[:ticksize]
204
+ swap[:current_diff] = (swap[:current_value] - zero[ohlc]) * (high ? 1 : -1 )
205
+ swap[:current_dist] = (swap[:current_diff] / sym[:ticksize]).to_i
206
+ swap[:exceeded] = zero[:datetime] if swap[:current_dist] < grace
207
+ swap
208
+ end
175
209
  end
176
210
 
177
- Intraday_Stencils = Intraday_Stencil
178
211
  end
212
+
179
213
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cotcube-level
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin L. Tischendorf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-05 00:00:00.000000000 Z
11
+ date: 2021-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport