a lot of stuff
This commit is contained in:
parent
d6cd0f1f20
commit
ea7c8394a3
@ -21,6 +21,15 @@ pub struct EventMetadata {
|
|||||||
order_id: Option<u64>,
|
order_id: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EventMetadata {
|
||||||
|
pub fn new(position_id: Option<u64>, order_id: Option<u64>) -> Self {
|
||||||
|
EventMetadata {
|
||||||
|
position_id,
|
||||||
|
order_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum EventKind {
|
pub enum EventKind {
|
||||||
NewMinimum,
|
NewMinimum,
|
||||||
|
@ -32,12 +32,13 @@ impl PairStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_position(&mut self, position: Position) {
|
pub fn add_position(&mut self, position: Position) {
|
||||||
let (pw, events) = {
|
let (pw, events, signals) = {
|
||||||
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),
|
PositionWrapper::new(position.clone(), position.pl(), position.pl_perc(), None),
|
||||||
vec![],
|
vec![],
|
||||||
|
vec![],
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -61,4 +62,14 @@ impl PairStatus {
|
|||||||
|
|
||||||
self.dispatcher.call_event_handlers(&event, &self);
|
self.dispatcher.call_event_handlers(&event, &self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn current_tick(&self) -> u64 {
|
||||||
|
self.current_tick
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn previous_pw(&self, id: u64) -> Option<&PositionWrapper> {
|
||||||
|
self.positions
|
||||||
|
.get(&(self.current_tick - 1))
|
||||||
|
.and_then(|x| x.iter().find(|x| x.position().position_id() == id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,120 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bitfinex::positions::Position;
|
use bitfinex::positions::Position;
|
||||||
|
|
||||||
use crate::events::Event;
|
use crate::events::{Event, EventKind, EventMetadata, SignalKind};
|
||||||
use crate::positions::PositionWrapper;
|
|
||||||
use crate::pairs::PairStatus;
|
use crate::pairs::PairStatus;
|
||||||
|
use crate::positions::{PositionState, PositionWrapper};
|
||||||
|
|
||||||
pub trait Strategy {
|
pub trait Strategy {
|
||||||
fn position_on_new_tick(&self, position: &Position, status: &PairStatus) -> (PositionWrapper, Vec<Event>);
|
fn position_on_new_tick(
|
||||||
|
&self,
|
||||||
|
position: &Position,
|
||||||
|
status: &PairStatus,
|
||||||
|
) -> (PositionWrapper, Vec<Event>, Vec<SignalKind>);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TrailingStop {
|
||||||
|
stop_percentages: HashMap<u64, f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrailingStop {
|
||||||
|
const BREAK_EVEN_PERC: f64 = 0.2;
|
||||||
|
const MIN_PROFIT_PERC: f64 = TrailingStop::BREAK_EVEN_PERC + 0.3;
|
||||||
|
const GOOD_PROFIT_PERC: f64 = TrailingStop::MIN_PROFIT_PERC * 2.5;
|
||||||
|
const MAX_LOSS_PERC: f64 = -1.7;
|
||||||
|
|
||||||
|
const TAKER_FEE: f64 = 0.2;
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
TrailingStop {
|
||||||
|
stop_percentages: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn net_pl_percentage(pl: f64, fee: f64) -> f64 {
|
||||||
|
pl - fee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Strategy for TrailingStop {
|
||||||
|
fn position_on_new_tick(
|
||||||
|
&self,
|
||||||
|
position: &Position,
|
||||||
|
status: &PairStatus,
|
||||||
|
) -> (PositionWrapper, Vec<Event>, Vec<SignalKind>) {
|
||||||
|
let mut signals = vec![];
|
||||||
|
let pl_perc = TrailingStop::net_pl_percentage(position.pl_perc(), TrailingStop::TAKER_FEE);
|
||||||
|
let events = vec![];
|
||||||
|
|
||||||
|
let state = {
|
||||||
|
if pl_perc > TrailingStop::GOOD_PROFIT_PERC {
|
||||||
|
PositionState::Profit
|
||||||
|
} else if TrailingStop::MIN_PROFIT_PERC <= pl_perc
|
||||||
|
&& pl_perc < TrailingStop::GOOD_PROFIT_PERC
|
||||||
|
{
|
||||||
|
PositionState::MinimumProfit
|
||||||
|
} else if 0.0 <= pl_perc && pl_perc < TrailingStop::MIN_PROFIT_PERC {
|
||||||
|
PositionState::BreakEven
|
||||||
|
} else if TrailingStop::MAX_LOSS_PERC < pl_perc && pl_perc < 0.0 {
|
||||||
|
PositionState::Loss
|
||||||
|
} else {
|
||||||
|
signals.push(SignalKind::ClosePosition);
|
||||||
|
PositionState::Critical
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let opt_pre_pw = status.previous_pw(position.position_id());
|
||||||
|
let event_metadata = EventMetadata::new(Some(position.position_id()), None);
|
||||||
|
let pw = PositionWrapper::new(position.clone(), position.pl(), pl_perc, Some(state));
|
||||||
|
|
||||||
|
match opt_pre_pw {
|
||||||
|
Some(prev) => {
|
||||||
|
if prev.state() == Some(state) {
|
||||||
|
return (pw, events, signals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return (pw, events, signals),
|
||||||
|
};
|
||||||
|
|
||||||
|
let events = {
|
||||||
|
let mut events = vec![];
|
||||||
|
|
||||||
|
if state == PositionState::Profit {
|
||||||
|
events.push(Event::new(
|
||||||
|
EventKind::ReachedGoodProfit,
|
||||||
|
status.current_tick(),
|
||||||
|
Some(event_metadata),
|
||||||
|
));
|
||||||
|
} else if state == PositionState::MinimumProfit {
|
||||||
|
events.push(Event::new(
|
||||||
|
EventKind::ReachedMinProfit,
|
||||||
|
status.current_tick(),
|
||||||
|
Some(event_metadata),
|
||||||
|
));
|
||||||
|
} else if state == PositionState::BreakEven {
|
||||||
|
events.push(Event::new(
|
||||||
|
EventKind::ReachedBreakEven,
|
||||||
|
status.current_tick(),
|
||||||
|
Some(event_metadata),
|
||||||
|
));
|
||||||
|
} else if state == PositionState::Loss {
|
||||||
|
events.push(Event::new(
|
||||||
|
EventKind::ReachedLoss,
|
||||||
|
status.current_tick(),
|
||||||
|
Some(event_metadata),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
events.push(Event::new(
|
||||||
|
EventKind::ReachedMaxLoss,
|
||||||
|
status.current_tick(),
|
||||||
|
Some(event_metadata),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
events
|
||||||
|
};
|
||||||
|
|
||||||
|
return (pw, events, signals);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user