Adding a venue: an Alpaca order-book worker
This walkthrough adds an order-book worker for Alpaca. It adds one file to the new worker's repo. No other repo, and no central file, changes.
1. The fragment
naming/virtufin.worker.alpacaorderbook.yaml in the worker's repo:
fragment: virtufin.worker.alpacaorderbook
imports: [virtufin.market]
venues:
alpaca:
symbol: "{BASE}/{QUOTE}" # BTC_USD <-> BTC/USD
intervals: {1Min: 1m, 1Hour: 1h, 1Day: 1d}
bind:
# Partial application: the venue-generic order book with venue = alpaca.
orderbook: {entity: virtufin.market/orderbook, with: {venue: alpaca}}
workers:
alpacaorderbook:
consumes: [orderbook.update]
produces: [orderbook.changed, orderbook.gap]
If a second Alpaca worker appears later, move the venues and bind
blocks into a shared virtufin.venue.alpaca fragment and import it from
both workers.
2. The names it gets
| Name | Value |
|---|---|
| raw feed topic (consumed) | act.exchange.alpaca.orderbook.update |
| changed topic | act.exchange.alpaca.orderbook.changed.BTC_USD |
| gap topic | act.exchange.alpaca.orderbook.gap.BTC_USD |
| state key | act.exchange.alpaca.orderbook.BTC_USD |
| ce-subject | currency_pair/BTC_USD |
| ce-type | com.virtufin.exchange.alpaca.orderbook.changed |
| worker response / error | wrk.alpacaorderbook.response / wrk.alpacaorderbook.error |
venue symbol of BTC_USD |
BTC/USD |
3. The code
var names = NameRegistry.Load(typeof(AlpacaOrderBookWorker).Assembly);
var book = names.GetEntity("virtufin.worker.alpacaorderbook/orderbook");
var alpaca = names.GetVenue("alpaca");
foreach (var pair in config.Pairs) // canonical: BTC_USD
{
var symbol = alpaca.ToVenueSymbol(pair); // BTC/USD, for the Alpaca API
var topic = book.Topic("changed", World.Act, pair); // act.exchange.alpaca.orderbook.changed.BTC_USD
var key = book.Key(World.Act, pair);
}
// Incoming venue symbol back to the canonical pair, among the configured pairs.
alpaca.TryFromVenueSymbol("BTC/USD", config.Pairs, out var canonical);
The generic entity can also be bound in code, without a fragment:
names.GetEntity("virtufin.market/orderbook").Bind(venue). Only the
fragment makes the family visible to the docs and to the conflict check,
so a deployed worker always ships one.
4. What protects everyone else
- The fragment cannot change existing names: composition adds families and never edits them. The conformance suite checks that every Binance name is unchanged after the Alpaca fragment is added.
- If another repo also declared venue
alpaca, or bound the order book toalpacaagain, composition would fail with a message naming both fragments, and so would the specs site build.