cotcube-level 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/VERSION +1 -1
- data/lib/cotcube-level/eod_stencil.rb +2 -2
- data/lib/cotcube-level/helpers.rb +73 -31
- data/lib/cotcube-level/tritangulate.rb +6 -3
- 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: 9a349cee7bdea128658af11ee026dcc2ff995d711c930c5ee188396b1cca045a
|
4
|
+
data.tar.gz: edc2b404b579336d585efeba20b12d8e2572ae3242a939aa060c286b405eee4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e395bcc4db6052b95b08a1daad0d3ed1b344f533aa779d257de64ba205daf23ccc40853e284ff55dace36c8d3e4e6053e2694a37cee75def861c29e8cab28efe
|
7
|
+
data.tar.gz: c6e059bd6dfbac4a4a4e3da069ff557f9ebecf46596983f056c78c6675447f6a3cd3eedde2b0ad2f48f9552c1e5bc01ba3fc2057a5f81f4129db3360d501ce50
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.3.3 (October 05, 2021)
|
2
|
+
- helpers::load_swaps: added :exceed to allow 1(sic) swap to be exceeded while loading
|
3
|
+
- tritangulate: added :manual for feature of manual swap creation with base of 2 members
|
4
|
+
- helpers::load_swap added :digest to filter for swaps starting with pattern
|
5
|
+
- helpers: minor readability improvements
|
6
|
+
- eod_stencil: minor readability improvements
|
7
|
+
- helpers: few optimizations
|
8
|
+
|
1
9
|
## 0.3.2 (August 29, 2021)
|
2
10
|
- tritangulate: fixing 'finalize', as Integer zero won't comparte to Float zero
|
3
11
|
- cotcube-level.rb: added :check_exceedance
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.3
|
@@ -146,10 +146,10 @@ module Cotcube
|
|
146
146
|
ohlc = high ? :high : :low
|
147
147
|
start = base.find{|x| swap[:datetime] == x[:datetime]}
|
148
148
|
swap[:current_change] = (swap[:tpi] * start[:x]).round(8)
|
149
|
-
swap[:current_value] =
|
149
|
+
swap[:current_value] = swap[:members].last[ ohlc ] + swap[:current_change] * sym[:ticksize]
|
150
150
|
swap[:current_diff] = (swap[:current_value] - zero[ohlc]) * (high ? 1 : -1 )
|
151
151
|
swap[:current_dist] = (swap[:current_diff] / sym[:ticksize]).to_i
|
152
|
-
swap[:exceeded] =
|
152
|
+
swap[:exceeded] = zero[:datetime] if swap[:current_dist] < grace
|
153
153
|
swap
|
154
154
|
end
|
155
155
|
end
|
@@ -24,14 +24,14 @@ module Cotcube
|
|
24
24
|
# human readable output
|
25
25
|
# please note the format must be given, that should be taken from :sym
|
26
26
|
def member_to_human(member,side: ,format:, daily: false)
|
27
|
-
high = side == :upper
|
28
|
-
"#{member[:datetime].strftime("%a, %Y-%m-%d#{daily ? "" :" %I:%M%p"}")
|
29
|
-
} x: #{format '%-4d',
|
27
|
+
high = (side == :upper)
|
28
|
+
"#{ member[:datetime].strftime("%a, %Y-%m-%d#{daily ? "" :" %I:%M%p"}")
|
29
|
+
} x: #{format '%-4d', member[:x]
|
30
30
|
} dx: #{format '%-8.3f', (member[:dx].nil? ? member[:x] : member[:dx].round(3))
|
31
31
|
} #{high ? "high" : "low"
|
32
|
-
}: #{format format,
|
33
|
-
} i: #{(format '%4d',
|
34
|
-
} d: #{format '%6.2f',
|
32
|
+
}: #{format format, member[high ? :high : :low]
|
33
|
+
} i: #{(format '%4d', member[:i]) unless member[:i].nil?
|
34
|
+
} d: #{format '%6.2f', member[:dev] unless member[:dev].nil?
|
35
35
|
} #{member[:near].nil? ? '' : "near: #{member[:near]}"
|
36
36
|
}"
|
37
37
|
end
|
@@ -40,22 +40,23 @@ module Cotcube
|
|
40
40
|
# format: e.g. sym[:format]
|
41
41
|
# short: print one line / less verbose
|
42
42
|
# notice: add this to output as well
|
43
|
-
def puts_swap(swap, format: , short:
|
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])
|
45
|
+
daily = %i[ continuous daily ].include?(swap[:interval].to_sym)
|
46
46
|
datetime_format = daily ? '%Y-%m-%d' : '%Y-%m-%d %H:%M'
|
47
47
|
high = swap[:side] == :high
|
48
48
|
ohlc = high ? :high : :low
|
49
49
|
if short
|
50
|
-
puts "
|
51
|
-
|
52
|
-
}
|
53
|
-
}
|
54
|
-
}
|
55
|
-
}
|
56
|
-
}
|
57
|
-
}
|
58
|
-
}#{
|
50
|
+
puts (hash ? "#{swap[:digest][...hash]} ".colorize(:light_white) : '') +
|
51
|
+
"S: #{swap[:side]
|
52
|
+
} L: #{ format '%4d', swap[:length]
|
53
|
+
} R: #{ format '%4d', swap[:rating]
|
54
|
+
} D: #{ format '%4d', swap[:depth]
|
55
|
+
} P: #{ format '%10s', (format '%5.2f', swap[:ppi])
|
56
|
+
} F: #{ format format, swap[:members].last[ ohlc ]
|
57
|
+
} S: #{ swap[:members].first[:datetime].strftime(datetime_format)
|
58
|
+
} - #{ swap[:members].last[:datetime].strftime(datetime_format)
|
59
|
+
}#{ format('%20s', (swap[:exceeded] ? " XXX: #{swap[:exceeded].strftime(datetime_format)}" : ''))
|
59
60
|
}#{" NOTE: #{notice}" unless notice.nil?}".colorize(swap[:color] || :white )
|
60
61
|
else
|
61
62
|
puts "side: #{swap[:side] }\tlen: #{swap[:length]} \trating: #{swap[:rating]}".colorize(swap[:color] || :white )
|
@@ -114,7 +115,7 @@ module Cotcube
|
|
114
115
|
|
115
116
|
# loading of swaps is also straight forward
|
116
117
|
# it takes few more efforts to normalize the values to their expected format
|
117
|
-
def load_swaps(interval:, swap_type:, contract:, sym: nil, datetime: nil)
|
118
|
+
def load_swaps(interval:, swap_type:, contract:, sym: nil, datetime: nil, recent: false, digest: nil, quiet: false, exceed: false)
|
118
119
|
file = get_jsonl_name(interval: interval, swap_type: swap_type, contract: contract, sym: sym)
|
119
120
|
jsonl = File.read(file)
|
120
121
|
data = jsonl.
|
@@ -123,22 +124,22 @@ module Cotcube
|
|
123
124
|
JSON.parse(x).
|
124
125
|
deep_transform_keys(&:to_sym).
|
125
126
|
tap do |sw|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
127
|
+
sw[:datetime] = DateTime.parse(sw[:datetime]) rescue nil
|
128
|
+
(sw[:exceeded] = DateTime.parse(sw[:exceeded]) rescue nil) if sw[:exceeded]
|
129
|
+
sw[:interval] = interval
|
130
|
+
sw[:swap_type] = swap_type
|
131
|
+
sw[:contract] = contract
|
132
|
+
%i[ side ].each {|key| sw[key] = sw[key].to_sym rescue false }
|
133
|
+
unless sw[:empty] or sw[:exceeded]
|
134
|
+
sw[:color] = sw[:color].to_sym
|
135
|
+
sw[:members].map{|mem| mem[:datetime] = DateTime.parse(mem[:datetime]) }
|
136
|
+
end
|
136
137
|
end
|
137
138
|
end
|
138
139
|
# assign exceedance data to actual swaps
|
139
140
|
data.select{|swap| swap[:exceeded] }.each do |exc|
|
140
141
|
swap = data.find{|ref| ref[:digest] == exc[:ref]}
|
141
|
-
raise RuntimeError, "
|
142
|
+
raise RuntimeError, "Inconsistent history for '#{exc}'. Origin not found." if swap.nil?
|
142
143
|
swap[:exceeded] = exc[:exceeded]
|
143
144
|
end
|
144
145
|
# do not return bare exceedance information
|
@@ -146,9 +147,38 @@ module Cotcube
|
|
146
147
|
# do not return swaps that are found 'later'
|
147
148
|
data.reject!{|swap| swap[:datetime] > datetime } unless datetime.nil?
|
148
149
|
# do not return exceeded swaps, that are exceeded in the past
|
149
|
-
|
150
|
+
recent = 7.days if recent.is_a? TrueClass
|
151
|
+
recent += 5.hours if recent
|
152
|
+
data.reject!{|swap| swap[:exceeded] and swap[:exceeded] < datetime - (recent ? recent : 0) } unless datetime.nil?
|
150
153
|
# remove exceedance information that is found 'later'
|
151
|
-
data.map{|swap| swap.delete(:exceeded) if swap[:exceeded] and swap[:exceeded] > datetime}
|
154
|
+
data.map{|swap| swap.delete(:exceeded) if swap[:exceeded] and swap[:exceeded] > datetime} unless datetime.nil?
|
155
|
+
unless digest.nil?
|
156
|
+
data.select! do |z|
|
157
|
+
(Cotcube::Helpers.sub(minimum: digest.length){ z[:digest] } === digest) and
|
158
|
+
not z[:empty]
|
159
|
+
end
|
160
|
+
case data.size
|
161
|
+
when 0
|
162
|
+
puts "No swaps found for digest '#{digest}'." unless quiet
|
163
|
+
when 1
|
164
|
+
sym ||= Cotcube::Helpers.get_id_set(contract: contract)
|
165
|
+
if not quiet or exceed
|
166
|
+
puts "Found 1 digest: "
|
167
|
+
data.each {|d| puts_swap( d, format: sym[:format], short: true, hash: digest.size + 2) }
|
168
|
+
if exceed
|
169
|
+
exceed = DateTime.now if exceed.is_a? TrueClass
|
170
|
+
mark_exceeded(swap: data.first, datetime: exceed)
|
171
|
+
puts "Swap marked exceeded."
|
172
|
+
end
|
173
|
+
end
|
174
|
+
else
|
175
|
+
sym ||= Cotcube::Helpers.get_id_set(contract: contract)
|
176
|
+
unless quiet
|
177
|
+
puts "Too many digests found for digest '#{digest}', please consider sending more figures: "
|
178
|
+
data.each {|d| puts_swap( d, format: sym[:format], short: true, hash: digest.size + 3)}
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
152
182
|
data
|
153
183
|
end
|
154
184
|
|
@@ -175,6 +205,18 @@ module Cotcube
|
|
175
205
|
end.compact
|
176
206
|
end
|
177
207
|
|
208
|
+
def mark_exceeded(swap:, datetime:, debug: false)
|
209
|
+
to_save = {
|
210
|
+
datetime: datetime,
|
211
|
+
ref: swap[:digest],
|
212
|
+
side: swap[:side],
|
213
|
+
exceeded: datetime
|
214
|
+
}
|
215
|
+
save_swaps to_save, interval: swap[:interval], swap_type: swap[:swap_type], sym: Cotcube::Helpers.get_id_set(contract: swap[:contract]), contract: swap[:contract], quiet: (not debug)
|
216
|
+
swap[:exceeded] = datetime
|
217
|
+
swap
|
218
|
+
end
|
219
|
+
|
178
220
|
end
|
179
221
|
end
|
180
222
|
|
@@ -19,6 +19,7 @@ module Cotcube
|
|
19
19
|
swap_type: nil, # if not given, a warning is printed and swaps won't be saved or loaded
|
20
20
|
with_flaws: 0, # the maximum amount of consecutive bars that would actually break the current swap
|
21
21
|
# should be set to 0 for dailies and I suggest no more than 3 for intraday
|
22
|
+
manual: false, # some triggers must be set differently when manual entry is used
|
22
23
|
deviation: 2 # the maximum shift of :x-values of found members
|
23
24
|
)
|
24
25
|
|
@@ -70,8 +71,10 @@ module Cotcube
|
|
70
71
|
|
71
72
|
# abs_peak is the absolute high / low of the base. the shearing operation ends there,
|
72
73
|
# but results might be influenced when abs_peak becomes affected by :with_flaws
|
73
|
-
|
74
|
-
|
74
|
+
unless manual
|
75
|
+
abs_peak = base.send(high ? :max_by : :min_by){|x| x[high ? :high : :low] }[:datetime]
|
76
|
+
base.reject!{|x| x[:datetime] < abs_peak}
|
77
|
+
end
|
75
78
|
|
76
79
|
###########################################################################################################################z
|
77
80
|
# only if (and only if) the range portion above change the underlying base
|
@@ -155,7 +158,7 @@ module Cotcube
|
|
155
158
|
# first member is solitary
|
156
159
|
if new_members.empty?
|
157
160
|
mem_sorted=members.sort
|
158
|
-
if mem_sorted[1] == mem_sorted[0] + 1
|
161
|
+
if mem_sorted[1] == mem_sorted[0] + 1 and not manual
|
159
162
|
b2 = b[mem_sorted[1]..mem_sorted[-1]].map{|x| x.dup; x[:dx] = nil; x}
|
160
163
|
puts 'starting recursive rerun'.light_red if debug
|
161
164
|
alternative_slope = get_slope.call(b2)
|
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.3
|
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-
|
11
|
+
date: 2021-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|