nautilus_trading/examples/strategies/composite_market_maker/config.rs
1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3// https://nautechsystems.io
4//
5// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6// You may not use this file except in compliance with the License.
7// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Configuration for the composite market making strategy.
17
18use nautilus_model::{
19 identifiers::{InstrumentId, StrategyId},
20 types::Quantity,
21};
22
23use crate::strategy::StrategyConfig;
24
25/// Configuration for the composite market making strategy.
26#[derive(Debug, Clone, bon::Builder)]
27#[cfg_attr(
28 feature = "python",
29 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.trading", from_py_object)
30)]
31#[cfg_attr(
32 feature = "python",
33 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.trading")
34)]
35pub struct CompositeMarketMakerConfig {
36 /// Base strategy configuration.
37 #[builder(default = StrategyConfig {
38 strategy_id: Some(StrategyId::from("COMPOSITE_MM-001")),
39 order_id_tag: Some("001".to_string()),
40 ..Default::default()
41 })]
42 pub base: StrategyConfig,
43 /// Target instrument the strategy quotes on.
44 pub instrument_id: InstrumentId,
45 /// Signal instrument that drives the signal skew. Typically a
46 /// `SyntheticInstrument`, but any instrument that publishes quotes works.
47 pub signal_instrument_id: InstrumentId,
48 /// Trade size per quote. When `None`, resolved from the instrument's
49 /// `min_quantity` during `on_start`.
50 pub trade_size: Option<Quantity>,
51 /// Half of the desired quoted spread, in basis points of the anchor.
52 /// E.g. `5` = 5 bps, so the full quoted spread is 10 bps before skew.
53 #[builder(default = 5)]
54 pub half_spread_bps: u32,
55 /// Inventory skew gain in price units per unit of net position. Both sides
56 /// shift down by `factor * net_position` so a long position widens the bid
57 /// and tightens the ask.
58 #[builder(default = 0.0)]
59 pub inventory_skew_factor: f64,
60 /// Signal skew gain in price units per unit of normalized signal residual.
61 /// Both sides shift up by `factor * residual` where
62 /// `residual = (signal_mid - baseline) / baseline`.
63 #[builder(default = 0.0)]
64 pub signal_skew_factor: f64,
65 /// Optional baseline price for the signal residual. When `None`, the first
66 /// observed signal mid is captured as the baseline. When `Some(_)`, the
67 /// configured value is used so backtests are deterministic.
68 pub signal_baseline: Option<f64>,
69 /// Hard cap on net exposure (long or short).
70 pub max_position: Quantity,
71 /// Minimum movement in basis points of the anchor before re-quoting.
72 /// Applied to both anchor movement and the signal residual's price impact
73 /// (`signal_skew_factor * residual`); whichever clears the threshold first
74 /// triggers a requote.
75 #[builder(default = 5)]
76 pub requote_threshold_bps: u32,
77 /// Optional order expiry in seconds. When set, orders use GTD time-in-force
78 /// with `expire_time = now + expire_time_secs`.
79 pub expire_time_secs: Option<u64>,
80 /// When `true`, resubmit on the next quote tick after an external cancel.
81 /// Useful for venues that proactively cancel short-term orders.
82 #[builder(default = false)]
83 pub on_cancel_resubmit: bool,
84}