Class: BitexBot::ClosingFlow

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
lib/bitex_bot/models/closing_flow.rb

Direct Known Subclasses

BuyClosingFlow, SellClosingFlow

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.close_open_positionsObject

Start a new CloseBuy that closes exising OpenBuy’s by selling on another exchange what was just bought on bitex.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/bitex_bot/models/closing_flow.rb', line 7

def self.close_open_positions
  open_positions = open_position_class.open
  return if open_positions.empty?

  quantity = open_positions.collect(&:quantity).sum
  amount = open_positions.collect(&:amount).sum
  suggested_amount = open_positions.collect do |open|
    open.quantity * open.opening_flow.suggested_closing_price
  end.sum
  price = suggested_amount / quantity

  # Don't even bother trying to close a position that's too small.
  return if quantity * price < minimum_amount_for_closing

  flow = create!(
    desired_price: price,
    quantity: quantity,
    amount: amount,
    open_positions: open_positions)
  
  flow.create_initial_order_and_close_position
  
  return flow
end

.close_time_to_liveObject



100
101
102
# File 'lib/bitex_bot/models/closing_flow.rb', line 100

def self.close_time_to_live
  30
end

.minimum_amount_for_closingObject

When placing a closing order we need to be aware of the smallest order amount permitted by the other exchange. If the other order is less than this USD amount then we do not attempt to close the positions yet.



96
97
98
# File 'lib/bitex_bot/models/closing_flow.rb', line 96

def self.minimum_amount_for_closing
  5
end

Instance Method Details

#create_initial_order_and_close_positionObject



32
33
34
# File 'lib/bitex_bot/models/closing_flow.rb', line 32

def create_initial_order_and_close_position
  create_order_and_close_position(quantity, desired_price)
end

#create_order_and_close_position(quantity, price) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/bitex_bot/models/closing_flow.rb', line 36

def create_order_and_close_position(quantity, price)
  order = BitexBot::Robot.taker.place_order(
    order_method, price.round(2), quantity.round(4))
  if order.nil? || order.id.nil?
    Robot.logger.error("Closing: Error on #{order_method} for "\
      "#{self.class.name} ##{id} #{quantity} BTC @ $#{price}."\
      "#{order.to_s}")
    return
  end
  Robot.logger.info("Closing: Going to #{order_method} ##{order.id} for"\
    "#{self.class.name} ##{id} #{quantity} BTC @ $#{price}")
  close_positions.create!(order_id: order.id)
end

#sync_closed_positions(orders, transactions) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/bitex_bot/models/closing_flow.rb', line 50

def sync_closed_positions(orders, transactions)
  latest_close = close_positions.last

  # Maybe we couldn't create the bitstamp order when this flow
  # was created, so we try again when syncing.
  if latest_close.nil?
    create_initial_order_and_close_position
    return
  end

  order_id = latest_close.order_id.to_s
  order = orders.find{|x| x.id.to_s == order_id }

  # When ask is nil it means the other exchange is done executing it
  # so we can now have a look of all the sales that were spawned from it.
  if order.nil?
    latest_close.amount, latest_close.quantity =
      BitexBot::Robot.taker.amount_and_quantity(order_id, transactions)
    latest_close.save!
    
    next_price, next_quantity = get_next_price_and_quantity
    if (next_quantity * next_price) > self.class.minimum_amount_for_closing
      create_order_and_close_position(next_quantity, next_price)
    else
      self.btc_profit = get_btc_profit
      self.usd_profit = get_usd_profit
      self.done = true
      Robot.logger.info("Closing: Finished #{self.class.name} ##{id}"\
        "earned $#{self.usd_profit} and #{self.btc_profit} BTC. ")
      save!
    end
  elsif latest_close.created_at < self.class.close_time_to_live.seconds.ago
    Robot.with_cooldown do
      begin
        order.cancel!
      rescue StandardError => e
        nil # just pass, we'll keep on trying until it's not in orders anymore.
      end
    end
  end
end