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 +4 -4
- data/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/lib/cotcube-level/helpers.rb +7 -5
- data/lib/cotcube-level/intraday_stencil.rb +101 -67
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '04184473172dd9ffd09c49a16bf6c2a724eb5cbef3f0f3d5423c44dea55f530f'
|
4
|
+
data.tar.gz: 75d1363041e3767a2f79c277a0d945fd830c1521df481194d8162c36b36044f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 %
|
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
|
-
}#{
|
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
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
126
|
-
|
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
|
-
|
130
|
-
def apply(to:, type:, force: false, debug: false)
|
170
|
+
def apply(to: )
|
131
171
|
offset = 0
|
132
|
-
|
172
|
+
@base.each_index do |i|
|
133
173
|
begin
|
134
|
-
offset += 1 while
|
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
|
-
|
139
|
-
@base << to[i]
|
177
|
+
to << @base[i]
|
140
178
|
next
|
141
179
|
end
|
142
|
-
if
|
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
|
-
|
150
|
-
|
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
|
-
|
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.
|
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-
|
11
|
+
date: 2021-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|