order closing working
This commit is contained in:
parent
a1354c2862
commit
a1d905ebea
@ -1,11 +1,14 @@
|
|||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bitfinex::api::Bitfinex;
|
use bitfinex::api::Bitfinex;
|
||||||
use bitfinex::orders::OrderMeta;
|
use bitfinex::orders::{OrderMeta, OrderResponse};
|
||||||
use bitfinex::ticker::TradingPairTicker;
|
use bitfinex::ticker::TradingPairTicker;
|
||||||
|
use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::currency::SymbolPair;
|
use crate::currency::SymbolPair;
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
@ -13,7 +16,6 @@ use crate::models::{
|
|||||||
PriceTicker,
|
PriceTicker,
|
||||||
};
|
};
|
||||||
use crate::BoxError;
|
use crate::BoxError;
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
|
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
|
||||||
pub enum ExchangeKind {
|
pub enum ExchangeKind {
|
||||||
@ -65,6 +67,10 @@ impl Client {
|
|||||||
pub async fn order_book(&self, pair: &SymbolPair) -> Result<OrderBook, BoxError> {
|
pub async fn order_book(&self, pair: &SymbolPair) -> Result<OrderBook, BoxError> {
|
||||||
self.inner.order_book(pair).await
|
self.inner.order_book(pair).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn cancel_order(&self, order: &ActiveOrder) -> Result<ActiveOrder, BoxError> {
|
||||||
|
self.inner.cancel_order(order).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -75,6 +81,7 @@ pub trait Connector: Send + Sync {
|
|||||||
async fn order_book(&self, pair: &SymbolPair) -> Result<OrderBook, BoxError>;
|
async fn order_book(&self, pair: &SymbolPair) -> Result<OrderBook, BoxError>;
|
||||||
async fn active_orders(&self, pair: &SymbolPair) -> Result<Vec<ActiveOrder>, BoxError>;
|
async fn active_orders(&self, pair: &SymbolPair) -> Result<Vec<ActiveOrder>, BoxError>;
|
||||||
async fn submit_order(&self, order: OrderForm) -> Result<ActiveOrder, BoxError>;
|
async fn submit_order(&self, order: OrderForm) -> Result<ActiveOrder, BoxError>;
|
||||||
|
async fn cancel_order(&self, order: &ActiveOrder) -> Result<ActiveOrder, BoxError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for dyn Connector {
|
impl Debug for dyn Connector {
|
||||||
@ -169,21 +176,7 @@ impl Connector for BitfinexConnector {
|
|||||||
|
|
||||||
let response = self.bfx.orders.submit_order(&order_form).await?;
|
let response = self.bfx.orders.submit_order(&order_form).await?;
|
||||||
|
|
||||||
Ok(ActiveOrder {
|
Ok(response.try_into()?)
|
||||||
id: response.id(),
|
|
||||||
group_id: response.gid(),
|
|
||||||
client_id: response.cid(),
|
|
||||||
symbol: SymbolPair::from_str(response.symbol())?,
|
|
||||||
creation_timestamp: response.mts_create(),
|
|
||||||
update_timestamp: response.mts_update(),
|
|
||||||
amount: response.amount(),
|
|
||||||
amount_original: response.amount_orig(),
|
|
||||||
order_type: (&response.order_type()).into(),
|
|
||||||
previous_order_type: response.prev_order_type().map(|x| (&x).into()),
|
|
||||||
price: response.price(),
|
|
||||||
price_avg: response.price_avg(),
|
|
||||||
hidden: response.hidden(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn order_book(&self, pair: &SymbolPair) -> Result<OrderBook, BoxError> {
|
async fn order_book(&self, pair: &SymbolPair) -> Result<OrderBook, BoxError> {
|
||||||
@ -207,6 +200,43 @@ impl Connector for BitfinexConnector {
|
|||||||
|
|
||||||
Ok(OrderBook::new(pair.clone()).with_entries(entries))
|
Ok(OrderBook::new(pair.clone()).with_entries(entries))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn cancel_order(&self, order: &ActiveOrder) -> Result<ActiveOrder, BoxError> {
|
||||||
|
let date = DateTime::<Utc>::from_utc(
|
||||||
|
NaiveDateTime::from_timestamp(order.update_timestamp as i64, 0),
|
||||||
|
Utc,
|
||||||
|
);
|
||||||
|
let cancel_form = bitfinex::orders::CancelOrderForm::new(order.id, order.client_id, date);
|
||||||
|
|
||||||
|
Ok(self
|
||||||
|
.bfx
|
||||||
|
.orders
|
||||||
|
.cancel_order(&cancel_form)
|
||||||
|
.await?
|
||||||
|
.try_into()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<bitfinex::orders::OrderResponse> for ActiveOrder {
|
||||||
|
type Error = BoxError;
|
||||||
|
|
||||||
|
fn try_from(response: OrderResponse) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
id: response.id(),
|
||||||
|
group_id: response.gid(),
|
||||||
|
client_id: response.cid(),
|
||||||
|
symbol: SymbolPair::from_str(response.symbol())?,
|
||||||
|
creation_timestamp: response.mts_create(),
|
||||||
|
update_timestamp: response.mts_update(),
|
||||||
|
amount: response.amount(),
|
||||||
|
amount_original: response.amount_orig(),
|
||||||
|
order_type: (&response.order_type()).into(),
|
||||||
|
previous_order_type: response.prev_order_type().map(|x| (&x).into()),
|
||||||
|
price: response.price(),
|
||||||
|
price_avg: response.price_avg(),
|
||||||
|
hidden: response.hidden(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryInto<Position> for bitfinex::positions::Position {
|
impl TryInto<Position> for bitfinex::positions::Position {
|
||||||
|
@ -449,8 +449,15 @@ impl OrderManager {
|
|||||||
// TODO FIXME
|
// TODO FIXME
|
||||||
match order_kind {
|
match order_kind {
|
||||||
OrderKind::Market => {
|
OrderKind::Market => {
|
||||||
self.submit_market_order(1.0, position.amount().neg())
|
info!("Closing open order with a market order.");
|
||||||
.await?;
|
if let Ok(_) = self
|
||||||
|
.submit_market_order(1.0, position.amount().neg())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// cancel active order
|
||||||
|
info!("Cancelling open order #{}", open_order.id);
|
||||||
|
self.client.cancel_order(open_order).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -495,7 +502,7 @@ impl OrderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn submit_limit_order(
|
pub async fn submit_limit_order(
|
||||||
&mut self,
|
&self,
|
||||||
closing_price: f64,
|
closing_price: f64,
|
||||||
amount: f64,
|
amount: f64,
|
||||||
) -> Result<ActiveOrder, BoxError> {
|
) -> Result<ActiveOrder, BoxError> {
|
||||||
@ -510,7 +517,7 @@ impl OrderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn submit_exchange_limit_order(
|
pub async fn submit_exchange_limit_order(
|
||||||
&mut self,
|
&self,
|
||||||
closing_price: f64,
|
closing_price: f64,
|
||||||
amount: f64,
|
amount: f64,
|
||||||
) -> Result<ActiveOrder, BoxError> {
|
) -> Result<ActiveOrder, BoxError> {
|
||||||
@ -526,7 +533,7 @@ impl OrderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn submit_market_order(
|
pub async fn submit_market_order(
|
||||||
&mut self,
|
&self,
|
||||||
closing_price: f64,
|
closing_price: f64,
|
||||||
amount: f64,
|
amount: f64,
|
||||||
) -> Result<ActiveOrder, BoxError> {
|
) -> Result<ActiveOrder, BoxError> {
|
||||||
@ -541,7 +548,7 @@ impl OrderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn submit_exchange_market_order(
|
pub async fn submit_exchange_market_order(
|
||||||
&mut self,
|
&self,
|
||||||
closing_price: f64,
|
closing_price: f64,
|
||||||
amount: f64,
|
amount: f64,
|
||||||
) -> Result<ActiveOrder, BoxError> {
|
) -> Result<ActiveOrder, BoxError> {
|
||||||
|
@ -16,7 +16,7 @@ use crate::BoxError;
|
|||||||
* DEFINITIONS
|
* DEFINITIONS
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
pub trait PositionStrategy: DynClone + Send {
|
pub trait PositionStrategy: DynClone + Send + Sync {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
fn on_new_tick(
|
fn on_new_tick(
|
||||||
&self,
|
&self,
|
||||||
@ -31,7 +31,7 @@ impl Debug for dyn PositionStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait OrderStrategy: DynClone + Send {
|
pub trait OrderStrategy: DynClone + Send + Sync {
|
||||||
/// The name of the strategy, used for debugging purposes
|
/// The name of the strategy, used for debugging purposes
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
/// This method is called when the OrderManager checks the open orders on a new tick.
|
/// This method is called when the OrderManager checks the open orders on a new tick.
|
||||||
@ -235,11 +235,6 @@ impl OrderStrategy for FastOrderStrategy {
|
|||||||
// ask the manager to close the position with a market order
|
// ask the manager to close the position with a market order
|
||||||
let delta = (1.0 - (offer_comparison / order.price)) * 100.0;
|
let delta = (1.0 - (offer_comparison / order.price)) * 100.0;
|
||||||
|
|
||||||
debug!(
|
|
||||||
"Offer comp: {} | Our offer: {} | Current delta: {}",
|
|
||||||
offer_comparison, order.price, delta
|
|
||||||
);
|
|
||||||
|
|
||||||
if delta > self.threshold {
|
if delta > self.threshold {
|
||||||
messages.push(Message::ClosePosition {
|
messages.push(Message::ClosePosition {
|
||||||
position: active_position.clone(),
|
position: active_position.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user