a lot of stuff
This commit is contained in:
parent
d6cd0f1f20
commit
ea7c8394a3
@ -21,6 +21,15 @@ pub struct EventMetadata {
|
||||
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)]
|
||||
pub enum EventKind {
|
||||
NewMinimum,
|
||||
|
@ -32,12 +32,13 @@ impl PairStatus {
|
||||
}
|
||||
|
||||
pub fn add_position(&mut self, position: Position) {
|
||||
let (pw, events) = {
|
||||
let (pw, events, signals) = {
|
||||
match &self.strategy {
|
||||
Some(strategy) => strategy.position_on_new_tick(&position, &self),
|
||||
None => (
|
||||
PositionWrapper::new(position.clone(), position.pl(), position.pl_perc(), None),
|
||||
vec![],
|
||||
vec![],
|
||||
),
|
||||
}
|
||||
};
|
||||
@ -61,4 +62,14 @@ impl PairStatus {
|
||||
|
||||
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 crate::events::Event;
|
||||
use crate::positions::PositionWrapper;
|
||||
use crate::events::{Event, EventKind, EventMetadata, SignalKind};
|
||||
use crate::pairs::PairStatus;
|
||||
use crate::positions::{PositionState, PositionWrapper};
|
||||
|
||||
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