rex/spec/order_book_spec.rb
Tim Kächele 0efb6b0e88 Remove limit volume tracking from order book
It is not super relevant for the current matching engine,
we are going to solve this in the server implementation
2023-10-30 20:43:49 +01:00

162 lines
4.4 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Rex::OrderBook do
let(:instance) { described_class.new }
describe "#add_order" do
let(:order_a) { build(:order, id: nil, is_buy: true, price: 100) }
let(:order_b) { build(:order, id: nil, is_buy: true, price: 101) }
it "adds the order to the order book" do
instance.add_order(order_a)
expect(instance.best_buy_price).to eq(100)
end
it "assigns an order id" do
expect { instance.add_order(order_a) }.to change(order_a, :id).from(nil).to(1)
expect { instance.add_order(order_b) }.to change(order_b, :id).from(nil).to(2)
end
context "with multiple orders at the same price" do
let(:order_b) { build(:order, is_buy: true, price: 100) }
it "regards the new order as the best buy price" do
instance.add_order(order_a)
instance.add_order(order_b)
expect(instance.best_buy_price).to eq(100)
expect(instance.highest_buy_order).to eq(order_a)
end
end
context "with multiple orders at the different price levels" do
let(:order_b) { build(:order, is_buy: true, price: 120) }
it "regards the new order as the best buy price" do
instance.add_order(order_b)
instance.add_order(order_a)
expect(instance.best_buy_price).to eq(120)
expect(instance.highest_buy_order).to eq(order_b)
end
end
context "with multiple orders on different sides" do
let(:order_b) { build(:order, is_buy: false, price: 120) }
it "returns the correct prices for both sides" do
instance.add_order(order_a)
instance.add_order(order_b)
expect(instance.best_buy_price).to eq(100)
expect(instance.best_sell_price).to eq(120)
end
end
end
describe "add_and_match_order" do
context "when matcher is given" do
let(:matcher) { instance_double(Rex::Matcher) }
let(:instance) { described_class.new(matcher: matcher) }
let(:order) { build(:order, is_buy: true, price: 100) }
before do
allow(matcher).to receive(:match).with(instance)
end
it "adds the order" do
expect(instance).to receive(:add_order).with(order)
instance.add_and_match_order(order)
end
it "calls the matcher" do
expect(matcher).to receive(:match).with(instance)
instance.add_and_match_order(order)
end
end
end
describe "#highest_buy_order" do
context "when there is nothing in the book" do
it "returns nil " do
expect(instance.highest_buy_order).to eq(nil)
end
end
end
describe "#best_sell_price" do
context "when the order book is empty" do
it "returns nil" do
expect(instance.best_sell_price).to eq(nil)
end
end
end
describe "#lowest_sell_Order" do
context "when there is nothing in the book" do
it "returns nil " do
expect(instance.highest_buy_order).to eq(nil)
end
end
end
describe "#cancel_order" do
let(:buy_order) { build(:order, is_buy: true, price: 100) }
let(:sell_order) { build(:order, is_buy: false, price: 121) }
before do
instance.add_order(buy_order)
end
context "when the order id is unknown" do
it "returns nil" do
expect(instance.cancel_order(-1)).to eq(nil)
end
end
context "when it is the last order for the given price" do
it "removes the order from the side" do
instance.cancel_order(buy_order.id)
expect(instance.best_buy_price).to eq(nil)
end
end
context "when it is not the last order for the given price" do
let(:another_buy_order) { build(:order, is_buy: true, price: 100) }
before do
instance.add_order(another_buy_order)
end
it "removes the order from the side" do
instance.cancel_order(buy_order.id)
expect(instance.best_buy_price).to eq(100)
end
end
context "an order on the sell side is removed" do
before do
instance.add_order(buy_order)
instance.add_order(sell_order)
end
it "does not affect the buy side" do
instance.cancel_order(sell_order.id)
expect(instance.best_buy_price).to eq(100)
end
end
end
describe "#next_trade_id" do
it "returns an increasing trade id" do
expect(instance.next_trade_id).to eq(1)
expect(instance.next_trade_id).to eq(2)
expect(instance.next_trade_id).to eq(3)
end
end
end