# frozen_string_literal: true module Cryptum # Cryptum::UI Module used for Presenting the # Cryptum Curses Interface module UI # Cryptum::UI::Order Namespace module Order # Update the Execute Section of the UI (When Active) module Execute # Supported Method Parameters:: # Cryptum::UI::Order::Execute.refresh( # order_book: 'required - Order Book Data Structure', # event: 'required - Event from Coinbase Web Socket' # ) public_class_method def self.refresh(opts = {}) option_choice = opts[:option_choice] order_execute_win = opts[:order_execute_win] env = opts[:env] event_history = opts[:event_history] indicator_status = opts[:indicator_status] bot_conf = opts[:bot_conf] event_type = event_history.event_type event_side = event_history.event[:side].to_s.to_sym event_reason = event_history.event[:reason].to_s.to_sym ticker_price = event_history.order_book[:ticker_price].to_f open_24h = event_history.order_book[:open_24h].to_f this_product = event_history.order_book[:this_product] min_market_funds = this_product[:min_market_funds] base_increment = this_product[:base_increment] quote_increment = this_product[:quote_increment] crypto_smallest_decimal = base_increment.to_s.split('.')[-1].length fiat_smallest_decimal = quote_increment.to_s.split('.')[-1].length last_three_prices_arr = [] last_ticker_price = event_history.order_book[:ticker_price].to_f second_to_last_ticker_price = event_history.order_book[:ticker_price_second_to_last].to_f third_to_last_ticker_price = event_history.order_book[:ticker_price_third_to_last].to_f last_three_prices_arr.push(last_ticker_price) last_three_prices_arr.push(second_to_last_ticker_price) last_three_prices_arr.push(third_to_last_ticker_price) limit_price = last_three_prices_arr.sort[1] return event_history unless limit_price.positive? # tpm = bot_conf[:target_profit_margin_percent].to_f # tpm_cast_as_decimal = tpm / 100 order_history_meta = event_history.order_book[:order_history_meta] order_history = event_history.order_book[:order_history] margin_percent_open_24h = (1 - (open_24h / ticker_price)) * 100 cast_margin_to_sec = margin_percent_open_24h * 0.1 # Reset times to max or default depending on # BULL or BEAR market trend event_history.bullish_trend = true if cast_margin_to_sec.positive? event_history.bullish_trend = false if cast_margin_to_sec.negative? buy_total = event_history.order_book[:market_trend][:buy].to_i sell_total = event_history.order_book[:market_trend][:sell].to_i if event_history.order_book[:order_plan].length.positive? if event_history.order_ready event_history.order_book[:last_order_exec] = Time.now.strftime( '%Y-%m-%d %H:%M:%S.%N%z' ) end # BUY # Reset times to max or default depending on # BULL or BEAR market trend event_history.time_between_orders = event_history.time_between_orders_max if buy_total >= sell_total && !event_history.bullish_trend event_history.time_between_orders = event_history.time_between_orders_reset if sell_total > buy_total && !event_history.bullish_trend if event_history.order_ready && indicator_status.action_signal == :buy && !event_history.red_pill this_order = event_history.order_book[:order_plan].first # If price is greater than the previous order, # force it to be slightly less last_order = order_history_meta.select do |order| order if order[:color] == 'yellow' end.last last_purchase_price = 0.0 last_purchase_price = last_order[:price].to_f if last_order limit_price = last_purchase_price - quote_increment.to_f if last_purchase_price.positive? && last_purchase_price < limit_price # Debug last order -------------------------------# debug_last_order = "Last Order: #{last_order}" debug_last_order += "Last Purchase Price: #{last_purchase_price}" debug_last_order += "Limit Price (Should be <= quote_increment-- ^): #{limit_price}" debug_last_order += "\n\n\n" Cryptum::Log.append( level: :debug, msg: debug_last_order, which_self: self, event_history: event_history ) #-------------------------------------------------# price = format( "%0.#{fiat_smallest_decimal}f", limit_price ) size = this_order[:invest].to_f / limit_price loop do size = size.to_f + base_increment.to_f break if (size.to_f * price.to_f) > min_market_funds.to_f end size = format( "%0.#{crypto_smallest_decimal}f", size ) fiat_invested_this_order = size.to_f * price.to_f fiat_portfolio = event_history.order_book[:fiat_portfolio] fiat_avail_to_trade = format('%0.2f', fiat_portfolio.first[:available]) event_history.red_pill = true if fiat_invested_this_order > fiat_avail_to_trade.to_f unless event_history.red_pill event_history = Cryptum::Event::Buy.crypto( option_choice: option_choice, env: env, price: price, size: size, event_history: event_history, bot_conf: bot_conf ) end # SAUCE 4 (SAUCE 3 RELATES TO SAUCE 4) # Time between orders # Increment n Seconds between buys to # account for bearish and bullish trends dynamic_time_increment = cast_margin_to_sec * -1 # Lets also take balance into play balance_as_arbitrary_float = fiat_avail_to_trade.to_f / 1_000_000 tbo = dynamic_time_increment - balance_as_arbitrary_float event_history.time_between_orders += tbo # Time between orders should never # be less than event_history.time_between_orders_min event_history.time_between_orders = event_history.time_between_orders_min if event_history.time_between_orders < event_history.time_between_orders_min # Time between orders should never # be more than event_history.time_between_orders_max event_history.time_between_orders = event_history.time_between_orders_max if event_history.time_between_orders > event_history.time_between_orders_max end end # Update Completed Sell Orders w/ Green if event_type == :open && event_side == :buy buy_order_id = event_history.event[:order_id] order_history_meta.each do |meta| meta[:color] = :red if meta[:buy_order_id] == buy_order_id end end if event_type == :done && event_side == :buy && event_reason == :canceled buy_order_id = event_history.event[:order_id] order_history_meta.each do |meta| next unless meta[:buy_order_id] == buy_order_id meta[:done_at] = Time.now.strftime('%Y-%m-%d %H:%M:%S.%N%z') meta[:color] = :white end end if event_type == :done && event_side == :buy && event_reason != :canceled order_ready_to_sell_arr = order_history_meta.select do |meta| meta[:buy_order_id] == event_history.event[:order_id] end if order_ready_to_sell_arr.length.positive? order_ready_to_sell = order_ready_to_sell_arr.first buy_order_id = order_ready_to_sell[:buy_order_id] price = format( "%0.#{fiat_smallest_decimal}f", order_ready_to_sell[:target_price] ) size = order_ready_to_sell[:size] event_history = Cryptum::Event::Sell.crypto( option_choice: option_choice, env: env, price: price, size: size, event_history: event_history, bot_conf: bot_conf, buy_order_id: buy_order_id ) end end # Update Canceled Sell Orders w/ Black && # Include done_at Timestamp for 24h gain calc if event_type == :done && event_side == :sell && event_reason == :canceled sell_order_id = event_history.event[:order_id] order_history_meta.each do |meta| next unless meta[:sell_order_id] == sell_order_id meta[:done_at] = Time.now.strftime('%Y-%m-%d %H:%M:%S.%N%z') # Reinitiate GTFO if the previous GTFO Order Expires. terminal_win.key_press_event.key_g = true if meta[:color] == :magenta meta[:color] = :white end end # Update Completed Sell Orders w/ Green && # Include done_at Timestamp for 24h gain calc if event_type == :done && event_side == :sell && event_reason != :canceled sell_order_id = event_history.event[:order_id] order_history_meta.each do |meta| next unless meta[:sell_order_id] == sell_order_id meta[:done_at] = Time.now.strftime('%Y-%m-%d %H:%M:%S.%N%z') meta[:color] = :green # Obtain buy && sell order details from order history # using buy && sell IDs from respective meta object # and append to JSON log to allow for machine learning. buy_order_id = meta[:buy_order_id] learning = meta order_history_buy_details = order_history.select { |oh| oh[:id] == buy_order_id } order_history_sell_details = order_history.select { |oh| oh[:id] == sell_order_id } learning[:buy_details] = order_history_buy_details.first learning[:sell_details] = order_history_sell_details.first Cryptum::Log.append( level: :learning, msg: learning, which_self: self, event_history: event_history ) end end # OK, now let's tally up everything... twenty_four_hrs_ago = Time.now - 86_400 # Snag all sold orders oh_meta_sold_arr = order_history_meta.select do |ohm| ohm[:color].to_sym == :green && ohm.key?(:done_at) end order_hist_meta_sold = oh_meta_sold_arr.length # Snag all sold orders within past 24 hrs ohm_sold_twenty_four_arr = [] unless oh_meta_sold_arr.empty? ohm_sold_twenty_four_arr = oh_meta_sold_arr.select do |o| Time.parse(o[:done_at]) >= twenty_four_hrs_ago end end order_hist_meta_sold_twenty_four = ohm_sold_twenty_four_arr.length # Snag all expired orders oh_meta_expired_arr = order_history_meta.select do |ohm| ohm[:color].to_sym == :white && ohm.key?(:done_at) end order_hist_meta_expired = oh_meta_expired_arr.length # Snag all expired orders within past 24 hrs ohm_expire_twenty_four_arr = [] unless oh_meta_expired_arr.empty? ohm_expire_twenty_four_arr = oh_meta_expired_arr.select do |o| Time.parse(o[:done_at]) >= twenty_four_hrs_ago end end order_hist_meta_24h_expired = ohm_expire_twenty_four_arr.length # Calculate total gains and gains within past 24 hrs gains_sum = oh_meta_sold_arr.map do |ohms| ohms[:profit].to_f end.sum gains_out = Cryptum.beautify_large_number( value: format( '%0.2f', gains_sum ) ) gains_24h_sum = ohm_sold_twenty_four_arr.map do |ohms| ohms[:profit].to_f end.sum gains_24h_out = Cryptum.beautify_large_number( value: format( '%0.2f', gains_24h_sum ) ) total_to_sell = order_history.select do |oh| oh[:status].to_sym == :open && oh[:side].to_sym == :sell end.length event_history.open_sell_orders = total_to_sell oh_meta_total_selling_profit_arr = order_history_meta.select do |ohm| ohm[:color].to_sym == :yellow end total_selling_profit = oh_meta_total_selling_profit_arr.map do |ohms| ohms[:profit].to_f end.sum total_selling_profit_out = Cryptum.beautify_large_number( value: format( '%0.2f', total_selling_profit ) ) # TODO: when event_history.open_sell_orders > event_history.open_sell_orders_max # Capture highest amount to sell, cancel all orders, and create _one_ limit sell # order set to a price of the previously captured highest amount to sell. event_history.open_sell_orders_merge = true if total_to_sell > event_history.open_sell_orders_max # TODO: Everything Above this Line Needs to be Indicators ^ # UI col_just1 = Curses.cols - Cryptum::UI.col_first # ROW 1 out_line_no = 0 line_color = :white header_color = :white header_style = :bold style = :bold if event_history.order_execute_win_active line_color = :blue header_color = :blue header_style = :reverse end Cryptum::UI.line( ui_win: order_execute_win, out_line_no: out_line_no, color: line_color ) # ROW 2 out_line_no += 1 order_execute_win.setpos(out_line_no, Cryptum::UI.col_first) order_execute_win.clrtoeol Cryptum::UI.colorize( ui_win: order_execute_win, color: header_color, style: header_style, string: ''.ljust(col_just1, ' ') ) header_str = '- ORDER HISTORY -' order_execute_win.setpos( out_line_no, Cryptum::UI.col_center(str: header_str) ) Cryptum::UI.colorize( ui_win: order_execute_win, color: header_color, style: header_style, string: header_str ) # ROWS 3-10 remaining_blank_rows = 0 max_rows_to_display = event_history.order_execute_max_rows_to_display remaining_blank_rows = max_rows_to_display if order_history_meta.empty? first_row = event_history.order_execute_index_offset last_row = first_row + max_rows_to_display if last_row >= order_history_meta.length last_row = order_history_meta.length - 1 event_history.order_execute_max_records_available_to_display = last_row if last_row < max_rows_to_display first_row = last_row - event_history.order_execute_max_records_available_to_display event_history.order_execute_index_offset = first_row remaining_blank_rows = max_rows_to_display - last_row end if order_history_meta.any? selected_order = event_history.order_execute_selected_data order_history_meta.reverse[first_row..last_row].each do |meta| out_line_no += 1 current_line = out_line_no - 2 style = :normal if event_history.order_execute_row_to_select == current_line style = :highlight selected_order = meta selected_order[:color] = meta[:color] end invest_out = Cryptum.beautify_large_number( value: meta[:invest] ) price_out = Cryptum.beautify_large_number( value: meta[:price] ) size_out = Cryptum.beautify_large_number( value: meta[:size] ) target_price_out = Cryptum.beautify_large_number( value: meta[:target_price] ) plan_no = meta[:plan_no] buy_created_at_hash_arr = order_history.select do |oh| oh[:id] == meta[:buy_order_id] end buy_created_at = '____-__-__ __:__:__' unless buy_created_at_hash_arr.empty? buy_created_at = Time.parse( buy_created_at_hash_arr.first[:created_at] ).strftime('%Y-%m-%d %H:%M:%S') end invest = "$#{invest_out} @ " tick = "$#{price_out} = " size = "*#{size_out} + " tpm_out = "#{meta[:tpm]}% = " targ_tick = "$#{target_price_out}" profit = "|Profit: $#{meta[:profit]}" order_exec_ln = "#{buy_created_at}|#{invest}#{tick}#{size}#{tpm_out}#{targ_tick}#{profit}|#{plan_no}" order_execute_win.setpos(out_line_no, Cryptum::UI.col_first) order_execute_win.clrtoeol Cryptum::UI.colorize( ui_win: order_execute_win, color: meta[:color], style: style, string: order_exec_ln.ljust(col_just1, '.') ) end event_history.order_execute_selected_data = selected_order end # Clear to SUMMARY # (Only Applicable if order_book[:order_history_meta] < max_rows_to_display) # out_line_no += 1 if remaining_blank_rows.positive? rows_to_blank = out_line_no + remaining_blank_rows out_line_no += 1 (out_line_no..rows_to_blank).each do |clr_line| out_line_no = clr_line order_execute_win.setpos(clr_line, Cryptum::UI.col_first) order_execute_win.clrtoeol Cryptum::UI.colorize( ui_win: order_execute_win, color: :white, style: :normal, string: ''.ljust(col_just1, ' ') ) end end # ROW 10 out_line_no += 1 order_execute_win.setpos(out_line_no, Cryptum::UI.col_first) order_execute_win.clrtoeol Cryptum::UI.colorize( ui_win: order_execute_win, color: header_color, style: header_style, string: ''.ljust(col_just1, ' ') ) header_str = "SELLING: #{total_to_sell} w tProf: $#{total_selling_profit_out} | " header_str += "SOLD 24h: #{order_hist_meta_sold_twenty_four} Tot: #{order_hist_meta_sold} | " header_str += "GAINS 24h: $#{gains_24h_out} Tot: $#{gains_out} | " header_str += "EXPIRED 24h: #{order_hist_meta_24h_expired} Tot: #{order_hist_meta_expired}" order_execute_win.setpos( out_line_no, Cryptum::UI.col_center(str: header_str) ) Cryptum::UI.colorize( ui_win: order_execute_win, color: header_color, style: header_style, string: header_str ) # ROW 11 out_line_no += 1 Cryptum::UI.line( ui_win: order_execute_win, out_line_no: out_line_no, color: line_color ) order_execute_win.refresh # Reset Order Ready && Open Sell Orders Merge (If Applicable) Booleans event_history.order_ready = false event_history.open_sell_orders_merge = false event_history rescue Interrupt, StandardError => e Cryptum::Log.append(level: :error, msg: e, which_self: self, event_history: event_history) end # Display Usage for this Module public_class_method def self.help puts "USAGE: #{self}.refresh( order_book: 'required - Order Book Data Structure', event: 'required - Event from Coinbase Web Socket' ) " end end end end end