Add futures expiration schedule
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use serde::Serialize;
|
||||
@@ -104,6 +104,7 @@ pub struct BacktestEngine<S, C, R> {
|
||||
subscriptions: BTreeSet<String>,
|
||||
futures_account: Option<FuturesAccountState>,
|
||||
next_futures_order_id: u64,
|
||||
futures_expirations: BTreeMap<NaiveDate, BTreeMap<String, f64>>,
|
||||
}
|
||||
|
||||
impl<S, C, R> BacktestEngine<S, C, R> {
|
||||
@@ -124,6 +125,7 @@ impl<S, C, R> BacktestEngine<S, C, R> {
|
||||
subscriptions: BTreeSet::new(),
|
||||
futures_account: None,
|
||||
next_futures_order_id: 1,
|
||||
futures_expirations: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +151,27 @@ impl<S, C, R> BacktestEngine<S, C, R> {
|
||||
self.futures_account.as_mut()
|
||||
}
|
||||
|
||||
pub fn with_futures_expiration(
|
||||
mut self,
|
||||
date: NaiveDate,
|
||||
symbol: impl Into<String>,
|
||||
settlement_price: f64,
|
||||
) -> Self {
|
||||
self.futures_expirations
|
||||
.entry(date)
|
||||
.or_default()
|
||||
.insert(symbol.into(), settlement_price);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_futures_expirations(
|
||||
mut self,
|
||||
expirations: BTreeMap<NaiveDate, BTreeMap<String, f64>>,
|
||||
) -> Self {
|
||||
self.futures_expirations = expirations;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn process_event_bus_mut(&mut self) -> &mut ProcessEventBus {
|
||||
&mut self.process_event_bus
|
||||
}
|
||||
@@ -1412,6 +1435,8 @@ where
|
||||
&mut settlement_decision,
|
||||
&mut directive_report,
|
||||
)?;
|
||||
let futures_expiration_report = self.settle_futures_expirations(execution_date);
|
||||
merge_broker_report(&mut directive_report, futures_expiration_report);
|
||||
let dynamic_universe_snapshot = self.dynamic_universe.clone();
|
||||
let subscriptions_snapshot = self.subscriptions.clone();
|
||||
let management_fee_report = self.apply_management_fee(
|
||||
@@ -1841,6 +1866,26 @@ where
|
||||
report
|
||||
}
|
||||
|
||||
fn settle_futures_expirations(&mut self, date: NaiveDate) -> BrokerExecutionReport {
|
||||
let mut report = BrokerExecutionReport::default();
|
||||
let Some(expirations) = self.futures_expirations.remove(&date) else {
|
||||
return report;
|
||||
};
|
||||
let Some(account) = self.futures_account.as_mut() else {
|
||||
report.diagnostics.push(format!(
|
||||
"futures_expiration_skipped date={date} reason=no_future_account count={}",
|
||||
expirations.len()
|
||||
));
|
||||
return report;
|
||||
};
|
||||
for (symbol, settlement_price) in expirations {
|
||||
let futures_report =
|
||||
account.expire_contract(date, &symbol, settlement_price, "data_driven_expiration");
|
||||
merge_futures_report(&mut report, futures_report);
|
||||
}
|
||||
report
|
||||
}
|
||||
|
||||
fn apply_management_fee(
|
||||
&mut self,
|
||||
execution_date: NaiveDate,
|
||||
|
||||
Reference in New Issue
Block a user