2021-01-14 18:56:31 +00:00
|
|
|
use std::collections::HashMap;
|
2021-01-02 12:16:48 +00:00
|
|
|
use std::future::Future;
|
|
|
|
|
|
|
|
use tokio::task::JoinHandle;
|
2021-01-02 14:10:16 +00:00
|
|
|
|
2021-01-16 11:43:16 +00:00
|
|
|
use crate::managers::{OrderManager, PositionManager, PriceManager};
|
2021-01-13 08:57:36 +00:00
|
|
|
use crate::models::{Position, PositionProfitState};
|
2021-01-02 12:16:48 +00:00
|
|
|
|
2021-01-16 11:43:16 +00:00
|
|
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
2021-01-02 15:22:48 +00:00
|
|
|
pub enum SignalKind {
|
2021-01-16 21:38:00 +00:00
|
|
|
Update(u64),
|
2021-01-16 11:43:16 +00:00
|
|
|
ClosePosition(Position),
|
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-16 11:43:16 +00:00
|
|
|
pub struct Dispatcher {
|
2021-01-14 12:42:23 +00:00
|
|
|
event_handlers: HashMap<EventKind, Vec<Box<dyn Fn(&Event, &PriceManager) -> JoinHandle<()>>>>,
|
2021-01-05 14:51:03 +00:00
|
|
|
profit_state_handlers:
|
2021-01-14 12:42:23 +00:00
|
|
|
HashMap<PositionProfitState, Vec<Box<dyn Fn(&Position, &PriceManager) -> JoinHandle<()>>>>,
|
2021-01-11 17:16:17 +00:00
|
|
|
signal_handlers: HashMap<SignalKind, Vec<Box<dyn Fn(&SignalKind) -> JoinHandle<()>>>>,
|
2021-01-16 11:43:16 +00:00
|
|
|
|
2021-01-14 12:42:23 +00:00
|
|
|
on_any_event_handlers: Vec<Box<dyn Fn(&Event, &PriceManager) -> JoinHandle<()>>>,
|
|
|
|
on_any_profit_state_handlers: Vec<Box<dyn Fn(&Position, &PriceManager) -> JoinHandle<()>>>,
|
2021-01-02 12:16:48 +00:00
|
|
|
}
|
|
|
|
|
2021-01-16 11:43:16 +00:00
|
|
|
impl Dispatcher {
|
2021-01-02 12:16:48 +00:00
|
|
|
pub fn new() -> Self {
|
2021-01-16 11:43:16 +00:00
|
|
|
Dispatcher {
|
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-14 12:42:23 +00:00
|
|
|
pub fn call_event_handlers(&self, event: &Event, status: &PriceManager) {
|
2021-01-04 12:28:40 +00:00
|
|
|
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-14 12:42:23 +00:00
|
|
|
pub fn call_position_state_handlers(&self, position: &Position, status: &PriceManager) {
|
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
|
2021-01-14 12:42:23 +00:00
|
|
|
F: Fn(&Event, &PriceManager) -> Fut,
|
2021-01-04 12:28:40 +00:00
|
|
|
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-14 12:42:23 +00:00
|
|
|
F: Fn(&Position, &PriceManager) -> 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
|
|
|
}
|