core/rustybot/src/events.rs

188 lines
5.1 KiB
Rust
Raw Normal View History

2021-01-04 13:23:59 +00:00
use std::collections::{HashMap, HashSet};
2021-01-02 12:16:48 +00:00
use std::future::Future;
2021-01-04 13:23:59 +00:00
use tokio::stream::StreamExt;
2021-01-02 12:16:48 +00:00
use tokio::task::JoinHandle;
2021-01-02 14:10:16 +00:00
2021-01-11 18:40:19 +00:00
use crate::bot::BfxBot;
use crate::models::{Position, PositionProfitState};
2021-01-02 15:22:48 +00:00
use crate::pairs::PairStatus;
2021-01-04 12:28:40 +00:00
use crate::BoxError;
2021-01-02 12:16:48 +00:00
2021-01-11 17:16:17 +00:00
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
2021-01-02 15:22:48 +00:00
pub enum SignalKind {
2021-01-11 17:16:17 +00:00
ClosePosition { position_id: u64 },
2021-01-02 12:16:48 +00:00
OpenPosition,
}
2021-01-05 19:50:14 +00:00
#[derive(Copy, Clone, Debug)]
2021-01-02 15:22:48 +00:00
pub struct EventMetadata {
2021-01-02 12:16:48 +00:00
position_id: Option<u64>,
order_id: Option<u64>,
}
2021-01-04 19:29:01 +00:00
impl EventMetadata {
pub fn new(position_id: Option<u64>, order_id: Option<u64>) -> Self {
EventMetadata {
position_id,
order_id,
}
}
}
2021-01-05 19:50:14 +00:00
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
2021-01-02 15:22:48 +00:00
pub enum EventKind {
2021-01-02 12:16:48 +00:00
NewMinimum,
NewMaximum,
ReachedLoss,
ReachedBreakEven,
ReachedMinProfit,
ReachedGoodProfit,
ReachedMaxLoss,
TrailingStopSet,
TrailingStopMoved,
OrderSubmitted,
NewTick,
2021-01-04 13:23:59 +00:00
Any,
2021-01-02 12:16:48 +00:00
}
2021-01-05 19:50:14 +00:00
#[derive(Copy, Clone, Debug)]
2021-01-02 14:10:16 +00:00
pub struct Event {
2021-01-02 12:16:48 +00:00
kind: EventKind,
tick: u64,
metadata: Option<EventMetadata>,
}
impl Event {
pub fn new(kind: EventKind, tick: u64, metadata: Option<EventMetadata>) -> Self {
Event {
kind,
tick,
metadata,
}
}
fn has_metadata(&self) -> bool {
self.metadata.is_some()
}
2021-01-02 18:34:13 +00:00
pub fn kind(&self) -> EventKind {
self.kind
}
pub fn tick(&self) -> u64 {
self.tick
}
pub fn metadata(&self) -> Option<EventMetadata> {
self.metadata
}
2021-01-02 12:16:48 +00:00
}
2021-01-02 14:10:16 +00:00
pub struct EventDispatcher {
2021-01-04 12:28:40 +00:00
event_handlers: HashMap<EventKind, Vec<Box<dyn Fn(&Event, &PairStatus) -> JoinHandle<()>>>>,
2021-01-05 14:51:03 +00:00
profit_state_handlers:
HashMap<PositionProfitState, Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>>,
2021-01-11 17:16:17 +00:00
signal_handlers: HashMap<SignalKind, Vec<Box<dyn Fn(&SignalKind) -> JoinHandle<()>>>>,
2021-01-04 13:23:59 +00:00
on_any_event_handlers: Vec<Box<dyn Fn(&Event, &PairStatus) -> JoinHandle<()>>>,
2021-01-05 14:51:03 +00:00
on_any_profit_state_handlers: Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>,
2021-01-02 12:16:48 +00:00
}
2021-01-02 14:10:16 +00:00
impl EventDispatcher {
2021-01-02 12:16:48 +00:00
pub fn new() -> Self {
2021-01-02 14:10:16 +00:00
EventDispatcher {
2021-01-02 15:22:48 +00:00
event_handlers: HashMap::new(),
2021-01-05 14:51:03 +00:00
profit_state_handlers: HashMap::new(),
2021-01-11 17:16:17 +00:00
signal_handlers: HashMap::new(),
2021-01-04 13:23:59 +00:00
on_any_event_handlers: Vec::new(),
2021-01-05 14:51:03 +00:00
on_any_profit_state_handlers: Vec::new(),
2021-01-02 12:16:48 +00:00
}
}
2021-01-11 18:40:19 +00:00
pub fn call_signal_handlers(&self, signal: &SignalKind) {
if let Some(functions) = self.signal_handlers.get(&signal) {
for f in functions {
f(signal);
}
}
}
2021-01-04 12:28:40 +00:00
pub fn call_event_handlers(&self, event: &Event, status: &PairStatus) {
if let Some(functions) = self.event_handlers.get(&event.kind()) {
for f in functions {
f(event, status);
2021-01-02 15:22:48 +00:00
}
}
2021-01-04 13:23:59 +00:00
for f in &self.on_any_event_handlers {
f(event, status);
}
}
2021-01-05 12:58:47 +00:00
pub fn call_position_state_handlers(&self, position: &Position, status: &PairStatus) {
2021-01-05 14:51:03 +00:00
if let Some(profit_state) = &position.profit_state() {
if let Some(functions) = self.profit_state_handlers.get(profit_state) {
for f in functions {
f(position, status);
}
2021-01-04 13:23:59 +00:00
}
}
2021-01-05 14:51:03 +00:00
for f in &self.on_any_profit_state_handlers {
2021-01-05 12:58:47 +00:00
f(position, status);
2021-01-04 13:23:59 +00:00
}
2021-01-02 14:10:16 +00:00
}
2021-01-04 12:28:40 +00:00
pub fn register_event_handler<F: 'static, Fut: 'static>(&mut self, event: EventKind, f: F)
where
F: Fn(&Event, &PairStatus) -> Fut,
Fut: Future<Output = ()> + Send,
{
2021-01-04 13:27:30 +00:00
match event {
2021-01-04 13:35:34 +00:00
EventKind::Any => self
.on_any_event_handlers
.push(Box::new(move |e, s| tokio::spawn(f(&e, s)))),
_ => self
.event_handlers
.entry(event)
.or_default()
.push(Box::new(move |e, s| tokio::spawn(f(&e, s)))),
2021-01-04 13:27:30 +00:00
}
2021-01-02 12:16:48 +00:00
}
2021-01-04 13:23:59 +00:00
pub fn register_positionstate_handler<F: 'static, Fut: 'static>(
&mut self,
2021-01-05 14:51:03 +00:00
state: PositionProfitState,
2021-01-04 13:23:59 +00:00
f: F,
) where
2021-01-05 12:58:47 +00:00
F: Fn(&Position, &PairStatus) -> Fut,
2021-01-04 13:23:59 +00:00
Fut: Future<Output = ()> + Send,
{
2021-01-04 13:27:30 +00:00
match state {
2021-01-05 14:51:03 +00:00
// PositionProfitState::Any => self
// .on_any_position_state_handlers
// .push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
2021-01-04 13:27:30 +00:00
_ => self
2021-01-05 14:51:03 +00:00
.profit_state_handlers
2021-01-04 13:27:30 +00:00
.entry(state)
.or_default()
2021-01-05 12:58:47 +00:00
.push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
2021-01-04 13:27:30 +00:00
}
2021-01-04 13:23:59 +00:00
}
2021-01-11 17:16:17 +00:00
pub fn register_signal_handler<F: 'static, Fut: 'static>(&mut self, signal: SignalKind, f: F)
where
F: Fn(&SignalKind) -> Fut,
Fut: Future<Output = ()> + Send,
{
match signal {
// PositionProfitState::Any => self
// .on_any_position_state_handlers
// .push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
_ => self
.signal_handlers
.entry(signal)
.or_default()
.push(Box::new(move |s| tokio::spawn(f(s)))),
}
}
2021-01-02 15:22:48 +00:00
}