Routing model and matching¶
Route¶
| Field | Type | Default | Meaning |
|---|---|---|---|
id |
int | assigned | Immutable route id |
name |
string | required | Unique route name |
description |
string | empty | Administrative description |
priority |
int | 0 |
Higher values are evaluated first |
enabled |
bool | true |
Whether the route participates in matching |
conditions.operation |
string/int | ANY / 0 |
Request operation |
conditions.group_mask |
string | * |
Wildcard account-group expression |
conditions.symbol_mask |
string | * |
Wildcard symbol expression |
conditions.login |
int | 0 |
Exact login; 0 matches every login |
conditions.cmd |
int | OP_NOTHING |
Exact trade command; OP_NOTHING matches every command |
conditions.reason |
int | -1 |
Exact reason; negative matches every reason |
conditions.volume_min |
int | 0 |
Inclusive minimum; 0 disables the lower bound |
conditions.volume_max |
int | 0 |
Inclusive maximum; 0 disables the upper bound |
steps |
array | required | Ordered execution targets |
created_at |
int64 | assigned | Creation timestamp |
updated_at |
int64 | assigned | Last mutation timestamp |
All configured conditions use AND. Group and symbol expressions use the server wildcard matcher. Volumes are represented in the server's integer volume units.
Operations¶
| Name | Value |
|---|---|
ANY |
0 |
OPEN |
1 |
CLOSE |
2 |
PARTIAL_CLOSE |
3 |
Route steps¶
| Field | Type | Meaning |
|---|---|---|
id |
int | Server-assigned step id |
route_id |
int | Owning route id |
position |
int | Zero-based position in the execution plan |
target |
string/int | Execution target |
timeout_ms |
int | Time before advancing to the next step |
dealer_pool_id |
int | Manual dealer pool identifier |
virtual_dealer_policy_id |
int | Virtual Dealer policy identifier |
gateway_id |
int | Configured Gateway instance identifier |
| Target | Value | Behavior |
|---|---|---|
INTERNAL |
0 |
Continue the existing execution flow |
MANUAL_DEALER |
1 |
Create a request for the selected manual dealer pool |
VIRTUAL_DEALER |
2 |
Evaluate the referenced automatic dealer policy |
REJECT |
3 |
Reject the routed trade operation |
GATEWAY |
4 |
Execute through the selected Gateway/LP instance and continue the chain |
GATEWAY is an independent execution target. Group selection remains a route
condition; symbol mapping and lot limits are taken from the confirmed Gateway
runtime specifications.
Example chain:
[
{"position":0,"target":"VIRTUAL_DEALER","virtual_dealer_policy_id":3,"timeout_ms":3000},
{"position":1,"target":"GATEWAY","gateway_id":1,"timeout_ms":5000},
{"position":2,"target":"INTERNAL","timeout_ms":0}
]
Validation¶
namemust not be empty and must be unique.- Login and volume bounds cannot be negative.
- A non-zero
volume_maxcannot be less thanvolume_min. - A route must contain at least one step.
- Step positions must be contiguous and start at
0. - Timeouts cannot be negative.
MANUAL_DEALERrequires a positivedealer_pool_id.VIRTUAL_DEALERrequires a positivevirtual_dealer_policy_id.GATEWAYrequires a positivegateway_id.- The referenced manual pool, Virtual Dealer policy, or Gateway configuration must exist when a route is created or updated.
- Every non-final manual, virtual dealer, or Gateway step requires a positive timeout.
INTERNALandREJECTare terminal and may only be the final step.- The final step must be
INTERNALorREJECTso every chain terminates deterministically.
Resolution¶
The cached route list is ordered by:
ORDER BY priority DESC, id ASC
The first enabled route whose conditions match is returned with all its steps. Equal priorities are therefore stable: the older route with the lower id wins.
No match produces an implicit plan that is not stored in the database:
{
"matched": false,
"route_id": 0,
"route_name": "default",
"steps": [{"target":"INTERNAL","target_id":0}],
"snapshot_version": 7
}
Persistence and cache¶
RoutingManager owns bases/routing.db with two tables:
routescontains conditions and ordering fields;route_stepscontains the ordered target chain and is deleted through its route foreign key.
Create and update operations persist a route and all steps in one SQLite transaction. After commit, the manager loads and atomically publishes a complete immutable RoutingSnapshot. Read and resolve operations acquire this snapshot and do not hold the database mutex.
snapshot_version changes after every successful reload and identifies the exact ruleset used by dry-run resolution. Optimistic concurrency based on this version is not implemented yet.
Trade execution integration¶
DealerPolicyService builds the routing context for OPEN, CLOSE, and PARTIAL_CLOSE. Routing runs after the operation's existing validation and before it is committed to the trade queue.
With routing execution disabled, trade behavior is unchanged. With it enabled, the ordered plan is executed as follows:
INTERNALcontinues Core execution;REJECTreturnsRET_TRADE_DISABLE;MANUAL_DEALERcreates a persistent request and defers execution;VIRTUAL_DEALERevaluates its policy and accepts, rejects, or advances to the next step.GATEWAYsends an execution request to the selected ready Gateway instance.
Virtual Dealer ACCEPT advances to the next configured step. Manual Dealer
ACCEPT also resumes from the following step. A Gateway EXECUTED result
advances to the next step, normally INTERNAL. NOT_APPLICABLE, unavailable,
transport failure, and timeout advance to the configured fallback step. An
explicit Gateway/LP REJECTED result terminates the chain with
RET_TRADE_DISABLE.
INTERNAL remains terminal. Post-trade hedging such as INTERNAL → GATEWAY
requires a separate HEDGE lifecycle and is not executed by this version.
A rejected pending activation follows the existing non-retryable activation-error path and cancels the pending order. ImportOpenTrade is excluded because it restores an already accepted position. Virtual Dealer policy details are documented in Dealing Center: Virtual Dealer.