position manager working

This commit is contained in:
Giulio De Pasquale 2021-01-14 18:36:56 +00:00
parent 3eca8aef2d
commit 2c151ae6c1
5 changed files with 99 additions and 27 deletions

View File

@ -33,21 +33,21 @@ impl BfxBot {
tick_duration: Duration,
) -> Self {
let clients: Vec<_> = exchanges.iter().map(|x| Client::new(x)).collect();
let pairs: Vec<_> = trading_symbols
.iter()
.map(|x| SymbolPair::new(quote.clone(), x.clone()))
.collect();
let mut pos_managers = Vec::new();
let mut order_managers = Vec::new();
let mut pair_statuses = Vec::new();
for c in clients {
pos_managers.push(PositionManager::new(c.clone()));
order_managers.push(OrderManager::new(c.clone()));
pair_statuses.extend(
trading_symbols
.iter()
.map(|x| SymbolPair::new(quote.clone(), x.clone()))
.map(|x| PriceManager::new(x, c.clone()))
.collect::<Vec<PriceManager>>(),
)
for p in &pairs {
pos_managers.push(PositionManager::new(p.clone(), c.clone()));
order_managers.push(OrderManager::new(p.clone(), c.clone()));
pair_statuses.push(PriceManager::new(p.clone(), c.clone()));
}
}
BfxBot {
@ -79,10 +79,23 @@ impl BfxBot {
async fn update_managers(&mut self) -> Result<(), BoxError> {
self.update_price_managers().await?;
self.update_position_managers().await?;
Ok(())
}
async fn update_position_managers(&mut self) -> Result<Option<Vec<Event>>, BoxError> {
for mgr in &mut self.pos_managers {
let tick = self.ticker.current_tick();
mgr.update(tick).await?;
println!("{:?}", mgr);
}
Ok(None)
}
async fn update_price_managers(&mut self) -> Result<Option<Vec<Event>>, BoxError> {
let futures: Vec<_> = self
.price_managers

View File

@ -45,7 +45,10 @@ impl Client {
}
}
pub async fn active_positions(&self, pair: &SymbolPair) -> Result<Vec<Position>, BoxError> {
pub async fn active_positions(
&self,
pair: &SymbolPair,
) -> Result<Option<Vec<Position>>, BoxError> {
self.inner.active_positions(pair).await
}
@ -70,7 +73,7 @@ impl Client {
#[async_trait]
pub trait Connector: Send + Sync {
async fn active_positions(&self, pair: &SymbolPair) -> Result<Vec<Position>, BoxError>;
async fn active_positions(&self, pair: &SymbolPair) -> Result<Option<Vec<Position>>, BoxError>;
async fn current_prices(&self, pair: &SymbolPair) -> Result<TradingPairTicker, BoxError>;
async fn active_orders(&self, pair: &SymbolPair) -> Result<Vec<Order>, BoxError>;
async fn submit_order(
@ -123,14 +126,20 @@ impl BitfinexConnector {
#[async_trait]
impl Connector for BitfinexConnector {
async fn active_positions(&self, pair: &SymbolPair) -> Result<Vec<Position>, BoxError> {
async fn active_positions(&self, pair: &SymbolPair) -> Result<Option<Vec<Position>>, BoxError> {
let active_positions = self.bfx.positions.active_positions().await?;
Ok(active_positions
let positions: Vec<_> = active_positions
.into_iter()
.filter_map(|x| x.try_into().ok())
.filter(|x: &Position| x.pair() == pair)
.collect())
.collect();
if positions.is_empty() {
Ok(None)
} else {
Ok(Some(positions))
}
}
async fn current_prices(&self, pair: &SymbolPair) -> Result<TradingPairTicker, BoxError> {

View File

@ -147,18 +147,21 @@ impl PriceEntry {
}
}
#[derive(Debug)]
pub struct PositionManager {
queue: VecDeque<Position>,
open_positions: Vec<Position>,
pair: SymbolPair,
positions_history: HashMap<u64, Position>,
active_position: Option<Position>,
client: Client,
strategy: Option<Box<dyn PositionStrategy>>,
}
impl PositionManager {
pub fn new(client: Client) -> Self {
pub fn new(pair: SymbolPair, client: Client) -> Self {
PositionManager {
queue: VecDeque::new(),
open_positions: Vec::new(),
pair,
positions_history: HashMap::new(),
active_position: None,
client,
strategy: None,
}
@ -169,21 +172,61 @@ impl PositionManager {
self
}
pub fn update(&self) -> Option<Vec<Event>> {
unimplemented!()
pub async fn update(&mut self, tick: u64) -> Result<Option<Vec<Event>>, BoxError> {
let mut opt_active_positions = self.client.active_positions(&self.pair).await?;
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))
}
}
}
pub struct OrderManager {
queue: VecDeque<Order>,
pair: SymbolPair,
open_orders: Vec<Order>,
client: Client,
}
impl OrderManager {
pub fn new(client: Client) -> Self {
pub fn new(pair: SymbolPair, client: Client) -> Self {
OrderManager {
queue: VecDeque::new(),
pair,
open_orders: Vec::new(),
client,
}

View File

@ -66,7 +66,7 @@ pub enum OrderKind {
* Positions
***************/
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct Position {
pair: SymbolPair,
state: PositionState,

View File

@ -1,18 +1,25 @@
use std::collections::HashMap;
use crate::events::{Event, EventKind, EventMetadata, SignalKind};
use crate::managers::PriceManager;
use crate::managers::{PositionManager, PriceManager};
use crate::models::{Position, PositionProfitState};
use dyn_clone::DynClone;
use std::fmt::{Debug, Formatter};
pub trait PositionStrategy: DynClone {
fn on_new_tick(
&self,
position: &Position,
status: &PriceManager,
manager: &PositionManager,
) -> (Position, Vec<Event>, Vec<SignalKind>);
}
impl Debug for dyn PositionStrategy {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "PositionStrategy")
}
}
// #[derive(Clone, Debug)]
// pub struct TrailingStop {
// stop_percentages: HashMap<u64, f64>,