ALF example clients and parser libraries¶
These examples demonstrate how to connect to pm-alf-gwy as an external
client over TCP. They replicate the workflow of pm-alf-console but without
any ZeroMQ or edumatcher package dependency — only a plain TCP socket and
the ALF text protocol.
alf/
├── python/
│ ├── alf_parser.py # Protocol library: parse, build, AlfSession
│ └── alf_client.py # Interactive client with tab-completion
└── c/
├── alf_parser.h # C library header
├── alf_parser.c # C library implementation
├── alf_client.c # Interactive C client with readline
└── Makefile # Build helper
Prerequisites¶
Engine and gateway running:
TRADER01 must be listed in engine_config.yaml under participants.
Python: Python 3.9+, no extra packages needed.
C: GNU readline.
- macOS: brew install readline
- Linux: sudo apt install libreadline-dev
ALF wire format¶
- Command verbs and field keys are case-insensitive (normalized to uppercase)
- Fields without
=are silently skipped - Duplicate keys: last value wins
Python¶
Library: alf_parser.py¶
from alf_parser import parse_alf_line, build_alf_line, AlfSession, AlfMessage
# Parse one line received from the gateway
msg: AlfMessage = parse_alf_line("ACK|ORDER_ID=abc|ACCEPTED=FALSE|REJECT_CODE=ORDER_NOT_FOUND|REASON=missing")
print(msg.msg_type) # "ACK"
print(msg.fields) # {"ORDER_ID": "ABC", "ACCEPTED": "FALSE", "REJECT_CODE": "ORDER_NOT_FOUND", ...}
# Build a line to send
line: str = build_alf_line("NEW", {"SYM": "AAPL", "SIDE": "BUY",
"TYPE": "LIMIT", "QTY": "100", "PRICE": "150.00", "TAG": "ORDER-001"})
# → "NEW|SYM=AAPL|SIDE=BUY|TYPE=LIMIT|QTY=100|PRICE=150.00|TAG=ORDER-001\n"
# Full session: connect, HELLO/WELCOME handshake, send/recv
session = AlfSession.connect("127.0.0.1", 5565, "TRADER01")
print(session.gateway_id) # "TRADER01"
print(session.welcome.gw_name) # "alf-gwy01"
session.send("SYMBOLS")
msg = session.recv_msg() # first line of SYMBOLS response
session.close()
Interactive client: alf_client.py¶
cd docs/examples/alf/python
# Connect to local gateway
python3 alf_client.py --id TRADER01
# Connect to remote gateway
python3 alf_client.py --host 10.0.0.5 --port 5565 --id TRADER01
# Custom client name in gateway logs
python3 alf_client.py --id MM01 --client "my-mm-bot"
At the prompt:
[TRADER01]> NEW|SYM=AAPL|SIDE=BUY|TYPE=LIMIT|QTY=100|PRICE=150.00|TAG=order-001
[TRADER01]> AMEND|ID=<order-id>|PRICE=151.00|RTAG=req-001
[TRADER01]> CANCEL|ID=<order-id>|RTAG=req-002
[TRADER01]> SYMBOLS
[TRADER01]> ORDERS
[TRADER01]> POS
[TRADER01]> STATUS
[TRADER01]> HELP
[TRADER01]> EXIT
Tab completes command verbs, field names, and enum values.
Command history is saved to ~/.alf_client_history.
C¶
Build¶
Run¶
# Connect to local gateway
./alf_client --id TRADER01
# Connect to remote gateway
./alf_client --host 10.0.0.5 --port 5565 --id TRADER01
# Disable ANSI colour codes
./alf_client --id TRADER01 --no-color
The C client supports the same commands as the Python client. Tab-completion covers command verbs, field names, and common enum values.
C library usage¶
#include "alf_parser.h"
/* Parse */
char line[] = "ACK|ORDER_ID=abc|ACCEPTED=TRUE";
alf_message_t msg;
alf_parse_line(line, &msg);
printf("%s\n", msg.msg_type); /* "ACK" */
printf("%s\n", alf_get_field(&msg, "ACCEPTED")); /* "TRUE" */
/* Build */
const char *kv[] = {"SYM", "AAPL", "SIDE", "BUY",
"TYPE", "LIMIT", "QTY", "100", "PRICE", "150.00", "TAG", "ORDER-001", NULL};
char buf[4096];
alf_build_line(buf, sizeof(buf), "NEW", kv);
/* → "NEW|SYM=AAPL|SIDE=BUY|TYPE=LIMIT|QTY=100|PRICE=150.00|TAG=ORDER-001\n" */
write(sockfd, buf, strlen(buf));
Differences from pm-alf-console¶
| Feature | pm-alf-console |
alf_client (Python/C) |
|---|---|---|
| Transport | ZMQ PUSH/SUB directly | TCP via pm-alf-gwy |
| Machine | Same host as engine | Any host |
| Dependencies | edumatcher package + ZMQ |
stdlib only |
| P&L / POS | From local fill tracking | From local fill tracking |
POS\|GW=<id> (query another gateway) |
Yes | Yes |
| STATUS | Rich terminal display | Text table |
| QLEGS | Yes (local cache) | Yes (engine round trip) |
| Tab completion | Full context-aware | Commands, fields, enums |