Connect a data source
You'll plug your own market data into helixio: the market asks your source for exactly what a book needs, prices on the answer, and tells you every gap at once when the answer is incomplete.
Before you start
- helixio installed: see installing.
- Access to your quotes and fixings from code: a database, a file, a service. The program uses a sheet held in memory so it runs offline.
Steps
- Write a source: any object with
fetch(demand, as_of)in Python, or a type implementingMarketDataSourcein Rust. It returns the strips and prints the demand asks for. - Give the market your source with
with_data_source, and ask itdemand(book)to see what the book needs: quote strips by template, and prints by series and date. - Attach the market to the book. In Python, attaching fetches the market's own date; in Rust,
call
fetch_market_datafor it. Readfetch_report()to see what was answered. - Value the book as usual.
The comments in the program match these steps.
Rust
use std::sync::Arc;
use chrono::NaiveDate;
use helixrs::{
Book, DataSource, Demand, Locator, MarketContext, MarketData, MarketDataSource, SourceError,
StripQuotes, Termination, template,
};
type Outcome<T> = Result<T, Box<dyn std::error::Error>>;
/// What your source holds: the close, its quotes across the curve's segments,
/// and the SOFR prints before the close.
const SOFR_CLOSE_DATE: (i32, u32, u32) = (2026, 10, 1);
const USD_SOFR_LADDER: &[(&str, &str, f64)] = &[
("USD-SOFR-DEPO", "1W", 0.0389),
("USD-SOFR-MeetingOIS", "2026-10-28", 0.0388),
("USD-SOFR-3M-FUT", "MAR27", 95.65),
("USD-SOFR-3M-FUT", "JUN27", 95.55),
("USD-SOFR-OIS", "2Y", 0.0459),
("USD-SOFR-OIS", "5Y", 0.0471),
("USD-SOFR-OIS", "10Y", 0.0483),
];
const USD_SOFR_PRINTS: &[(&str, (i32, u32, u32), f64)] = &[
("USD-SOFR", (2026, 9, 28), 0.0390),
("USD-SOFR", (2026, 9, 29), 0.0388),
("USD-SOFR", (2026, 9, 30), 0.0390),
];
fn date((year, month, day): (i32, u32, u32)) -> NaiveDate {
NaiveDate::from_ymd_opt(year, month, day).expect("a real calendar date")
}
/// Answers every strip it holds that the market asks for, and its prints.
struct DeskSheet {
sheet: Vec<(&'static str, &'static str, f64)>,
}
impl MarketDataSource for DeskSheet {
fn fetch(&self, demand: &Demand, as_of: NaiveDate) -> Result<MarketData, SourceError> {
let unreadable = |message: String| SourceError::Source {
source: "desk sheet".to_owned(),
message,
};
let mut strips = Vec::new();
for asked in &demand.strips {
let mut entries = Vec::new();
for (_, locator, quote) in self.sheet.iter().filter(|(t, _, _)| *t == asked.template) {
let at = Locator::parse(locator).map_err(|e| unreadable(e.to_string()))?;
entries.push((at, *quote));
}
if !entries.is_empty() {
strips.push(StripQuotes {
template: asked.template.clone(),
observed: as_of,
entries,
});
}
}
let fixings = USD_SOFR_PRINTS
.iter()
.map(|(series, day, value)| ((*series).to_owned(), date(*day), *value))
.collect();
Ok(MarketData {
strips,
fixings,
fx: Vec::new(),
})
}
}
fn sourced(close: NaiveDate, only: Option<&str>) -> MarketContext {
let sheet = USD_SOFR_LADDER
.iter()
.copied()
.filter(|(template, _, _)| only.is_none_or(|kept| kept == *template))
.collect();
MarketContext::as_of(close).with_data_source(Some(DataSource::new(Arc::new(DeskSheet { sheet }))))
}
fn main() -> Outcome<()> {
let close = date(SOFR_CLOSE_DATE);
// Ask what a book needs. A swap traded on 24 September has accrued three days
// by the close, so the book reads three prints, and the USD recipe four strips.
let seasoned = template("USD-SOFR-OIS")?
.swap(date((2026, 9, 24)))?
.with_maturity("5Y".parse::<Termination>()?)?
.with_notional(50_000_000.0)
.with_fixed_rate(0.0466)
.build()?;
let book = Book::new().add("SOFR-5Y", seasoned.clone(), 1.0);
let market = sourced(close, None);
let demand = market.demand(&book)?;
for strip in &demand.strips {
println!("strip {}", strip.template);
}
for (series, day) in &demand.fixings {
println!("fixing {series} {day}");
}
// Attach the market and fetch its date; Rust fetches nothing until asked.
// The report says what came back.
let mut book = book.attach_market(market);
book.fetch_market_data(close)?;
let npv = book.npv(close)?;
let rows = &book.fetch_report().rows;
let answered = rows.iter().filter(|(_, _, status)| *status == "answered").count();
println!("answered {answered} of {}", rows.len());
println!("npv {npv:.2}");
// A source that holds only the swaps leaves three strips unanswered. The
// snapshot is refused, and the refusal names every gap at once.
let partial = sourced(close, Some("USD-SOFR-OIS"));
let mut thin = Book::new().add("SOFR-5Y", seasoned, 1.0).attach_market(partial);
let gaps_refused = match thin.fetch_market_data(close) {
Ok(_) => String::new(),
Err(refused) => refused.to_string(),
};
println!(
"refused, naming 3 gaps at once: {}",
if gaps_refused.contains("3 gap(s)") { "yes" } else { "no" }
);
Ok(())
}Python
import datetime as dt
import helixio as hlx
# What your source holds: the close, its quotes across the curve's segments,
# and the SOFR prints before the close.
SOFR_CLOSE_DATE = dt.date(2026, 10, 1)
USD_SOFR_LADDER = {
"USD-SOFR-DEPO": {"1W": 0.0389},
"USD-SOFR-MeetingOIS": {"2026-10-28": 0.0388},
"USD-SOFR-3M-FUT": {"MAR27": 95.65, "JUN27": 95.55},
"USD-SOFR-OIS": {"2Y": 0.0459, "5Y": 0.0471, "10Y": 0.0483},
}
USD_SOFR_PRINTS = [
("USD-SOFR", dt.date(2026, 9, 28), 0.0390),
("USD-SOFR", dt.date(2026, 9, 29), 0.0388),
("USD-SOFR", dt.date(2026, 9, 30), 0.0390),
]
class DeskSheet:
"""Answers every strip it holds that the market asks for, and its prints."""
def __init__(self, sheet):
self.sheet = sheet
def fetch(self, demand, as_of):
asked = demand.strips.to_dict()["template"]
strips = [
(template, as_of, list(self.sheet[template].items()))
for template in asked
if template in self.sheet
]
return hlx.MarketData(strips=strips, fixings=list(USD_SOFR_PRINTS))
# Ask what a book needs. A swap traded on 24 September has accrued three days
# by the close, so the book reads three prints, and the USD recipe four strips.
seasoned = (
hlx.templates.get("USD-SOFR-OIS")
.swap(dt.date(2026, 9, 24))
.with_maturity("5Y")
.with_notional(50_000_000.0)
.with_fixed_rate(0.0466)
.build()
)
book = hlx.Book().add("SOFR-5Y", seasoned, 1.0)
market = hlx.MarketContext(SOFR_CLOSE_DATE).with_data_source(DeskSheet(USD_SOFR_LADDER))
demand = market.demand(book)
for template in demand.strips.to_dict()["template"]:
print(f"strip {template}")
for series, day in zip(demand.fixings.to_dict()["series"], demand.fixings.to_dict()["date"]):
print(f"fixing {series} {day}")
# Attach the market: attaching fetches the market's own date. The report says
# what came back.
book.attach_market(market)
npv = book.npv(as_of=SOFR_CLOSE_DATE)
report = book.fetch_report().to_dict()
print(f"answered {report['status'].count('answered')} of {len(report['status'])}")
print(f"npv {npv:.2f}")
# A source that holds only the swaps leaves three strips unanswered. The
# snapshot is refused, and the refusal names every gap at once.
partial = hlx.MarketContext(SOFR_CLOSE_DATE).with_data_source(
DeskSheet({"USD-SOFR-OIS": USD_SOFR_LADDER["USD-SOFR-OIS"]})
)
try:
hlx.Book().add("SOFR-5Y", seasoned, 1.0).attach_market(partial)
gaps_refused = ""
except hlx.SnapshotError as refused:
gaps_refused = str(refused)
print(f"refused, naming 3 gaps at once: {'yes' if '3 gap(s)' in gaps_refused else 'no'}")strip USD-SOFR-3M-FUT
strip USD-SOFR-DEPO
strip USD-SOFR-MeetingOIS
strip USD-SOFR-OIS
fixing USD-SOFR 2026-09-28
fixing USD-SOFR 2026-09-29
fixing USD-SOFR 2026-09-30
answered 7 of 7
npv -102966.25
refused, naming 3 gaps at once: yes
Check it worked
- Every row of the fetch report is
answered. - The book values.
- If your source can't answer a strip, the fetch is refused with one message naming every gap, not just the first.
Related
- Data sources, the reference for the source protocol.
- Quote sheets and recipes, for what a strip is.
From the 0.0 line at revision bf7f2e2. Every printed number is that revision's own output.