Class: Trader::FakeBackend

Inherits:
Object
  • Object
show all
Defined in:
lib/trade-o-matic/adapters/fake_backend.rb

Defined Under Namespace

Classes: FakeBalance, FakeOrder

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(_config = nil) ⇒ FakeBackend

Returns a new instance of FakeBackend.



48
49
50
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 48

def initialize(_config=nil)
  get_session(_config) unless _config.nil?
end

Instance Attribute Details

#asksObject (readonly)

Returns the value of attribute asks.



26
27
28
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 26

def asks
  @asks
end

#bidsObject (readonly)

Returns the value of attribute bids.



26
27
28
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 26

def bids
  @bids
end

#pairObject (readonly)

Returns the value of attribute pair.



26
27
28
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 26

def pair
  @pair
end

#verboseObject (readonly)

Returns the value of attribute verbose.



26
27
28
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 26

def verbose
  @verbose
end

Class Method Details

.instanceObject



40
41
42
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 40

def self.instance
  @@instance ||= self.new
end

.reset_instanceObject



44
45
46
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 44

def self.reset_instance
  @@instance = nil
end

Instance Method Details

#available_base_balanceObject



60
61
62
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 60

def available_base_balance
  @base_balance
end

#available_quote_balanceObject



64
65
66
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 64

def available_quote_balance
  @quote_balance
end

#cancel_order(_session, _order_id) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 144

def cancel_order(_session, _order_id)
  order = find_order_by_id(_order_id)

  info "Closing #{order[:instruction]} order for #{order[:pend_volume] + order[:traded_volume]} #{pair.base} @ #{order[:price]} #{pair.quote}", :red

  if order[:status] == AccountOrder::OPEN
    if order[:instruction] == Order::ASK
      @base_balance += order[:pend_volume]
    else
      @quote_balance += order[:pend_volume] * order[:price]
    end
    order[:status] = AccountOrder::CANCELED
  end

  FakeOrder.new order.clone
end

#create_order(_session, _pair, _volume, _price, _instruction) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 110

def create_order(_session, _pair, _volume, _price, _instruction)
  raise 'market not supported' unless _pair == pair
  raise 'market orders not supported' if _price.nil?

  if _instruction == Order::ASK
    raise 'Not enough funds' if _volume > @base_balance
    @base_balance -= _volume
  else
    raise 'Not enough funds' if _volume * _price > @quote_balance
    @quote_balance -= _volume * _price
  end

  info "Creating #{_instruction} order for #{_volume} #{pair.base} @ #{_price} #{pair.quote}", :green

  raw_order = {
    id: @id.to_s,
    pair: pair,
    instruction: _instruction,
    status: AccountOrder::OPEN,
    price: _price,
    pend_volume: _volume,
    traded_volume: 0.0
  }

  @id += 1
  (_instruction == Order::ASK ? @asks : @bids) << raw_order

  FakeOrder.new raw_order.clone
end

#fetch_order(_session, _order_id) ⇒ Object



140
141
142
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 140

def fetch_order(_session, _order_id)
  FakeOrder.new find_order_by_id(_order_id).clone
end

#fill_book(_book) ⇒ Object



56
57
58
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 56

def fill_book(_book)
  # TODO
end

#get_available_marketsObject



52
53
54
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 52

def get_available_markets
  [@pair]
end

#get_balance(_session, _currency) ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 95

def get_balance(_session, _currency)
  if _currency == pair.base
    FakeBalance.new(total_base_balance, available_base_balance)
  elsif _currency == pair.quote
    FakeBalance.new(total_quote_balance, available_quote_balance)
  else
    raise 'currency not supported'
  end
end

#get_orders(_session, _pair) ⇒ Object



105
106
107
108
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 105

def get_orders(_session, _pair)
  return [] unless _pair == pair
  (@bids + @asks).map { |o| FakeOrder.new o.clone }
end

#get_session(_config) ⇒ Object

Raises:

  • (ArgumentError)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 76

def get_session(_config)
  raise ArgumentError, 'must provide login information' if _config.nil?

  if @config.nil?
    @pair = CurrencyPair.for_code(_config[:base], _config[:quote])
    @base_balance = _config[:base_balance]
    @quote_balance = _config[:quote_balance]
    @verbose = !!_config[:verbose]
    @config = _config
    @bids = []
    @asks = []
    @id = 1
  elsif @config != _config
    raise ArgumentError, 'invalid credentials'
  end

  nil
end

#open_asksObject



32
33
34
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 32

def open_asks
  asks.select { |o| o[:status] == AccountOrder::OPEN }
end

#open_bidsObject



28
29
30
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 28

def open_bids
  bids.select { |o| o[:status] == AccountOrder::OPEN }
end

#open_ordersObject



36
37
38
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 36

def open_orders
  open_bids + open_asks
end

#simulate_buy(_price, _volume) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 161

def simulate_buy(_price, _volume)
  ordered_asks = @asks.sort { |b| b[:price] * -1 }
  ordered_asks.each do |order|
    if order[:status] == AccountOrder::OPEN and order[:price] <= _price and _volume > 0
      if order[:pend_volume] > _volume
        @quote_balance += _volume * order[:price]
        order[:pend_volume] -= _volume
        order[:traded_volume] += _volume
        _volume = 0
      else
        @quote_balance += order[:pend_volume] * order[:price]
        _volume -= order[:pend_volume]
        order[:traded_volume] += order[:pend_volume]
        order[:pend_volume] = 0
      end

      if order[:pend_volume] == 0
        order[:status] = AccountOrder::CLOSED
      end
    end
  end
end

#simulate_sell(_price, _volume) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 184

def simulate_sell(_price, _volume)
  ordered_bids = @bids.sort { |b| b[:price] }
  ordered_bids.each do |order|
    if order[:status] == AccountOrder::OPEN and order[:price] >= _price and _volume > 0
      if order[:pend_volume] > _volume
        @base_balance += _volume
        order[:pend_volume] -= _volume
        order[:traded_volume] += _volume
        _volume = 0
      else
        @base_balance += order[:pend_volume]
        _volume -= order[:pend_volume]
        order[:traded_volume] += order[:pend_volume]
        order[:pend_volume] = 0
      end

      if order[:pend_volume] == 0
        order[:status] = AccountOrder::CLOSED
      end
    end
  end
end

#total_base_balanceObject



68
69
70
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 68

def total_base_balance
  @base_balance + frozen_base
end

#total_quote_balanceObject



72
73
74
# File 'lib/trade-o-matic/adapters/fake_backend.rb', line 72

def total_quote_balance
  @quote_balance + frozen_quote
end