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.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +16 -0
- data/.gitignore +30 -0
- data/.rspec +3 -0
- data/.rspec_status +0 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +250 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +36 -0
- data/LICENSE +674 -0
- data/README.md +72 -0
- data/Rakefile +19 -0
- data/bin/cryptum +72 -0
- data/bin/cryptum-forecast +199 -0
- data/bin/cryptum-repl +73 -0
- data/bin/cryptum_autoinc_version +38 -0
- data/build_cryptum_gem.sh +52 -0
- data/cryptum.gemspec +50 -0
- data/cryptum_container.sh +1 -0
- data/docker/cryptum.json +60 -0
- data/docker/cryptum_container.sh +59 -0
- data/docker/packer_secrets.json.EXAMPLE +7 -0
- data/docker/provisioners/cryptum.sh +11 -0
- data/docker/provisioners/docker_bashrc.sh +2 -0
- data/docker/provisioners/docker_rvm.sh +22 -0
- data/docker/provisioners/init_image.sh +28 -0
- data/docker/provisioners/post_install.sh +6 -0
- data/docker/provisioners/ruby.sh +16 -0
- data/docker/provisioners/upload_globals.sh +49 -0
- data/etc/bot_confs/.gitkeep +0 -0
- data/etc/bot_confs/BOT_CONF.TEMPLATE +10 -0
- data/etc/coinbase_pro.yaml.EXAMPLE +8 -0
- data/git_commit.sh +22 -0
- data/lib/cryptum/api.rb +693 -0
- data/lib/cryptum/bot_conf.rb +76 -0
- data/lib/cryptum/event/buy.rb +144 -0
- data/lib/cryptum/event/cancel.rb +49 -0
- data/lib/cryptum/event/history.rb +64 -0
- data/lib/cryptum/event/key_press.rb +64 -0
- data/lib/cryptum/event/sell.rb +120 -0
- data/lib/cryptum/event.rb +168 -0
- data/lib/cryptum/log.rb +34 -0
- data/lib/cryptum/matrix.rb +181 -0
- data/lib/cryptum/option/choice.rb +26 -0
- data/lib/cryptum/option.rb +161 -0
- data/lib/cryptum/order_book/generate.rb +111 -0
- data/lib/cryptum/order_book/indicator.rb +16 -0
- data/lib/cryptum/order_book/market_trend.rb +161 -0
- data/lib/cryptum/order_book/profit_margin.rb +55 -0
- data/lib/cryptum/order_book/weighted_avg.rb +157 -0
- data/lib/cryptum/order_book.rb +156 -0
- data/lib/cryptum/portfolio/balance.rb +123 -0
- data/lib/cryptum/portfolio.rb +15 -0
- data/lib/cryptum/ui/command.rb +274 -0
- data/lib/cryptum/ui/key_press_event.rb +22 -0
- data/lib/cryptum/ui/market_trend.rb +117 -0
- data/lib/cryptum/ui/order_execution.rb +478 -0
- data/lib/cryptum/ui/order_plan.rb +376 -0
- data/lib/cryptum/ui/order_timer.rb +119 -0
- data/lib/cryptum/ui/portfolio.rb +231 -0
- data/lib/cryptum/ui/signal_engine.rb +122 -0
- data/lib/cryptum/ui/terminal_window.rb +95 -0
- data/lib/cryptum/ui/ticker.rb +317 -0
- data/lib/cryptum/ui.rb +306 -0
- data/lib/cryptum/version.rb +5 -0
- data/lib/cryptum/web_sock/coinbase.rb +94 -0
- data/lib/cryptum/web_sock/event_machine.rb +182 -0
- data/lib/cryptum/web_sock.rb +16 -0
- data/lib/cryptum.rb +183 -0
- data/order_books/.gitkeep +0 -0
- data/reinstall_cryptum_gemset.sh +29 -0
- data/spec/lib/cryptum/api_spec.rb +10 -0
- data/spec/lib/cryptum/event_spec.rb +10 -0
- data/spec/lib/cryptum/log_spec.rb +10 -0
- data/spec/lib/cryptum/option_spec.rb +10 -0
- data/spec/lib/cryptum/order_book/generate_spec.rb +10 -0
- data/spec/lib/cryptum/order_book/market_trend_spec.rb +10 -0
- data/spec/lib/cryptum/order_book_spec.rb +10 -0
- data/spec/lib/cryptum/ui/command_spec.rb +10 -0
- data/spec/lib/cryptum/ui/ticker_spec.rb +10 -0
- data/spec/lib/cryptum/ui_spec.rb +10 -0
- data/spec/lib/cryptum/web_sock_spec.rb +10 -0
- data/spec/lib/cryptum_spec.rb +10 -0
- data/spec/spec_helper.rb +3 -0
- data/upgrade_Gemfile_gems.sh +20 -0
- data/upgrade_cryptum.sh +13 -0
- data/upgrade_gem.sh +4 -0
- data/upgrade_ruby.sh +46 -0
- metadata +472 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Cryptum
|
6
|
+
# This plugin is used to read and update bot conf files.
|
7
|
+
module BotConf
|
8
|
+
# Deserialize Cryptum Bot Conf
|
9
|
+
public_class_method def self.read(opts = {})
|
10
|
+
option_choice = opts[:option_choice]
|
11
|
+
|
12
|
+
bot_conf_file = "#{option_choice.repo_root}/etc/bot_confs/#{option_choice.symbol}_bot_conf.yaml"
|
13
|
+
unless File.exist?(bot_conf_file)
|
14
|
+
FileUtils.cp(
|
15
|
+
"#{option_choice.repo_root}/etc/bot_confs/BOT_CONF.TEMPLATE",
|
16
|
+
bot_conf_file
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
YAML.load_file(
|
21
|
+
bot_conf_file,
|
22
|
+
symbolize_names: true
|
23
|
+
)
|
24
|
+
rescue Errno::ENOENT, NoMethodError => e
|
25
|
+
File.open('/tmp/cryptum-errors.txt', 'a') do |f|
|
26
|
+
f.puts Time.now.strftime('%Y-%m-%d %H:%M:%S.%N %z')
|
27
|
+
f.puts "Module: #{self}"
|
28
|
+
f.puts "#{e}\n\n\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
retry
|
32
|
+
rescue Interrupt
|
33
|
+
# Exit Gracefully if CTRL+C is Pressed During Session
|
34
|
+
Cryptum.exit_gracefully(which_self: self)
|
35
|
+
rescue StandardError => e
|
36
|
+
# Produce a Stacktrace for anything else
|
37
|
+
Curses.close_screen
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
|
41
|
+
# Update Key/Value Pair in Bot Conf and Serialize to YAML File
|
42
|
+
public_class_method def self.update(opts = {})
|
43
|
+
option_choice = opts[:option_choice]
|
44
|
+
bot_conf = opts[:bot_conf]
|
45
|
+
key = opts[:key].to_s.to_sym
|
46
|
+
value = opts[:value]
|
47
|
+
|
48
|
+
bot_conf_file = "#{option_choice.repo_root}/etc/bot_confs/#{option_choice.symbol}_bot_conf.yaml"
|
49
|
+
|
50
|
+
bot_conf[key] = value
|
51
|
+
File.write(bot_conf_file, bot_conf.to_yaml)
|
52
|
+
rescue Errno::ENOENT, NoMethodError => e
|
53
|
+
File.open('/tmp/cryptum-errors.txt', 'a') do |f|
|
54
|
+
f.puts Time.now.strftime('%Y-%m-%d %H:%M:%S.%N %z')
|
55
|
+
f.puts "Module: #{self}"
|
56
|
+
f.puts "#{e}\n\n\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
retry
|
60
|
+
rescue Interrupt
|
61
|
+
# Exit Gracefully if CTRL+C is Pressed During Session
|
62
|
+
Cryptum.exit_gracefully(which_self: self)
|
63
|
+
rescue StandardError => e
|
64
|
+
# Produce a Stacktrace for anything else
|
65
|
+
Curses.close_screen
|
66
|
+
raise e
|
67
|
+
end
|
68
|
+
# Display Usage for this Module
|
69
|
+
|
70
|
+
public_class_method def self.help
|
71
|
+
puts "USAGE:
|
72
|
+
logger = #{self}.create()
|
73
|
+
"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cryptum
|
4
|
+
# This plugin is used to Submit a Limit Order
|
5
|
+
# to Buy Crypto Currency
|
6
|
+
|
7
|
+
module Event
|
8
|
+
module Buy
|
9
|
+
# Supported Method Parameters::
|
10
|
+
# Cryptum::Event::Buy.crypto(
|
11
|
+
# )
|
12
|
+
public_class_method def self.crypto(opts = {})
|
13
|
+
option_choice = opts[:option_choice]
|
14
|
+
env = opts[:env]
|
15
|
+
bot_conf = opts[:bot_conf]
|
16
|
+
event_history = opts[:event_history]
|
17
|
+
order_type = opts[:order_type]
|
18
|
+
fiat_smallest_decimal = opts[:fiat_smallest_decimal]
|
19
|
+
fiat_portfolio_file = opts[:fiat_portfolio_file]
|
20
|
+
order_history = opts[:order_history]
|
21
|
+
crypto_smallest_decimal = opts[:crypto_smallest_decimal]
|
22
|
+
base_min_size = opts[:base_min_size]
|
23
|
+
indicator_status = opts[:indicator_status]
|
24
|
+
|
25
|
+
# Initialize some bot_conf variables
|
26
|
+
pie_in_sky_buy_percent = bot_conf[:pie_in_sky_buy_percent].to_f
|
27
|
+
autotrade_portfolio_percent = bot_conf[:autotrade_portfolio_percent].to_f
|
28
|
+
target_profit_margin_percent = bot_conf[:target_profit_margin_percent].to_f
|
29
|
+
|
30
|
+
crypto_currency = option_choice.symbol.to_s.upcase.split('_').first
|
31
|
+
portfolio = event_history.order_book[:portfolio]
|
32
|
+
symbol_portfolio = portfolio.select do |this_portfolio|
|
33
|
+
this_portfolio if this_portfolio[:currency] == crypto_currency
|
34
|
+
end
|
35
|
+
|
36
|
+
symbol_balance = format(
|
37
|
+
'%0.8f',
|
38
|
+
symbol_portfolio.first[:balance].to_f
|
39
|
+
).to_f
|
40
|
+
|
41
|
+
# 2. Calculate Price, Size, Fees
|
42
|
+
# Get the middle of last 3 ticker prices
|
43
|
+
# to avoid over purcase blips.
|
44
|
+
last_three_prices_arr = []
|
45
|
+
last_ticker_price = event_history.order_book[:ticker_price].to_f
|
46
|
+
second_to_last_ticker_price = event_history.order_book[:ticker_price_second_to_last].to_f
|
47
|
+
third_to_last_ticker_price = event_history.order_book[:ticker_price_third_to_last].to_f
|
48
|
+
last_three_prices_arr.push(last_ticker_price)
|
49
|
+
last_three_prices_arr.push(second_to_last_ticker_price)
|
50
|
+
last_three_prices_arr.push(third_to_last_ticker_price)
|
51
|
+
|
52
|
+
case order_type
|
53
|
+
when :pie
|
54
|
+
limit_price = last_three_prices_arr.sort[1]
|
55
|
+
pie_in_sky_buy_percent_cast_as_decimal = format(
|
56
|
+
'%0.2f',
|
57
|
+
pie_in_sky_buy_percent * 0.01
|
58
|
+
).to_f
|
59
|
+
|
60
|
+
limit_price -= (limit_price * pie_in_sky_buy_percent_cast_as_decimal)
|
61
|
+
when :tpm
|
62
|
+
limit_price = last_three_prices_arr.sort[1]
|
63
|
+
when :gtfo
|
64
|
+
# price = format("%0.#{fiat_smallest_decimal}f", limit_price)
|
65
|
+
raise "ERROR: Why is a Buy Submitted for #{order_type}?"
|
66
|
+
else
|
67
|
+
raise "ERROR: Unknown order_type: #{order_type}"
|
68
|
+
end
|
69
|
+
|
70
|
+
price = format("%0.#{fiat_smallest_decimal}f", limit_price)
|
71
|
+
|
72
|
+
# TODO: Determine if our N% Autotrade
|
73
|
+
# Threshold has already been met
|
74
|
+
# Buying Crypto w/ Fiat
|
75
|
+
autotrade_portfolio_percent_cast_as_decimal = format(
|
76
|
+
'%0.7f',
|
77
|
+
autotrade_portfolio_percent * 0.01
|
78
|
+
).to_f
|
79
|
+
|
80
|
+
fiat_portfolio = event_history.order_book[:fiat_portfolio]
|
81
|
+
fiat_balance_available = format(
|
82
|
+
"%0.#{fiat_smallest_decimal}f",
|
83
|
+
fiat_portfolio.first[:available]
|
84
|
+
).to_f
|
85
|
+
|
86
|
+
# Make sure size is within constraints
|
87
|
+
# of autotrade_portfolio_percent
|
88
|
+
total_limit_buy_orders_open = order_history.select do |orders|
|
89
|
+
orders[:type] == 'limit' &&
|
90
|
+
orders[:side] == 'buy' &&
|
91
|
+
orders[:status] == 'open'
|
92
|
+
end
|
93
|
+
|
94
|
+
total_limit_buy_order_open_tot = total_limit_buy_orders_open.length
|
95
|
+
total_limit_buy_orders_open_size = total_limit_buy_orders_open.inject(0) do |sum, hash|
|
96
|
+
sum + hash[:size].to_f
|
97
|
+
end.to_f
|
98
|
+
|
99
|
+
fiat_to_autotrade = fiat_balance_available * autotrade_portfolio_percent_cast_as_decimal
|
100
|
+
calc_fiat_to_buy = (fiat_to_autotrade / last_ticker_price) - symbol_balance
|
101
|
+
size = format(
|
102
|
+
"%0.#{crypto_smallest_decimal}f",
|
103
|
+
calc_fiat_to_buy - total_limit_buy_orders_open_size
|
104
|
+
)
|
105
|
+
|
106
|
+
if base_min_size.to_i >= 1
|
107
|
+
size = (
|
108
|
+
(calc_fiat_to_buy - total_limit_buy_orders_open_size).to_i - base_min_size.to_i
|
109
|
+
).to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
if size.to_f >= base_min_size.to_f &&
|
113
|
+
total_limit_buy_order_open_tot.zero? &&
|
114
|
+
price.to_f.positive?
|
115
|
+
# SUBMIT BUY ORDER
|
116
|
+
event_history.order_submitted = true
|
117
|
+
event_history.event_notes = "{ \"event_type\": \"#{event_history.event_type}\", \"cancel\": \"#{event_history.order_canceled}\", \"submitted\": \"#{event_history.order_submitted}\" }" if option_choice.proxy
|
118
|
+
|
119
|
+
event_history = Cryptum::API.submit_limit_order(
|
120
|
+
option_choice: option_choice,
|
121
|
+
env: env,
|
122
|
+
price: price,
|
123
|
+
size: size,
|
124
|
+
buy_or_sell: :buy,
|
125
|
+
order_type: order_type,
|
126
|
+
event_history: event_history,
|
127
|
+
indicator_status: indicator_status
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
event_history
|
132
|
+
rescue StandardError => e
|
133
|
+
raise e
|
134
|
+
end
|
135
|
+
|
136
|
+
# Display Usage for this Module
|
137
|
+
public_class_method def self.help
|
138
|
+
puts "USAGE:
|
139
|
+
event_history = #{self}.crypto()
|
140
|
+
"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cryptum
|
4
|
+
# This plugin is used to Cancel Open Limit Orders
|
5
|
+
module Event
|
6
|
+
module Cancel
|
7
|
+
# Supported Method Parameters::
|
8
|
+
# Cryptum::Event::Cancel.open_orders(
|
9
|
+
# )
|
10
|
+
public_class_method def self.open_orders(opts = {})
|
11
|
+
option_choice = opts[:option_choice]
|
12
|
+
env = opts[:env]
|
13
|
+
event_history = opts[:event_history]
|
14
|
+
order_type = opts[:order_type]
|
15
|
+
order_action = opts[:order_action]
|
16
|
+
|
17
|
+
# Consume Latest Order History Justification from
|
18
|
+
# Order Book & cancel orders tagged as pie
|
19
|
+
# event_history = Cryptum::API.cancel_synced_oj_and_oh(
|
20
|
+
# option_choice: option_choice,
|
21
|
+
# env: env,
|
22
|
+
# event_history: event_history,
|
23
|
+
# order_type: order_type,
|
24
|
+
# order_action: order_action
|
25
|
+
# )
|
26
|
+
|
27
|
+
# event_history
|
28
|
+
event_history.order_canceled = true
|
29
|
+
event_history.event_notes = "{ \"event_type\": \"#{event_history.event_type}\", \"cancel\": \"#{event_history.order_canceled}\", \"submitted\": \"#{event_history.order_submitted}\" }" if option_choice.proxy
|
30
|
+
|
31
|
+
Cryptum::API.cancel_all_open_orders(
|
32
|
+
env: env,
|
33
|
+
option_choice: option_choice,
|
34
|
+
order_type: order_type,
|
35
|
+
event_notes: event_history.event_notes
|
36
|
+
)
|
37
|
+
rescue StandardError => e
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
|
41
|
+
# Display Usage for this Module
|
42
|
+
public_class_method def self.help
|
43
|
+
puts "USAGE:
|
44
|
+
event_history = #{self}.crypto()
|
45
|
+
"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cryptum
|
4
|
+
# This plugin is used to Cancel Open Limit Orders
|
5
|
+
module Event
|
6
|
+
# Keep Last Event History When Terminal Resize Occuers
|
7
|
+
class History
|
8
|
+
attr_accessor :bullish_trend,
|
9
|
+
:event,
|
10
|
+
:event_notes,
|
11
|
+
:event_type,
|
12
|
+
:first_event,
|
13
|
+
:market_trend_event,
|
14
|
+
:order_book,
|
15
|
+
:order_canceled,
|
16
|
+
:order_submitted,
|
17
|
+
:order_ready,
|
18
|
+
:plan_no,
|
19
|
+
:reconnected,
|
20
|
+
:red_pill,
|
21
|
+
:reset_market_trend,
|
22
|
+
:start_time,
|
23
|
+
:ticker_event,
|
24
|
+
:time_between_orders,
|
25
|
+
:time_between_orders_max,
|
26
|
+
:time_between_orders_min,
|
27
|
+
:time_between_orders_reset
|
28
|
+
|
29
|
+
def initialize(opts = {})
|
30
|
+
option_choice = opts[:option_choice]
|
31
|
+
start_time = opts[:start_time]
|
32
|
+
order_book = opts[:order_book]
|
33
|
+
|
34
|
+
self.bullish_trend = false
|
35
|
+
self.first_event = true
|
36
|
+
self.order_canceled = false
|
37
|
+
self.order_submitted = false
|
38
|
+
self.order_ready = false
|
39
|
+
self.order_book = order_book
|
40
|
+
self.plan_no = 0
|
41
|
+
self.start_time = start_time
|
42
|
+
self.reconnected = false
|
43
|
+
self.red_pill = false
|
44
|
+
self.reset_market_trend = false
|
45
|
+
|
46
|
+
# 60 seconds
|
47
|
+
self.time_between_orders = option_choice.market_trend_reset
|
48
|
+
self.time_between_orders_reset = self.time_between_orders
|
49
|
+
|
50
|
+
# 60 minutes
|
51
|
+
self.time_between_orders_max = self.time_between_orders_reset * 60
|
52
|
+
|
53
|
+
# 5 seconds
|
54
|
+
self.time_between_orders_min = 5
|
55
|
+
end
|
56
|
+
rescue Interrupt
|
57
|
+
# Exit Gracefully if CTRL+C is Pressed During Session
|
58
|
+
Cryptum.exit_gracefully(which_self: self)
|
59
|
+
rescue StandardError => e
|
60
|
+
# Produce a Stacktrace for anything else
|
61
|
+
raise e
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cryptum
|
4
|
+
# This plugin is used to Cancel Open Limit Orders
|
5
|
+
module Event
|
6
|
+
module KeyPress
|
7
|
+
# Supported Method Parameters::
|
8
|
+
# Cryptum::Event::KeyPress.detect(
|
9
|
+
# )
|
10
|
+
public_class_method def self.detect(opts = {})
|
11
|
+
terminal_win = opts[:terminal_win]
|
12
|
+
|
13
|
+
Cryptum::UI.detect_key_press_in_ui(
|
14
|
+
key_press_event: terminal_win.key_press_event,
|
15
|
+
ui_win: terminal_win.ticker_section
|
16
|
+
)
|
17
|
+
|
18
|
+
Cryptum::UI.detect_key_press_in_ui(
|
19
|
+
key_press_event: terminal_win.key_press_event,
|
20
|
+
ui_win: terminal_win.portfolio_section
|
21
|
+
)
|
22
|
+
|
23
|
+
Cryptum::UI.detect_key_press_in_ui(
|
24
|
+
key_press_event: terminal_win.key_press_event,
|
25
|
+
ui_win: terminal_win.order_plan_section
|
26
|
+
)
|
27
|
+
|
28
|
+
Cryptum::UI.detect_key_press_in_ui(
|
29
|
+
key_press_event: terminal_win.key_press_event,
|
30
|
+
ui_win: terminal_win.order_timer_section
|
31
|
+
)
|
32
|
+
|
33
|
+
Cryptum::UI.detect_key_press_in_ui(
|
34
|
+
key_press_event: terminal_win.key_press_event,
|
35
|
+
ui_win: terminal_win.market_trend_section
|
36
|
+
)
|
37
|
+
|
38
|
+
Cryptum::UI.detect_key_press_in_ui(
|
39
|
+
key_press_event: terminal_win.key_press_event,
|
40
|
+
ui_win: terminal_win.signal_engine_section
|
41
|
+
)
|
42
|
+
|
43
|
+
Cryptum::UI.detect_key_press_in_ui(
|
44
|
+
key_press_event: terminal_win.key_press_event,
|
45
|
+
ui_win: terminal_win.order_execute_section
|
46
|
+
)
|
47
|
+
|
48
|
+
Cryptum::UI.detect_key_press_in_ui(
|
49
|
+
key_press_event: terminal_win.key_press_event,
|
50
|
+
ui_win: terminal_win.command_section
|
51
|
+
)
|
52
|
+
rescue StandardError => e
|
53
|
+
raise e
|
54
|
+
end
|
55
|
+
|
56
|
+
# Display Usage for this Module
|
57
|
+
public_class_method def self.help
|
58
|
+
puts "USAGE:
|
59
|
+
order_book = #{self}.crypto()
|
60
|
+
"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cryptum
|
4
|
+
# This plugin is used to Submit a Limit Order
|
5
|
+
# to Sell Crypto Currency
|
6
|
+
|
7
|
+
module Event
|
8
|
+
module Sell
|
9
|
+
# Supported Method Parameters::
|
10
|
+
# Cryptum::Event::Sell.crypto(
|
11
|
+
# )
|
12
|
+
public_class_method def self.crypto(opts = {})
|
13
|
+
option_choice = opts[:option_choice]
|
14
|
+
env = opts[:env]
|
15
|
+
bot_conf = opts[:bot_conf]
|
16
|
+
stuck_in_pos_status = opts[:stuck_in_pos_status]
|
17
|
+
event_history = opts[:event_history]
|
18
|
+
order_type = opts[:order_type]
|
19
|
+
fiat_smallest_decimal = opts[:fiat_smallest_decimal]
|
20
|
+
crypto_smallest_decimal = opts[:crypto_smallest_decimal]
|
21
|
+
base_min_size = opts[:base_min_size]
|
22
|
+
indicator_status = opts[:indicator_status]
|
23
|
+
quote_increment = opts[:quote_increment]
|
24
|
+
|
25
|
+
# Initialize some bot_conf variables
|
26
|
+
pie_in_sky_sell_percent = bot_conf[:pie_in_sky_sell_percent].to_f
|
27
|
+
|
28
|
+
crypto_currency = option_choice.symbol.to_s.upcase.split('_').first
|
29
|
+
portfolio = event_history.order_book[:portfolio]
|
30
|
+
symbol_portfolio = portfolio.select do |this_portfolio|
|
31
|
+
this_portfolio if this_portfolio[:currency] == crypto_currency
|
32
|
+
end
|
33
|
+
|
34
|
+
symbol_balance_available = format(
|
35
|
+
'%0.8f',
|
36
|
+
symbol_portfolio.first[:available].to_f
|
37
|
+
).to_f
|
38
|
+
|
39
|
+
# 2. Calculate Price, Size, Fees
|
40
|
+
# Get the middle of last 3 ticker prices
|
41
|
+
# to avoid over purcase blips.
|
42
|
+
last_three_prices_arr = []
|
43
|
+
last_ticker_price = event_history.order_book[:ticker_price].to_f
|
44
|
+
second_to_last_ticker_price = event_history.order_book[:ticker_price_second_to_last].to_f
|
45
|
+
third_to_last_ticker_price = event_history.order_book[:ticker_price_third_to_last].to_f
|
46
|
+
last_three_prices_arr.push(last_ticker_price)
|
47
|
+
last_three_prices_arr.push(second_to_last_ticker_price)
|
48
|
+
last_three_prices_arr.push(third_to_last_ticker_price)
|
49
|
+
# limit_price = last_three_prices_arr.min
|
50
|
+
# limit_price = last_three_prices_arr.max
|
51
|
+
|
52
|
+
# Obtain our Target Price based on TPM configurations
|
53
|
+
target_symbol_price = stuck_in_pos_status[:target_symbol_price].to_f
|
54
|
+
|
55
|
+
case order_type
|
56
|
+
when :pie
|
57
|
+
pie_in_sky_sell_percent_cast_as_decimal = format(
|
58
|
+
'%0.2f',
|
59
|
+
pie_in_sky_sell_percent * 0.01
|
60
|
+
).to_f
|
61
|
+
|
62
|
+
target_profit = target_symbol_price * pie_in_sky_sell_percent_cast_as_decimal
|
63
|
+
limit_price = target_symbol_price + target_profit
|
64
|
+
|
65
|
+
when :tpm
|
66
|
+
limit_price = target_symbol_price
|
67
|
+
order_type = :tpm
|
68
|
+
when :gtfo
|
69
|
+
# Attempt to get in front of falling price.
|
70
|
+
limit_price = last_three_prices_arr.sort[1]
|
71
|
+
gtfo_price = limit_price -= quote_increment.to_f
|
72
|
+
limit_price = gtfo_price if gtfo_price.positive?
|
73
|
+
else
|
74
|
+
raise "ERROR: Unknown order_type: #{order_type}"
|
75
|
+
end
|
76
|
+
|
77
|
+
price = format("%0.#{fiat_smallest_decimal}f", limit_price)
|
78
|
+
|
79
|
+
# Selling Available Crytpo Balance in its Entirety
|
80
|
+
# We Will Likely Want to Change this in the Future.
|
81
|
+
size = format(
|
82
|
+
"%0.#{crypto_smallest_decimal}f",
|
83
|
+
symbol_balance_available.floor(crypto_smallest_decimal)
|
84
|
+
)
|
85
|
+
|
86
|
+
size = symbol_balance_available if base_min_size.to_i == 1
|
87
|
+
|
88
|
+
if size.to_f >= base_min_size.to_f &&
|
89
|
+
price.to_f.positive?
|
90
|
+
|
91
|
+
# SUBMIT SELL ORDER
|
92
|
+
event_history.order_submitted = true
|
93
|
+
event_history.event_notes = "{ \"event_type\": \"#{event_history.event_type}\", \"cancel\": \"#{event_history.order_canceled}\", \"submitted\": \"#{event_history.order_submitted}\" }" if option_choice.proxy
|
94
|
+
|
95
|
+
event_history = Cryptum::API.submit_limit_order(
|
96
|
+
option_choice: option_choice,
|
97
|
+
env: env,
|
98
|
+
price: price,
|
99
|
+
size: size,
|
100
|
+
buy_or_sell: :sell,
|
101
|
+
order_type: order_type,
|
102
|
+
event_history: event_history,
|
103
|
+
indicator_status: indicator_status
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
event_history
|
108
|
+
rescue StandardError => e
|
109
|
+
raise e
|
110
|
+
end
|
111
|
+
|
112
|
+
# Display Usage for this Module
|
113
|
+
public_class_method def self.help
|
114
|
+
puts "USAGE:
|
115
|
+
order_book = #{self}.crypto()
|
116
|
+
"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Cryptum
|
6
|
+
# This plugin is used to parse Coinbase Pro Web Socket Events in the HTTP Response
|
7
|
+
module Event
|
8
|
+
autoload :Buy, 'cryptum/event/buy'
|
9
|
+
autoload :Cancel, 'cryptum/event/cancel'
|
10
|
+
autoload :History, 'cryptum/event/history'
|
11
|
+
autoload :KeyPress, 'cryptum/event/key_press'
|
12
|
+
autoload :Sell, 'cryptum/event/sell'
|
13
|
+
|
14
|
+
# Supported Method Parameters::
|
15
|
+
# Cryptum::Event.parse(
|
16
|
+
# )
|
17
|
+
|
18
|
+
public_class_method def self.parse(opts = {})
|
19
|
+
option_choice = opts[:option_choice]
|
20
|
+
env = opts[:env]
|
21
|
+
terminal_win = opts[:terminal_win]
|
22
|
+
event_history = opts[:event_history]
|
23
|
+
indicator_status = opts[:indicator_status]
|
24
|
+
indicator_history = opts[:indicator_history]
|
25
|
+
bot_conf = opts[:bot_conf]
|
26
|
+
ai_enabled = opts[:ai_enabled]
|
27
|
+
|
28
|
+
candles = event_history.order_book[:candles]
|
29
|
+
order_history = event_history.order_book[:order_history]
|
30
|
+
this_product = event_history.order_book[:this_product]
|
31
|
+
fiat = this_product[:quote_currency]
|
32
|
+
fiat_portfolio_file = "#{option_choice.repo_root}/order_books/#{fiat}_PORTFOLIO.json"
|
33
|
+
|
34
|
+
# Detect Key Press Events
|
35
|
+
Cryptum::Event::KeyPress.detect(terminal_win: terminal_win)
|
36
|
+
|
37
|
+
# Determine if Summary UI needs updated data
|
38
|
+
event_history = Cryptum::Portfolio::Balance.refresh(
|
39
|
+
env: env,
|
40
|
+
option_choice: option_choice,
|
41
|
+
terminal_win: terminal_win,
|
42
|
+
event_history: event_history,
|
43
|
+
fiat_portfolio_file: fiat_portfolio_file
|
44
|
+
)
|
45
|
+
|
46
|
+
# If the Terminal Window has been Resized, Resize the UI
|
47
|
+
if Curses.cols != terminal_win.cols
|
48
|
+
terminal_win.cols = Curses.cols
|
49
|
+
terminal_win.ticker_ui_resize = true
|
50
|
+
terminal_win.market_trend_ui_resize = true
|
51
|
+
end
|
52
|
+
|
53
|
+
Cryptum::UI::Portfolio.refresh(
|
54
|
+
option_choice: option_choice,
|
55
|
+
portfolio_win: terminal_win.portfolio_section,
|
56
|
+
event_history: event_history,
|
57
|
+
key_press_event: terminal_win.key_press_event,
|
58
|
+
indicator_status: indicator_status,
|
59
|
+
bot_conf: bot_conf,
|
60
|
+
fiat_portfolio_file: fiat_portfolio_file
|
61
|
+
)
|
62
|
+
|
63
|
+
if event_history.event_type == :ticker ||
|
64
|
+
terminal_win.ticker_ui_resize
|
65
|
+
|
66
|
+
ticker_event = event_history.ticker_event = event_history.event if event_history.event_type == :ticker
|
67
|
+
ticker_event = event_history.ticker_event if terminal_win.ticker_ui_resize
|
68
|
+
Cryptum::UI::Ticker.refresh(
|
69
|
+
option_choice: option_choice,
|
70
|
+
start_time: event_history.start_time,
|
71
|
+
ticker_win: terminal_win.ticker_section,
|
72
|
+
key_press_event: terminal_win.key_press_event,
|
73
|
+
order_book: event_history.order_book,
|
74
|
+
event: ticker_event
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
order_countdown = Cryptum::UI::OrderTimer.refresh(
|
79
|
+
option_choice: option_choice,
|
80
|
+
event_history: event_history,
|
81
|
+
order_timer_win: terminal_win.order_timer_section,
|
82
|
+
indicator_status: indicator_status,
|
83
|
+
key_press_event: terminal_win.key_press_event
|
84
|
+
)
|
85
|
+
|
86
|
+
if event_history.event_type == :l2update ||
|
87
|
+
terminal_win.market_trend_ui_resize
|
88
|
+
|
89
|
+
market_trend_event = event_history.market_trend_event = event_history.event if event_history.event_type == :l2update
|
90
|
+
market_trend_event = event_history.market_trend_event if terminal_win.market_trend_ui_resize
|
91
|
+
Cryptum::UI::MarketTrend.refresh(
|
92
|
+
option_choice: option_choice,
|
93
|
+
market_trend_win: terminal_win.market_trend_section,
|
94
|
+
event_history: event_history,
|
95
|
+
key_press_event: terminal_win.key_press_event,
|
96
|
+
event: market_trend_event,
|
97
|
+
indicator_status: indicator_status,
|
98
|
+
bot_conf: bot_conf
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
indicator_status = Cryptum::UI::SignalEngine.refresh(
|
103
|
+
option_choice: option_choice,
|
104
|
+
signal_engine_win: terminal_win.signal_engine_section,
|
105
|
+
event_history: event_history,
|
106
|
+
key_press_event: terminal_win.key_press_event,
|
107
|
+
indicator_status: indicator_status,
|
108
|
+
bot_conf: bot_conf,
|
109
|
+
fiat_portfolio_file: fiat_portfolio_file
|
110
|
+
)
|
111
|
+
|
112
|
+
Cryptum::UI::OrderPlan.refresh(
|
113
|
+
option_choice: option_choice,
|
114
|
+
order_plan_win: terminal_win.order_plan_section,
|
115
|
+
event_history: event_history,
|
116
|
+
key_press_event: terminal_win.key_press_event,
|
117
|
+
indicator_status: indicator_status,
|
118
|
+
bot_conf: bot_conf,
|
119
|
+
fiat_portfolio_file: fiat_portfolio_file
|
120
|
+
)
|
121
|
+
|
122
|
+
event_history = Cryptum::UI::OrderExecution.refresh(
|
123
|
+
option_choice: option_choice,
|
124
|
+
order_execute_win: terminal_win.order_execute_section,
|
125
|
+
env: env,
|
126
|
+
event_history: event_history,
|
127
|
+
key_press_event: terminal_win.key_press_event,
|
128
|
+
indicator_status: indicator_status,
|
129
|
+
bot_conf: bot_conf,
|
130
|
+
fiat_portfolio_file: fiat_portfolio_file
|
131
|
+
)
|
132
|
+
|
133
|
+
# Refresh Command Section for Cryptum Session Usage
|
134
|
+
Cryptum::UI::Command.refresh(
|
135
|
+
command_win: terminal_win.command_section,
|
136
|
+
key_press_event: terminal_win.key_press_event
|
137
|
+
)
|
138
|
+
|
139
|
+
last_ticker_price = event_history.order_book[:ticker_price].to_f
|
140
|
+
second_to_last_ticker_price = event_history.order_book[:ticker_price_second_to_last].to_f
|
141
|
+
third_to_last_ticker_price = event_history.order_book[:ticker_price_third_to_last].to_f
|
142
|
+
|
143
|
+
event_history
|
144
|
+
rescue LoadError => e
|
145
|
+
# This happens when autoloading modules fail.
|
146
|
+
File.open('/tmp/cryptum-errors.txt', 'a') do |f|
|
147
|
+
f.puts Time.now.strftime('%Y-%m-%d %H:%M:%S.%N %z')
|
148
|
+
f.puts "Module: #{self}"
|
149
|
+
f.puts "#{e}\n\n\n"
|
150
|
+
end
|
151
|
+
|
152
|
+
retry
|
153
|
+
rescue Interrupt
|
154
|
+
# Exit Gracefully if CTRL+C is Pressed During Session
|
155
|
+
Cryptum.exit_gracefully(which_self: self)
|
156
|
+
rescue StandardError => e
|
157
|
+
raise e
|
158
|
+
ensure
|
159
|
+
$stdout.flush
|
160
|
+
end
|
161
|
+
|
162
|
+
# Display Usage for this Module
|
163
|
+
|
164
|
+
public_class_method def self.help
|
165
|
+
constants.sort
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|