Skip to content

Commit

Permalink
use genserver for order management
Browse files Browse the repository at this point in the history
  • Loading branch information
Dania02525 committed Jan 19, 2018
1 parent 9903199 commit 10d44cf
Show file tree
Hide file tree
Showing 11 changed files with 320 additions and 201 deletions.
2 changes: 1 addition & 1 deletion lib/elixir_exchange/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ defmodule ElixirExchange.Application do
# Start the endpoint when the application starts
supervisor(ElixirExchangeWeb.Endpoint, []),

supervisor(ElixirExchange.OrderSupervisor, []),
worker(ElixirExchange.GraphCache, []),
worker(ElixirExchange.OrderCache, []),
worker(ElixirExchange.Cron, [[
%{
module: ElixirExchange.GraphData,
Expand Down
50 changes: 0 additions & 50 deletions lib/elixir_exchange/caches/order_cache.ex

This file was deleted.

65 changes: 0 additions & 65 deletions lib/elixir_exchange/data/market_order_filler.ex

This file was deleted.

63 changes: 2 additions & 61 deletions lib/elixir_exchange/data/order_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ defmodule ElixirExchange.OrderData do
ElixirExchange.FakeOrderData.market_price()
end

def query_active_buy_orders(pair) do
def query_active_orders(pair, "buy") do
ElixirExchange.FakeOrderData.fake_orders
|> Enum.filter(fn({_k, o})->
o.side == "buy" && (o.status == "open" || o.status == "partially_filled") && o.type == "limit"
end)
|> Enum.map(fn {_k, v}-> v end)
end

def query_active_sell_orders(pair) do
def query_active_orders(pair, "sell") do
ElixirExchange.FakeOrderData.fake_orders
|> Enum.filter(fn({_k, o})->
o.side == "sell" && (o.status == "open" || o.status == "partially_filled") && o.type == "limit"
Expand All @@ -26,63 +26,4 @@ defmodule ElixirExchange.OrderData do
end)
|> Enum.map(fn {_k, v}-> v end)
end

def cached_buy_orders(pair) do
ElixirExchange.OrderCache.buy_orders(pair)
end

def cached_sell_orders(pair) do
ElixirExchange.OrderCache.sell_orders(pair)
end

# order filling logic
def fill_market_order(order) do
sell_orders = cached_sell_orders(order.pair)
[order, modified_orders, new_market_price] =
ElixirExchange.MarketOrderFiller.fill_market_order(order, sell_orders)

ElixirExchange.OrderCache.update_modified_sell_orders(order.pair, modified_orders)

# asyncronously balance limit orders

broadcast_new_order_data(order.pair, new_market_price)
end

def balance_limit_orders do
# not impl
end

def broadcast_new_order_data(pair, price) do
data = %{
order_data: %{
buys: collapse_orders(cached_buy_orders(pair)),
sells: collapse_orders(cached_sell_orders(pair))
},
market_price: price
}

ElixirExchangeWeb.Endpoint.broadcast("trading:#{pair}", "update_orders", data)
end

defp collapse_orders(orders) do
Enum.reduce(orders, %{}, fn(o, acc)->
existing = Map.get(acc, o.price)
if existing do
order = %{
price: o.price,
quantity: existing.quantity + o.unfilled_quantity
}
Map.put(acc, o.price, order)
else
order = %{
price: o.price,
quantity: o.unfilled_quantity
}
Map.put(acc, o.price, order)
end
end)
|> Enum.map(fn {_k, v}->
v
end)
end
end
23 changes: 23 additions & 0 deletions lib/elixir_exchange/imports/format_helpers.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule ElixirExchange.FormatHelpers do
def collapse_orders(orders) do
Enum.reduce(orders, %{}, fn(o, acc)->
existing = Map.get(acc, o.price)
if existing do
order = %{
price: o.price,
quantity: existing.quantity + o.unfilled_quantity
}
Map.put(acc, o.price, order)
else
order = %{
price: o.price,
quantity: o.unfilled_quantity
}
Map.put(acc, o.price, order)
end
end)
|> Enum.map(fn {_k, v}->
v
end)
end
end
121 changes: 121 additions & 0 deletions lib/elixir_exchange/imports/server_helpers.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
defmodule ElixirExchange.ServerHelpers do
import ElixirExchange.FormatHelpers

def process_alias(pair, side) do
String.to_atom("#{side}_#{pair}")
end

##
#
# Notifier
#
##


def notify_market(old_state, new_state) do
market_leader =
old_state
|> Enum.reverse
|> Enum.find(fn(o)->
o.type == "limit" && (o.status == "filled" || o.status == "partially_filled")
end)

do_notify_market(new_state, market_leader)
end

def do_notify_market(state, %{side: "sell"} = market_leader) do
payload = %{
order_data: %{
sells: collapse_orders(state)
},
market_price: market_leader.price
}

pair = market_leader.pair

ElixirExchangeWeb.Endpoint.broadcast("trading:#{pair}", "update_orders", payload)
end

def do_notify_market(state, %{side: "buy"} = market_leader) do
payload = %{
order_data: %{
buys: collapse_orders(state)
},
market_price: market_leader.price
}

pair = market_leader.pair

ElixirExchangeWeb.Endpoint.broadcast("trading:#{pair}", "update_orders", payload)
end

def do_notify_market(_state, _any) do
:noop
end


##
#
# Order filling
#
##

def maybe_fill_order(order, []) do
push_order(order)
[]
end

def maybe_fill_order(%{type: "market"} = order, state) do
do_fill_order(order, state)
end

def maybe_fill_order(%{type: "limit", side: "sell"} = order, state) do
if List.first(state).price > order.price do
do_fill_order(order, state)
else
push_order(order)
state
end
end

def maybe_fill_order(%{type: "limit", side: "buy"} = order, state) do
if List.first(state).price < order.price do
do_fill_order(order, state)
else
push_order(order)
state
end
end

def do_fill_order(order, state) do
[order, mixed_state] = ElixirExchange.OrderFiller.fill_order(order, state)

new_state =
Enum.reject(mixed_state, fn(o)->
o.status == "filled" && o.unfilled_quantity == 0
end)

notify_market(mixed_state, new_state)
push_order(order)

new_state
end

##
#
# Order Caching
#
##

def push_order(%{unfilled_quantity: 0, status: "filled"}) do
:noop
end

def push_order(%{side: "buy", pair: pair} = order) do
GenServer.cast(process_alias(pair, "buy"), {:push_order, order})
end

def push_order(%{side: "sell", pair: pair} = order) do
GenServer.cast(process_alias(pair, "sell"), {:push_order, order})
end
end
File renamed without changes.
Loading

0 comments on commit 10d44cf

Please sign in to comment.