traits and shit
This commit is contained in:
		
							parent
							
								
									ea7c8394a3
								
							
						
					
					
						commit
						78b57b3899
					
				
							
								
								
									
										12
									
								
								rustybot/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								rustybot/Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -15,6 +15,17 @@ version = "0.2.3"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
 | 
					checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "async-trait"
 | 
				
			||||||
 | 
					version = "0.1.42"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "autocfg"
 | 
					name = "autocfg"
 | 
				
			||||||
version = "1.0.1"
 | 
					version = "1.0.1"
 | 
				
			||||||
@ -1016,6 +1027,7 @@ checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
 | 
				
			|||||||
name = "rustybot"
 | 
					name = "rustybot"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "async-trait",
 | 
				
			||||||
 "bitfinex",
 | 
					 "bitfinex",
 | 
				
			||||||
 "futures-util",
 | 
					 "futures-util",
 | 
				
			||||||
 "tokio 0.2.24",
 | 
					 "tokio 0.2.24",
 | 
				
			||||||
 | 
				
			|||||||
@ -11,3 +11,4 @@ bitfinex = { path= "/home/giulio/dev/bitfinex-rs" }
 | 
				
			|||||||
tokio = { version = "0.2", features=["full"]}
 | 
					tokio = { version = "0.2", features=["full"]}
 | 
				
			||||||
tokio-tungstenite = "*"
 | 
					tokio-tungstenite = "*"
 | 
				
			||||||
futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"] }
 | 
					futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"] }
 | 
				
			||||||
 | 
					async-trait = "0.1"
 | 
				
			||||||
@ -3,34 +3,17 @@ use std::collections::HashMap;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use bitfinex::api::Bitfinex;
 | 
					use bitfinex::api::Bitfinex;
 | 
				
			||||||
use bitfinex::positions::Position;
 | 
					use bitfinex::positions::Position;
 | 
				
			||||||
 | 
					use bitfinex::ticker::TradingPairTicker;
 | 
				
			||||||
use tokio::time::delay_for;
 | 
					use tokio::time::delay_for;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::BoxError;
 | 
					use crate::connectors::Connector;
 | 
				
			||||||
use crate::currency::{Symbol, SymbolPair};
 | 
					use crate::currency::{Symbol, SymbolPair};
 | 
				
			||||||
use crate::pairs::PairStatus;
 | 
					use crate::pairs::PairStatus;
 | 
				
			||||||
use crate::ticker::Ticker;
 | 
					use crate::ticker::Ticker;
 | 
				
			||||||
use bitfinex::ticker::TradingPairTicker;
 | 
					use crate::BoxError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct BfxWrapper {
 | 
					pub struct BfxBot<'a> {
 | 
				
			||||||
    bfx: Bitfinex
 | 
					    connector: Box<dyn Connector + 'a>,
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl BfxWrapper {
 | 
					 | 
				
			||||||
    pub fn new(api_key: &str, api_secret: &str) -> Self {
 | 
					 | 
				
			||||||
        BfxWrapper {
 | 
					 | 
				
			||||||
            bfx: Bitfinex::new(Some(api_key.into()), Some(api_secret.into()))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn current_prices(&self, pair: &SymbolPair) -> Result<TradingPairTicker, BoxError> {
 | 
					 | 
				
			||||||
        let ticker: TradingPairTicker = self.bfx.ticker.trading_pair(pair.clone()).await?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ok(ticker)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct BfxBot {
 | 
					 | 
				
			||||||
    pub bfx: BfxWrapper,
 | 
					 | 
				
			||||||
    ticker: Ticker,
 | 
					    ticker: Ticker,
 | 
				
			||||||
    pair_status: Vec<PairStatus>,
 | 
					    pair_status: Vec<PairStatus>,
 | 
				
			||||||
    quote: Symbol,
 | 
					    quote: Symbol,
 | 
				
			||||||
@ -39,10 +22,15 @@ pub struct BfxBot {
 | 
				
			|||||||
    // ledger: String,
 | 
					    // ledger: String,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl BfxBot {
 | 
					impl<'a> BfxBot<'a> {
 | 
				
			||||||
    pub fn new<S: Into<String>>(api_key: S, api_secret: S, trading_symbols: Vec<Symbol>, quote: Symbol, tick_duration: Duration) -> Self {
 | 
					    pub fn new<C: Connector + 'a>(
 | 
				
			||||||
 | 
					        connector: C,
 | 
				
			||||||
 | 
					        trading_symbols: Vec<Symbol>,
 | 
				
			||||||
 | 
					        quote: Symbol,
 | 
				
			||||||
 | 
					        tick_duration: Duration,
 | 
				
			||||||
 | 
					    ) -> Self {
 | 
				
			||||||
        BfxBot {
 | 
					        BfxBot {
 | 
				
			||||||
            bfx: BfxWrapper::new(&api_key.into(), &api_secret.into()),
 | 
					            connector: Box::new(connector),
 | 
				
			||||||
            ticker: Ticker::new(tick_duration),
 | 
					            ticker: Ticker::new(tick_duration),
 | 
				
			||||||
            pair_status: trading_symbols
 | 
					            pair_status: trading_symbols
 | 
				
			||||||
                .iter()
 | 
					                .iter()
 | 
				
			||||||
@ -59,11 +47,11 @@ impl BfxBot {
 | 
				
			|||||||
    pub async fn current_prices(&self, symbol: Symbol) -> Result<TradingPairTicker, BoxError> {
 | 
					    pub async fn current_prices(&self, symbol: Symbol) -> Result<TradingPairTicker, BoxError> {
 | 
				
			||||||
        let trading_pair = SymbolPair::new(self.quote.clone(), symbol.clone());
 | 
					        let trading_pair = SymbolPair::new(self.quote.clone(), symbol.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if !self.trading_symbols.contains(&symbol){
 | 
					        if !self.trading_symbols.contains(&symbol) {
 | 
				
			||||||
            return Err("Symbol not supported.".into());
 | 
					            return Err("Symbol not supported.".into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.bfx.current_prices(&trading_pair).await
 | 
					        self.connector.current_prices(&trading_pair).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn update(&mut self) {
 | 
					    pub async fn update(&mut self) {
 | 
				
			||||||
@ -80,4 +68,3 @@ impl BfxBot {
 | 
				
			|||||||
    //     for p in active_positions {}
 | 
					    //     for p in active_positions {}
 | 
				
			||||||
    // }
 | 
					    // }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,11 @@
 | 
				
			|||||||
use std::collections::{HashMap, HashSet};
 | 
					use std::collections::{HashMap, HashSet};
 | 
				
			||||||
use std::future::Future;
 | 
					use std::future::Future;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use bitfinex::positions::Position;
 | 
					 | 
				
			||||||
use tokio::stream::StreamExt;
 | 
					use tokio::stream::StreamExt;
 | 
				
			||||||
use tokio::task::JoinHandle;
 | 
					use tokio::task::JoinHandle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::pairs::PairStatus;
 | 
					use crate::pairs::PairStatus;
 | 
				
			||||||
use crate::positions::{PositionState, PositionWrapper};
 | 
					use crate::positions::{Position, PositionState};
 | 
				
			||||||
use crate::BoxError;
 | 
					use crate::BoxError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
@ -80,11 +79,10 @@ impl Event {
 | 
				
			|||||||
pub struct EventDispatcher {
 | 
					pub struct EventDispatcher {
 | 
				
			||||||
    event_handlers: HashMap<EventKind, Vec<Box<dyn Fn(&Event, &PairStatus) -> JoinHandle<()>>>>,
 | 
					    event_handlers: HashMap<EventKind, Vec<Box<dyn Fn(&Event, &PairStatus) -> JoinHandle<()>>>>,
 | 
				
			||||||
    position_state_handlers:
 | 
					    position_state_handlers:
 | 
				
			||||||
        HashMap<PositionState, Vec<Box<dyn Fn(&PositionWrapper, &PairStatus) -> JoinHandle<()>>>>,
 | 
					        HashMap<PositionState, Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    on_any_event_handlers: Vec<Box<dyn Fn(&Event, &PairStatus) -> JoinHandle<()>>>,
 | 
					    on_any_event_handlers: Vec<Box<dyn Fn(&Event, &PairStatus) -> JoinHandle<()>>>,
 | 
				
			||||||
    on_any_position_state_handlers:
 | 
					    on_any_position_state_handlers: Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>,
 | 
				
			||||||
        Vec<Box<dyn Fn(&PositionWrapper, &PairStatus) -> JoinHandle<()>>>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl EventDispatcher {
 | 
					impl EventDispatcher {
 | 
				
			||||||
@ -109,17 +107,15 @@ impl EventDispatcher {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn call_position_state_handlers(&self, pw: &PositionWrapper, status: &PairStatus) {
 | 
					    pub fn call_position_state_handlers(&self, position: &Position, status: &PairStatus) {
 | 
				
			||||||
        if let Some(state) = pw.state() {
 | 
					        if let Some(functions) = self.position_state_handlers.get(&position.state()) {
 | 
				
			||||||
            if let Some(functions) = self.position_state_handlers.get(&state) {
 | 
					            for f in functions {
 | 
				
			||||||
                for f in functions {
 | 
					                f(position, status);
 | 
				
			||||||
                    f(pw, status);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for f in &self.on_any_position_state_handlers {
 | 
					        for f in &self.on_any_position_state_handlers {
 | 
				
			||||||
            f(pw, status);
 | 
					            f(position, status);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -145,18 +141,18 @@ impl EventDispatcher {
 | 
				
			|||||||
        state: PositionState,
 | 
					        state: PositionState,
 | 
				
			||||||
        f: F,
 | 
					        f: F,
 | 
				
			||||||
    ) where
 | 
					    ) where
 | 
				
			||||||
        F: Fn(&PositionWrapper, &PairStatus) -> Fut,
 | 
					        F: Fn(&Position, &PairStatus) -> Fut,
 | 
				
			||||||
        Fut: Future<Output = ()> + Send,
 | 
					        Fut: Future<Output = ()> + Send,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        match state {
 | 
					        match state {
 | 
				
			||||||
            PositionState::Any => self
 | 
					            PositionState::Any => self
 | 
				
			||||||
                .on_any_position_state_handlers
 | 
					                .on_any_position_state_handlers
 | 
				
			||||||
                .push(Box::new(move |pw, s| tokio::spawn(f(&pw, s)))),
 | 
					                .push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
 | 
				
			||||||
            _ => self
 | 
					            _ => self
 | 
				
			||||||
                .position_state_handlers
 | 
					                .position_state_handlers
 | 
				
			||||||
                .entry(state)
 | 
					                .entry(state)
 | 
				
			||||||
                .or_default()
 | 
					                .or_default()
 | 
				
			||||||
                .push(Box::new(move |pw, s| tokio::spawn(f(&pw, s)))),
 | 
					                .push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,35 +1,40 @@
 | 
				
			|||||||
use bitfinex::api::Bitfinex;
 | 
					use tokio::time::{delay_for, Duration};
 | 
				
			||||||
use bitfinex::ticker::TradingPairTicker;
 | 
					 | 
				
			||||||
use tokio::time::{Duration, delay_for};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::bot::BfxBot;
 | 
					use crate::bot::BfxBot;
 | 
				
			||||||
use crate::currency::{Symbol, SymbolPair};
 | 
					use crate::currency::{Symbol, SymbolPair};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod ticker;
 | 
					mod bot;
 | 
				
			||||||
 | 
					mod connectors;
 | 
				
			||||||
 | 
					mod currency;
 | 
				
			||||||
mod events;
 | 
					mod events;
 | 
				
			||||||
 | 
					mod orders;
 | 
				
			||||||
mod pairs;
 | 
					mod pairs;
 | 
				
			||||||
mod positions;
 | 
					mod positions;
 | 
				
			||||||
mod strategy;
 | 
					mod strategy;
 | 
				
			||||||
mod bot;
 | 
					mod ticker;
 | 
				
			||||||
mod currency;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
 | 
					pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[tokio::main]
 | 
					#[tokio::main]
 | 
				
			||||||
async fn main() -> Result<(), BoxError> {
 | 
					async fn main() -> Result<(), BoxError> {
 | 
				
			||||||
    let test_api_key = "P1EVE68DJByDAkGQvpIkTwfrbYXd2Vo2ZaIhTYb9vx2";
 | 
					    // let test_api_key = "P1EVE68DJByDAkGQvpIkTwfrbYXd2Vo2ZaIhTYb9vx2";
 | 
				
			||||||
    let test_api_secret = "1nicg8z0zKVEt5Rb7ZDpIYjVYVTgvCaCPMZqB0niFli";
 | 
					    // let test_api_secret = "1nicg8z0zKVEt5Rb7ZDpIYjVYVTgvCaCPMZqB0niFli";
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
    let mut bot = BfxBot::new(test_api_key, test_api_secret, vec![Symbol::BTC, Symbol::ETH, Symbol::XMR], Symbol::USD, Duration::new(20, 0));
 | 
					    // let mut bot = BfxBot::new(
 | 
				
			||||||
 | 
					    //     test_api_key,
 | 
				
			||||||
    loop {
 | 
					    //     test_api_secret,
 | 
				
			||||||
        let ticker = bot.current_prices("ETH".into()).await?;
 | 
					    //     vec![Symbol::BTC, Symbol::ETH, Symbol::XMR],
 | 
				
			||||||
        bot.update().await;
 | 
					    //     Symbol::USD,
 | 
				
			||||||
 | 
					    //     Duration::new(20, 0),
 | 
				
			||||||
        // let ticker = bot.current_prices("ETH".into()).await?;
 | 
					    // );
 | 
				
			||||||
        println!("{:?}", ticker);
 | 
					    //
 | 
				
			||||||
    }
 | 
					    // loop {
 | 
				
			||||||
 | 
					    //     let ticker = bot.current_prices("ETH".into()).await?;
 | 
				
			||||||
 | 
					    //     bot.update().await;
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    //     // let ticker = bot.current_prices("ETH".into()).await?;
 | 
				
			||||||
 | 
					    //     println!("{:?}", ticker);
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								rustybot/src/orders.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								rustybot/src/orders.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					pub struct Order {
 | 
				
			||||||
 | 
					    pub id: i64,
 | 
				
			||||||
 | 
					    pub group_id: Option<i32>,
 | 
				
			||||||
 | 
					    pub client_id: i64,
 | 
				
			||||||
 | 
					    pub symbol: String,
 | 
				
			||||||
 | 
					    pub creation_timestamp: i64,
 | 
				
			||||||
 | 
					    pub update_timestamp: i64,
 | 
				
			||||||
 | 
					    pub amount: f64,
 | 
				
			||||||
 | 
					    pub amount_original: f64,
 | 
				
			||||||
 | 
					    pub order_type: String,
 | 
				
			||||||
 | 
					    pub previous_order_type: Option<String>,
 | 
				
			||||||
 | 
					    pub flags: Option<i32>,
 | 
				
			||||||
 | 
					    pub order_status: Option<String>,
 | 
				
			||||||
 | 
					    pub price: f64,
 | 
				
			||||||
 | 
					    pub price_avg: f64,
 | 
				
			||||||
 | 
					    pub price_trailing: Option<f64>,
 | 
				
			||||||
 | 
					    pub price_aux_limit: Option<f64>,
 | 
				
			||||||
 | 
					    pub notify: i32,
 | 
				
			||||||
 | 
					    pub hidden: i32,
 | 
				
			||||||
 | 
					    pub placed_id: Option<i32>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,10 +1,9 @@
 | 
				
			|||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use bitfinex::positions::Position;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::currency::SymbolPair;
 | 
					use crate::currency::SymbolPair;
 | 
				
			||||||
use crate::events::{Event, EventDispatcher};
 | 
					use crate::events::{Event, EventDispatcher};
 | 
				
			||||||
use crate::positions::PositionWrapper;
 | 
					use crate::orders::Order;
 | 
				
			||||||
 | 
					use crate::positions::Position;
 | 
				
			||||||
use crate::strategy::Strategy;
 | 
					use crate::strategy::Strategy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct PairStatus {
 | 
					pub struct PairStatus {
 | 
				
			||||||
@ -12,8 +11,8 @@ pub struct PairStatus {
 | 
				
			|||||||
    dispatcher: EventDispatcher,
 | 
					    dispatcher: EventDispatcher,
 | 
				
			||||||
    prices: HashMap<u64, f64>,
 | 
					    prices: HashMap<u64, f64>,
 | 
				
			||||||
    events: Vec<Event>,
 | 
					    events: Vec<Event>,
 | 
				
			||||||
    // orders: HashMap<u64, Vec<Order>>,
 | 
					    orders: HashMap<u64, Vec<Order>>,
 | 
				
			||||||
    positions: HashMap<u64, Vec<PositionWrapper>>,
 | 
					    positions: HashMap<u64, Vec<Position>>,
 | 
				
			||||||
    current_tick: u64,
 | 
					    current_tick: u64,
 | 
				
			||||||
    strategy: Option<Box<dyn Strategy>>,
 | 
					    strategy: Option<Box<dyn Strategy>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -28,6 +27,7 @@ impl PairStatus {
 | 
				
			|||||||
            positions: HashMap::new(),
 | 
					            positions: HashMap::new(),
 | 
				
			||||||
            current_tick,
 | 
					            current_tick,
 | 
				
			||||||
            strategy,
 | 
					            strategy,
 | 
				
			||||||
 | 
					            orders: HashMap::new(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,7 +36,8 @@ impl PairStatus {
 | 
				
			|||||||
            match &self.strategy {
 | 
					            match &self.strategy {
 | 
				
			||||||
                Some(strategy) => strategy.position_on_new_tick(&position, &self),
 | 
					                Some(strategy) => strategy.position_on_new_tick(&position, &self),
 | 
				
			||||||
                None => (
 | 
					                None => (
 | 
				
			||||||
                    PositionWrapper::new(position.clone(), position.pl(), position.pl_perc(), None),
 | 
					                    position,
 | 
				
			||||||
 | 
					                    // PositionWrapper::new(position.clone(), position.pl(), position.pl_perc(), None),
 | 
				
			||||||
                    vec![],
 | 
					                    vec![],
 | 
				
			||||||
                    vec![],
 | 
					                    vec![],
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
@ -67,9 +68,9 @@ impl PairStatus {
 | 
				
			|||||||
        self.current_tick
 | 
					        self.current_tick
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn previous_pw(&self, id: u64) -> Option<&PositionWrapper> {
 | 
					    pub fn previous_pw(&self, id: u64) -> Option<&Position> {
 | 
				
			||||||
        self.positions
 | 
					        self.positions
 | 
				
			||||||
            .get(&(self.current_tick - 1))
 | 
					            .get(&(self.current_tick - 1))
 | 
				
			||||||
            .and_then(|x| x.iter().find(|x| x.position().position_id() == id))
 | 
					            .and_then(|x| x.iter().find(|x| x.position_id() == id))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,81 @@
 | 
				
			|||||||
use bitfinex::positions::Position;
 | 
					use crate::currency::{Symbol, SymbolPair};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone)]
 | 
				
			||||||
 | 
					pub struct Position {
 | 
				
			||||||
 | 
					    pair: SymbolPair,
 | 
				
			||||||
 | 
					    state: PositionState,
 | 
				
			||||||
 | 
					    amount: f64,
 | 
				
			||||||
 | 
					    base_price: f64,
 | 
				
			||||||
 | 
					    pl: f64,
 | 
				
			||||||
 | 
					    pl_perc: f64,
 | 
				
			||||||
 | 
					    price_liq: f64,
 | 
				
			||||||
 | 
					    position_id: u64,
 | 
				
			||||||
 | 
					    creation_date: Option<u64>,
 | 
				
			||||||
 | 
					    creation_update: Option<u64>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Position {
 | 
				
			||||||
 | 
					    pub fn new(
 | 
				
			||||||
 | 
					        pair: SymbolPair,
 | 
				
			||||||
 | 
					        state: PositionState,
 | 
				
			||||||
 | 
					        amount: f64,
 | 
				
			||||||
 | 
					        base_price: f64,
 | 
				
			||||||
 | 
					        pl: f64,
 | 
				
			||||||
 | 
					        pl_perc: f64,
 | 
				
			||||||
 | 
					        price_liq: f64,
 | 
				
			||||||
 | 
					        position_id: u64,
 | 
				
			||||||
 | 
					    ) -> Self {
 | 
				
			||||||
 | 
					        Position {
 | 
				
			||||||
 | 
					            pair,
 | 
				
			||||||
 | 
					            state,
 | 
				
			||||||
 | 
					            amount,
 | 
				
			||||||
 | 
					            base_price,
 | 
				
			||||||
 | 
					            pl,
 | 
				
			||||||
 | 
					            pl_perc,
 | 
				
			||||||
 | 
					            price_liq,
 | 
				
			||||||
 | 
					            position_id,
 | 
				
			||||||
 | 
					            creation_date: None,
 | 
				
			||||||
 | 
					            creation_update: None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn with_creation_date(mut self, creation_date: u64) -> Self {
 | 
				
			||||||
 | 
					        self.creation_date = Some(creation_date);
 | 
				
			||||||
 | 
					        self.creation_update = Some(creation_date);
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn pair(&self) -> &SymbolPair {
 | 
				
			||||||
 | 
					        &self.pair
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn state(&self) -> PositionState {
 | 
				
			||||||
 | 
					        self.state
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn amount(&self) -> f64 {
 | 
				
			||||||
 | 
					        self.amount
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn base_price(&self) -> f64 {
 | 
				
			||||||
 | 
					        self.base_price
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn pl(&self) -> f64 {
 | 
				
			||||||
 | 
					        self.pl
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn pl_perc(&self) -> f64 {
 | 
				
			||||||
 | 
					        self.pl_perc
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn price_liq(&self) -> f64 {
 | 
				
			||||||
 | 
					        self.price_liq
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn position_id(&self) -> u64 {
 | 
				
			||||||
 | 
					        self.position_id
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn creation_date(&self) -> Option<u64> {
 | 
				
			||||||
 | 
					        self.creation_date
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn creation_update(&self) -> Option<u64> {
 | 
				
			||||||
 | 
					        self.creation_update
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
 | 
					#[derive(Copy, Clone, Eq, PartialEq, Hash)]
 | 
				
			||||||
pub enum PositionState {
 | 
					pub enum PositionState {
 | 
				
			||||||
@ -7,6 +84,7 @@ pub enum PositionState {
 | 
				
			|||||||
    BreakEven,
 | 
					    BreakEven,
 | 
				
			||||||
    MinimumProfit,
 | 
					    MinimumProfit,
 | 
				
			||||||
    Profit,
 | 
					    Profit,
 | 
				
			||||||
 | 
					    Closed,
 | 
				
			||||||
    Any,
 | 
					    Any,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,44 +95,8 @@ impl PositionState {
 | 
				
			|||||||
            PositionState::Critical | PositionState::Loss => "red",
 | 
					            PositionState::Critical | PositionState::Loss => "red",
 | 
				
			||||||
            PositionState::BreakEven => "yellow",
 | 
					            PositionState::BreakEven => "yellow",
 | 
				
			||||||
            PositionState::MinimumProfit | PositionState::Profit => "green",
 | 
					            PositionState::MinimumProfit | PositionState::Profit => "green",
 | 
				
			||||||
 | 
					            PositionState::Closed => "gray",
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        .into()
 | 
					        .into()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Clone)]
 | 
					 | 
				
			||||||
pub struct PositionWrapper {
 | 
					 | 
				
			||||||
    position: Position,
 | 
					 | 
				
			||||||
    net_pl: f64,
 | 
					 | 
				
			||||||
    net_pl_perc: f64,
 | 
					 | 
				
			||||||
    state: Option<PositionState>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl PositionWrapper {
 | 
					 | 
				
			||||||
    pub fn new(
 | 
					 | 
				
			||||||
        position: Position,
 | 
					 | 
				
			||||||
        net_pl: f64,
 | 
					 | 
				
			||||||
        net_pl_perc: f64,
 | 
					 | 
				
			||||||
        state: Option<PositionState>,
 | 
					 | 
				
			||||||
    ) -> Self {
 | 
					 | 
				
			||||||
        PositionWrapper {
 | 
					 | 
				
			||||||
            position,
 | 
					 | 
				
			||||||
            net_pl,
 | 
					 | 
				
			||||||
            net_pl_perc,
 | 
					 | 
				
			||||||
            state,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn position(&self) -> &Position {
 | 
					 | 
				
			||||||
        &self.position
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pub fn net_pl(&self) -> f64 {
 | 
					 | 
				
			||||||
        self.net_pl
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pub fn net_pl_perc(&self) -> f64 {
 | 
					 | 
				
			||||||
        self.net_pl_perc
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pub fn state(&self) -> Option<PositionState> {
 | 
					 | 
				
			||||||
        self.state
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,15 @@
 | 
				
			|||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use bitfinex::positions::Position;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::events::{Event, EventKind, EventMetadata, SignalKind};
 | 
					use crate::events::{Event, EventKind, EventMetadata, SignalKind};
 | 
				
			||||||
use crate::pairs::PairStatus;
 | 
					use crate::pairs::PairStatus;
 | 
				
			||||||
use crate::positions::{PositionState, PositionWrapper};
 | 
					use crate::positions::{Position, PositionState};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait Strategy {
 | 
					pub trait Strategy {
 | 
				
			||||||
    fn position_on_new_tick(
 | 
					    fn position_on_new_tick(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        position: &Position,
 | 
					        position: &Position,
 | 
				
			||||||
        status: &PairStatus,
 | 
					        status: &PairStatus,
 | 
				
			||||||
    ) -> (PositionWrapper, Vec<Event>, Vec<SignalKind>);
 | 
					    ) -> (Position, Vec<Event>, Vec<SignalKind>);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TrailingStop {
 | 
					struct TrailingStop {
 | 
				
			||||||
@ -42,7 +40,7 @@ impl Strategy for TrailingStop {
 | 
				
			|||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        position: &Position,
 | 
					        position: &Position,
 | 
				
			||||||
        status: &PairStatus,
 | 
					        status: &PairStatus,
 | 
				
			||||||
    ) -> (PositionWrapper, Vec<Event>, Vec<SignalKind>) {
 | 
					    ) -> (Position, Vec<Event>, Vec<SignalKind>) {
 | 
				
			||||||
        let mut signals = vec![];
 | 
					        let mut signals = vec![];
 | 
				
			||||||
        let pl_perc = TrailingStop::net_pl_percentage(position.pl_perc(), TrailingStop::TAKER_FEE);
 | 
					        let pl_perc = TrailingStop::net_pl_percentage(position.pl_perc(), TrailingStop::TAKER_FEE);
 | 
				
			||||||
        let events = vec![];
 | 
					        let events = vec![];
 | 
				
			||||||
@ -66,11 +64,12 @@ impl Strategy for TrailingStop {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let opt_pre_pw = status.previous_pw(position.position_id());
 | 
					        let opt_pre_pw = status.previous_pw(position.position_id());
 | 
				
			||||||
        let event_metadata = EventMetadata::new(Some(position.position_id()), None);
 | 
					        let event_metadata = EventMetadata::new(Some(position.position_id()), None);
 | 
				
			||||||
        let pw = PositionWrapper::new(position.clone(), position.pl(), pl_perc, Some(state));
 | 
					        // let pw = PositionWrapper::new(position.clone(), position.pl(), pl_perc, Some(state));
 | 
				
			||||||
 | 
					        let pw = position.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match opt_pre_pw {
 | 
					        match opt_pre_pw {
 | 
				
			||||||
            Some(prev) => {
 | 
					            Some(prev) => {
 | 
				
			||||||
                if prev.state() == Some(state) {
 | 
					                if prev.state() == state {
 | 
				
			||||||
                    return (pw, events, signals);
 | 
					                    return (pw, events, signals);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user