Skip to content

Commit 3ab0011

Browse files
committed
Add historical data-based chain builder example
Introduced `historical_build_chain.rs` to demonstrate option chain simulation using historical price data and volatility adjustments. Minor updates were made to `random_walk_build_chain.rs`, including reorganization of imports and parameter changes. Updated drawings for both simulation types.
1 parent b5b9cf4 commit 3ab0011

4 files changed

Lines changed: 122 additions & 7 deletions

File tree

53.8 KB
Loading
7.76 KB
Loading
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use optionstratlib::chains::chain::OptionChain;
2+
use optionstratlib::chains::utils::OptionDataPriceParams;
3+
use optionstratlib::chains::{OptionChainBuildParams, generator_optionchain};
4+
use optionstratlib::simulation::randomwalk::RandomWalk;
5+
use optionstratlib::simulation::steps::{Step, Xstep, Ystep};
6+
use optionstratlib::simulation::{WalkParams, WalkType, WalkTypeAble};
7+
use optionstratlib::utils::others::calculate_log_returns;
8+
use optionstratlib::utils::time::{TimeFrame, get_x_days_formatted};
9+
use optionstratlib::utils::{read_ohlcv_from_zip, setup_logger};
10+
use optionstratlib::visualization::utils::{Graph, GraphBackend};
11+
use optionstratlib::volatility::{adjust_volatility, constant_volatility};
12+
use optionstratlib::{ExpirationDate, Positive, pos};
13+
use rust_decimal::Decimal;
14+
use rust_decimal_macros::dec;
15+
use tracing::{debug, info};
16+
17+
#[warn(dead_code)]
18+
struct Walker {}
19+
20+
impl Walker {
21+
fn new() -> Self {
22+
Walker {}
23+
}
24+
}
25+
26+
impl WalkTypeAble<Positive, OptionChain> for Walker {}
27+
28+
fn main() -> Result<(), Box<dyn std::error::Error>> {
29+
setup_logger();
30+
31+
let ohlc = read_ohlcv_from_zip("examples/Data/cl-1m-sample.zip", None, None)?;
32+
let ohlc = ohlc.iter().take(1000).collect::<Vec<_>>(); // Take only 1000 minutes
33+
let prices: Vec<Positive> = ohlc.iter().map(|x| Positive::from(x.close)).collect();
34+
let log_returns: Vec<Decimal> = calculate_log_returns(&prices)?
35+
.iter()
36+
.map(|p| p.to_dec())
37+
.collect();
38+
let implied_volatility = adjust_volatility(
39+
constant_volatility(&log_returns)?,
40+
TimeFrame::Minute,
41+
TimeFrame::Year,
42+
)?;
43+
44+
info!("Volatility {}", implied_volatility);
45+
info!("Prices Lenght: {}", prices.len());
46+
47+
let n_steps = prices.len();
48+
let underlying_price = prices[0];
49+
let days = pos!(30.0);
50+
// let std_dev = implied_volatility * 100.0;
51+
let risk_free_rate = dec!(0.02);
52+
let dividend_yield = pos!(0.01);
53+
let symbol = "AAPL".to_string();
54+
let volume = Some(Positive::ONE);
55+
let chain_size = 30;
56+
let strike_interval = pos!(1.0);
57+
let skew_factor = dec!(0.0005);
58+
let spread = pos!(0.01);
59+
let decimal_places = 2;
60+
61+
let price_params = OptionDataPriceParams::new(
62+
underlying_price,
63+
ExpirationDate::Days(days),
64+
Some(implied_volatility),
65+
risk_free_rate,
66+
dividend_yield,
67+
Some(symbol.clone()),
68+
);
69+
let build_params = OptionChainBuildParams::new(
70+
symbol,
71+
volume,
72+
chain_size,
73+
strike_interval,
74+
skew_factor,
75+
spread,
76+
decimal_places,
77+
price_params,
78+
);
79+
let mut initial_chain = OptionChain::build_chain(&build_params);
80+
initial_chain.update_expiration_date(get_x_days_formatted(2));
81+
let walker = Box::new(Walker::new());
82+
83+
let walk_params = WalkParams {
84+
size: n_steps,
85+
init_step: Step {
86+
x: Xstep::new(Positive::ONE, TimeFrame::Minute, ExpirationDate::Days(days)),
87+
y: Ystep::new(0, initial_chain),
88+
},
89+
walk_type: WalkType::Historical {
90+
timeframe: TimeFrame::Minute,
91+
prices,
92+
},
93+
walker: walker,
94+
};
95+
96+
let random_walk = RandomWalk::new(
97+
"Random Walk".to_string(),
98+
&walk_params,
99+
generator_optionchain,
100+
);
101+
debug!("Random Walk: {}", random_walk);
102+
103+
random_walk.graph(
104+
GraphBackend::Bitmap {
105+
file_path: "Draws/Simulation/historical_build_chain.png",
106+
size: (1200, 800),
107+
},
108+
20,
109+
)?;
110+
info!("First Chain: {}", random_walk.first().unwrap().y.value());
111+
info!("Last Chain: {}", random_walk.last().unwrap().y.value());
112+
113+
Ok(())
114+
}

examples/examples_simulation/src/bin/random_walk_build_chain.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use optionstratlib::chains::chain::OptionChain;
2-
use optionstratlib::chains::{generator_optionchain, OptionChainBuildParams};
2+
use optionstratlib::chains::utils::OptionDataPriceParams;
3+
use optionstratlib::chains::{OptionChainBuildParams, generator_optionchain};
34
use optionstratlib::simulation::randomwalk::RandomWalk;
45
use optionstratlib::simulation::steps::{Step, Xstep, Ystep};
56
use optionstratlib::simulation::{WalkParams, WalkType, WalkTypeAble};
@@ -9,7 +10,6 @@ use optionstratlib::visualization::utils::{Graph, GraphBackend};
910
use optionstratlib::{ExpirationDate, Positive, pos};
1011
use rust_decimal_macros::dec;
1112
use tracing::{debug, info};
12-
use optionstratlib::chains::utils::OptionDataPriceParams;
1313

1414
#[warn(dead_code)]
1515
struct Walker {}
@@ -24,11 +24,12 @@ impl WalkTypeAble<Positive, OptionChain> for Walker {}
2424

2525
fn main() -> Result<(), Box<dyn std::error::Error>> {
2626
setup_logger();
27-
let n_steps = 43_200; // 30 days in minutes
27+
// let n_steps = 43_200; // 30 days in minutes
28+
let n_steps = 5; // 30 days in minutes
2829
let underlying_price = pos!(150.0);
2930
let days = pos!(30.0);
3031
let std_dev = pos!(20.0);
31-
let implied_volatility = Some(std_dev/100.0);
32+
let implied_volatility = Some(std_dev / 100.0);
3233
let risk_free_rate = dec!(0.02);
3334
let dividend_yield = pos!(0.01);
3435
let symbol = "AAPL".to_string();
@@ -38,7 +39,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3839
let skew_factor = dec!(0.00001);
3940
let spread = pos!(0.01);
4041
let decimal_places = 2;
41-
42+
4243
let price_params = OptionDataPriceParams::new(
4344
underlying_price,
4445
ExpirationDate::Days(days),
@@ -60,15 +61,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
6061
let mut initial_chain = OptionChain::build_chain(&build_params);
6162
initial_chain.update_expiration_date(get_x_days_formatted(2));
6263
let walker = Box::new(Walker::new());
63-
64+
6465
let walk_params = WalkParams {
6566
size: n_steps,
6667
init_step: Step {
6768
x: Xstep::new(Positive::ONE, TimeFrame::Minute, ExpirationDate::Days(days)),
6869
y: Ystep::new(0, initial_chain),
6970
},
7071
walk_type: WalkType::GeometricBrownian {
71-
dt: convert_time_frame(pos!(1.0) / days, &TimeFrame::Minute, &TimeFrame::Day),
72+
dt: convert_time_frame(pos!(1.0) / days, &TimeFrame::Minute, &TimeFrame::Day),
7273
drift: dec!(0.0),
7374
volatility: std_dev,
7475
},

0 commit comments

Comments
 (0)