pub struct AlertEngine { /* private fields */ }Expand description
An Alerts service that keeps alerts in memory and evaluates them on the bars the host
feeds it with update, as PaperAccount fills orders
on the prices it is fed. It needs no egui, so a server can run the same code. A host that
evaluates alerts on its own server implements Alerts itself instead.
With studies, AlertEvaluator reads the saved source definitions from a datafeed and
supplies these evaluations without constructing a chart.
The host keeps the alerts: alerts returns them with their status for
storage, and with_alerts restores them. Evaluation state lives in
memory only, so after a restart an alert that fires on every occurrence may fire again while
its condition still holds; an alert with frequency Once that fired
stays Triggered.
§Rules
Subject. An alert is evaluated on its symbol, or on each member of its watchlist as
set_watchlist gave it, with its own state per symbol. An update for
another symbol, or for a timeframe other than the alert’s, does not touch the alert. An alert
without a timeframe takes the timeframe of the first update that reaches it, which the engine
saves and pushes as an AlertEvent::Upsert, so it is fixed from then on.
Evaluated bar. The newest bar, still forming, or for
OncePerBarClose the newest completed one. Every rule of
an alert, the first and the additional conditions, is judged on that bar, and the alert holds
when every rule holds. A missing or non-finite value makes its rule false. Price is the close
and volume the volume of a bar; the value function of update resolves the other sources.
Change. An update whose evaluated bar, its close and volume and the value of every source equal those of the previous update does nothing, unless a per-minute alert enters a new minute or its schedule opens. An update whose evaluated bar is older than the newest one already evaluated for the alert is ignored: reloading history, rewinding a replay or switching to a coarser timeframe never fires an alert again.
Crossings. The previous value is the value at the alert’s previous evaluation, within a bar
and across bars, and on the first evaluation the value one bar earlier. Crossing up needs a
previous value strictly below the level and a current value at or above it, crossing down the
reverse; a value that touches the level and stays there fires once. Moving by and volume
above average read the bars before the evaluated one, as AlertCondition documents.
Moving channels resolve the preceding bar again when a new bar arrives, so edits and
skipped updates use that bar’s current geometry. Within a bar they use the previous evaluation.
Frequency. Once fires on the first evaluation that holds and the
alert becomes Triggered; a watchlist alert fires once per member
and stays active. EveryTime fires on every evaluation that
holds, OncePerBar at most once per bar open time, and
OncePerBarClose evaluates each completed bar once.
OncePerMinute fires at most once per minute of the update
time now; moving the clock backwards does not repeat a minute.
Schedule. An alert’s schedule restricts triggers. Outside it the engine keeps observing
values for crossings, but does not fire or consume an occurrence. A once alert stays armed.
Expiry. Every update and tick first marks active alerts whose expiry has
passed as Expired, so an alert never fires at or after its expiry
and expires without data. Disabled, triggered and expired alerts are not evaluated, and
saving or removing an alert discards its evaluation state, so a resumed alert starts afresh.
use chrono::{DateTime, Utc};
use egui_charts::model::{Alert, AlertCondition, Bar, Timeframe};
use egui_charts::services::AlertEngine;
let mut alert = Alert::new("AAPL", AlertCondition::CrossingUp(100.0));
alert.timeframe = Some(Timeframe::Min1);
let engine = AlertEngine::new().with_alerts(vec![alert]);
let time = |seconds| DateTime::<Utc>::from_timestamp(seconds, 0).unwrap();
let bar = |seconds, close| Bar::new(time(seconds), close, close, close, close, 1.0);
// The close rises through 100 on the second bar; `update` also takes the chart's source values.
engine.update("AAPL", Timeframe::Min1, &[bar(0, 99.0), bar(60, 101.0)], time(61), |_, _| None);Implementations§
Source§impl AlertEngine
impl AlertEngine
Sourcepub fn new() -> Self
pub fn new() -> Self
An engine without alerts. Alerts saved without an id get “1”, “2” and so on, skipping the ids in use.
Sourcepub fn on_trigger(
self,
deliver: impl Fn(&Alert, &AlertEvent) + MaybeSend + 'static,
) -> Self
pub fn on_trigger( self, deliver: impl Fn(&Alert, &AlertEvent) + MaybeSend + 'static, ) -> Self
Calls deliver with the alert and its AlertEvent::TriggeredForSymbol on every trigger,
after the event is pushed, so the host can send email, push notifications or web requests.
The call comes from the thread that fed the engine and must return at once; it may use
the engine.
Sourcepub fn with_alerts(self, alerts: Vec<Alert>) -> Self
pub fn with_alerts(self, alerts: Vec<Alert>) -> Self
Starts with alerts as alerts returned them, giving those without an
id one after the others.
Sourcepub fn subjects(&self, id: &AlertId) -> Vec<String>
pub fn subjects(&self, id: &AlertId) -> Vec<String>
Active symbols still armed for id, including watchlist members. A once-per-member
alert omits symbols that already fired, so a host can release their subscriptions.
Sourcepub fn set_watchlist(&self, id: &str, symbols: Vec<String>)
pub fn set_watchlist(&self, id: &str, symbols: Vec<String>)
Sets the members of the watchlist id, as the host’s watchlist holds them. A member that
leaves loses its evaluation state, so it starts afresh if it returns.
Sourcepub fn update(
&self,
symbol: &str,
timeframe: Timeframe,
bars: &[Bar],
now: DateTime<Utc>,
value: impl Fn(&AlertSource, usize) -> Option<f64>,
)
pub fn update( &self, symbol: &str, timeframe: Timeframe, bars: &[Bar], now: DateTime<Utc>, value: impl Fn(&AlertSource, usize) -> Option<f64>, )
Evaluates every active alert whose subject is symbol on timeframe against the newest
of bars, oldest first, at the time now. value resolves a study or drawing source at
a bar index of bars, for instance with Chart::alert_value; price and volume come from
bars. Call it each frame with the bars of every live chart, but not with a chart in
replay.
Sourcepub fn update_alert(
&self,
id: &AlertId,
symbol: &str,
timeframe: Timeframe,
bars: &[Bar],
now: DateTime<Utc>,
value: impl Fn(&AlertSource, usize) -> Option<f64>,
)
pub fn update_alert( &self, id: &AlertId, symbol: &str, timeframe: Timeframe, bars: &[Bar], now: DateTime<Utc>, value: impl Fn(&AlertSource, usize) -> Option<f64>, )
Evaluates one alert with its retained source definitions. Other alerts may refer to different study instances with the same chart-local identifiers.
Sourcepub fn strategy_fills(
&self,
run: &str,
symbol: &str,
timeframe: Timeframe,
fills: &[StrategyFill],
now: DateTime<Utc>,
)
pub fn strategy_fills( &self, run: &str, symbol: &str, timeframe: Timeframe, fills: &[StrategyFill], now: DateTime<Utc>, )
Delivers each new fill of run to matching strategy-fill alerts. Use a unique run id
for each Backtest instance, retained for its lifetime, and forward its update batches.
Repeated batches are ignored by sequence, including after edits or rearming an alert
on the same run and when multiple fills share a timestamp.
now gates expiry and notification schedules; event times are the source fill times.
Empty messages use the execution side, quantity, price and resulting signed position.
Custom messages expand the usual placeholders using a flat bar at the fill price, with
its source time and zero volume. Strategy-fill alerts need no price-reader subscription.
Delivery callbacks run after unlocking, as they do for price alerts.
Trait Implementations§
Source§impl Alerts for AlertEngine
impl Alerts for AlertEngine
Source§fn engine(&self) -> Option<&AlertEngine>
fn engine(&self) -> Option<&AlertEngine>
Source§fn watch(&self, events: Events<AlertEvent>)
fn watch(&self, events: Events<AlertEvent>)
events is inactive. On the first call,
also push the triggers that fired while the application was closed; do not push them again
on a later call. Read moreSource§fn save(&self, alert: Alert, reply: Reply<()>)
fn save(&self, alert: Alert, reply: Reply<()>)
alert.id is None) or replaces an alert. Keep alert.inputs with the alert:
its independent study parameters and source view must survive copies and restoration.
Answer Ok once the change is kept;
the alert appears when watch pushes it, so push the saved alert, with its id, as
AlertEvent::Upsert.Auto Trait Implementations§
impl !Freeze for AlertEngine
impl !RefUnwindSafe for AlertEngine
impl !UnwindSafe for AlertEngine
impl Send for AlertEngine
impl Sync for AlertEngine
impl Unpin for AlertEngine
impl UnsafeUnpin for AlertEngine
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more