Implement a limit volume tracker
Implement the limit volume tracker that keeps track of the limit volumes and emits change events that can be used by clients to update their copy of the order book
This commit is contained in:
parent
b7df45794c
commit
188f45d4c4
@ -5,6 +5,7 @@ require_relative "book/trade"
|
|||||||
require_relative "book/order"
|
require_relative "book/order"
|
||||||
require_relative "book/limit_order_book"
|
require_relative "book/limit_order_book"
|
||||||
require_relative "book/matcher"
|
require_relative "book/matcher"
|
||||||
|
require_relative "book/limit_volume_tracker"
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
module Book
|
module Book
|
||||||
|
63
lib/rex/book/limit_volume_tracker.rb
Normal file
63
lib/rex/book/limit_volume_tracker.rb
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
module Rex
|
||||||
|
module Book
|
||||||
|
class LimitVolumeTracker
|
||||||
|
LimitVolumeChange = Struct.new(:side, :price, :new_volume)
|
||||||
|
|
||||||
|
attr_reader :volumes
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@volumes = Hash.new { 0 }
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_order(order)
|
||||||
|
volumes[[order.is_buy, order.price]] += order.remaining_quantity
|
||||||
|
|
||||||
|
[
|
||||||
|
LimitVolumeChange.new(
|
||||||
|
side(order),
|
||||||
|
order.price,
|
||||||
|
volumes[[order.is_buy, order.price]]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_order(order)
|
||||||
|
volumes[[order.is_buy, order.price]] -= order.remaining_quantity
|
||||||
|
|
||||||
|
[
|
||||||
|
LimitVolumeChange.new(
|
||||||
|
side(order),
|
||||||
|
order.price,
|
||||||
|
volumes[[order.is_buy, order.price]]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_trade(trade)
|
||||||
|
buy_order = trade.buy_order
|
||||||
|
sell_order = trade.sell_order
|
||||||
|
|
||||||
|
volumes[[buy_order.is_buy, buy_order.price]] -= trade.quantity
|
||||||
|
volumes[[sell_order.is_buy, sell_order.price]] -= trade.quantity
|
||||||
|
[
|
||||||
|
LimitVolumeChange.new(
|
||||||
|
:buy,
|
||||||
|
buy_order.price,
|
||||||
|
volumes[[buy_order.is_buy, buy_order.price]]
|
||||||
|
),
|
||||||
|
LimitVolumeChange.new(
|
||||||
|
:sell,
|
||||||
|
sell_order.price,
|
||||||
|
volumes[[sell_order.is_buy, sell_order.price]]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def side(order)
|
||||||
|
order.is_buy ? :buy : :sell
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
71
spec/book/limit_volume_tracker_spec.rb
Normal file
71
spec/book/limit_volume_tracker_spec.rb
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Rex::Book::LimitVolumeTracker do
|
||||||
|
let(:instance) { described_class.new }
|
||||||
|
let(:sell_order) { build(:order, is_buy: false, price: 100, quantity: 250) }
|
||||||
|
let(:buy_order) { build(:order, is_buy: true, price: 100, quantity: 200) }
|
||||||
|
|
||||||
|
describe "#add_order" do
|
||||||
|
it "adds the quantity to the limit volume" do
|
||||||
|
expect { instance.add_order(sell_order) }.to(
|
||||||
|
change { instance.volumes[[false, 100]] }.to(250)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the changes limit volumes as a struct" do
|
||||||
|
expect(instance.add_order(sell_order)).to eq([
|
||||||
|
Rex::Book::LimitVolumeTracker::LimitVolumeChange.new(:sell, 100, 250)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#remove_order" do
|
||||||
|
before do
|
||||||
|
instance.add_order(sell_order)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "removes the quantity from the limit volume" do
|
||||||
|
expect { instance.remove_order(sell_order) }.to(
|
||||||
|
change { instance.volumes[[false, 100]] }.from(250).to(0)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the changes limit volumes as a struct" do
|
||||||
|
expect(instance.remove_order(sell_order)).to eq([
|
||||||
|
Rex::Book::LimitVolumeTracker::LimitVolumeChange.new(:sell, 100, 0)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#process_trade" do
|
||||||
|
let(:trade) do
|
||||||
|
Rex::Book::Trade.new(
|
||||||
|
buy_order: buy_order,
|
||||||
|
sell_order: sell_order,
|
||||||
|
price: 100,
|
||||||
|
quantity: 200
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
instance.add_order(sell_order)
|
||||||
|
instance.add_order(buy_order)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the volumes of the involved limits" do
|
||||||
|
expect { instance.process_trade(trade) }.to(
|
||||||
|
change { instance.volumes[[false, 100]] }.from(250).to(50)
|
||||||
|
.and(
|
||||||
|
change { instance.volumes[[true, 100]] }.from(200).to(0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the changes limit volumes as a struct" do
|
||||||
|
expect(instance.process_trade(trade)).to eq([
|
||||||
|
Rex::Book::LimitVolumeTracker::LimitVolumeChange.new(:buy, 100, 0),
|
||||||
|
Rex::Book::LimitVolumeTracker::LimitVolumeChange.new(:sell, 100, 50)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user