cotcube-level 0.3.1 → 0.3.2

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: 7756ccc0318477cf223fc205720c986daaaad4304439108b960ca410a15acf79
4
- data.tar.gz: ba7a79e928da4c89b0e7103394899096ab42f5977986892c5e7396fe5d4abeff
3
+ metadata.gz: 81e95a5e617ba6dd8fdf5df13c0395455ff19a337e2e72e79f485a37489049c0
4
+ data.tar.gz: d592daecc1be2e4686fd3a6807d82c5f5429de6b451b96e4aee30430fe0fbe9d
5
5
  SHA512:
6
- metadata.gz: ceb38b4a6c827b0d8a7b09e0c0f86e9050e49dce54504cf5075d2d2da5fb9fe99186c8e9aa3403a14b61d5d6fa831e86a43886279dea8e20efd1c818e119d1f0
7
- data.tar.gz: f53b20c6848b4d7cc825a18819ace61ebade1238706dbd125e76318eeb2dd1e4abbc6dca2d9872accb0069df8ac9edb16762c45ea7bc9a8293b95452d36102a6
6
+ metadata.gz: 78459e2694a2c1f97357307d550df8c9920b18be785b1c28d712b8d61c074ba4326c867b107b62985030fac412805c548858ee086f13802dec13b01e75c10f9c
7
+ data.tar.gz: 0a7ccd8153cda7309f70fbffb2fc2fe7f2595194ddf4688bcc13d28c86418fbe0f23322f5c47a2fba7b4aca0832e95b877747158bd17ad1da33a634bbc3eb529
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## 0.3.2 (August 29, 2021)
2
+ - tritangulate: fixing 'finalize', as Integer zero won't comparte to Float zero
3
+ - cotcube-level.rb: added :check_exceedance
4
+ - helpers:member_to_human: added :daily param to distinguish stencils
5
+ - tritangulate: added 'min_ratio' as param with lambda
6
+ - eod_stencil: added #use to calculate current swap line value / dist;
7
+ - tritangulate: added interval to be saved with the swap information.
8
+ - helpers: moved puts_swaps to puts_swap, and added a :short switch for 1-liners per swap
9
+
10
+ ## 0.3.1.1 (August 25, 2021)
11
+ - trying to fix versioning mistake
12
+ - Bump version to 0.3.2.1.
13
+ - minor fixes correcting mistakes sneaked in during documentation rework
14
+ - minor fix
15
+
16
+ ## 0.3.2.1 (August 25, 2021)
17
+ - minor fixes correcting mistakes sneaked in during documentation rework
18
+ - minor fix
19
+
1
20
  ## 0.3.1 (August 24, 2021)
2
21
  - renaming triangulation to tritangulation
3
22
  - minor fixes in README and gemspec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.3.2
@@ -43,7 +43,6 @@ module Cotcube
43
43
  range: nil, # used to shrink the stencil size, accepts String or Date
44
44
  interval:,
45
45
  swap_type:,
46
- contract: nil,
47
46
  date: nil,
48
47
  debug: false,
49
48
  version: nil, # when referring to a specicic version of the stencil
@@ -54,7 +53,6 @@ module Cotcube
54
53
  @debug = debug
55
54
  @interval = interval == :continuous ? :daily : interval
56
55
  @swap_type = swap_type
57
- @contract = contract
58
56
  @warnings = warnings
59
57
  step = case @interval
60
58
  when :hours, :hour; 1.hour
@@ -108,7 +106,6 @@ module Cotcube
108
106
  interval: @interval,
109
107
  swap_type: @swap_type,
110
108
  date: @date,
111
- contract: @contract,
112
109
  stencil: @base.map{|x| x.dup}
113
110
  )
114
111
  end
@@ -139,6 +136,22 @@ module Cotcube
139
136
  to.reject!{|x| x[:x].nil? }
140
137
  end
141
138
 
139
+ def use(with:, sym:, zero:, grace: -2)
140
+ # todo: validate with (check if vslid swap
141
+ # sym (check keys)
142
+ # zero (ohlc with x.zero?)
143
+ # side ( upper or lower)
144
+ swap = with.dup
145
+ high = swap[:side] == :upper
146
+ ohlc = high ? :high : :low
147
+ start = base.find{|x| swap[:datetime] == x[:datetime]}
148
+ swap[:current_change] = (swap[:tpi] * start[:x]).round(8)
149
+ swap[:current_value] = swap[:members].last[ ohlc ] + swap[:current_change] * sym[:ticksize]
150
+ swap[:current_diff] = (swap[:current_value] - zero[ohlc]) * (high ? 1 : -1 )
151
+ swap[:current_dist] = (swap[:current_diff] / sym[:ticksize]).to_i
152
+ swap[:exceeded] = zero[:datetime] if swap[:current_dist] < grace
153
+ swap
154
+ end
142
155
  end
143
156
 
144
157
  end
@@ -17,15 +17,15 @@ module Cotcube
17
17
  member[:yy] =
18
18
  member[:y] +
19
19
  (member[:dx].nil? ? member[:x] : member[:dx]) * tan
20
- bar
20
+ member
21
21
  }
22
22
  end
23
23
 
24
24
  # human readable output
25
25
  # please note the format must be given, that should be taken from :sym
26
- def member_to_human(member,side: ,format:)
26
+ def member_to_human(member,side: ,format:, daily: false)
27
27
  high = side == :upper
28
- "#{member[:datetime].strftime("%a, %Y-%m-%d %I:%M%p")
28
+ "#{member[:datetime].strftime("%a, %Y-%m-%d#{daily ? "" :" %I:%M%p"}")
29
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"
@@ -37,14 +37,32 @@ module Cotcube
37
37
  end
38
38
 
39
39
  # human readable output
40
- # list all swaps contained in an array (e.g. result of tritangulate)
41
- def puts_swaps(swaps, format: )
42
- swaps = [ swaps ] unless swaps.is_a? Array
43
- swaps.each do |swap|
40
+ # format: e.g. sym[:format]
41
+ # short: print one line / less verbose
42
+ # notice: add this to output as well
43
+ def puts_swap(swap, format: , short: false, notice: nil)
44
+ return if swap[:empty]
45
+ daily = %i[ continuous daily ].include?(swap[:interval])
46
+ datetime_format = daily ? '%Y-%m-%d' : '%Y-%m-%d %H:%M'
47
+ high = swap[:side] == :high
48
+ ohlc = high ? :high : :low
49
+ if short
50
+ puts "S: #{swap[:side]
51
+ } L: #{format '%4d', swap[:length]
52
+ } R: #{format '%4d', swap[:rating]
53
+ } D: #{format '%4d', swap[:depth]
54
+ } P: #{format '%10s', (format '%5.2f', swap[:ppi])
55
+ } F: #{format format, swap[:members].last[ ohlc ]
56
+ } S: #{swap[:members].first[:datetime].strftime(datetime_format)
57
+ } - #{swap[:members].last[:datetime].strftime(datetime_format)
58
+ }#{format('%20s', (swap[:exceeded] ? " XXX: #{swap[:exceeded].strftime(datetime_format)}" : ''))
59
+ }#{" NOTE: #{notice}" unless notice.nil?}".colorize(swap[:color] || :white )
60
+ else
44
61
  puts "side: #{swap[:side] }\tlen: #{swap[:length]} \trating: #{swap[:rating]}".colorize(swap[:color] || :white )
45
62
  puts "diff: #{swap[:ticks]}\tdif: #{swap[:diff].round(7)}\tdepth: #{swap[:depth]}".colorize(swap[:color] || :white )
46
63
  puts "tpi: #{swap[:tpi] }\tppi: #{swap[:ppi]}".colorize(swap[:color] || :white )
47
- swap[:members].each {|x| puts member_to_human(x, side: swap[:side], format: format) }
64
+ puts "NOTE: #{notice}".colorize(:light_white) unless notice.nil?
65
+ swap[:members].each {|x| puts member_to_human(x, side: swap[:side], format: format, daily: daily) }
48
66
  end
49
67
  end
50
68
 
@@ -66,42 +84,95 @@ module Cotcube
66
84
 
67
85
  # the name says it all.
68
86
  # just note the addition of a digest, that serves to check whether same swap has been yet saved
69
- # to the cache
70
- def save_swaps(swaps, interval:, swap_type:, contract:, sym: nil)
87
+ # to the cache.
88
+ #
89
+ # there are actually 3 types of information, that are saved here:
90
+ # 1. a swap
91
+ # 2. an 'empty' information, referring to an interval that has been processed but no swaps were found
92
+ # 3. an 'exceeded' information, referring to another swap, that has been exceeded
93
+ #
94
+ def save_swaps(swaps, interval:, swap_type:, contract:, sym: nil, quiet: false)
71
95
  file = get_jsonl_name(interval: interval, swap_type: swap_type, contract: contract, sym: sym)
96
+ swaps = [ swaps ] unless swaps.is_a? Array
72
97
  swaps.each do |swap|
73
- swap_json = swap.to_json
98
+ raise "Illegal swap info: Must contain keys :datetime, :side... #{swap}" unless (%i[ datetime side ] - swap.keys).empty?
99
+ %i[ interval swap_type ].map {|key| swap.delete(key) }
100
+ sorted_keys = [ :datetime, :side ] + ( swap.keys - [ :datetime, :side ])
101
+ swap_json = swap.slice(*sorted_keys).to_json
74
102
  digest = Digest::SHA256.hexdigest swap_json
75
- res = `cat #{file} | grep #{digest}`.strip
103
+ res = `cat #{file} | grep '"digest":"#{digest}"'`.strip
76
104
  unless res.empty?
77
- puts "Cannot save swap, it is already in #{file}:"
78
- p swap
105
+ puts "Cannot save swap, it is already in #{file}:".light_red unless quiet
106
+ p swap unless quiet
79
107
  else
80
108
  swap[:digest] = digest
81
- File.open(file, 'a+'){|f| f.write(swap.to_json + "\n") }
109
+ sorted_keys += %i[digest]
110
+ File.open(file, 'a+'){|f| f.write(swap.slice(*sorted_keys).to_json + "\n") }
82
111
  end
83
112
  end
84
113
  end
85
114
 
86
115
  # loading of swaps is also straight forward
87
116
  # it takes few more efforts to normalize the values to their expected format
88
- def load_swaps(interval:, swap_type:, contract:, sym: nil)
117
+ def load_swaps(interval:, swap_type:, contract:, sym: nil, datetime: nil)
89
118
  file = get_jsonl_name(interval: interval, swap_type: swap_type, contract: contract, sym: sym)
90
119
  jsonl = File.read(file)
91
- jsonl.
120
+ data = jsonl.
92
121
  each_line.
93
122
  map do |x|
94
123
  JSON.parse(x).
95
124
  deep_transform_keys(&:to_sym).
96
125
  tap do |sw|
97
126
  sw[:datetime] = DateTime.parse(sw[:datetime]) rescue nil
98
- sw[:side] = sw[:side].to_sym
99
- unless sw[:empty]
127
+ (sw[:exceeded] = DateTime.parse(sw[:exceeded]) rescue nil) if sw[:exceeded]
128
+ sw[:interval] = interval
129
+ sw[:swap_type] = swap_type
130
+ sw[:contract] = contract
131
+ %i[ side ].each {|key| sw[key] = sw[key].to_sym rescue false }
132
+ unless sw[:empty] or sw[:exceeded]
100
133
  sw[:color] = sw[:color].to_sym
101
134
  sw[:members].map{|mem| mem[:datetime] = DateTime.parse(mem[:datetime]) }
102
135
  end
103
136
  end
104
137
  end
138
+ # assign exceedance data to actual swaps
139
+ data.select{|swap| swap[:exceeded] }.each do |exc|
140
+ swap = data.find{|ref| ref[:digest] == exc[:ref]}
141
+ raise RuntimeError, "Consistent history for '#{exc}'. Origin not found." if swap.nil?
142
+ swap[:exceeded] = exc[:exceeded]
143
+ end
144
+ # do not return bare exceedance information
145
+ data.reject!{|swap| swap[:exceeded] and swap[:members].nil? }
146
+ # do not return swaps that are found 'later'
147
+ data.reject!{|swap| swap[:datetime] > datetime } unless datetime.nil?
148
+ # do not return exceeded swaps, that are exceeded in the past
149
+ data.reject!{|swap| swap[:exceeded] and swap[:exceeded] < datetime } unless datetime.nil?
150
+ # remove exceedance information that is found 'later'
151
+ data.map{|swap| swap.delete(:exceeded) if swap[:exceeded] and swap[:exceeded] > datetime}
152
+ data
153
+ end
154
+
155
+ # :swaps is an array of swaps
156
+ # :zero is the current interval (ohlc)
157
+ # :stencil is the according current stencil (eod or intraday)
158
+ def check_exceedance(swaps:, zero:, stencil:, contract:, sym:, debug: false)
159
+ swaps.map do |swap|
160
+ # swaps cannot exceed the day they are found (or if they are found in the future)
161
+ next if swap[:datetime] >= zero[:datetime] or swap[:empty]
162
+ update = stencil.use with: swap, sym: sym, zero: zero
163
+ if update[:exceeded]
164
+ to_save = {
165
+ datetime: zero[:datetime],
166
+ ref: swap[:digest],
167
+ side: swap[:side],
168
+ exceeded: update[:exceeded]
169
+ }
170
+ save_swaps to_save, interval: swap[:interval], swap_type: swap[:swap_type], contract: contract, sym: sym, quiet: (not debug)
171
+ swap[:exceeded] = update[:exceeded]
172
+ end
173
+ %i[ current_change current_value current_diff current_dist ].map{|key| swap[key] = update[key] }
174
+ swap
175
+ end.compact
105
176
  end
106
177
 
107
178
  end
@@ -9,15 +9,18 @@ module Cotcube
9
9
  range: (0..-1), # range is relative to base
10
10
  max: 90, # the range which to scan for swaps goes from deg 0 to max
11
11
  debug: false,
12
- min_rating: 3, # swaps having a lower rating are discarded
13
- min_length: 8, # shorter swaps are discared
12
+ min_rating: 3, # 1st criteria: swaps having a lower rating are discarded
13
+ min_length: 8, # 2nd criteria: shorter swaps are discared
14
+ min_ratio: # 3rd criteria: the ratio between rating and length (if true, swap is discarded)
15
+ lambda {|r,l| r < l / 4.0 },
14
16
  save: true, # allow saving of results
15
17
  cached: true, # allow loading of cached results
16
18
  interval: , # interval (currently) is one of %i[ daily continuous halfs ]
17
19
  swap_type: nil, # if not given, a warning is printed and swaps won't be saved or loaded
18
20
  with_flaws: 0, # the maximum amount of consecutive bars that would actually break the current swap
19
21
  # should be set to 0 for dailies and I suggest no more than 3 for intraday
20
- deviation: 2) # the maximum shift of :x-values of found members
22
+ deviation: 2 # the maximum shift of :x-values of found members
23
+ )
21
24
 
22
25
  raise ArgumentError, "'0 < max < 90, but got '#{max}'" unless max.is_a? Numeric and 0 < max and max <= 90
23
26
  raise ArgumentError, 'need :side either :upper or :lower for dots' unless [:upper, :lower].include? side
@@ -26,7 +29,7 @@ module Cotcube
26
29
  # init some helpers
27
30
  #
28
31
  high = side == :upper
29
- # DELETE first = base.to_a.find{|x| not x[:high].nil? }
32
+ first = base.to_a.find{|x| not x[:high].nil? }
30
33
  zero = base.select{|x| x[:x].zero? }
31
34
  raise ArgumentError, "Inappropriate base, it should contain ONE :x.zero, but contains #{zero.size}." unless zero.size==1
32
35
  zero = zero.first
@@ -34,15 +37,16 @@ module Cotcube
34
37
  contract ||= zero[:contract]
35
38
  sym ||= Cotcube::Helpers.get_id_set(contract: contract)
36
39
 
40
+
37
41
  if cached
38
42
  if interval.nil? or swap_type.nil?
39
43
  puts "Warning: Cannot use cache as both :interval and :swap_type must be given".light_yellow
40
44
  else
41
- cache = load_swaps(interval: interval, swap_type: swap_type, contract: contract, sym: sym)
42
- # if the current datetime has been yet processed but nothing has been found,
45
+ cache = load_swaps(interval: interval, swap_type: swap_type, contract: contract, sym: sym, datetime: zero[:datetime])
46
+ # if the current datetime was already processed but nothing has been found,
43
47
  # an 'empty' value is saved.
44
- # that means, if neither an array of swaps nor :empty is found, the datetime has not been processed yet
45
- selected = cache.select{|sw| sw[:datetime] == zero[:datetime] and sw[:side] == side}
48
+ # that means, if neither a swap (or more) nor :empty is found, the datetime has not been processed yet
49
+ selected = cache.select{|sw| sw[:datetime] == zero[:datetime] and sw[:side] == side }
46
50
  unless selected.empty?
47
51
  puts 'cache_hit'.light_white if debug
48
52
  return (selected.first[:empty] ? [] : selected )
@@ -100,13 +104,12 @@ module Cotcube
100
104
  finalize = lambda do |results|
101
105
  results.map do |result|
102
106
  result[:members].each do |member|
103
- next if member[:yy].nil? or member[:yy].zero?
107
+ next if member[:yy].nil? or member[:yy].round(PRECISION-5).zero?
104
108
 
105
109
  diff = (member[:x] - member[:dx]).abs / 2.0
106
110
  member[:dx] = member[:x] + diff
107
111
  # it employs another binary-search
108
- while member[:yy].round(PRECISION) != 0
109
- print '.' if debug
112
+ while member[:yy].round(PRECISION-5) != 0.0
110
113
  member[:yy] = shear_to_deg(deg: result[:deg], base: [ member ] ).first[:yy]
111
114
  diff /= 2.0
112
115
  if member[:yy] > 0
@@ -115,7 +118,7 @@ module Cotcube
115
118
  member[:dx] -= diff
116
119
  end
117
120
  end
118
- member[:yy] = member[:yy].abs.round(8)
121
+ member[:yy] = member[:yy].abs.round(PRECISION-5)
119
122
  end
120
123
 
121
124
  puts 'done!'.magenta if debug
@@ -174,7 +177,7 @@ module Cotcube
174
177
  current_slope[:members] << b[i] unless current_slope[:members].map{|x| x[:datetime]}.include? b[i][:datetime]
175
178
  current_slope[:members].sort_by!{|x| x[:datetime]}
176
179
  end
177
- current_slope
180
+ return current_slope
178
181
 
179
182
  end
180
183
  # all new members found in current iteration have now receive their new :x value, depending on their distance to
@@ -215,6 +218,7 @@ module Cotcube
215
218
  swap_base = shear_to_deg(base: swap_base, deg: swap[:deg])
216
219
  swap_base.map!{|x| x[:dev] = (x[:yy] / sym[:ticksize].to_f); x[:dev] = -( x[:dev] > 0 ? x[:dev].floor : x[:dev].ceil); x}
217
220
  invalids = swap_base.select{|x| x[:dev] < 0 }
221
+ with_flaws = 0 unless with_flaws # support legacy versions, where with_flaws was boolean
218
222
  if with_flaws > 0
219
223
  # TODO: this behaves only as expected when with_flaws == 2
220
224
  last_invalid = invalids[(invalids[-2][:i] + 1 == invalids[-1][:i] ) ? -3 : -2] rescue nil
@@ -243,6 +247,8 @@ module Cotcube
243
247
  swap[:avg_dev] = (swap_base.reject{|x| x[:dev].zero?}.map{|x| x[:dev].abs}.reduce(:+) / (swap_base.size - swap[:members].size).to_f).ceil rescue 0
244
248
  # depth: the maximum distance to the swap line
245
249
  swap[:depth] = swap_base.max_by{|x| x[:dev]}[:dev]
250
+ swap[:interval] = interval
251
+ swap[:swap_type] = swap_type
246
252
  swap[:raw] = swap[:members].map{|x| x[:x]}.reverse
247
253
  swap[:size] = swap[:members].size
248
254
  swap[:length] = swap[:raw][-1] - swap[:raw][0]
@@ -256,11 +262,11 @@ module Cotcube
256
262
  unless %i[ daily continuous ].include? interval
257
263
  swap[:color] = ((rat > 150) ? :light_blue : (rat > 80) ? :magenta : (rat > 30) ? :light_magenta : (rat > 15) ? :light_yellow : high ? :green : :red)
258
264
  end
259
- swap[:diff] = swap[:members].last[ high ? :high : :low ] - swap[:members].first[ high ? :high : :low ]
265
+ swap[:diff] = (swap[:members].last[ high ? :high : :low ] - swap[:members].first[ high ? :high : :low ]).round(8)
260
266
  swap[:ticks] = (swap[:diff] / sym[:ticksize]).to_i
261
267
  # tpi: ticks per interval, how many ticks are passed each :interval
262
268
  swap[:tpi] = (swap[:ticks].to_f / swap[:length]).round(3)
263
- # ppi: power per interval, how many dollar value is passed each :interval
269
+ # ppi: power per interval, how many $dollar value is passed each :interval
264
270
  swap[:ppi] = (swap[:tpi] * sym[:power]).round(3)
265
271
  end # swap
266
272
  end # lambda
@@ -303,7 +309,7 @@ module Cotcube
303
309
  binding.irb if debug
304
310
 
305
311
  # reject all results that do not suffice
306
- current_results.reject!{|swap| swap[:rating] < min_rating or swap[:length] < min_length or swap[:rating] < swap[:length] / 4.to_f}
312
+ current_results.reject!{|swap| swap[:rating] < min_rating or swap[:length] < min_length or min_ratio.call(swap[:rating],swap[:length])}
307
313
 
308
314
  #####################################################################################################################3
309
315
  # finally save results for caching and return them
@@ -312,7 +318,7 @@ module Cotcube
312
318
  puts "WARNING: Cannot save swaps, as both :interval and :swap_type must be given".colorize(:light_yellow)
313
319
  else
314
320
  current_results.map{|sw| mem = sw[:members]; sw[:slope] = (mem.last[:y] - mem.first[:y]) / (mem.last[mem.last[:dx].nil? ? :x : :dx] - mem.first[mem.first[:dx].nil? ? :x : :dx]).to_f }
315
- to_save = current_results.empty? ? [ { datetime: zero[:datetime], side: side, empty: true } ] : current_results
321
+ to_save = current_results.empty? ? [ { datetime: zero[:datetime], side: side, empty: true, interval: interval, swap_type: swap_type } ] : current_results
316
322
  save_swaps(to_save, interval: interval, swap_type: swap_type, contract: contract, sym: sym)
317
323
  end
318
324
  end
data/lib/cotcube-level.rb CHANGED
@@ -35,10 +35,11 @@ module Cotcube
35
35
  :shear_to_rad, # same all below
36
36
  :rad2deg,
37
37
  :deg2rad,
38
- :puts_swaps,
38
+ :puts_swap,
39
39
  :save_swaps,
40
40
  :get_jsonl_name,
41
41
  :load_swaps,
42
+ :check_exceedance,
42
43
  :member_to_human
43
44
 
44
45
  # please note that module_functions of sources provided in non-public files must slso be published within these
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.1
4
+ version: 0.3.2
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-08-24 00:00:00.000000000 Z
11
+ date: 2021-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -116,7 +116,6 @@ executables: []
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
- - ".irbrc.rb"
120
119
  - CHANGELOG.md
121
120
  - Gemfile
122
121
  - README.md
data/.irbrc.rb DELETED
@@ -1,12 +0,0 @@
1
- def verbose_toggle
2
- irb_context.echo ? irb_context.echo = false : irb_context.echo = true
3
- end
4
-
5
- alias vt verbose_toggle
6
-
7
- $debug = true
8
- IRB.conf[:USE_MULTILINE] = false
9
- # require 'bundler'
10
- # Bundler.require
11
-
12
- require_relative 'lib/cotcube-level'