How to Handle CSV/JSON Import/Export for Option Chains with the optionstratlib `chains` Module
The chains module provides synchronous and asynchronous methods on the OptionChain struct to serialize option market data to CSV or JSON files and reconstruct it later, handling missing fields and format conversions automatically.
The chains module in the joaquinbejar/optionstratlib repository manages option market data through the OptionChain struct, which stores collections of option contracts. When you need to persist this data for backtesting, caching, or interoperability with other tools, the module offers a robust CSV/JSON import/export pipeline that handles serialization, deserialization, and data normalization without manual field mapping.
Synchronous CSV Export
To persist an option chain to a CSV file, use the save_to_csv method implemented in src/chains/chain.rs (lines 1054-1087). This method generates a filename from the chain title (formatted as symbol-expiration-price) and writes a header row followed by one record per OptionData contract.
The CSV writer includes standard market data fields such as strike, bid/ask prices, implied volatility (IV), Greeks, volume, and open interest (OI). When numeric fields are missing, the helper default_empty_string ensures the output contains empty strings rather than malformed data.
use optionstratlib::chains::chain::OptionChain;
use optionstratlib::error::chains::ChainError;
fn persist_chain(chain: &OptionChain) -> Result<(), ChainError> {
// Saves to "output/SP500-18-oct-2024-5781.88.csv"
chain.save_to_csv("output")?;
Ok(())
}
Synchronous CSV Import
Loading a previously saved chain uses the load_from_csv method (lines 1159-1195), which returns Result<OptionChain, ChainError>. The implementation uses csv::Reader to parse each record and applies the internal parse helper from src/chains/utils.rs (lines 591-597) to convert string fields into numeric types.
Missing or malformed numeric fields become None rather than causing panics. After parsing, the method calculates mid-prices via set_mid_prices and assembles the records into a BTreeSet<OptionData> within a new OptionChain instance.
use optionstratlib::chains::chain::OptionChain;
use optionstratlib::error::chains::ChainError;
fn restore_chain() -> Result<OptionChain, ChainError> {
let chain = OptionChain::load_from_csv("data/SP500-18-oct-2024-5781.88.csv")?;
// Chain is ready for analysis or strategy application
Ok(chain)
}
JSON Export and Import
For structured storage and REST API interoperability, the OptionChain struct derives Serialize and Deserialize from serde, enabling seamless JSON round-tripping.
Exporting uses save_to_json (lines 1121-1126), which calls serde_json::to_writer_pretty to generate a human-readable JSON file in the specified directory.
Importing via load_from_json (lines 1235-1252) uses serde_json::from_reader followed by post-processing: the chain recalculates mid-prices, updates Greeks, and normalizes implied volatility from percentage to decimal format via check_and_convert_implied_volatility.
use optionstratlib::chains::chain::OptionChain;
// Export to JSON
chain.save_to_json("cache")?;
// Later, reconstruct exactly
let restored = OptionChain::load_from_json("cache/SP500-18-oct-2024-5781.88.json")?;
Asynchronous Operations
When compiling with the async Cargo feature, the module provides non-blocking variants that wrap the synchronous implementations in blocking tasks compatible with Tokio. These methods return Result types identical to their blocking counterparts.
save_to_csv_async(&self, dir: &str)load_from_csv_async(path: &str)save_to_json_async(&self, dir: &str)load_from_json_async(path: &str)
use optionstratlib::chains::chain::OptionChain;
use optionstratlib::error::chains::ChainError;
#[tokio::main]
async fn main() -> Result<(), ChainError> {
let chain = OptionChain::load_from_csv_async("data/my_chain.csv").await?;
chain.save_to_json_async("cache").await?;
Ok(())
}
Error Handling
All import/export operations propagate errors through the ChainError type defined in src/error/chains.rs. This unified error type encapsulates IO failures, CSV parsing errors, JSON deserialization issues, and format validation problems, allowing callers to handle persistence failures gracefully without matching multiple error variants.
Summary
- The
OptionChainstruct insrc/chains/chain.rsimplements CSV/JSON import/export via eight dedicated methods (four synchronous, four asynchronous). - CSV operations use the
csvcrate with custom parsing logic insrc/chains/utils.rsto handle missing numeric fields safely. - JSON operations rely on serde for automatic serialization, with post-import normalization of implied volatility and mid-prices.
- Async variants require the
asyncfeature flag and integrate with Tokio’s blocking task API. - All methods return
Resulttypes withChainErrorfor consistent error handling across IO and parsing boundaries.
Frequently Asked Questions
What file naming convention does save_to_csv use?
The method automatically constructs filenames using the pattern symbol-expiration-price.csv derived from the OptionChain title field, placing the file in the directory specified by the dir parameter.
How does the library handle missing or empty CSV fields?
During import, the generic parse helper in src/chains/utils.rs converts empty or invalid strings into None for optional numeric fields, ensuring the OptionData struct initializes correctly without panicking on malformed market data.
Can I use these methods in an async runtime like Tokio?
Yes. Enable the async feature in your Cargo.toml to access load_from_csv_async, save_to_json_async, and related methods. These spawn blocking operations that prevent the async runtime from stalling during file IO.
What data format does the JSON export produce?
The JSON output is prettified (human-readable) and contains the complete OptionChain structure, including the BTreeSet<OptionData> collection with all strikes, Greeks, and market data fields as defined in the source struct.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →