Thank you Clippy!
This commit is contained in:
parent
597dc57bd5
commit
e133092831
@ -208,7 +208,7 @@ impl BitfinexConnector {
|
|||||||
if e.to_string().contains("nonce: small") {
|
if e.to_string().contains("nonce: small") {
|
||||||
return RetryPolicy::WaitRetry(Duration::from_millis(1));
|
return RetryPolicy::WaitRetry(Duration::from_millis(1));
|
||||||
}
|
}
|
||||||
return RetryPolicy::ForwardError(e);
|
RetryPolicy::ForwardError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(api_key: &str, api_secret: &str) -> Self {
|
pub fn new(api_key: &str, api_secret: &str) -> Self {
|
||||||
@ -218,16 +218,14 @@ impl BitfinexConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn format_trading_pair(pair: &SymbolPair) -> String {
|
fn format_trading_pair(pair: &SymbolPair) -> String {
|
||||||
if pair.to_string().to_lowercase().contains("test") {
|
if pair.to_string().to_lowercase().contains("test")
|
||||||
format!("{}:{}", pair.base(), pair.quote())
|
|| pair.to_string().to_lowercase().contains("f0")
|
||||||
} else {
|
{
|
||||||
if pair.to_string().to_lowercase().contains("f0") {
|
|
||||||
format!("{}:{}", pair.base(), pair.quote())
|
format!("{}:{}", pair.base(), pair.quote())
|
||||||
} else {
|
} else {
|
||||||
format!("{}{}", pair.base(), pair.quote())
|
format!("{}{}", pair.base(), pair.quote())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// retry to submit the request until it succeeds.
|
// retry to submit the request until it succeeds.
|
||||||
// the function may fail due to concurrent signed requests
|
// the function may fail due to concurrent signed requests
|
||||||
@ -736,7 +734,7 @@ impl From<&bitfinex::responses::TradeResponse> for Trade {
|
|||||||
price: response.execution_price(),
|
price: response.execution_price(),
|
||||||
amount: response.execution_amount(),
|
amount: response.execution_amount(),
|
||||||
fee,
|
fee,
|
||||||
fee_currency: Symbol::new(response.symbol().to_owned().clone()),
|
fee_currency: Symbol::new(response.symbol().to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,13 +44,10 @@ impl PriceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_message(&mut self, message: ActorMessage) -> Result<(), BoxError> {
|
pub async fn handle_message(&mut self, message: ActorMessage) -> Result<(), BoxError> {
|
||||||
match message.message {
|
if let Message::Update { tick } = message.message {
|
||||||
Message::Update { tick } => {
|
|
||||||
let a = self.update(tick).await?;
|
let a = self.update(tick).await?;
|
||||||
self.add_entry(a);
|
self.add_entry(a);
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(message
|
Ok(message
|
||||||
.respond_to
|
.respond_to
|
||||||
@ -247,11 +244,7 @@ impl PositionManager {
|
|||||||
|
|
||||||
Some(positions) => {
|
Some(positions) => {
|
||||||
// checking if there are positions open for our pair
|
// checking if there are positions open for our pair
|
||||||
match positions
|
match positions.into_iter().find(|x| x.pair() == &self.pair) {
|
||||||
.into_iter()
|
|
||||||
.filter(|x| x.pair() == &self.pair)
|
|
||||||
.next()
|
|
||||||
{
|
|
||||||
// no open positions for our pair, setting active position to none
|
// no open positions for our pair, setting active position to none
|
||||||
None => {
|
None => {
|
||||||
self.active_position = None;
|
self.active_position = None;
|
||||||
@ -300,10 +293,7 @@ impl PositionManager {
|
|||||||
None => self.current_tick() - 1,
|
None => self.current_tick() - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.positions_history
|
self.positions_history.get(&tick).filter(|x| x.id() == id)
|
||||||
.get(&tick)
|
|
||||||
.filter(|x| x.id() == id)
|
|
||||||
.and_then(|x| Some(x))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,13 +411,14 @@ impl OrderManager {
|
|||||||
if let Some(position) = open_positions.into_iter().find(|x| x.id() == position_id) {
|
if let Some(position) = open_positions.into_iter().find(|x| x.id() == position_id) {
|
||||||
let opt_position_order = open_orders
|
let opt_position_order = open_orders
|
||||||
.iter()
|
.iter()
|
||||||
.find(|x| x.details.amount().neg() == position.amount());
|
// avoid using direct equality, using error margin instead
|
||||||
|
.find(|x| (x.details.amount().neg() - position.amount()).abs() < 0.0000001);
|
||||||
|
|
||||||
// checking if the position has an open order.
|
// checking if the position has an open order.
|
||||||
// If so, don't do anything since the order is taken care of
|
// If so, don't do anything since the order is taken care of
|
||||||
// in the update phase.
|
// in the update phase.
|
||||||
// If no order is open, send an undercut limit order at the best current price.
|
// If no order is open, send an undercut limit order at the best current price.
|
||||||
if let None = opt_position_order {
|
if opt_position_order.is_none() {
|
||||||
// No open order, undercutting best price with limit order
|
// No open order, undercutting best price with limit order
|
||||||
let closing_price = self.best_closing_price(&position, &order_book);
|
let closing_price = self.best_closing_price(&position, &order_book);
|
||||||
|
|
||||||
@ -508,7 +499,6 @@ impl OrderManager {
|
|||||||
let avg = (bid + ask) / 2.0;
|
let avg = (bid + ask) / 2.0;
|
||||||
let delta = (ask - bid) / 10.0;
|
let delta = (ask - bid) / 10.0;
|
||||||
|
|
||||||
let closing_price = {
|
|
||||||
let closing_price = {
|
let closing_price = {
|
||||||
if position.is_short() {
|
if position.is_short() {
|
||||||
bid - delta
|
bid - delta
|
||||||
@ -526,9 +516,6 @@ impl OrderManager {
|
|||||||
} else {
|
} else {
|
||||||
closing_price
|
closing_price
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
closing_price
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,8 +537,8 @@ impl PairManager {
|
|||||||
Box::new(FastOrderStrategy::default()),
|
Box::new(FastOrderStrategy::default()),
|
||||||
),
|
),
|
||||||
position_manager: PositionManagerHandle::new(
|
position_manager: PositionManagerHandle::new(
|
||||||
pair.clone(),
|
pair,
|
||||||
client.clone(),
|
client,
|
||||||
Box::new(TrailingStop::new()),
|
Box::new(TrailingStop::new()),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -578,12 +565,9 @@ impl PairManager {
|
|||||||
// TODO: to move into Handler?
|
// TODO: to move into Handler?
|
||||||
if let Some(messages) = messages {
|
if let Some(messages) = messages {
|
||||||
for m in messages {
|
for m in messages {
|
||||||
match m {
|
if let Message::ClosePosition { position_id } = m {
|
||||||
Message::ClosePosition { position_id } => {
|
|
||||||
self.order_manager.close_position(position_id).await?;
|
self.order_manager.close_position(position_id).await?;
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,21 +578,19 @@ impl PairManager {
|
|||||||
pub struct ExchangeManager {
|
pub struct ExchangeManager {
|
||||||
kind: ExchangeDetails,
|
kind: ExchangeDetails,
|
||||||
pair_managers: Vec<PairManager>,
|
pair_managers: Vec<PairManager>,
|
||||||
client: Client,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExchangeManager {
|
impl ExchangeManager {
|
||||||
pub fn new(kind: &ExchangeDetails, pairs: &Vec<SymbolPair>) -> Self {
|
pub fn new(kind: &ExchangeDetails, pairs: &[SymbolPair]) -> Self {
|
||||||
let client = Client::new(kind);
|
let client = Client::new(kind);
|
||||||
let pair_managers = pairs
|
let pair_managers = pairs
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|x| PairManager::new(x.clone(), client.clone()))
|
.map(|x| PairManager::new(x.clone(), client.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
kind: kind.clone(),
|
kind: kind.clone(),
|
||||||
pair_managers,
|
pair_managers,
|
||||||
client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +602,7 @@ impl ExchangeManager {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// execute the futures
|
// execute the futures
|
||||||
while let Some(_) = futures.next().await {}
|
while futures.next().await.is_some() {}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -139,18 +139,6 @@ impl OrderDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exchange(&self) -> Exchange {
|
|
||||||
self.exchange
|
|
||||||
}
|
|
||||||
pub fn platform(&self) -> TradingPlatform {
|
|
||||||
self.platform
|
|
||||||
}
|
|
||||||
pub fn kind(&self) -> OrderKind {
|
|
||||||
self.kind
|
|
||||||
}
|
|
||||||
pub fn execution_timestamp(&self) -> u64 {
|
|
||||||
self.execution_timestamp
|
|
||||||
}
|
|
||||||
pub fn id(&self) -> u64 {
|
pub fn id(&self) -> u64 {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
@ -496,17 +484,6 @@ pub enum PositionProfitState {
|
|||||||
Profit,
|
Profit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositionProfitState {
|
|
||||||
fn color(self) -> String {
|
|
||||||
match self {
|
|
||||||
PositionProfitState::Critical | PositionProfitState::Loss => "red",
|
|
||||||
PositionProfitState::BreakEven => "yellow",
|
|
||||||
PositionProfitState::MinimumProfit | PositionProfitState::Profit => "green",
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub enum PositionState {
|
pub enum PositionState {
|
||||||
Closed,
|
Closed,
|
||||||
|
@ -7,11 +7,7 @@ use log::info;
|
|||||||
use crate::connectors::Connector;
|
use crate::connectors::Connector;
|
||||||
use crate::events::{Event, EventKind, EventMetadata, Message};
|
use crate::events::{Event, EventKind, EventMetadata, Message};
|
||||||
use crate::managers::OptionUpdate;
|
use crate::managers::OptionUpdate;
|
||||||
|
use crate::models::{ActiveOrder, OrderBook, OrderForm, OrderKind, Position, PositionProfitState};
|
||||||
use crate::models::{
|
|
||||||
ActiveOrder, OrderBook, OrderBookEntry, OrderForm, OrderKind, Position, PositionProfitState,
|
|
||||||
PositionState, TradingFees, TradingPlatform,
|
|
||||||
};
|
|
||||||
use crate::BoxError;
|
use crate::BoxError;
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
@ -159,9 +155,9 @@ impl PositionStrategy for TrailingStop {
|
|||||||
&& pl_perc < TrailingStop::GOOD_PROFIT_PERC
|
&& pl_perc < TrailingStop::GOOD_PROFIT_PERC
|
||||||
{
|
{
|
||||||
PositionProfitState::MinimumProfit
|
PositionProfitState::MinimumProfit
|
||||||
} else if 0.0 <= pl_perc && pl_perc < TrailingStop::MIN_PROFIT_PERC {
|
} else if (0.0..TrailingStop::MIN_PROFIT_PERC).contains(&pl_perc) {
|
||||||
PositionProfitState::BreakEven
|
PositionProfitState::BreakEven
|
||||||
} else if TrailingStop::MAX_LOSS_PERC < pl_perc && pl_perc < 0.0 {
|
} else if (TrailingStop::MAX_LOSS_PERC..0.0).contains(&pl_perc) {
|
||||||
PositionProfitState::Loss
|
PositionProfitState::Loss
|
||||||
} else {
|
} else {
|
||||||
PositionProfitState::Critical
|
PositionProfitState::Critical
|
||||||
@ -170,7 +166,7 @@ impl PositionStrategy for TrailingStop {
|
|||||||
|
|
||||||
let opt_prev_position = positions_history.get(&(current_tick - 1));
|
let opt_prev_position = positions_history.get(&(current_tick - 1));
|
||||||
let event_metadata = EventMetadata::new(Some(position.id()), None);
|
let event_metadata = EventMetadata::new(Some(position.id()), None);
|
||||||
let new_position = position.clone().with_profit_state(Some(state));
|
let new_position = position.with_profit_state(Some(state));
|
||||||
|
|
||||||
match opt_prev_position {
|
match opt_prev_position {
|
||||||
Some(prev) => {
|
Some(prev) => {
|
||||||
@ -219,7 +215,7 @@ impl PositionStrategy for TrailingStop {
|
|||||||
events
|
events
|
||||||
};
|
};
|
||||||
|
|
||||||
return (new_position, Some(events), None);
|
(new_position, Some(events), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_tick(
|
fn post_tick(
|
||||||
@ -233,14 +229,9 @@ impl PositionStrategy for TrailingStop {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// if critical, early return with close position
|
// if critical, early return with close position
|
||||||
if let Some(profit_state) = position.profit_state() {
|
if let Some(PositionProfitState::Critical) = position.profit_state() {
|
||||||
match profit_state {
|
|
||||||
PositionProfitState::Critical => {
|
|
||||||
info!("Maximum loss reached. Closing position.");
|
info!("Maximum loss reached. Closing position.");
|
||||||
return (position, None, Some(vec![close_message]));
|
return (position, None, Some(vec![close_message]));
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// let's check if we surpassed an existing stop percentage
|
// let's check if we surpassed an existing stop percentage
|
||||||
@ -270,12 +261,6 @@ impl Default for FastOrderStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FastOrderStrategy {
|
|
||||||
pub fn new(threshold: f64) -> Self {
|
|
||||||
Self { threshold }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OrderStrategy for FastOrderStrategy {
|
impl OrderStrategy for FastOrderStrategy {
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
"Fast order strategy".into()
|
"Fast order strategy".into()
|
||||||
@ -310,7 +295,7 @@ impl OrderStrategy for FastOrderStrategy {
|
|||||||
order: OrderForm::new(
|
order: OrderForm::new(
|
||||||
order.symbol.clone(),
|
order.symbol.clone(),
|
||||||
OrderKind::Market {},
|
OrderKind::Market {},
|
||||||
order.details.platform().clone(),
|
*order.details.platform(),
|
||||||
order.details.amount(),
|
order.details.amount(),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user