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…
Reference in New Issue
Block a user