cryptum 0.0.230

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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  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 +5 -0
  7. data/.rubocop_todo.yml +250 -0
  8. data/.ruby-gemset +1 -0
  9. data/.ruby-version +1 -0
  10. data/CODE_OF_CONDUCT.md +84 -0
  11. data/Gemfile +36 -0
  12. data/LICENSE +674 -0
  13. data/README.md +72 -0
  14. data/Rakefile +19 -0
  15. data/bin/cryptum +72 -0
  16. data/bin/cryptum-forecast +199 -0
  17. data/bin/cryptum-repl +73 -0
  18. data/bin/cryptum_autoinc_version +38 -0
  19. data/build_cryptum_gem.sh +52 -0
  20. data/cryptum.gemspec +50 -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/git_commit.sh +22 -0
  36. data/lib/cryptum/api.rb +693 -0
  37. data/lib/cryptum/bot_conf.rb +76 -0
  38. data/lib/cryptum/event/buy.rb +144 -0
  39. data/lib/cryptum/event/cancel.rb +49 -0
  40. data/lib/cryptum/event/history.rb +64 -0
  41. data/lib/cryptum/event/key_press.rb +64 -0
  42. data/lib/cryptum/event/sell.rb +120 -0
  43. data/lib/cryptum/event.rb +168 -0
  44. data/lib/cryptum/log.rb +34 -0
  45. data/lib/cryptum/matrix.rb +181 -0
  46. data/lib/cryptum/option/choice.rb +26 -0
  47. data/lib/cryptum/option.rb +161 -0
  48. data/lib/cryptum/order_book/generate.rb +111 -0
  49. data/lib/cryptum/order_book/indicator.rb +16 -0
  50. data/lib/cryptum/order_book/market_trend.rb +161 -0
  51. data/lib/cryptum/order_book/profit_margin.rb +55 -0
  52. data/lib/cryptum/order_book/weighted_avg.rb +157 -0
  53. data/lib/cryptum/order_book.rb +156 -0
  54. data/lib/cryptum/portfolio/balance.rb +123 -0
  55. data/lib/cryptum/portfolio.rb +15 -0
  56. data/lib/cryptum/ui/command.rb +274 -0
  57. data/lib/cryptum/ui/key_press_event.rb +22 -0
  58. data/lib/cryptum/ui/market_trend.rb +117 -0
  59. data/lib/cryptum/ui/order_execution.rb +478 -0
  60. data/lib/cryptum/ui/order_plan.rb +376 -0
  61. data/lib/cryptum/ui/order_timer.rb +119 -0
  62. data/lib/cryptum/ui/portfolio.rb +231 -0
  63. data/lib/cryptum/ui/signal_engine.rb +122 -0
  64. data/lib/cryptum/ui/terminal_window.rb +95 -0
  65. data/lib/cryptum/ui/ticker.rb +317 -0
  66. data/lib/cryptum/ui.rb +306 -0
  67. data/lib/cryptum/version.rb +5 -0
  68. data/lib/cryptum/web_sock/coinbase.rb +94 -0
  69. data/lib/cryptum/web_sock/event_machine.rb +182 -0
  70. data/lib/cryptum/web_sock.rb +16 -0
  71. data/lib/cryptum.rb +183 -0
  72. data/order_books/.gitkeep +0 -0
  73. data/reinstall_cryptum_gemset.sh +29 -0
  74. data/spec/lib/cryptum/api_spec.rb +10 -0
  75. data/spec/lib/cryptum/event_spec.rb +10 -0
  76. data/spec/lib/cryptum/log_spec.rb +10 -0
  77. data/spec/lib/cryptum/option_spec.rb +10 -0
  78. data/spec/lib/cryptum/order_book/generate_spec.rb +10 -0
  79. data/spec/lib/cryptum/order_book/market_trend_spec.rb +10 -0
  80. data/spec/lib/cryptum/order_book_spec.rb +10 -0
  81. data/spec/lib/cryptum/ui/command_spec.rb +10 -0
  82. data/spec/lib/cryptum/ui/ticker_spec.rb +10 -0
  83. data/spec/lib/cryptum/ui_spec.rb +10 -0
  84. data/spec/lib/cryptum/web_sock_spec.rb +10 -0
  85. data/spec/lib/cryptum_spec.rb +10 -0
  86. data/spec/spec_helper.rb +3 -0
  87. data/upgrade_Gemfile_gems.sh +20 -0
  88. data/upgrade_cryptum.sh +13 -0
  89. data/upgrade_gem.sh +4 -0
  90. data/upgrade_ruby.sh +46 -0
  91. metadata +472 -0
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cryptum
4
+ # This plugin is used to indicate if the
5
+ # Projected Profit Margin is greater than
6
+ # the Target Profit Margin Outlined in the
7
+ # Respective Bot Conf
8
+
9
+ module OrderBook
10
+ module ProfitMargin
11
+ # Supported Method Parameters::
12
+ # Cryptum::OrderBook::ProfitMargin.status(
13
+ # )
14
+
15
+ public_class_method def self.status(opts = {})
16
+ indicator_hash = {}
17
+ target_profit_margin_percent = opts[:target_profit_margin_percent]
18
+ total_invested = opts[:total_invested]
19
+ total_projected_return = opts[:total_projected_return]
20
+ indicator_status = opts[:indicator_status]
21
+ invested = opts[:invested]
22
+
23
+ ave_profit_margin_percent = 100 - ((total_invested / total_projected_return) * 100)
24
+
25
+ if ave_profit_margin_percent > target_profit_margin_percent
26
+ indicator_hash[:color] = :green
27
+ pm_op = '>'
28
+ elsif ave_profit_margin_percent < target_profit_margin_percent
29
+ indicator_hash[:color] = :red
30
+ pm_op = '<'
31
+ else
32
+ indicator_hash[:color] = :yellow
33
+ pm_op = '=='
34
+ end
35
+
36
+ profit_margin_status_out = "Profit Margin #{pm_op} TPM"
37
+ indicator_hash[:invested] = invested
38
+ indicator_hash[:status] = profit_margin_status_out
39
+
40
+ indicator_status.profit_margin = indicator_hash
41
+ rescue StandardError => e
42
+ raise e
43
+ end
44
+
45
+ # Display Usage for this Module
46
+
47
+ public_class_method def self.help
48
+ puts "USAGE:
49
+ weighted_ave_indicator_hash = #{self}.status(
50
+ )
51
+ "
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cryptum
4
+ # This plugin is used to indicate if the Weighted Executed Buy Orders are less than the Weighted Excuted Sell Orders
5
+
6
+ module OrderBook
7
+ module WeightedAvg
8
+ # Supported Method Parameters::
9
+ # Cryptum::OrderBook::WeightedAvg.status(
10
+ # order_book: 'required - order_book data structure'
11
+ # )
12
+
13
+ public_class_method def self.status(opts = {})
14
+ order_book = opts[:order_book]
15
+ order_history = order_book[:order_history]
16
+ indicator_status = opts[:indicator_status]
17
+ invested = opts[:invested]
18
+
19
+ indicator_hash = {}
20
+ indicator_hash[:invested] = invested
21
+
22
+ buy_orders_done = order_history.select do |orders|
23
+ orders[:side] == 'buy' &&
24
+ orders[:status] == 'done' &&
25
+ orders[:done_reason] == 'filled'
26
+ end
27
+
28
+ total_buy_orders_done = buy_orders_done.length
29
+ avg_buy_exec = format('%0.7f', 0.00).to_f
30
+ # total_buy_executed = 0.00
31
+ # total_invested = 0.00
32
+ # buy_fees = 0.00
33
+ if total_buy_orders_done.positive?
34
+ # Calculate Weighted Avg. of Completed Buy Orders
35
+ weighted_buy_prices_arr = []
36
+ buy_orders_done.each do |order|
37
+ weighted_hash = {}
38
+ executed_value = order[:executed_value].to_f
39
+ filled_size = order[:filled_size].to_f
40
+ weighted_hash[:price] = (executed_value / filled_size).to_f
41
+ weighted_hash[:filled_size] = filled_size
42
+ weighted_hash[:price_times_filled_size] = weighted_hash[:price] * filled_size
43
+ weighted_buy_prices_arr.push(weighted_hash)
44
+ end
45
+
46
+ price_times_filled_size = weighted_buy_prices_arr.sum do |orders|
47
+ orders[:price_times_filled_size].to_f
48
+ end
49
+
50
+ this_filled_size = weighted_buy_prices_arr.sum do |orders|
51
+ orders[:filled_size]
52
+ end
53
+
54
+ calc_avg_buy_exec = price_times_filled_size / this_filled_size
55
+ avg_buy_exec = format('%0.7f', calc_avg_buy_exec).to_f
56
+
57
+ executed_value = buy_orders_done.sum do |orders|
58
+ orders[:executed_value].to_f
59
+ end
60
+
61
+ # total_buy_executed = format('%0.7f', executed_value).to_f
62
+
63
+ # fill_fees = buy_orders_done.sum do |orders|
64
+ # orders[:fill_fees].to_f
65
+ # end
66
+
67
+ # buy_fees = format('%0.7f', fill_fees).to_f
68
+
69
+ # calc_total_invested = total_buy_executed.to_f - buy_fees.to_f
70
+ # total_invested = format('%0.7f', calc_total_invested).to_f
71
+ end
72
+ order_book[:avg_buy_exec] = avg_buy_exec
73
+
74
+ sell_orders_done = order_history.select do |orders|
75
+ orders[:side] == 'sell' &&
76
+ orders[:status] == 'done' &&
77
+ orders[:done_reason] == 'filled'
78
+ end
79
+
80
+ total_sell_orders_done = sell_orders_done.length
81
+ avg_sell_exec = format('%0.7f', 0.00).to_f
82
+ # total_sell_executed = format('%0.7f', 0.00).to_f
83
+ # total_return = format('%0.7f', 0.00).to_f
84
+ # sell_fees = format('%0.7f', 0.00).to_f
85
+ if total_sell_orders_done.positive?
86
+ # Calculate Weighted Avg. of Completed Sell Orders
87
+ weighted_sell_prices_arr = []
88
+ sell_orders_done.each do |order|
89
+ weighted_hash = {}
90
+ executed_value = order[:executed_value].to_f
91
+ filled_size = order[:filled_size].to_f
92
+ weighted_hash[:price] = (executed_value / filled_size).to_f
93
+ weighted_hash[:filled_size] = filled_size
94
+ weighted_hash[:price_times_filled_size] = weighted_hash[:price] * filled_size
95
+ weighted_sell_prices_arr.push(weighted_hash)
96
+ end
97
+
98
+ price_times_filled_size = weighted_sell_prices_arr.sum do |orders|
99
+ orders[:price_times_filled_size].to_f
100
+ end
101
+
102
+ this_filled_size = weighted_sell_prices_arr.sum do |orders|
103
+ orders[:filled_size]
104
+ end
105
+
106
+ calc_avg_sell_exec = price_times_filled_size / this_filled_size
107
+ avg_sell_exec = format('%0.7f', calc_avg_sell_exec).to_f
108
+
109
+ executed_value = sell_orders_done.sum do |orders|
110
+ orders[:executed_value].to_f
111
+ end
112
+
113
+ # total_sell_executed = format('%0.7f', executed_value).to_f
114
+
115
+ # fill_fees = sell_orders_done.sum do |orders|
116
+ # orders[:fill_fees].to_f
117
+ # end
118
+
119
+ # sell_fees = format('%0.7f', fill_fees).to_f
120
+ # calc_total_made = total_sell_executed.to_f - sell_fees.to_f
121
+ # total_return = format('%0.7f', calc_total_made).to_f
122
+ end
123
+ order_book[:avg_sell_exec] = avg_sell_exec
124
+
125
+ if avg_buy_exec < avg_sell_exec
126
+ indicator_hash[:color] = :green
127
+ weight_op = '<'
128
+ elsif avg_buy_exec > avg_sell_exec
129
+ indicator_hash[:color] = :red
130
+ weight_op = '>'
131
+ else
132
+ indicator_hash[:color] = :yellow
133
+ weight_op = '=='
134
+ end
135
+ weighted_avg_status_out = "VWAPB #{weight_op} VWAPS"
136
+ order_book[:candles].last[:weighted_avg_status] = weighted_avg_status_out
137
+ indicator_hash[:status] = weighted_avg_status_out
138
+ # indicator_hash[:order_book] = order_book
139
+
140
+ indicator_status.weighted_avg = indicator_hash
141
+ # indicator_hash
142
+ rescue StandardError => e
143
+ raise e
144
+ end
145
+
146
+ # Display Usage for this Module
147
+
148
+ public_class_method def self.help
149
+ puts "USAGE:
150
+ weighted_avg_indicator_hash = #{self}.status(
151
+ order_book: 'required - order_book data structure'
152
+ )
153
+ "
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'logger'
5
+
6
+ module Cryptum
7
+ # This module is used to define the Order Book Data Structure
8
+ module OrderBook
9
+ autoload :Generate, 'cryptum/order_book/generate'
10
+ autoload :Indicator, 'cryptum/order_book/indicator'
11
+ autoload :MarketTrend, 'cryptum/order_book/market_trend'
12
+ autoload :ProfitMargin, 'cryptum/order_book/profit_margin'
13
+
14
+ # Supported Method Parameters::
15
+ # Cryptum::OrderBook.get_populated_indicators(
16
+ # indicator_status: 'required - indicator_status object instantiated via Cryptum::OrderBook::Indicators'
17
+ # )
18
+ public_class_method def self.get_populated_indicators(opts = {})
19
+ indicator_status = opts[:indicator_status]
20
+
21
+ indicator_type_hash = {}
22
+ indicator_type_hash[:trend_indicator_arr] = []
23
+ trend_indicator_arr = indicator_type_hash[:trend_indicator_arr]
24
+
25
+ indicator_type_hash[:health_indicator_arr] = []
26
+ health_indicator_arr = indicator_type_hash[:health_indicator_arr]
27
+
28
+ if indicator_status.order_trend
29
+ trend_indicator_arr.push(
30
+ indicator_status.order_trend
31
+ )
32
+ end
33
+
34
+ if indicator_status.weighted_avg
35
+ health_indicator_arr.push(
36
+ indicator_status.weighted_avg
37
+ )
38
+ end
39
+
40
+ if indicator_status.profit_margin
41
+ health_indicator_arr.push(
42
+ indicator_status.profit_margin
43
+ )
44
+ end
45
+
46
+ indicator_type_hash
47
+ rescue StandardError => e
48
+ raise e
49
+ end
50
+
51
+ # Supported Method Parameters::
52
+ # base_currency_overrides = Cryptum::OrderBook.base_currency_overrides
53
+ public_class_method def self.base_currency_overrides
54
+ %i[
55
+ 1inch
56
+ aave
57
+ ada
58
+ amp
59
+ ankr
60
+ bal
61
+ band
62
+ bat
63
+ bnt
64
+ bond
65
+ cgld
66
+ chz
67
+ clv
68
+ comp
69
+ crv
70
+ ctsi
71
+ dot
72
+ enj
73
+ farm
74
+ fet
75
+ fil
76
+ forth
77
+ grt
78
+ gtc
79
+ icp
80
+ keep
81
+ lpt
82
+ lrc
83
+ mana
84
+ mask
85
+ matic
86
+ mir
87
+ mkr
88
+ mln
89
+ nkn
90
+ nmr
91
+ nu
92
+ ogn
93
+ poly
94
+ qnt
95
+ ren
96
+ rly
97
+ shib
98
+ skl
99
+ snx
100
+ sol
101
+ storj
102
+ sushi
103
+ trb
104
+ tribe
105
+ uma
106
+ uni
107
+ wbtc
108
+ yfi
109
+ zrx
110
+ ]
111
+ rescue StandardError => e
112
+ raise e
113
+ end
114
+
115
+ # Supported Method Parameters::
116
+ # Cryptum::OrderBook.analyze(
117
+ # order_book_file: 'required - path to order book file'
118
+ # )
119
+ public_class_method def self.analyze(opts = {})
120
+ order_book_file = opts[:order_book_file]
121
+ option_choice = opts[:option_choice]
122
+ # TODO: Handle File that exists
123
+ # w/ Zero size...N number of
124
+ # attempts? Timeout may be better.
125
+ order_book = JSON.parse(
126
+ File.read(order_book_file),
127
+ symbolize_names: true
128
+ )
129
+
130
+ order_book[:option_choice] = option_choice
131
+
132
+ bot_conf = Cryptum::BotConf.read(option_choice: option_choice)
133
+ order_book[:bot_conf] = bot_conf
134
+
135
+ env = Cryptum::Option.get_env(option_choice: option_choice)
136
+ order_book[:env] = env
137
+
138
+ order_book
139
+ rescue JSON::ParserError => e
140
+ File.open('/tmp/cryptum-errors.txt', 'a') do |f|
141
+ f.puts Time.now.strftime('%Y-%m-%d %H:%M:%S.%N %z')
142
+ f.puts "Module: #{self}"
143
+ f.puts "#{e}\n\n\n"
144
+ end
145
+
146
+ retry
147
+ rescue StandardError => e
148
+ raise e
149
+ end
150
+
151
+ # Display Usage for this Module
152
+ public_class_method def self.help
153
+ constants.sort
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Cryptum
6
+ # This plugin is used to instantiate a Cryptum logger with a custom message format
7
+ module Portfolio
8
+ module Balance
9
+ # Supported Method Parameters::
10
+ # Cryptum::Event::Update.summary(
11
+ # )
12
+ public_class_method def self.refresh(opts = {})
13
+ option_choice = opts[:option_choice]
14
+ env = opts[:env]
15
+ terminal_win = opts[:terminal_win]
16
+ event_history = opts[:event_history]
17
+ fiat_portfolio_file = opts[:fiat_portfolio_file]
18
+
19
+ this_product = event_history.order_book[:this_product]
20
+ crypto = this_product[:base_currency]
21
+ fiat = this_product[:quote_currency]
22
+
23
+ if event_history.first_event ||
24
+ event_history.reconnected ||
25
+ event_history.event_type == :received ||
26
+ event_history.event_type == :open ||
27
+ event_history.event_type == :done ||
28
+ event_history.event_type == :match ||
29
+ event_history.event_type == :change ||
30
+ event_history.event_type == :activate ||
31
+ terminal_win.key_press_event.key_u
32
+
33
+ etype = event_history.event_type
34
+ manual_refresh = terminal_win.key_press_event.key_u
35
+ etype = :manual_refresh if manual_refresh
36
+ etype = :first_event if event_history.first_event
37
+ etype = :reconnected if event_history.reconnected
38
+ event_history.event_type = etype
39
+
40
+ # Prevent Multiple Order Events from Occuring --- #
41
+ ocancel = event_history.order_canceled
42
+ osubmit = event_history.order_submitted
43
+
44
+ # POTENTIAL STOP IN ORDERS WHEN
45
+ # event_history.order_canceled = true
46
+ # Verify it's not due to EMA being red.
47
+ # ocancel = false if (etype == :open || etype == :done) &&
48
+ # osubmit == false &&
49
+ # !manual_refresh
50
+
51
+ ocancel = false if etype == :done &&
52
+ osubmit == true &&
53
+ !manual_refresh
54
+
55
+ event_history.order_canceled = ocancel
56
+
57
+ osubmit = false if etype == :done &&
58
+ !manual_refresh
59
+
60
+ event_history.order_submitted = osubmit
61
+ # ---------------------------------------------- #
62
+
63
+ enotes = event_history.event_notes
64
+ enotes = "{ \"event_type\": \"#{etype}\", \"cancel\": \"#{ocancel}\", \"submitted\": \"#{osubmit}\" }" if option_choice.proxy
65
+ event_history.event_notes = enotes
66
+
67
+ portfolio = Cryptum::API.get_portfolio(
68
+ option_choice: option_choice,
69
+ env: env,
70
+ crypto: crypto,
71
+ fiat: fiat,
72
+ fiat_portfolio_file: fiat_portfolio_file,
73
+ event_notes: event_history.event_notes
74
+ )
75
+ event_history.order_book[:portfolio] = portfolio unless portfolio.empty?
76
+
77
+ order_history = Cryptum::API.get_order_history(
78
+ option_choice: option_choice,
79
+ env: env
80
+ )
81
+ event_history.order_book[:order_history] = order_history unless order_history.empty?
82
+
83
+ fees = Cryptum::API.get_fees(
84
+ option_choice: option_choice,
85
+ env: env
86
+ )
87
+ event_history.order_book[:fees] = fees unless fees.empty?
88
+
89
+ terminal_win.key_press_event.key_u = false if manual_refresh
90
+ # First Event to Refresh No Longer Needed
91
+ event_history.first_event = false
92
+ # Reconnected Event to Refresh No Longer Needed
93
+ event_history.reconnected = false
94
+ end
95
+
96
+ # Always reload fiat portfolio as it's shared
97
+ # by all sessions (unless it's empty)
98
+ fpf = ''
99
+ fpf = File.read(fiat_portfolio_file) unless File.empty?(
100
+ fiat_portfolio_file
101
+ )
102
+
103
+ unless fpf.empty?
104
+ event_history.order_book[:fiat_portfolio] = JSON.parse(
105
+ fpf,
106
+ symbolize_names: true
107
+ )
108
+ end
109
+
110
+ event_history
111
+ rescue StandardError => e
112
+ raise e
113
+ end
114
+
115
+ # Display Usage for this Module
116
+ public_class_method def self.help
117
+ puts "USAGE:
118
+ event_history.order_book = #{self}.crypto()
119
+ "
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Cryptum
6
+ # This plugin is used to instantiate a Cryptum logger with a custom message format
7
+ module Portfolio
8
+ autoload :Balance, 'cryptum/portfolio/balance'
9
+
10
+ # Display Usage for this Module
11
+ public_class_method def self.help
12
+ constants.sort
13
+ end
14
+ end
15
+ end