cryptum 0.0.359 → 0.0.361

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +16 -0
  3. data/.gitignore +30 -0
  4. data/.rspec +3 -0
  5. data/.rspec_status +0 -0
  6. data/.rubocop.yml +31 -0
  7. data/.rubocop_todo.yml +36 -0
  8. data/.ruby-gemset +1 -0
  9. data/.ruby-version +1 -0
  10. data/CODE_OF_CONDUCT.md +84 -0
  11. data/Gemfile +38 -0
  12. data/LICENSE +674 -0
  13. data/README.md +87 -0
  14. data/Rakefile +19 -0
  15. data/bin/cryptum +73 -0
  16. data/bin/cryptum-forecast +200 -0
  17. data/bin/cryptum-repl +73 -0
  18. data/bin/cryptum_autoinc_version +38 -0
  19. data/build_cryptum_gem.sh +58 -0
  20. data/cryptum.gemspec +52 -0
  21. data/cryptum_container.sh +1 -0
  22. data/docker/cryptum.json +60 -0
  23. data/docker/cryptum_container.sh +59 -0
  24. data/docker/packer_secrets.json.EXAMPLE +7 -0
  25. data/docker/provisioners/cryptum.sh +11 -0
  26. data/docker/provisioners/docker_bashrc.sh +2 -0
  27. data/docker/provisioners/docker_rvm.sh +22 -0
  28. data/docker/provisioners/init_image.sh +28 -0
  29. data/docker/provisioners/post_install.sh +6 -0
  30. data/docker/provisioners/ruby.sh +16 -0
  31. data/docker/provisioners/upload_globals.sh +49 -0
  32. data/etc/bot_confs/.gitkeep +0 -0
  33. data/etc/bot_confs/BOT_CONF.TEMPLATE +10 -0
  34. data/etc/coinbase_pro.yaml.EXAMPLE +8 -0
  35. data/etc/open_ai.yaml.EXAMPLE +1 -0
  36. data/git_commit.sh +22 -0
  37. data/lib/cryptum/api.rb +688 -0
  38. data/lib/cryptum/bot_conf.rb +197 -0
  39. data/lib/cryptum/event/bot_conf.rb +34 -0
  40. data/lib/cryptum/event/buy.rb +145 -0
  41. data/lib/cryptum/event/cancel.rb +35 -0
  42. data/lib/cryptum/event/exit.rb +35 -0
  43. data/lib/cryptum/event/gtfo.rb +36 -0
  44. data/lib/cryptum/event/history.rb +108 -0
  45. data/lib/cryptum/event/key_press.rb +64 -0
  46. data/lib/cryptum/event/order_book.rb +34 -0
  47. data/lib/cryptum/event/pane.rb +65 -0
  48. data/lib/cryptum/event/parse.rb +181 -0
  49. data/lib/cryptum/event/scroll.rb +200 -0
  50. data/lib/cryptum/event/sell.rb +124 -0
  51. data/lib/cryptum/event.rb +27 -0
  52. data/lib/cryptum/log.rb +34 -0
  53. data/lib/cryptum/matrix.rb +181 -0
  54. data/lib/cryptum/open_ai.rb +156 -0
  55. data/lib/cryptum/option/choice.rb +28 -0
  56. data/lib/cryptum/option.rb +206 -0
  57. data/lib/cryptum/order_book/generate.rb +114 -0
  58. data/lib/cryptum/order_book/indicator.rb +15 -0
  59. data/lib/cryptum/order_book/market_trend.rb +137 -0
  60. data/lib/cryptum/order_book/profit_margin.rb +55 -0
  61. data/lib/cryptum/order_book.rb +19 -0
  62. data/lib/cryptum/portfolio/balance.rb +123 -0
  63. data/lib/cryptum/portfolio.rb +15 -0
  64. data/lib/cryptum/ui/command.rb +314 -0
  65. data/lib/cryptum/ui/key_press_event.rb +33 -0
  66. data/lib/cryptum/ui/market_trend.rb +77 -0
  67. data/lib/cryptum/ui/order_execute_details.rb +297 -0
  68. data/lib/cryptum/ui/order_execution.rb +583 -0
  69. data/lib/cryptum/ui/order_plan.rb +512 -0
  70. data/lib/cryptum/ui/order_plan_details.rb +240 -0
  71. data/lib/cryptum/ui/order_timer.rb +136 -0
  72. data/lib/cryptum/ui/portfolio.rb +221 -0
  73. data/lib/cryptum/ui/signal_engine.rb +109 -0
  74. data/lib/cryptum/ui/terminal_window.rb +111 -0
  75. data/lib/cryptum/ui/ticker.rb +319 -0
  76. data/lib/cryptum/ui.rb +343 -0
  77. data/lib/cryptum/version.rb +5 -0
  78. data/lib/cryptum/web_sock/coinbase.rb +104 -0
  79. data/lib/cryptum/web_sock/event_machine.rb +276 -0
  80. data/lib/cryptum/web_sock.rb +16 -0
  81. data/lib/cryptum.rb +120 -0
  82. data/order_books/.gitkeep +0 -0
  83. data/reinstall_cryptum_gemset.sh +29 -0
  84. data/spec/lib/cryptum/api_spec.rb +10 -0
  85. data/spec/lib/cryptum/event_spec.rb +10 -0
  86. data/spec/lib/cryptum/log_spec.rb +10 -0
  87. data/spec/lib/cryptum/option_spec.rb +10 -0
  88. data/spec/lib/cryptum/order_book/generate_spec.rb +10 -0
  89. data/spec/lib/cryptum/order_book/market_trend_spec.rb +10 -0
  90. data/spec/lib/cryptum/order_book_spec.rb +10 -0
  91. data/spec/lib/cryptum/ui/command_spec.rb +10 -0
  92. data/spec/lib/cryptum/ui/ticker_spec.rb +10 -0
  93. data/spec/lib/cryptum/ui_spec.rb +10 -0
  94. data/spec/lib/cryptum/web_sock_spec.rb +10 -0
  95. data/spec/lib/cryptum_spec.rb +10 -0
  96. data/spec/spec_helper.rb +3 -0
  97. data/upgrade_Gemfile_gems.sh +20 -0
  98. data/upgrade_cryptum.sh +13 -0
  99. data/upgrade_gem.sh +4 -0
  100. data/upgrade_ruby.sh +45 -0
  101. metadata +113 -10
data/lib/cryptum/ui.rb ADDED
@@ -0,0 +1,343 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'curses'
4
+ require 'time'
5
+
6
+ module Cryptum
7
+ # Cryptum::UI Module used for Presenting the
8
+ # Cryptum Curses Interface
9
+ module UI
10
+ require 'cryptum/ui/key_press_event'
11
+ require 'cryptum/ui/terminal_window'
12
+ require 'cryptum/ui/ticker'
13
+ require 'cryptum/ui/portfolio'
14
+ require 'cryptum/ui/order_plan'
15
+ require 'cryptum/ui/order_plan_details'
16
+ require 'cryptum/ui/order_timer'
17
+ require 'cryptum/ui/market_trend'
18
+ require 'cryptum/ui/signal_engine'
19
+ require 'cryptum/ui/order_execution'
20
+ require 'cryptum/ui/order_execute_details'
21
+ require 'cryptum/ui/command'
22
+
23
+ # Initialize the UI
24
+ public_class_method def self.init
25
+ # Initialize curses Screen
26
+ Curses.init_screen
27
+
28
+ # Ensure the cursor is invisible
29
+ Curses.curs_set(0)
30
+
31
+ # Do not echo keystrokes back to the UI
32
+ Curses.noecho
33
+
34
+ # Used to immediately evaluate characters submitted
35
+ # without pressing ENTER (e.g. b, r, & w key events)
36
+ Curses.crmode
37
+ # Curses.nocrmode
38
+ # Curses.raw # NO
39
+ # Curses.noraw
40
+ # Disable Line Buffering
41
+ Curses.ESCDELAY = 0
42
+
43
+ # Start Color!
44
+ Curses.start_color
45
+
46
+ # This is important to ensure -1 maintains
47
+ # the original background color in the terminal
48
+ # when defining color pairs
49
+ Curses.use_default_colors
50
+
51
+ # This object is used to pass all of the UI sections
52
+ # around to various Cryptum modules
53
+ Cryptum::UI::TerminalWindow.new
54
+ rescue Interrupt
55
+ # Exit Gracefully if CTRL+C is Pressed During Session
56
+ Cryptum.exit_gracefully(which_self: self)
57
+ rescue StandardError => e
58
+ # Produce a Stacktrace for anything else
59
+ Curses.close_screen
60
+ raise e
61
+ end
62
+
63
+ # Create New Curses Window
64
+ public_class_method def self.window(opts = {})
65
+ height = opts[:height].to_i
66
+ width = opts[:width].to_i
67
+ top = opts[:top].to_i
68
+ left = opts[:left].to_i
69
+
70
+ window = Curses::Window.new(
71
+ height,
72
+ width,
73
+ top,
74
+ left
75
+ )
76
+ window.nodelay = true
77
+
78
+ window
79
+ rescue Interrupt
80
+ # Exit Gracefully if CTRL+C is Pressed During Session
81
+ Cryptum.exit_gracefully(which_self: self)
82
+ rescue StandardError => e
83
+ # Produce a Stacktrace for anything else
84
+ Curses.close_screen
85
+ raise e
86
+ end
87
+
88
+ # Draw a Box Around a Window
89
+ public_class_method def self.line(opts = {})
90
+ ui_win = opts[:ui_win]
91
+ out_line_no = opts[:out_line_no].to_i
92
+ color = opts[:color]
93
+ color ||= :white
94
+
95
+ style = :normal
96
+ style = :bold unless color == :white
97
+
98
+ ui_win.setpos(out_line_no, 0)
99
+ colorize(
100
+ ui_win: ui_win,
101
+ color: color,
102
+ style: style,
103
+ string: "\u2500" * Curses.cols
104
+ )
105
+ rescue Interrupt
106
+ # Exit Gracefully if CTRL+C is Pressed During Session
107
+ Cryptum.exit_gracefully(which_self: self)
108
+ rescue StandardError => e
109
+ # Produce a Stacktrace for anything else
110
+ Curses.close_screen
111
+ raise e
112
+ end
113
+
114
+ # Jump to First Column
115
+ public_class_method def self.colorize(opts = {})
116
+ ui_win = opts[:ui_win]
117
+ color = opts[:color].to_s.to_sym
118
+ red = opts[:red].to_i
119
+ green = opts[:green].to_i
120
+ blue = opts[:blue].to_i
121
+
122
+ style = opts[:style].to_s.to_sym
123
+ style = :normal if opts[:style].nil?
124
+
125
+ bg = opts[:bg].to_i
126
+ bg = -1 if opts[:bg].nil?
127
+
128
+ string = opts[:string]
129
+
130
+ case color
131
+ when :black
132
+ # It's more Gray than Black
133
+ # color_id = 0
134
+ # color_fg = Curses::COLOR_BLACK
135
+ color_id = 256
136
+ Curses.init_color(color_id, 0, 0, 500)
137
+ color_fg = color_id
138
+ color_bg = bg
139
+ when :red
140
+ color_id = 1
141
+ color_fg = Curses::COLOR_RED
142
+ color_bg = bg
143
+ when :green
144
+ color_id = 2
145
+ color_fg = Curses::COLOR_GREEN
146
+ color_bg = bg
147
+ when :yellow
148
+ color_id = 3
149
+ color_fg = Curses::COLOR_YELLOW
150
+ color_bg = bg
151
+ when :blue
152
+ color_id = 4
153
+ color_fg = Curses::COLOR_BLUE
154
+ color_bg = bg
155
+ when :magenta
156
+ color_id = 5
157
+ color_fg = Curses::COLOR_MAGENTA
158
+ color_bg = bg
159
+ when :cyan
160
+ color_id = 6
161
+ color_fg = Curses::COLOR_CYAN
162
+ color_bg = bg
163
+ when :white
164
+ color_id = 7
165
+ color_fg = Curses::COLOR_WHITE
166
+ color_bg = bg
167
+ when :rainbow
168
+ color_id = 254
169
+ red = Random.rand(0..1000)
170
+ green = Random.rand(0..1000)
171
+ blue = Random.rand(0..1000)
172
+ Curses.init_color(color_id, red, green, blue)
173
+ color_fg = color_id
174
+ color_bg = bg
175
+ when :custom
176
+ color_id = 255
177
+ Curses.init_color(color_id, red, green, blue)
178
+ color_fg = color_id
179
+ color_bg = bg
180
+ else
181
+ raise "Color Not Implemented for this Method: #{color}"
182
+ end
183
+
184
+ case style
185
+ when :blink
186
+ font = Curses::A_BLINK
187
+ when :bold
188
+ font = Curses::A_BOLD
189
+ when :highlight
190
+ font = Curses::A_STANDOUT
191
+ when :normal
192
+ font = Curses::A_NORMAL
193
+ when :reverse
194
+ font = Curses::A_REVERSE
195
+ else
196
+ raise "Font Style Not Implemented for this Method: #{style}"
197
+ end
198
+
199
+ Curses.init_pair(color_id, color_fg, color_bg)
200
+ ui_win.attron(Curses.color_pair(color_id) | font) do
201
+ ui_win.addstr(string)
202
+ end
203
+ rescue Interrupt
204
+ # Exit Gracefully if CTRL+C is Pressed During Session
205
+ Cryptum.exit_gracefully(which_self: self)
206
+ rescue StandardError => e
207
+ # Produce a Stacktrace for anything else
208
+ Curses.close_screen
209
+ raise e
210
+ end
211
+
212
+ # Jump to First Column
213
+ public_class_method def self.col_center(opts = {})
214
+ str = opts[:str]
215
+
216
+ str_divided_by_two = str.length / 2
217
+ (Curses.cols / 2) - str_divided_by_two
218
+ rescue Interrupt
219
+ # Exit Gracefully if CTRL+C is Pressed During Session
220
+ Cryptum.exit_gracefully(which_self: self)
221
+ rescue StandardError => e
222
+ # Produce a Stacktrace for anything else
223
+ Curses.close_screen
224
+ raise e
225
+ end
226
+
227
+ public_class_method def self.col_first
228
+ 0
229
+ rescue Interrupt
230
+ # Exit Gracefully if CTRL+C is Pressed During Session
231
+ Cryptum.exit_gracefully(which_self: self)
232
+ rescue StandardError => e
233
+ # Produce a Stacktrace for anything else
234
+ Curses.close_screen
235
+ raise e
236
+ end
237
+
238
+ # Jump to Second Column
239
+ public_class_method def self.col_second
240
+ (Curses.cols / 8) + 5
241
+ rescue Interrupt
242
+ # Exit Gracefully if CTRL+C is Pressed During Session
243
+ Cryptum.exit_gracefully(which_self: self)
244
+ rescue StandardError => e
245
+ # Produce a Stacktrace for anything else
246
+ Curses.close_screen
247
+ raise e
248
+ end
249
+
250
+ # Jump to Third Column
251
+ public_class_method def self.col_third
252
+ ((Curses.cols / 8) * 3) + 2
253
+ rescue Interrupt
254
+ # Exit Gracefully if CTRL+C is Pressed During Session
255
+ Cryptum.exit_gracefully(which_self: self)
256
+ rescue StandardError => e
257
+ # Produce a Stacktrace for anything else
258
+ Curses.close_screen
259
+ raise e
260
+ end
261
+
262
+ # Jump to Fourth Column
263
+ public_class_method def self.col_fourth
264
+ ((Curses.cols / 4) * 3) - 3
265
+ rescue Interrupt
266
+ # Exit Gracefully if CTRL+C is Pressed During Session
267
+ Cryptum.exit_gracefully(which_self: self)
268
+ rescue StandardError => e
269
+ # Produce a Stacktrace for anything else
270
+ Curses.close_screen
271
+ raise e
272
+ end
273
+
274
+ public_class_method def self.detect_key_press_in_ui(opts = {})
275
+ key_press_event = opts[:key_press_event]
276
+ ui_win = opts[:ui_win]
277
+
278
+ key_press = ui_win.get_char
279
+
280
+ # Useful for detecting and logging actual key presses to file
281
+ # unless key_press.nil?
282
+ # File.open('/tmp/detect_key_press_in_ui-cryptum.txt', 'a') do |f|
283
+ # f.puts key_press.class
284
+ # f.print key_press.inspect
285
+ # f.puts "\n\n\n"
286
+ # end
287
+ # end
288
+
289
+ case key_press
290
+ when 'C'
291
+ key_press_event.key_c = true
292
+ when 'G'
293
+ key_press_event.key_g = true
294
+ when 'r'
295
+ key_press_event.key_r = true
296
+ when 'u'
297
+ key_press_event.key_u = true
298
+ when 'w'
299
+ key_press_event.key_w = true
300
+ when 'x'
301
+ key_press_event.key_x = true
302
+ when "\e"
303
+ key_press_event.key_esc = true
304
+ when "\n"
305
+ key_press_event.key_enter = true
306
+ when "\t"
307
+ key_press_event.key_tab = true
308
+ end
309
+
310
+ # What a hack to detect special keys (-.-)
311
+ if key_press_event.key_esc
312
+ key_press_event.key_ansi = true if key_press == '['
313
+ if key_press_event.key_ansi
314
+ key_press_event.key_up_arrow = true if key_press == 'A'
315
+ key_press_event.key_down_arrow = true if key_press == 'B'
316
+ # NOTE: the ~ at the end of these keys are ignored
317
+ # which may result in other keys working in place of them
318
+ # e.g. home is \e[1~ but we know it's home as soon as
319
+ # \e[1 is detected.
320
+ key_press_event.key_page_up = true if key_press == '5'
321
+ key_press_event.key_page_down = true if key_press == '6'
322
+ key_press_event.key_home = true if key_press == '1'
323
+ key_press_event.key_end = true if key_press == '4'
324
+ end
325
+ end
326
+
327
+ key_press_event
328
+ rescue Interrupt
329
+ # Exit Gracefully if CTRL+C is Pressed During Session
330
+ Cryptum.exit_gracefully(which_self: self)
331
+ rescue StandardError => e
332
+ # Produce a Stacktrace for anything else
333
+ Curses.close_screen
334
+ raise e
335
+ end
336
+
337
+ # Display a List of Every UI Module
338
+
339
+ public_class_method def self.help
340
+ constants.sort
341
+ end
342
+ end
343
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cryptum
4
+ VERSION = '0.0.361'
5
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faye/websocket'
4
+ require 'websocket/extensions'
5
+ require 'permessage_deflate'
6
+
7
+ module Cryptum
8
+ # This plugin is used to Establish a Web
9
+ # Socket Connection with Coinbase
10
+ module WebSock
11
+ # This module is used to Establish a Web
12
+ # Socket Connection with Coinbase
13
+ module Coinbase
14
+ # Supported Method Parameters::
15
+ # Cryptum::WebSock.connect(
16
+ # )
17
+ public_class_method def self.connect(opts = {})
18
+ option_choice = opts[:option_choice]
19
+ env = opts[:env]
20
+
21
+ # cb_pro_ws_feed = 'wss://ws-feed.pro.coinbase.com'
22
+ # cb_pro_ws_feed = 'wss://ws-feed-public.sandbox.pro.coinbase.com' if env[:env] == :sandbox
23
+ cb_pro_ws_feed = 'wss://ws-feed.exchange.coinbase.com'
24
+ cb_pro_ws_feed = 'wss://ws-feed-public.sandbox.exchange.coinbase.com' if env[:env] == :sandbox
25
+
26
+ extensions = [PermessageDeflate]
27
+
28
+ if option_choice.proxy
29
+ tls_opts = {
30
+ verify_peer: false
31
+ }
32
+
33
+ proxy_opts = {
34
+ origin: option_choice.proxy
35
+ }
36
+
37
+ ws = Faye::WebSocket::Client.new(
38
+ cb_pro_ws_feed,
39
+ [],
40
+ tls: tls_opts,
41
+ proxy: proxy_opts,
42
+ extensions: extensions,
43
+ ping: 9
44
+ )
45
+ else
46
+ ws = Faye::WebSocket::Client.new(
47
+ cb_pro_ws_feed,
48
+ [],
49
+ extensions: extensions,
50
+ ping: 9
51
+ )
52
+ end
53
+
54
+ ws
55
+ rescue Interrupt
56
+ # Exit Gracefully if CTRL+C is Pressed During Session
57
+ Cryptum.exit_gracefully(which_self: self)
58
+ rescue StandardError => e
59
+ raise e
60
+ end
61
+
62
+ public_class_method def self.subscribe_message(opts = {})
63
+ option_choice = opts[:option_choice]
64
+ env = opts[:env]
65
+ product_id = option_choice.symbol.to_s.gsub('_', '-').upcase
66
+
67
+ api_secret = env[:api_secret]
68
+ api_signature_response = Cryptum::API.generate_signature(
69
+ api_secret: api_secret
70
+ )
71
+ api_key = env[:api_key]
72
+ api_passphrase = env[:api_passphrase]
73
+ api_timestamp = api_signature_response[:api_timestamp]
74
+ api_signature = api_signature_response[:api_signature]
75
+
76
+ "{
77
+ \"type\": \"subscribe\",
78
+ \"product_ids\": [
79
+ \"#{product_id}\"
80
+ ],
81
+ \"channels\": [
82
+ \"level2_batch\",
83
+ \"ticker\",
84
+ \"user\"
85
+ ],
86
+ \"key\": \"#{api_key}\",
87
+ \"passphrase\": \"#{api_passphrase}\",
88
+ \"timestamp\": \"#{api_timestamp}\",
89
+ \"signature\": \"#{api_signature}\"
90
+ }"
91
+ rescue StandardError => e
92
+ raise e
93
+ end
94
+
95
+ # Display Usage for this Module
96
+
97
+ public_class_method def self.help
98
+ puts "USAGE:
99
+ logger = #{self}.create()
100
+ "
101
+ end
102
+ end
103
+ end
104
+ end