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
//! # Utils Module
//!
//! Cross-cutting helpers whose defining owner is the `core` layer: they
//! depend on nothing above `core` and every layer may call them. This
//! module is deliberately *not* a catch-all. Each file below names one
//! concern and one owner, and the ownership is machine-checked by
//! `scripts/check_module_boundaries.py` (`UTILS_FILE_LAYER`), so a helper
//! that grows a dependency on a higher layer fails the graph check instead
//! of quietly turning this module back into a shared dumping ground
//! (ADR-0001 D2, roadmap M1-09).
//!
//! | File | Owner | Contents |
//! |------|-------|----------|
//! | `json_format.rs` | core | `write_json`, `write_json_pretty` and the `impl_json_display!` / `impl_json_debug!` / `impl_json_debug_pretty!` macros |
//! | `numeric.rs` | core | `approx_equal`, `calculate_log_returns` |
//! | `rng.rs` | core | `deterministic_rng`, `get_random_element`, `random_decimal`, `DETERMINISTIC_RNG_DEFAULT_SEED` |
//! | `time.rs` | core | `TimeFrame`, `units_per_year`, `convert_time_frame`, date formatting |
//! | `traits.rs` | core | `Len` |
//!
//! Helpers that used to live here and now sit with their owner:
//!
//! - `prepare_file_path` is `visualization::prepare_file_path`: preparing a
//! path on disk exists to write a rendered chart, and nothing below
//! `visualization` calls it.
//! - CSV and OHLCV parsing belong to `market` (`chains`), re-homed in M1-08.
//! - `setup_logger` / `setup_logger_with_level` are **removed**. Installing a
//! global `tracing` subscriber is an application decision, not a library
//! one (`rules/global_rules.md`, "Logging & Observability"), so the library
//! no longer depends on `tracing-subscriber` at all. Install one from your
//! binary:
//!
//! ```rust,ignore
//! tracing_subscriber::fmt()
//! .with_max_level(tracing::Level::INFO)
//! .init();
//! ```
//!
//! The example binaries take theirs from the unpublished `osl-example-support`
//! workspace member, which is where application-side wiring belongs.
//!
//! Every other module keeps its own `utils.rs` (`greeks::utils`,
//! `chains::utils`, `strategies::utils`, ...). Those are owned by their
//! parent module by construction and are checked as part of it; nothing is
//! promoted here just because more than one caller wants it.
//!
//! ## Time frames
//!
//! ```rust
//! use positive::pos_or_panic;
//! use optionstratlib_core::utils::time::TimeFrame;
//!
//! let daily = TimeFrame::Day;
//! let trading_days_per_year = daily.periods_per_year(); // Returns 252.0
//!
//! let custom = TimeFrame::Custom(pos_or_panic!(365.0));
//! let periods = custom.periods_per_year(); // Returns 365.0
//! ```
//!
//! Time-frame conversions are constant-time; they read the predefined
//! period constants in `crate::constants`.
//!
//! ## Numeric comparison
//!
//! ```rust
//! use optionstratlib_core::utils::numeric::approx_equal;
//!
//! assert!(approx_equal(1.0, 1.000_000_01));
//! assert!(!approx_equal(1.0, 1.1));
//! ```
//!
//! ## Randomness
//!
//! Every Monte-Carlo or simulation test seeds deterministically, so an
//! upstream precision shift cannot flip an assertion by luck:
//!
//! ```rust
//! use optionstratlib_core::utils::deterministic_rng;
//! use rand::RngExt;
//!
//! let mut rng = deterministic_rng(42);
//! let _: u64 = rng.random();
//! ```
//!
//! Random element selection is O(n) in the size of the set.
/// JSON-backed `Debug` and `Display` writers and the macros that wire a
/// type to them.
/// Tolerance-based `f64` comparison and the logarithmic-return transform.
/// Deterministic seeding and generic random-sampling helpers.
/// Time frames, period conversions and date formatting.
/// Traits shared across the library.
pub use ;
pub use ;
pub use TimeFrame;
pub use Len;