2021-01-14 18:56:31 +00:00
|
|
|
use std::collections::HashMap;
|
2021-01-14 12:42:23 +00:00
|
|
|
|
2021-01-14 18:56:31 +00:00
|
|
|
use crate::connectors::Client;
|
2021-01-14 12:53:54 +00:00
|
|
|
use crate::currency::SymbolPair;
|
2021-01-14 18:56:31 +00:00
|
|
|
use crate::events::{Event, SignalKind};
|
2021-01-14 12:53:54 +00:00
|
|
|
use crate::models::{Order, Position, PriceTicker};
|
2021-01-14 12:42:23 +00:00
|
|
|
use crate::strategy::PositionStrategy;
|
2021-01-14 12:53:54 +00:00
|
|
|
use crate::BoxError;
|
2021-01-13 09:24:59 +00:00
|
|
|
|
2021-01-14 12:42:23 +00:00
|
|
|
pub struct EventManager {
|
2021-01-13 09:26:29 +00:00
|
|
|
events: Vec<Event>,
|
|
|
|
}
|
2021-01-13 09:03:24 +00:00
|
|
|
|
2021-01-14 12:53:54 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct PriceManager {
|
|
|
|
pair: SymbolPair,
|
|
|
|
prices: Vec<PriceEntry>,
|
|
|
|
client: Client,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PriceManager {
|
|
|
|
pub fn new(pair: SymbolPair, client: Client) -> Self {
|
|
|
|
PriceManager {
|
|
|
|
pair,
|
|
|
|
prices: Vec::new(),
|
|
|
|
client,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_entry(&mut self, entry: PriceEntry) {
|
|
|
|
self.prices.push(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn update(&mut self, tick: u64) -> Result<PriceEntry, BoxError> {
|
|
|
|
let current_prices = self.client.current_prices(&self.pair).await?.into();
|
|
|
|
|
|
|
|
Ok(PriceEntry::new(
|
|
|
|
tick,
|
|
|
|
current_prices,
|
|
|
|
self.pair.clone(),
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
// pub fn add_position(&mut self, position: Position) {
|
|
|
|
// let (new_position, events, signals) = {
|
|
|
|
// match &self.strategy {
|
|
|
|
// Some(strategy) => strategy.on_new_tick(&position, &self),
|
|
|
|
// None => (position, vec![], vec![]),
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// self.positions
|
|
|
|
// .entry(self.current_tick)
|
|
|
|
// .or_default()
|
|
|
|
// .push(new_position.clone());
|
|
|
|
//
|
|
|
|
// // calling position state callbacks
|
|
|
|
// self.dispatcher
|
|
|
|
// .call_position_state_handlers(&new_position, &self);
|
|
|
|
//
|
|
|
|
// // adding events and calling callbacks
|
|
|
|
// for e in events {
|
|
|
|
// self.add_event(e);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // adding signals to current tick vector
|
|
|
|
// for s in signals {
|
|
|
|
// self.add_signal(s);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// fn add_event(&mut self, event: Event) {
|
|
|
|
// self.events.push(event);
|
|
|
|
//
|
|
|
|
// self.dispatcher.call_event_handlers(&event, &self);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// fn add_signal(&mut self, signal: SignalKind) {
|
|
|
|
// self.signals.insert(self.current_tick(), signal);
|
|
|
|
// }
|
|
|
|
|
|
|
|
pub fn pair(&self) -> &SymbolPair {
|
|
|
|
&self.pair
|
|
|
|
}
|
|
|
|
|
|
|
|
// pub fn position_previous_tick(&self, id: u64, tick: Option<u64>) -> Option<&Position> {
|
|
|
|
// let tick = match tick {
|
|
|
|
// Some(tick) => {
|
|
|
|
// if tick < 1 {
|
|
|
|
// 1
|
|
|
|
// } else {
|
|
|
|
// tick
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// None => self.current_tick() - 1,
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// self.positions
|
|
|
|
// .get(&tick)
|
|
|
|
// .and_then(|x| x.iter().find(|x| x.position_id() == id))
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct PriceEntry {
|
|
|
|
tick: u64,
|
|
|
|
pair: SymbolPair,
|
|
|
|
price: PriceTicker,
|
|
|
|
events: Option<Vec<Event>>,
|
|
|
|
signals: Option<Vec<SignalKind>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PriceEntry {
|
|
|
|
pub fn new(
|
|
|
|
tick: u64,
|
|
|
|
price: PriceTicker,
|
|
|
|
pair: SymbolPair,
|
|
|
|
events: Option<Vec<Event>>,
|
|
|
|
signals: Option<Vec<SignalKind>>,
|
|
|
|
) -> Self {
|
|
|
|
PriceEntry {
|
|
|
|
tick,
|
|
|
|
pair,
|
|
|
|
price,
|
|
|
|
events,
|
|
|
|
signals,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tick(&self) -> u64 {
|
|
|
|
self.tick
|
|
|
|
}
|
|
|
|
pub fn pair(&self) -> &SymbolPair {
|
|
|
|
&self.pair
|
|
|
|
}
|
|
|
|
pub fn price(&self) -> PriceTicker {
|
|
|
|
self.price
|
|
|
|
}
|
|
|
|
pub fn events(&self) -> &Option<Vec<Event>> {
|
|
|
|
&self.events
|
|
|
|
}
|
|
|
|
pub fn signals(&self) -> &Option<Vec<SignalKind>> {
|
|
|
|
&self.signals
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-14 18:36:56 +00:00
|
|
|
#[derive(Debug)]
|
2021-01-14 12:42:23 +00:00
|
|
|
pub struct PositionManager {
|
2021-01-14 18:36:56 +00:00
|
|
|
pair: SymbolPair,
|
|
|
|
positions_history: HashMap<u64, Position>,
|
|
|
|
active_position: Option<Position>,
|
2021-01-13 09:24:59 +00:00
|
|
|
client: Client,
|
2021-01-14 12:42:23 +00:00
|
|
|
strategy: Option<Box<dyn PositionStrategy>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PositionManager {
|
2021-01-14 18:36:56 +00:00
|
|
|
pub fn new(pair: SymbolPair, client: Client) -> Self {
|
2021-01-14 12:42:23 +00:00
|
|
|
PositionManager {
|
2021-01-14 18:36:56 +00:00
|
|
|
pair,
|
|
|
|
positions_history: HashMap::new(),
|
|
|
|
active_position: None,
|
2021-01-14 12:42:23 +00:00
|
|
|
client,
|
|
|
|
strategy: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_strategy(mut self, strategy: Box<dyn PositionStrategy>) -> Self {
|
|
|
|
self.strategy = Some(strategy);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-01-14 18:36:56 +00:00
|
|
|
pub async fn update(&mut self, tick: u64) -> Result<Option<Vec<Event>>, BoxError> {
|
2021-01-14 18:56:31 +00:00
|
|
|
let opt_active_positions = self.client.active_positions(&self.pair).await?;
|
2021-01-14 18:36:56 +00:00
|
|
|
let mut events = vec![];
|
|
|
|
|
|
|
|
if opt_active_positions.is_none() {
|
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
|
|
|
|
// we assume there is only ONE active position per pair
|
|
|
|
match opt_active_positions
|
|
|
|
.unwrap()
|
|
|
|
.into_iter()
|
|
|
|
.filter(|x| x.pair() == &self.pair)
|
|
|
|
.next()
|
|
|
|
{
|
|
|
|
Some(position) => {
|
|
|
|
// applying strategy to position
|
|
|
|
let active_position = {
|
|
|
|
match &self.strategy {
|
|
|
|
Some(strategy) => {
|
|
|
|
let (pos, strategy_events, _) = strategy.on_new_tick(&position, &self);
|
|
|
|
|
|
|
|
events.extend(strategy_events);
|
|
|
|
pos
|
|
|
|
}
|
|
|
|
None => position,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
self.positions_history.insert(tick, active_position.clone());
|
|
|
|
self.active_position = Some(active_position);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
self.active_position = None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if events.is_empty() {
|
|
|
|
Ok(None)
|
|
|
|
} else {
|
|
|
|
Ok(Some(events))
|
|
|
|
}
|
2021-01-14 12:42:23 +00:00
|
|
|
}
|
2021-01-13 09:24:59 +00:00
|
|
|
}
|
2021-01-13 09:03:24 +00:00
|
|
|
|
2021-01-14 12:42:23 +00:00
|
|
|
pub struct OrderManager {
|
2021-01-14 18:36:56 +00:00
|
|
|
pair: SymbolPair,
|
2021-01-13 09:24:59 +00:00
|
|
|
open_orders: Vec<Order>,
|
|
|
|
client: Client,
|
|
|
|
}
|
2021-01-14 12:42:23 +00:00
|
|
|
|
|
|
|
impl OrderManager {
|
2021-01-14 18:36:56 +00:00
|
|
|
pub fn new(pair: SymbolPair, client: Client) -> Self {
|
2021-01-14 12:42:23 +00:00
|
|
|
OrderManager {
|
2021-01-14 18:36:56 +00:00
|
|
|
pair,
|
2021-01-14 12:42:23 +00:00
|
|
|
open_orders: Vec::new(),
|
|
|
|
client,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update(&self) -> Option<Vec<Event>> {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
}
|