other traits and shit
This commit is contained in:
parent
78b57b3899
commit
ae648b70a4
37
rustybot/Cargo.lock
generated
37
rustybot/Cargo.lock
generated
@ -15,6 +15,15 @@ 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 = "aho-corasick"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.42"
|
version = "0.1.42"
|
||||||
@ -958,6 +967,24 @@ version = "0.1.57"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
"thread_local",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "remove_dir_all"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
@ -1030,6 +1057,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"bitfinex",
|
"bitfinex",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"regex",
|
||||||
"tokio 0.2.24",
|
"tokio 0.2.24",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
]
|
]
|
||||||
@ -1195,6 +1223,15 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -11,4 +11,5 @@ 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"
|
async-trait = "0.1"
|
||||||
|
regex = "1"
|
@ -1,19 +1,26 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::convert::TryFrom;
|
||||||
|
use std::fmt::{Display, Error, Formatter};
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use crate::BoxError;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Hash)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct Symbol {
|
pub struct Symbol {
|
||||||
name: Cow<'static, str>
|
name: Cow<'static, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> From<S> for Symbol where S: Into<String> {
|
impl<S> From<S> for Symbol
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
fn from(item: S) -> Self {
|
fn from(item: S) -> Self {
|
||||||
Symbol::new(item.into())
|
Symbol::new(item.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Symbol {
|
impl Symbol {
|
||||||
pub const XMR: Symbol = Symbol::new_static("XMR");
|
pub const XMR: Symbol = Symbol::new_static("XMR");
|
||||||
pub const BTC: Symbol = Symbol::new_static("BTC");
|
pub const BTC: Symbol = Symbol::new_static("BTC");
|
||||||
@ -24,11 +31,15 @@ impl Symbol {
|
|||||||
pub const EUR: Symbol = Symbol::new_static("EUR");
|
pub const EUR: Symbol = Symbol::new_static("EUR");
|
||||||
|
|
||||||
pub fn new(name: String) -> Self {
|
pub fn new(name: String) -> Self {
|
||||||
Symbol { name: Cow::from(name) }
|
Symbol {
|
||||||
|
name: Cow::from(name),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn new_static(name: &'static str) -> Self {
|
pub const fn new_static(name: &'static str) -> Self {
|
||||||
Symbol { name: Cow::Borrowed(name) }
|
Symbol {
|
||||||
|
name: Cow::Borrowed(name),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
@ -72,6 +83,23 @@ impl Into<String> for SymbolPair {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for SymbolPair {
|
||||||
|
type Error = BoxError;
|
||||||
|
|
||||||
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
|
const REGEX: &str = r"^[t|f](?P<base>\w{3,4}):?(?P<quote>\w{3,4})";
|
||||||
|
|
||||||
|
let captures = Regex::new(REGEX)?.captures(&value).ok_or("Invalid input")?;
|
||||||
|
let quote = captures.name("quote").ok_or("Quote not found")?.as_str();
|
||||||
|
let base = captures.name("base").ok_or("Base not found")?.as_str();
|
||||||
|
|
||||||
|
Ok(SymbolPair {
|
||||||
|
quote: quote.into(),
|
||||||
|
base: base.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for SymbolPair {
|
impl Display for SymbolPair {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}{}", self.base, self.quote)
|
write!(f, "{}{}", self.base, self.quote)
|
||||||
@ -96,7 +124,13 @@ struct Balance {
|
|||||||
|
|
||||||
impl Balance {
|
impl Balance {
|
||||||
pub fn new(pair: SymbolPair, base_price: f64, base_amount: f64, wallet: WalletKind) -> Self {
|
pub fn new(pair: SymbolPair, base_price: f64, base_amount: f64, wallet: WalletKind) -> Self {
|
||||||
Balance { pair, base_price, base_amount, quote_equivalent: base_amount * base_price, wallet }
|
Balance {
|
||||||
|
pair,
|
||||||
|
base_price,
|
||||||
|
base_amount,
|
||||||
|
quote_equivalent: base_amount * base_price,
|
||||||
|
wallet,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pair(&self) -> &SymbolPair {
|
pub fn pair(&self) -> &SymbolPair {
|
||||||
@ -123,7 +157,10 @@ struct BalanceGroup {
|
|||||||
|
|
||||||
impl BalanceGroup {
|
impl BalanceGroup {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
BalanceGroup { balances: Vec::new(), quote_equivalent: 0f64 }
|
BalanceGroup {
|
||||||
|
balances: Vec::new(),
|
||||||
|
quote_equivalent: 0f64,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_balance(&mut self, balance: &Balance) {
|
pub fn add_balance(&mut self, balance: &Balance) {
|
||||||
@ -133,7 +170,8 @@ impl BalanceGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn currency_names(&self) -> Vec<String> {
|
pub fn currency_names(&self) -> Vec<String> {
|
||||||
self.balances.iter()
|
self.balances
|
||||||
|
.iter()
|
||||||
.map(|x| x.pair().base().name().into())
|
.map(|x| x.pair().base().name().into())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -142,6 +180,3 @@ impl BalanceGroup {
|
|||||||
&self.balances
|
&self.balances
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use tokio::stream::StreamExt;
|
|||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
use crate::pairs::PairStatus;
|
use crate::pairs::PairStatus;
|
||||||
use crate::positions::{Position, PositionState};
|
use crate::positions::{Position, PositionProfitState, PositionState};
|
||||||
use crate::BoxError;
|
use crate::BoxError;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -78,20 +78,20 @@ 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:
|
profit_state_handlers:
|
||||||
HashMap<PositionState, Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>>,
|
HashMap<PositionProfitState, 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: Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>,
|
on_any_profit_state_handlers: Vec<Box<dyn Fn(&Position, &PairStatus) -> JoinHandle<()>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventDispatcher {
|
impl EventDispatcher {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
EventDispatcher {
|
EventDispatcher {
|
||||||
event_handlers: HashMap::new(),
|
event_handlers: HashMap::new(),
|
||||||
position_state_handlers: HashMap::new(),
|
profit_state_handlers: HashMap::new(),
|
||||||
on_any_event_handlers: Vec::new(),
|
on_any_event_handlers: Vec::new(),
|
||||||
on_any_position_state_handlers: Vec::new(),
|
on_any_profit_state_handlers: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,13 +108,15 @@ impl EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_position_state_handlers(&self, position: &Position, status: &PairStatus) {
|
pub fn call_position_state_handlers(&self, position: &Position, status: &PairStatus) {
|
||||||
if let Some(functions) = self.position_state_handlers.get(&position.state()) {
|
if let Some(profit_state) = &position.profit_state() {
|
||||||
for f in functions {
|
if let Some(functions) = self.profit_state_handlers.get(profit_state) {
|
||||||
f(position, status);
|
for f in functions {
|
||||||
|
f(position, status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for f in &self.on_any_position_state_handlers {
|
for f in &self.on_any_profit_state_handlers {
|
||||||
f(position, status);
|
f(position, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,18 +140,18 @@ impl EventDispatcher {
|
|||||||
|
|
||||||
pub fn register_positionstate_handler<F: 'static, Fut: 'static>(
|
pub fn register_positionstate_handler<F: 'static, Fut: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: PositionState,
|
state: PositionProfitState,
|
||||||
f: F,
|
f: F,
|
||||||
) where
|
) where
|
||||||
F: Fn(&Position, &PairStatus) -> Fut,
|
F: Fn(&Position, &PairStatus) -> Fut,
|
||||||
Fut: Future<Output = ()> + Send,
|
Fut: Future<Output = ()> + Send,
|
||||||
{
|
{
|
||||||
match state {
|
match state {
|
||||||
PositionState::Any => self
|
// PositionProfitState::Any => self
|
||||||
.on_any_position_state_handlers
|
// .on_any_position_state_handlers
|
||||||
.push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
|
// .push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
|
||||||
_ => self
|
_ => self
|
||||||
.position_state_handlers
|
.profit_state_handlers
|
||||||
.entry(state)
|
.entry(state)
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
|
.push(Box::new(move |p, s| tokio::spawn(f(&p, s)))),
|
||||||
|
@ -4,6 +4,7 @@ use crate::currency::{Symbol, SymbolPair};
|
|||||||
pub struct Position {
|
pub struct Position {
|
||||||
pair: SymbolPair,
|
pair: SymbolPair,
|
||||||
state: PositionState,
|
state: PositionState,
|
||||||
|
profit_state: Option<PositionProfitState>,
|
||||||
amount: f64,
|
amount: f64,
|
||||||
base_price: f64,
|
base_price: f64,
|
||||||
pl: f64,
|
pl: f64,
|
||||||
@ -36,12 +37,22 @@ impl Position {
|
|||||||
position_id,
|
position_id,
|
||||||
creation_date: None,
|
creation_date: None,
|
||||||
creation_update: None,
|
creation_update: None,
|
||||||
|
profit_state: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_creation_date(mut self, creation_date: u64) -> Self {
|
pub fn with_creation_date(mut self, creation_date: Option<u64>) -> Self {
|
||||||
self.creation_date = Some(creation_date);
|
self.creation_date = creation_date;
|
||||||
self.creation_update = Some(creation_date);
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_creation_update(mut self, creation_update: Option<u64>) -> Self {
|
||||||
|
self.creation_update = creation_update;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_profit_state(mut self, profit_state: Option<PositionProfitState>) -> Self {
|
||||||
|
self.profit_state = profit_state;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +80,9 @@ impl Position {
|
|||||||
pub fn position_id(&self) -> u64 {
|
pub fn position_id(&self) -> u64 {
|
||||||
self.position_id
|
self.position_id
|
||||||
}
|
}
|
||||||
|
pub fn profit_state(&self) -> Option<PositionProfitState> {
|
||||||
|
self.profit_state
|
||||||
|
}
|
||||||
pub fn creation_date(&self) -> Option<u64> {
|
pub fn creation_date(&self) -> Option<u64> {
|
||||||
self.creation_date
|
self.creation_date
|
||||||
}
|
}
|
||||||
@ -78,25 +92,27 @@ impl Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum PositionState {
|
pub enum PositionProfitState {
|
||||||
Critical,
|
Critical,
|
||||||
Loss,
|
Loss,
|
||||||
BreakEven,
|
BreakEven,
|
||||||
MinimumProfit,
|
MinimumProfit,
|
||||||
Profit,
|
Profit,
|
||||||
Closed,
|
|
||||||
Any,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositionState {
|
impl PositionProfitState {
|
||||||
fn color(self) -> String {
|
fn color(self) -> String {
|
||||||
match self {
|
match self {
|
||||||
PositionState::Any => "blue",
|
PositionProfitState::Critical | PositionProfitState::Loss => "red",
|
||||||
PositionState::Critical | PositionState::Loss => "red",
|
PositionProfitState::BreakEven => "yellow",
|
||||||
PositionState::BreakEven => "yellow",
|
PositionProfitState::MinimumProfit | PositionProfitState::Profit => "green",
|
||||||
PositionState::MinimumProfit | PositionState::Profit => "green",
|
|
||||||
PositionState::Closed => "gray",
|
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub enum PositionState {
|
||||||
|
Closed,
|
||||||
|
Open,
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
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::{Position, PositionState};
|
use crate::positions::{Position, PositionProfitState, PositionState};
|
||||||
|
|
||||||
pub trait Strategy {
|
pub trait Strategy {
|
||||||
fn position_on_new_tick(
|
fn position_on_new_tick(
|
||||||
@ -47,18 +47,18 @@ impl Strategy for TrailingStop {
|
|||||||
|
|
||||||
let state = {
|
let state = {
|
||||||
if pl_perc > TrailingStop::GOOD_PROFIT_PERC {
|
if pl_perc > TrailingStop::GOOD_PROFIT_PERC {
|
||||||
PositionState::Profit
|
PositionProfitState::Profit
|
||||||
} else if TrailingStop::MIN_PROFIT_PERC <= pl_perc
|
} else if TrailingStop::MIN_PROFIT_PERC <= pl_perc
|
||||||
&& pl_perc < TrailingStop::GOOD_PROFIT_PERC
|
&& pl_perc < TrailingStop::GOOD_PROFIT_PERC
|
||||||
{
|
{
|
||||||
PositionState::MinimumProfit
|
PositionProfitState::MinimumProfit
|
||||||
} else if 0.0 <= pl_perc && pl_perc < TrailingStop::MIN_PROFIT_PERC {
|
} else if 0.0 <= pl_perc && pl_perc < TrailingStop::MIN_PROFIT_PERC {
|
||||||
PositionState::BreakEven
|
PositionProfitState::BreakEven
|
||||||
} else if TrailingStop::MAX_LOSS_PERC < pl_perc && pl_perc < 0.0 {
|
} else if TrailingStop::MAX_LOSS_PERC < pl_perc && pl_perc < 0.0 {
|
||||||
PositionState::Loss
|
PositionProfitState::Loss
|
||||||
} else {
|
} else {
|
||||||
signals.push(SignalKind::ClosePosition);
|
signals.push(SignalKind::ClosePosition);
|
||||||
PositionState::Critical
|
PositionProfitState::Critical
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ impl Strategy for TrailingStop {
|
|||||||
|
|
||||||
match opt_pre_pw {
|
match opt_pre_pw {
|
||||||
Some(prev) => {
|
Some(prev) => {
|
||||||
if prev.state() == state {
|
if prev.profit_state() == Some(state) {
|
||||||
return (pw, events, signals);
|
return (pw, events, signals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,25 +79,25 @@ impl Strategy for TrailingStop {
|
|||||||
let events = {
|
let events = {
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
|
|
||||||
if state == PositionState::Profit {
|
if state == PositionProfitState::Profit {
|
||||||
events.push(Event::new(
|
events.push(Event::new(
|
||||||
EventKind::ReachedGoodProfit,
|
EventKind::ReachedGoodProfit,
|
||||||
status.current_tick(),
|
status.current_tick(),
|
||||||
Some(event_metadata),
|
Some(event_metadata),
|
||||||
));
|
));
|
||||||
} else if state == PositionState::MinimumProfit {
|
} else if state == PositionProfitState::MinimumProfit {
|
||||||
events.push(Event::new(
|
events.push(Event::new(
|
||||||
EventKind::ReachedMinProfit,
|
EventKind::ReachedMinProfit,
|
||||||
status.current_tick(),
|
status.current_tick(),
|
||||||
Some(event_metadata),
|
Some(event_metadata),
|
||||||
));
|
));
|
||||||
} else if state == PositionState::BreakEven {
|
} else if state == PositionProfitState::BreakEven {
|
||||||
events.push(Event::new(
|
events.push(Event::new(
|
||||||
EventKind::ReachedBreakEven,
|
EventKind::ReachedBreakEven,
|
||||||
status.current_tick(),
|
status.current_tick(),
|
||||||
Some(event_metadata),
|
Some(event_metadata),
|
||||||
));
|
));
|
||||||
} else if state == PositionState::Loss {
|
} else if state == PositionProfitState::Loss {
|
||||||
events.push(Event::new(
|
events.push(Event::new(
|
||||||
EventKind::ReachedLoss,
|
EventKind::ReachedLoss,
|
||||||
status.current_tick(),
|
status.current_tick(),
|
||||||
|
Loading…
Reference in New Issue
Block a user