222 lines
6.1 KiB
Rust
222 lines
6.1 KiB
Rust
pub mod order;
|
|
pub mod table_mgmt;
|
|
|
|
use hmac_sha256::HMAC;
|
|
use crate::RunningMode::*;
|
|
use crate::{API_KEY, API_KEY_TESTNET, RUNNING_MODE, SECRET_KEY, SECRET_KEY_TESTNET, FUTURES_URL, FUTURES_URL_TEST};
|
|
use crate::strategy_team::{AllData, TimeData};
|
|
use crate::database_control::*;
|
|
use rust_decimal::Decimal;
|
|
use sqlx::FromRow;
|
|
use hex::ToHex;
|
|
use crate::future::table_mgmt::select_listuped_positions;
|
|
|
|
#[derive(Debug, PartialEq, Clone, sqlx::Type)]
|
|
pub enum Position {
|
|
Long,
|
|
Short
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone, sqlx::Type)]
|
|
pub enum Status {
|
|
#[sqlx(rename = "listup")]
|
|
Listup,
|
|
#[sqlx(rename = "filled")]
|
|
Filled,
|
|
#[sqlx(rename = "partially_filled")]
|
|
PartiallyFilled
|
|
}
|
|
|
|
impl std::fmt::Display for Position {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(f, "{:?}", self)
|
|
}
|
|
}
|
|
|
|
pub struct EntryCoinInfo {
|
|
pub symbol: String,
|
|
pub close_time: i64,
|
|
pub registered_server_epoch: i64,
|
|
}
|
|
|
|
impl EntryCoinInfo {
|
|
fn new() -> EntryCoinInfo {
|
|
let a = EntryCoinInfo {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
registered_server_epoch: 0
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum ContractType {
|
|
Perpetual, // this is the target
|
|
CurrentMonth,
|
|
NextMonth,
|
|
CurrentQuarter,
|
|
NextQuarter,
|
|
PerpetualDelivering,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum ContractStatus {
|
|
PendingTrading, // this is the target
|
|
Trading,
|
|
PreDelivering,
|
|
Delivering,
|
|
Delivered,
|
|
PreSettle,
|
|
Settling,
|
|
Close,
|
|
}
|
|
|
|
#[derive(Debug, FromRow, Clone)]
|
|
pub struct FuturesExchangeInfo {
|
|
pub stepsize: Decimal,
|
|
pub ticksize: Decimal,
|
|
pub contract_type: ContractType,
|
|
pub contract_status: ContractStatus,
|
|
pub base_asset_precision: u32,
|
|
pub quote_precision: u32,
|
|
pub notional: Decimal
|
|
}
|
|
|
|
impl FuturesExchangeInfo {
|
|
fn new() -> FuturesExchangeInfo {
|
|
let a = FuturesExchangeInfo {
|
|
stepsize: Decimal::new(0, 8),
|
|
ticksize: Decimal::new(0, 8),
|
|
contract_type: ContractType::Perpetual,
|
|
contract_status: ContractStatus::Trading,
|
|
base_asset_precision: 0,
|
|
quote_precision: 0,
|
|
notional: Decimal::new(0, 8),
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct FuturesTradeFee {
|
|
user_level: Option<i32>,
|
|
taker_fee_percent: Decimal,
|
|
maker_fee_percent: Decimal,
|
|
}
|
|
|
|
impl FuturesTradeFee {
|
|
pub fn new() -> FuturesTradeFee {
|
|
let a = FuturesTradeFee {
|
|
user_level: None,
|
|
taker_fee_percent: Decimal::new(0, 8),
|
|
maker_fee_percent: Decimal::new(0, 8),
|
|
};
|
|
a
|
|
}
|
|
}
|
|
#[derive(Debug, FromRow, Clone)]
|
|
pub struct PositionCoinList {
|
|
pub id: u64,
|
|
pub order_type: String,
|
|
pub status: String,
|
|
pub symbol: String,
|
|
pub order_id: u64,
|
|
pub position: String,
|
|
pub registered_server_epoch: i64,
|
|
pub transact_time: i64,
|
|
pub close_time: i64,
|
|
pub used_usdt: Decimal,
|
|
pub expected_get_usdt: f64,
|
|
pub expected_usdt_profit: f64,
|
|
pub entry_price: Decimal,
|
|
pub current_price: Decimal,
|
|
pub base_qty_ordered: Decimal,
|
|
pub base_qty_fee_adjusted: Decimal,
|
|
pub pure_profit_percent: f64,
|
|
pub minimum_profit_percent: f64,
|
|
pub maximum_profit_percent: f64,
|
|
}
|
|
|
|
impl PositionCoinList {
|
|
fn new() -> PositionCoinList {
|
|
let a = PositionCoinList{
|
|
id: 0,
|
|
order_type: String::new(),
|
|
status: String::new(),
|
|
symbol: String::new(),
|
|
order_id: 0,
|
|
position: String::new(),
|
|
registered_server_epoch: 0,
|
|
transact_time: 0,
|
|
close_time: 0,
|
|
used_usdt: Decimal::new(0, 8),
|
|
expected_get_usdt: 0.0,
|
|
expected_usdt_profit: 0.0,
|
|
entry_price: Decimal::new(0, 8),
|
|
current_price: Decimal::new(0, 8),
|
|
base_qty_ordered: Decimal::new(0, 8),
|
|
base_qty_fee_adjusted: Decimal::new(0, 8),
|
|
pure_profit_percent: 0.0,
|
|
minimum_profit_percent: 0.0,
|
|
maximum_profit_percent: 0.0,
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
async fn hmac_signature(query: &mut String) {
|
|
// fetch time information from [time] table
|
|
let table_name = String::from("time");
|
|
let columns = String::from("*");
|
|
let condition = None;
|
|
let mut time_info = TimeData {
|
|
server_epoch: 0,
|
|
local_epoch: 0,
|
|
epoch_difference: 0,
|
|
server_ymdhs: String::new(),
|
|
local_ymdhs: String::new(),
|
|
last_server_epoch: 0,
|
|
last_server_ymdhs: String::new(),
|
|
};
|
|
|
|
let select_result = select_record(&table_name, &columns, &condition, &time_info)
|
|
.await
|
|
.unwrap();
|
|
let difference_epoch = select_result.first().unwrap().epoch_difference;
|
|
let server_epoch = select_result.first().unwrap().server_epoch;
|
|
|
|
// build query message
|
|
// local 시간이 server 시간보다 너무 앞서거나 뒤쳐지면 USER_DATA를 요청할 수 없으므로 local과 server 의 시간 차이만큼을 local에서 빼어 보정한 뒤
|
|
// 이를 timestamp로 사용한다.
|
|
let mut timestamp;
|
|
if difference_epoch >= 0 {
|
|
timestamp = (server_epoch as u128 + difference_epoch as u128).to_string();
|
|
} else if difference_epoch < 0 {
|
|
timestamp = (server_epoch as u128 + (difference_epoch * -1) as u128).to_string();
|
|
} else {
|
|
timestamp = server_epoch.to_string();
|
|
}
|
|
let recv_window_size = "30000".to_string(); // default: 5,000ms, Max: 60,000ms
|
|
|
|
let mut query_build = String::from("×tamp=");
|
|
query_build.push_str(×tamp);
|
|
query_build.push_str("&recvWindow=");
|
|
query_build.push_str(&recv_window_size);
|
|
|
|
let mut secret_key = String::new();
|
|
unsafe {
|
|
if RUNNING_MODE == TEST {
|
|
secret_key.push_str(SECRET_KEY_TESTNET);
|
|
} else {
|
|
secret_key.push_str(SECRET_KEY);
|
|
}
|
|
}
|
|
|
|
query.push_str(&query_build);
|
|
let signature = HMAC::mac(&query.as_bytes(), secret_key.as_bytes());
|
|
|
|
query.push_str("&signature=");
|
|
query.push_str(signature.encode_hex::<String>().as_str());
|
|
}
|