navi_vm/events.rs
1use std::sync::Arc;
2
3pub use navi_types::BarStartEvent;
4use navi_types::Warnings;
5use navi_visuals::ChartEvent;
6use num_enum::FromPrimitive;
7use serde::{Deserialize, Serialize};
8
9use crate::{DrawEvent, SymbolInfo, script_info::ScriptInfo, strategy::StrategyEvent};
10
11/// Logging severity used by [`LogEvent`].
12#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, Serialize, Deserialize)]
13#[repr(i32)]
14#[serde(rename_all = "camelCase")]
15pub enum LogLevel {
16 /// Informational message.
17 #[default]
18 Info,
19 /// Warning condition.
20 Warning,
21 /// Error condition.
22 Error,
23}
24
25/// A log event emitted by script execution.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct LogEvent {
29 /// Severity level.
30 pub level: LogLevel,
31 /// Human-readable message.
32 pub message: String,
33}
34
35/// An alert event emitted by `alert()`/alertcondition-like behavior.
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[serde(rename_all = "camelCase")]
38pub struct AlertEvent {
39 /// Optional alert identifier.
40 pub id: Option<usize>,
41 /// Alert message.
42 pub message: String,
43}
44
45/// An event generated during VM execution.
46///
47/// Events are yielded by the [`Stream`](futures_util::Stream) returned from
48/// [`Instance::run`](crate::Instance::run).
49///
50/// Variants are grouped into three semantic categories, reflecting when they
51/// are emitted:
52///
53/// **Stream-level metadata** (emitted outside of bars, at most once per
54/// stream): [`SessionInfo`](Self::SessionInfo), [`Warning`](Self::Warning).
55///
56/// **Bar boundaries** (mark the start/end of execution phases):
57/// [`BarStart`](Self::BarStart), [`BarEnd`](Self::BarEnd),
58/// [`HistoryEnd`](Self::HistoryEnd).
59///
60/// **Per-bar data** (always appear between a `BarStart`/`BarEnd` pair):
61/// [`Draw`](Self::Draw), [`Strategy`](Self::Strategy),
62/// [`Log`](Self::Log), [`Alert`](Self::Alert).
63#[derive(Debug, Clone, Serialize, Deserialize)]
64#[serde(rename_all = "camelCase")]
65pub enum Event {
66 /// Session metadata emitted first in the stream, before any bar
67 /// (only in [`OutputMode::Stream`](crate::OutputMode::Stream)).
68 ///
69 /// Carries both the script declaration ([`ScriptInfo`]) and the symbol
70 /// metadata ([`SymbolInfo`]) for the current run.
71 SessionInfo {
72 /// Script-level metadata (type, declared inputs, series, alerts).
73 script_info: Arc<ScriptInfo>,
74 /// Symbol metadata for the chart symbol being analyzed.
75 symbol_info: Box<SymbolInfo>,
76 },
77 /// Compilation warnings, emitted after `ScriptInfo` and before any bar
78 /// (only when warnings are present).
79 Warning(Warnings),
80 /// Signals the start of a bar's execution.
81 BarStart(BarStartEvent),
82 /// Signals the end of a bar's execution.
83 BarEnd,
84 /// Signals the boundary between historical and real-time bars
85 /// (only in [`OutputMode::Stream`](crate::OutputMode::Stream)).
86 HistoryEnd,
87 /// A drawing instruction (only in
88 /// [`OutputMode::Stream`](crate::OutputMode::Stream)).
89 Draw(DrawEvent),
90 /// A strategy event (only in
91 /// [`OutputMode::Stream`](crate::OutputMode::Stream)).
92 Strategy(StrategyEvent),
93 /// A log message emitted by `log.*()` calls.
94 Log(LogEvent),
95 /// An alert emitted by `alert()`.
96 Alert(AlertEvent),
97}
98
99impl TryFrom<Event> for ChartEvent {
100 /// Returns the original `Event` when conversion is not possible.
101 type Error = Event;
102
103 fn try_from(event: Event) -> Result<ChartEvent, Event> {
104 match event {
105 Event::SessionInfo {
106 script_info,
107 symbol_info,
108 } => Ok(ChartEvent::SessionInfo {
109 script_info,
110 symbol_info,
111 }),
112 Event::HistoryEnd => Ok(ChartEvent::HistoryEnd),
113 Event::Draw(draw) => Ok(ChartEvent::from(draw)),
114 other => Err(other),
115 }
116 }
117}