Packages
tai
0.0.56
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.Actions
alias Tai.Trading.{
NotifyOrderUpdate,
OrderStore,
OrderResponses,
Order,
OrderSubmissions
}
@type order :: Order.t()
@type submission :: OrderSubmissions.Factory.submission()
@type response :: {:ok, order}
@spec create(submission) :: response
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: NotifyOrderUpdate.notify!(nil, order)
defp send_to_venue(order) do
result = Tai.Venues.Client.create_order(order)
{result, order}
end
defp parse_response({
{:ok, %OrderResponses.CreateAccepted{} = response},
order
}) do
%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()
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :open} = response},
order
}) do
%Actions.Open{
client_id: order.client_id,
venue_order_id: response.id,
cumulative_qty: response.cumulative_qty,
leaves_qty: response.leaves_qty,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :filled} = response},
order
}) do
%Actions.Fill{
client_id: order.client_id,
venue_order_id: response.id,
cumulative_qty: response.cumulative_qty,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :expired} = response},
order
}) do
%Actions.Expire{
client_id: order.client_id,
venue_order_id: response.id,
cumulative_qty: response.cumulative_qty,
leaves_qty: response.leaves_qty,
last_received_at: response.received_at,
last_venue_timestamp: response.venue_timestamp
}
|> OrderStore.update()
end
defp parse_response({
{:ok, %OrderResponses.Create{status: :rejected} = response},
order
}) do
%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()
end
defp parse_response({{:error, reason}, order}) do
%Actions.CreateError{
client_id: order.client_id,
reason: reason,
last_received_at: Timex.now()
}
|> OrderStore.update()
end
defp rescue_venue_adapter_error(reason, order) do
%Actions.CreateError{
client_id: order.client_id,
reason: {:unhandled, reason},
last_received_at: Timex.now()
}
|> OrderStore.update()
end
defp skip!(client_id) do
%Actions.Skip{
client_id: client_id
}
|> OrderStore.update()
end
defp notify_updated_order({:ok, {prev, current}}),
do: NotifyOrderUpdate.notify!(prev, current)
defp notify_updated_order({:error, {:invalid_status, _, _, %action_name{}}})
when action_name == Actions.AcceptCreate do
:ok
end
end