position manager working
This commit is contained in:
parent
3eca8aef2d
commit
2c151ae6c1
@ -33,21 +33,21 @@ impl BfxBot {
|
|||||||
tick_duration: Duration,
|
tick_duration: Duration,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let clients: Vec<_> = exchanges.iter().map(|x| Client::new(x)).collect();
|
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 pos_managers = Vec::new();
|
||||||
let mut order_managers = Vec::new();
|
let mut order_managers = Vec::new();
|
||||||
let mut pair_statuses = Vec::new();
|
let mut pair_statuses = Vec::new();
|
||||||
|
|
||||||
for c in clients {
|
for c in clients {
|
||||||
pos_managers.push(PositionManager::new(c.clone()));
|
for p in &pairs {
|
||||||
order_managers.push(OrderManager::new(c.clone()));
|
pos_managers.push(PositionManager::new(p.clone(), c.clone()));
|
||||||
pair_statuses.extend(
|
order_managers.push(OrderManager::new(p.clone(), c.clone()));
|
||||||
trading_symbols
|
pair_statuses.push(PriceManager::new(p.clone(), c.clone()));
|
||||||
.iter()
|
}
|
||||||
.map(|x| SymbolPair::new(quote.clone(), x.clone()))
|
|
||||||
.map(|x| PriceManager::new(x, c.clone()))
|
|
||||||
.collect::<Vec<PriceManager>>(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BfxBot {
|
BfxBot {
|
||||||
@ -79,10 +79,23 @@ impl BfxBot {
|
|||||||
|
|
||||||
async fn update_managers(&mut self) -> Result<(), BoxError> {
|
async fn update_managers(&mut self) -> Result<(), BoxError> {
|
||||||
self.update_price_managers().await?;
|
self.update_price_managers().await?;
|
||||||
|
self.update_position_managers().await?;
|
||||||
|
|
||||||
Ok(())
|
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> {
|
async fn update_price_managers(&mut self) -> Result<Option<Vec<Event>>, BoxError> {
|
||||||
let futures: Vec<_> = self
|
let futures: Vec<_> = self
|
||||||
.price_managers
|
.price_managers
|
||||||
|
@ -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
|
self.inner.active_positions(pair).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +73,7 @@ impl Client {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Connector: Send + Sync {
|
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 current_prices(&self, pair: &SymbolPair) -> Result<TradingPairTicker, BoxError>;
|
||||||
async fn active_orders(&self, pair: &SymbolPair) -> Result<Vec<Order>, BoxError>;
|
async fn active_orders(&self, pair: &SymbolPair) -> Result<Vec<Order>, BoxError>;
|
||||||
async fn submit_order(
|
async fn submit_order(
|
||||||
@ -123,14 +126,20 @@ impl BitfinexConnector {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Connector for BitfinexConnector {
|
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?;
|
let active_positions = self.bfx.positions.active_positions().await?;
|
||||||
|
|
||||||
Ok(active_positions
|
let positions: Vec<_> = active_positions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|x| x.try_into().ok())
|
.filter_map(|x| x.try_into().ok())
|
||||||
.filter(|x: &Position| x.pair() == pair)
|
.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> {
|
async fn current_prices(&self, pair: &SymbolPair) -> Result<TradingPairTicker, BoxError> {
|
||||||
|
@ -147,18 +147,21 @@ impl PriceEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct PositionManager {
|
pub struct PositionManager {
|
||||||
queue: VecDeque<Position>,
|
pair: SymbolPair,
|
||||||
open_positions: Vec<Position>,
|
positions_history: HashMap<u64, Position>,
|
||||||
|
active_position: Option<Position>,
|
||||||
client: Client,
|
client: Client,
|
||||||
strategy: Option<Box<dyn PositionStrategy>>,
|
strategy: Option<Box<dyn PositionStrategy>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositionManager {
|
impl PositionManager {
|
||||||
pub fn new(client: Client) -> Self {
|
pub fn new(pair: SymbolPair, client: Client) -> Self {
|
||||||
PositionManager {
|
PositionManager {
|
||||||
queue: VecDeque::new(),
|
pair,
|
||||||
open_positions: Vec::new(),
|
positions_history: HashMap::new(),
|
||||||
|
active_position: None,
|
||||||
client,
|
client,
|
||||||
strategy: None,
|
strategy: None,
|
||||||
}
|
}
|
||||||
@ -169,21 +172,61 @@ impl PositionManager {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self) -> Option<Vec<Event>> {
|
pub async fn update(&mut self, tick: u64) -> Result<Option<Vec<Event>>, BoxError> {
|
||||||
unimplemented!()
|
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 {
|
pub struct OrderManager {
|
||||||
queue: VecDeque<Order>,
|
pair: SymbolPair,
|
||||||
open_orders: Vec<Order>,
|
open_orders: Vec<Order>,
|
||||||
client: Client,
|
client: Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OrderManager {
|
impl OrderManager {
|
||||||
pub fn new(client: Client) -> Self {
|
pub fn new(pair: SymbolPair, client: Client) -> Self {
|
||||||
OrderManager {
|
OrderManager {
|
||||||
queue: VecDeque::new(),
|
pair,
|
||||||
open_orders: Vec::new(),
|
open_orders: Vec::new(),
|
||||||
client,
|
client,
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ pub enum OrderKind {
|
|||||||
* Positions
|
* Positions
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pair: SymbolPair,
|
pair: SymbolPair,
|
||||||
state: PositionState,
|
state: PositionState,
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::events::{Event, EventKind, EventMetadata, SignalKind};
|
use crate::events::{Event, EventKind, EventMetadata, SignalKind};
|
||||||
use crate::managers::PriceManager;
|
use crate::managers::{PositionManager, PriceManager};
|
||||||
use crate::models::{Position, PositionProfitState};
|
use crate::models::{Position, PositionProfitState};
|
||||||
use dyn_clone::DynClone;
|
use dyn_clone::DynClone;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
pub trait PositionStrategy: DynClone {
|
pub trait PositionStrategy: DynClone {
|
||||||
fn on_new_tick(
|
fn on_new_tick(
|
||||||
&self,
|
&self,
|
||||||
position: &Position,
|
position: &Position,
|
||||||
status: &PriceManager,
|
manager: &PositionManager,
|
||||||
) -> (Position, Vec<Event>, Vec<SignalKind>);
|
) -> (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)]
|
// #[derive(Clone, Debug)]
|
||||||
// pub struct TrailingStop {
|
// pub struct TrailingStop {
|
||||||
// stop_percentages: HashMap<u64, f64>,
|
// stop_percentages: HashMap<u64, f64>,
|
||||||
|
Loading…
Reference in New Issue
Block a user