cotcube-level 0.3.3 → 0.3.4

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