1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
use serde::{Deserialize, Serialize};
use crate::core::curves::CurveInput;
use crate::core::vols::VolInput;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "product_type", rename_all = "snake_case")]
pub enum ProductData {
Option(EquityOptionData),
Future(EquityFutureData),
Forward(EquityForwardData),
RainbowOption(crate::equity::rainbow::RainbowOptionData),
CliquetOption(crate::equity::cliquet::CliquetOptionData),
Accumulator(crate::equity::accumulator::AccumulatorData),
VarianceSwap(crate::equity::variance_swap::VarianceSwapData),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityInstrumentBase {
pub symbol: String,
pub currency: Option<String>,
pub exchange: Option<String>,
pub name: Option<String>,
pub cusip: Option<String>,
pub isin: Option<String>,
pub underlying_price: f64,
pub long_short: Option<i32>,
pub risk_free_rate: Option<f64>,
/// Continuous stock borrow (repo) cost; enters the carry like an
/// additional dividend yield (hard-to-borrow lowers the forward).
pub borrow_cost: Option<f64>,
pub settlement_type: Option<String>,
/// Pricing as-of date (`YYYY-MM-DD`). Defaults to today, but setting
/// it makes the contract price reproducibly and allows re-marking a
/// book as of any date.
pub valuation_date: Option<String>,
}
/// Resolve an optional contract `valuation_date`: parse it when present,
/// default to today's date otherwise.
pub fn parse_valuation_date(
field: Option<&str>,
) -> Result<chrono::NaiveDate, crate::core::errors::RustyQLibError> {
match field {
Some(s) => chrono::NaiveDate::parse_from_str(s.trim(), "%Y-%m-%d").map_err(|_| {
crate::core::errors::RustyQLibError::invalid_input(
"valuation_date",
format!("invalid date '{s}' (expected YYYY-MM-DD)"),
)
}),
None => Ok(chrono::Local::now().date_naive()),
}
}
/// A discrete cash dividend: ex-date and amount per share.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CashDividendData {
pub date: String,
pub amount: f64,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityFutureData {
#[serde(flatten)]
pub base: EquityInstrumentBase,
pub current_price: Option<f64>,
pub multiplier:Option<f64>,
pub entry_price:Option<f64>,
pub maturity: String,
pub dividend: Option<f64>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityForwardData {
#[serde(flatten)]
pub base: EquityInstrumentBase,
pub current_price: Option<f64>,
pub notional: Option<f64>,
pub entry_price:Option<f64>,
pub maturity: String,
pub dividend: Option<f64>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityOptionData {
#[serde(flatten)]
pub base: EquityInstrumentBase,
pub put_or_call: String, // "Call"/"Put"
pub payoff_type: String, // Vanilla/Barrier/Binary
/// Binary settlement: "cash" (default) or "asset".
pub binary_type: Option<String>,
/// Amount paid by a cash-or-nothing binary (default 1.0).
pub cash_amount: Option<f64>,
/// Barrier variant: "up_in" | "up_out" | "down_in" | "down_out".
pub barrier_type: Option<String>,
pub barrier_level: Option<f64>,
/// Second barrier level (makes the option a double barrier).
pub barrier_level2: Option<f64>,
/// Barrier rebate amount.
pub rebate: Option<f64>,
/// Knock-out rebate paid at the touch (default: at expiry).
pub rebate_at_hit: Option<bool>,
/// Lookback flavor: "floating" (default) or "fixed".
pub lookback_type: Option<String>,
/// Asian averaging: "arithmetic" (default) | "geometric".
pub averaging_type: Option<String>,
/// Asian strike: "fixed" (default, average price) | "floating" (average strike).
pub asian_strike_type: Option<String>,
/// Forward-start: strike fixing date and strike as a fraction of the
/// fixing spot (default 1.0).
pub forward_start_date: Option<String>,
pub strike_fraction: Option<f64>,
/// Autocallable: early-redemption and knock-in protection levels
/// (absolute), per-period coupon (rebate), observation count, notional.
pub autocall_barrier: Option<f64>,
pub protection_barrier: Option<f64>,
pub autocall_coupon: Option<f64>,
pub autocall_observations: Option<usize>,
/// Binomial tree parameterization: `LeisenReimer` (default), `CRR`,
/// `JarrowRudd`, `Tian`, `Trigeorgis`, `EQP`.
pub tree_type: Option<String>,
/// Binomial tree steps (default 1000; Leisen-Reimer bumps even
/// counts to odd).
pub tree_steps: Option<usize>,
/// Price the tree with term structures of rates and volatility
/// applied per step (variance-equal time grid). `tree_type` is then
/// ignored.
pub tree_term_structure: Option<bool>,
/// Bermudan exercise dates (`YYYY-MM-DD`, strictly increasing,
/// after valuation and at or before maturity). Required when
/// `exercise_style` is `Bermudan`. Expiry is always exercisable
/// through the terminal payoff.
pub exercise_dates: Option<Vec<String>>,
/// Explicit autocall observation dates (`YYYY-MM-DD`, strictly
/// increasing, after valuation and at or before maturity). Overrides
/// `autocall_observations`; use business-day adjusted dates from a
/// holiday calendar so observations do not land on weekends.
pub autocall_observation_dates: Option<Vec<String>>,
/// Phoenix: conditional-coupon barrier (absolute level).
pub coupon_barrier: Option<f64>,
/// Phoenix: memory coupons (missed coupons recovered later).
pub coupon_memory: Option<bool>,
pub notional: Option<f64>,
/// Discrete cash dividends (ex-date + amount per share).
pub cash_dividends: Option<Vec<CashDividendData>>,
/// When set, the option is on a future (Black-76): "discounted"
/// (standard) or "margined" (futures-style). `underlying_price` is then
/// the futures price.
pub futures_settlement: Option<String>,
/// Strike; required for vanilla/binary/barrier/asian payoffs, unused
/// for forward-start and autocallable contracts.
pub strike_price: Option<f64>,
/// Constant volatility; the simple alternative to `vol_surface`.
pub volatility: Option<f64>,
pub maturity: String,
pub dividend: Option<f64>,
pub current_price: Option<f64>,
pub multiplier:Option<f64>,
pub entry_price:Option<f64>,
/// Monte Carlo path count (engine "MC" only).
pub simulation: Option<u64>,
/// MC time steps: 1 = terminal simulation; > 1 = path-wise stepping.
pub mc_time_steps: Option<usize>,
/// "exact" (default) | "euler" | "milstein"
pub mc_scheme: Option<String>,
/// "sobol" (default, low-discrepancy) | "pseudo" (seeded PCG64)
pub mc_sampler: Option<String>,
pub mc_seed: Option<u64>,
/// "gbm" (default, constant vol) | "local_vol" (Dupire from the
/// option's vol surface). Applies to the MonteCarlo and
/// FiniteDifference engines.
pub mc_model: Option<String>,
/// Finite difference grid nodes in spot (default 400).
pub fd_spot_steps: Option<usize>,
/// Finite difference time steps (default 400).
pub fd_time_steps: Option<usize>,
/// Heston parameters; required when `mc_model` is "heston".
pub heston: Option<crate::equity::heston::HestonParams>,
pub exercise_style: Option<String>, //European, American,
pub pricer:Option<String>,
/// Optional discount curve; when absent a flat curve is built from
/// `risk_free_rate` (which stays the simple way to specify a rate).
pub discount_curve: Option<CurveInput>,
/// Optional volatility surface; when absent a flat surface is built
/// from `volatility`. One of the two must be provided.
pub vol_surface: Option<VolInput>,
}