Class: BitexBot::OpeningFlow

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

Overview

Any arbitrage workflow has 2 stages, opening positions and then closing them. The OpeningFlow stage places an order on bitex, detecting and storing all transactions spawn from that order as Open positions.

Direct Known Subclasses

BuyOpeningFlow, SellOpeningFlow

Statuses collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.activeObject



8
9
10
# File 'lib/bitex_bot/models/opening_flow.rb', line 8

def self.active
  where('status != "finalised"')
end

.create_for_market(remote_balance, order_book, transactions, bitex_fee, other_fee) ⇒ Object



40
41
42
43
44
45
46
47
48
49
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
# File 'lib/bitex_bot/models/opening_flow.rb', line 40

def self.create_for_market(remote_balance, order_book, transactions,
  bitex_fee, other_fee)

  plus_bitex = value_to_use + (value_to_use * bitex_fee / 100.0)
  value_to_use_needed = plus_bitex / (1 - other_fee / 100.0)
  
  safest_price = get_safest_price(transactions, order_book,
    value_to_use_needed)

  remote_value_to_use = get_remote_value_to_use(value_to_use_needed, safest_price)
  
  if remote_value_to_use > remote_balance
    raise CannotCreateFlow.new(
      "Needed #{remote_value_to_use} but you only have #{remote_balance}")
  end

  bitex_price = get_bitex_price(value_to_use, remote_value_to_use)      

  begin 
    order = order_class.create!(:btc, value_to_use, bitex_price, true)
  rescue StandardError => e
    raise CannotCreateFlow.new(e.message)
  end

  if order.reason == :not_enough_funds
    raise CannotCreateFlow.new(
      "You need to have #{value_to_use} on bitex to place this
      #{order_class.name}.")
  end

  Robot.logger.info("Opening: Placed #{order_class.name} ##{order.id} " \
    "#{value_to_use} @ $#{bitex_price} (#{remote_value_to_use})")

  begin 
    self.create!(price: bitex_price, value_to_use: value_to_use,
      suggested_closing_price: safest_price, status: 'executing', order_id: order.id)
  rescue StandardError => e
    raise CannotCreateFlow.new(e.message)
  end
end

.old_activeObject



12
13
14
15
# File 'lib/bitex_bot/models/opening_flow.rb', line 12

def self.old_active
  where('status != "finalised" AND created_at < ?',
    Settings.time_to_live.seconds.ago)
end

.statusesArray<String>

All possible flow statuses

Returns:

  • (Array<String>)


21
22
23
# File 'lib/bitex_bot/models/opening_flow.rb', line 21

def self.statuses
  %w(executing settling finalised)
end

.sync_open_positionsObject

Buys on bitex represent open positions, we mirror them locally so that we can plan on how to close them.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/bitex_bot/models/opening_flow.rb', line 83

def self.sync_open_positions
  threshold = open_position_class
    .order('created_at DESC').first.try(:created_at)
  Bitex::Trade.all.collect do |transaction|
    next unless transaction.is_a?(transaction_class)
    next if threshold && transaction.created_at < (threshold - 30.minutes)
    next if open_position_class.find_by_transaction_id(transaction.id)
    next if transaction.specie != :btc
    next unless flow = find_by_order_id(transaction_order_id(transaction))
    Robot.logger.info("Opening: #{name} ##{flow.id} "\
      "was hit for #{transaction.quantity} BTC @ $#{transaction.price}")
    open_position_class.create!(
      transaction_id: transaction.id,
      price: transaction.price,
      amount: transaction.amount,
      quantity: transaction.quantity,
      opening_flow: flow)
  end.compact
end

Instance Method Details

#executing?Boolean

The Bitex order has been placed, its id stored as order_id.

Returns:

  • (Boolean)


26
# File 'lib/bitex_bot/models/opening_flow.rb', line 26

def executing?; status == 'executing'; end

#finalise!Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/bitex_bot/models/opening_flow.rb', line 103

def finalise!
  order = self.class.order_class.find(order_id)
  if order.status == :cancelled || order.status == :completed
    Robot.logger.info(
      "Opening: #{self.class.order_class.name} ##{order_id} finalised.")
    self.status = 'finalised'
    save!
  else
    order.cancel!
    unless settling?
      self.status = 'settling'
      save!
    end
  end
end

#finalised?Boolean

Successfully settled or finished executing.

Returns:

  • (Boolean)


33
# File 'lib/bitex_bot/models/opening_flow.rb', line 33

def finalised?; status == 'finalised'; end

#settling?Boolean

In process of cancelling the Bitex order and any other outstanding order in the other exchange.

Returns:

  • (Boolean)


30
# File 'lib/bitex_bot/models/opening_flow.rb', line 30

def settling?; status == 'settling'; end