Packages
tai
0.0.23
0.0.75
0.0.74
0.0.73
0.0.72
0.0.71
0.0.70
0.0.69
0.0.68
0.0.67
0.0.66
0.0.65
0.0.64
0.0.63
0.0.62
0.0.61
0.0.60
0.0.59
0.0.58
0.0.57
0.0.56
0.0.55
0.0.54
0.0.53
0.0.52
0.0.51
0.0.50
0.0.49
0.0.48
0.0.47
0.0.46
0.0.45
0.0.44
0.0.43
0.0.42
0.0.41
0.0.40
0.0.39
0.0.38
0.0.37
0.0.36
0.0.35
0.0.34
0.0.33
0.0.32
0.0.31
0.0.30
0.0.29
0.0.28
0.0.27
0.0.26
0.0.25
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
A composable, real time, market data and trade execution toolkit
Current section
Files
Jump to
Current section
Files
lib/tai/trading/orders/create.ex
defmodule Tai.Trading.Orders.Create do
alias Tai.Trading.{
OrderStore,
OrderResponses,
Order,
Orders,
OrderSubmissions
}
@type order :: Order.t()
@type submission :: OrderSubmissions.Factory.submission()
@spec create(submission) :: {:ok, order}
def create(submission) do
{:ok, order} = OrderStore.enqueue(submission)
notify_initial_updated_order(order)
Task.async(fn ->
if Tai.Settings.send_orders?() do
try do
order
|> send_to_venue()
|> parse_response()
|> notify_updated_order()
rescue
e ->
{e, __STACKTRACE__}
|> rescue_venue_adapter_error(order)
|> notify_updated_order()
end
else
order.client_id
|> skip!
|> notify_updated_order()
end
end)
{:ok, order}
end
defp notify_initial_updated_order(order), do: Orders.updated!(nil, order)
defp notify_updated_order({_, {:ok, {prev, current}}}), do: Orders.updated!(prev, current)
defp notify_updated_order({:accept_create, {:error, {:invalid_status, _, _}}}), do: :ok
defp send_to_venue(order) do
result = Tai.Venue.create_order(order)
{result, order}
end
defp parse_response({
{:ok, %OrderResponses.CreateAccepted{} = response},
order
}) do
result =
%OrderStore.Actions.AcceptCreate{
client_id: order.client_id,
venue_order_id: response.id,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
{:accept_create, result}
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :open} = response},
order
}) do
result =
%OrderStore.Actions.Open{
client_id: order.client_id,
venue_order_id: response.id,
avg_price: response.avg_price,
cumulative_qty: response.cumulative_qty,
leaves_qty: response.leaves_qty,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
{:open, result}
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :filled} = response},
order
}) do
result =
%OrderStore.Actions.Fill{
client_id: order.client_id,
venue_order_id: response.id,
avg_price: response.avg_price,
cumulative_qty: response.cumulative_qty,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
{:fill, result}
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :expired} = response},
order
}) do
result =
%OrderStore.Actions.Expire{
client_id: order.client_id,
venue_order_id: response.id,
avg_price: response.avg_price,
cumulative_qty: response.cumulative_qty,
leaves_qty: response.leaves_qty,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
{:expire, result}
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :rejected} = response},
order
}) do
result =
%OrderStore.Actions.Reject{
client_id: order.client_id,
venue_order_id: response.id,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
{:reject, result}
end
defp parse_response({{:error, reason}, order}) do
result =
%OrderStore.Actions.CreateError{
client_id: order.client_id,
reason: reason,
last_received_at: Timex.now()
}
|> OrderStore.update()
{:create_error, result}
end
defp rescue_venue_adapter_error(reason, order) do
result =
%OrderStore.Actions.CreateError{
client_id: order.client_id,
reason: {:unhandled, reason},
last_received_at: Timex.now()
}
|> OrderStore.update()
{:create_error, result}
end
defp skip!(client_id) do
result = %OrderStore.Actions.Skip{client_id: client_id} |> OrderStore.update()
{:skip, result}
end
end