FixAlchemy.Backend behaviour (FIXAlchemy v0.2.4)
View SourceBase for a platform trading backend over the FIX engine.
use FixAlchemy.Backend gives a module the full backend API the
platform calls — connect/2, send_order/2, get_positions/1, and the rest —
plus the __backend__/0 marker that makes it auto-discoverable. The baseline
:fix backend is this module's defaults: generic connection fields, the plain
FixAlchemy.{Session,MarketData,Portfolio}.Plain handlers, FixAlchemy.Trading
as the order surface, and readiness on logon.
A broker adapter overrides the callbacks with @impl FixAlchemy.Backend
to change its config schema, handler set, readiness, trading surface, or the
extras it starts per connection — the connection/dispatch plumbing is shared:
defmodule MyBroker.TradingBackend do
use FixAlchemy.Backend
@impl FixAlchemy.Backend
def backend_config, do: %{FixAlchemy.Backend.default_config() | id: :mybroker}
@impl FixAlchemy.Backend
def trading_module, do: MyBroker
end
Summary
Callbacks
Config schema exposed to the platform for connection setup.
Whether sessions defer readiness until the adapter calls Client.ready/1.
Fetch historical candles for a symbol (default: unsupported).
Decimal places a price may carry for an instrument.
Per-session subscriber modules supervised with each client.
Start any per-connection extras once a trading session is up.
Stop any per-connection extras on disconnect.
The order-entry/read module used for this backend.
Functions
The sessions a connection config declares, in declaration order.
The baseline :fix backend config schema.
The generic connection fields shared by every FIX backend.
The sections a connection form lays its shared fields out in, in order.
The repeatable session group of a connection form.
The account the connection's orders and account reads use.
The accounts the connection's trading session holds.
The shared settings of fields a session may override, in declaration order.
Build what config needs before a session using it starts.
Select the account the connection's orders and account reads use.
Run fun with the client of the session serving role.
Run fun with the name of the session serving role.
Callbacks
@callback backend_config() :: map()
Config schema exposed to the platform for connection setup.
@callback defer_ready?() :: boolean()
Whether sessions defer readiness until the adapter calls Client.ready/1.
@callback get_historical_candles( connection_id :: binary(), symbol :: binary(), opts :: keyword() ) :: {:ok, [map()]} | {:error, term()}
Fetch historical candles for a symbol (default: unsupported).
@callback get_instrument_precision(connection_id :: binary(), symbol :: binary()) :: {:ok, non_neg_integer()} | {:error, term()}
Decimal places a price may carry for an instrument.
The default derives it from the security list's point size (FXCM's
fxcm_sym_point_size). A venue that expresses precision differently overrides
this with @impl FixAlchemy.Backend.
@callback handlers() :: [module()]
Per-session subscriber modules supervised with each client.
Start any per-connection extras once a trading session is up.
Stop any per-connection extras on disconnect.
@callback trading_module() :: module()
The order-entry/read module used for this backend.
Functions
@spec configured_sessions(keyword() | map()) :: [FixAlchemy.SessionConfig.t()]
The sessions a connection config declares, in declaration order.
Delegates to FixAlchemy.SessionConfig.from_connection_config/1: a config
listing sessions under :sessions gets those; one carrying the flat
host/port/sender_comp_id and host_md/port_md/sender_comp_id_md
groups instead gets the sessions :trading and :md those groups describe.
Sessions that are not fully configured are dropped, so an empty list means
the config names no usable session.
@spec default_config() :: map()
The baseline :fix backend config schema.
@spec default_fields() :: [map()]
The generic connection fields shared by every FIX backend.
@spec default_groups() :: [map()]
The sections a connection form lays its shared fields out in, in order.
Every field of default_fields/0 carries the :group it belongs to.
@spec default_session_group() :: map()
The repeatable session group of a connection form.
Each row is one FIX session: the fields it always carries, plus whichever
shared settings it overrides. The overridable settings are not listed here —
a form derives them from the backend's own :fields, taking every one that
does not declare overridable: false, so a backend adding a shared field
makes it overridable by the same act.
The account the connection's orders and account reads use.
The accounts the connection's trading session holds.
Accounts come from the venue: whatever it named on the messages the session
has received, in the order they were first seen. The :account a connection
is configured with stands in while the venue has named none.
The shared settings of fields a session may override, in declaration order.
Every field is overridable unless it declares overridable: false, which a
backend uses for a setting that belongs to the connection as a whole rather
than to any one session.
Build what config needs before a session using it starts.
Generates and caches the dictionaries config names. Repeat calls reuse what
is already built.
Returns {:error, reason} when a named dictionary cannot be built.
Select the account the connection's orders and account reads use.
account must be one of list_accounts/1; any other is rejected with
{:error, :unknown_account}. An order naming its own :account still goes to
that one.
Run fun with the client of the session serving role.
The role is resolved through FixAlchemy.SessionDirectory, so a connection
whose sessions are named anything at all is reached by what its sessions are
for. with_client/2 uses the :trading role.
Returns {:error, :not_found} when the connection runs no session,
{:error, {:no_session_for_role, role}} when none serves the role, and
{:error, {:session_not_ready, name}} when the session that does has no live
client.
@spec with_client(binary(), FixAlchemy.SessionConfig.role(), (pid() -> result)) :: result | {:error, term()} when result: term()
@spec with_session( binary(), FixAlchemy.SessionConfig.role(), (FixAlchemy.SessionConfig.name() -> result) ) :: result | {:error, term()} when result: term()
Run fun with the name of the session serving role.
Resolves as with_client/3 does, for callers addressing a session's
subscriber processes rather than its client.