|
@@ -1,1072 +0,0 @@
|
|
|
-// use std::collections::{BTreeMap, HashMap};
|
|
|
|
|
-// use std::io::{Error, ErrorKind};
|
|
|
|
|
-// use std::str::FromStr;
|
|
|
|
|
-// use tokio::sync::mpsc::Sender;
|
|
|
|
|
-// use async_trait::async_trait;
|
|
|
|
|
-// use futures::stream::FuturesUnordered;
|
|
|
|
|
-// use futures::TryStreamExt;
|
|
|
|
|
-// use rust_decimal::Decimal;
|
|
|
|
|
-// use rust_decimal::prelude::FromPrimitive;
|
|
|
|
|
-// use serde::{Deserialize, Serialize};
|
|
|
|
|
-// use serde_json::json;
|
|
|
|
|
-// use tokio::time::Instant;
|
|
|
|
|
-// use tracing::{debug, error};
|
|
|
|
|
-// use exchanges::okx_swap_rest::OkxSwapRest;
|
|
|
|
|
-// use global::trace_stack::TraceStack;
|
|
|
|
|
-// use crate::exchange::ExchangeEnum;
|
|
|
|
|
-// use crate::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Ticker, utils};
|
|
|
|
|
-//
|
|
|
|
|
-// /// Okx交易所账户信息请求数据结构
|
|
|
|
|
-// /// - 接口`"/api/v5/account/balance"`
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapAccount
|
|
|
|
|
-// /// - `adj_eq`: String, 美金层面有效保证金
|
|
|
|
|
-// /// - `borrow_froz`: String, 账户美金层面潜在借币占用保证金
|
|
|
|
|
-// /// - `details`: Vec<SwapAccountDetails>, 各币种资产详细信息
|
|
|
|
|
-// /// - `imr`: String, 美金层面占用保证金
|
|
|
|
|
-// /// - `iso_eq`: String, 美金层面逐仓仓位权益
|
|
|
|
|
-// /// - `mgn_ratio`: String, 美金层面保证金率
|
|
|
|
|
-// /// - `mmr`: String, 美金层面维持保证金
|
|
|
|
|
-// /// - `notional_usd`: String, 以美金价值为单位的持仓数量,即仓位美金价值
|
|
|
|
|
-// /// - `ord_froz`: String, 美金层面全仓挂单占用保证金
|
|
|
|
|
-// /// - `total_eq`: String, 美金层面权益
|
|
|
|
|
-// /// - `u_time`: String, 账户信息的更新时间
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapAccountDetails
|
|
|
|
|
-// /// - `avail_bal`: Decimal, 可用余额
|
|
|
|
|
-// /// - `avail_eq`: Decimal, 可用保证金
|
|
|
|
|
-// /// - `cash_bal`: Decimal, 币种余额
|
|
|
|
|
-// /// - `ccy`: String, 币种
|
|
|
|
|
-// /// - `cross_liab`: String, 币种全仓负债额
|
|
|
|
|
-// /// - `dis_eq`: Decimal, 美金层面币种折算权益
|
|
|
|
|
-// /// - `eq`: Decimal, 币种总权益
|
|
|
|
|
-// /// - `eq_usd`: Decimal, 币种权益美金价值
|
|
|
|
|
-// /// - `fixed_bal`: Decimal, 币种冻结金额
|
|
|
|
|
-// /// - `frozen_bal`: Decimal, 币种占用金额
|
|
|
|
|
-// /// - `interest`:String, 计息,应扣未扣利息。
|
|
|
|
|
-// /// - `iso_eq`: Decimal, 币种逐仓仓位权益
|
|
|
|
|
-// /// - `iso_liab`: String, 逐仓未实现盈亏
|
|
|
|
|
-// /// - `iso_upl`: Decimal, 币种逐仓负债额
|
|
|
|
|
-// /// - `liab`: String, 币种负债额
|
|
|
|
|
-// /// - `max_loan`: String, 币种最大可借
|
|
|
|
|
-// /// - `mgn_ratio`: String, 保证金率
|
|
|
|
|
-// /// - `notional_lever`: Decimal, 币种杠杆倍数
|
|
|
|
|
-// /// - `ord_frozen`: Decimal, 挂单冻结数量
|
|
|
|
|
-// /// - `twap`: Decimal, 当前负债币种触发系统自动换币的风险
|
|
|
|
|
-// /// - `u_time`: String, 币种余额信息的更新时间
|
|
|
|
|
-// /// - `upl`: Decimal, 未实现盈亏
|
|
|
|
|
-// /// - `upl_liab`: String, 由于仓位未实现亏损导致的负债
|
|
|
|
|
-// /// - `stgy_eq`: Decimal, 策略权益
|
|
|
|
|
-// /// - `spot_in_use_amt`: String, 现货对冲占用数量
|
|
|
|
|
-// /// - `borrow_froz`: String, 币种美金层面潜在借币占用保证金
|
|
|
|
|
-// #[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// struct SwapAccount {
|
|
|
|
|
-// adj_eq: String,
|
|
|
|
|
-// borrow_froz: String,
|
|
|
|
|
-// details: Vec<SwapAccountDetails>,
|
|
|
|
|
-// imr: String,
|
|
|
|
|
-// iso_eq: String,
|
|
|
|
|
-// mgn_ratio: String,
|
|
|
|
|
-// mmr: String,
|
|
|
|
|
-// notional_usd: String,
|
|
|
|
|
-// ord_froz: String,
|
|
|
|
|
-// total_eq: String,
|
|
|
|
|
-// u_time: String,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// #[derive(Debug, Clone, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// struct SwapAccountDetails {
|
|
|
|
|
-// avail_bal: Decimal,
|
|
|
|
|
-// avail_eq: Decimal,
|
|
|
|
|
-// cash_bal: Decimal,
|
|
|
|
|
-// ccy: String,
|
|
|
|
|
-// cross_liab: String,
|
|
|
|
|
-// dis_eq: Decimal,
|
|
|
|
|
-// eq: Decimal,
|
|
|
|
|
-// eq_usd: Decimal,
|
|
|
|
|
-// fixed_bal: Decimal,
|
|
|
|
|
-// frozen_bal: Decimal,
|
|
|
|
|
-// interest: String,
|
|
|
|
|
-// iso_eq: Decimal,
|
|
|
|
|
-// iso_liab: String,
|
|
|
|
|
-// iso_upl: Decimal,
|
|
|
|
|
-// liab: String,
|
|
|
|
|
-// max_loan: String,
|
|
|
|
|
-// mgn_ratio: String,
|
|
|
|
|
-// notional_lever: Decimal,
|
|
|
|
|
-// ord_frozen: Decimal,
|
|
|
|
|
-// twap: Decimal,
|
|
|
|
|
-// u_time: String,
|
|
|
|
|
-// upl: Decimal,
|
|
|
|
|
-// upl_liab: String,
|
|
|
|
|
-// stgy_eq: Decimal,
|
|
|
|
|
-// spot_in_use_amt: String,
|
|
|
|
|
-// borrow_froz: String,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// /// Okx交易所持仓信息请求数据结构
|
|
|
|
|
-// /// - 接口`"/api/v5/account/positions"`
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapPosition
|
|
|
|
|
-// /// - `adl`: Decimal, 信号区
|
|
|
|
|
-// /// - `avail_pos`: Decimal, 可平仓数量,适用于 币币杠杆,交割/永续(开平仓模式)
|
|
|
|
|
-// /// - `avg_px`: Decimal, 开仓平均价
|
|
|
|
|
-// /// - `c_time`: String, 持仓创建时间
|
|
|
|
|
-// /// - `ccy`: String, 占用保证金的币种
|
|
|
|
|
-// /// - `delta_b_s`: String, 美金本位持仓仓位delta,仅适用于期权
|
|
|
|
|
-// /// - `delta_p_a`: String, 币本位持仓仓位delta,仅适用于期权
|
|
|
|
|
-// /// - `gamma_b_s`: String, 美金本位持仓仓位gamma,仅适用于期权
|
|
|
|
|
-// /// - `gamma_p_a`: String, 币本位持仓仓位gamma,仅适用于期权
|
|
|
|
|
-// /// - `imr`: String, 初始保证金,仅适用于全仓
|
|
|
|
|
-// /// - `inst_id`: String, 产品ID
|
|
|
|
|
-// /// - `inst_type`: String, 产品类型
|
|
|
|
|
-// /// - `interest`: Decimal, 利息,已经生成的未扣利息
|
|
|
|
|
-// /// - `idx_px`: Decimal, 最新指数价格
|
|
|
|
|
-// /// - `last`: Decimal, 最新成交价
|
|
|
|
|
-// /// - `usd_px`: String, 美金价格
|
|
|
|
|
-// /// - `be_px`: Decimal, 盈亏平衡价
|
|
|
|
|
-// /// - `lever`: Decimal, 杠杆倍数,不适用于期权
|
|
|
|
|
-// /// - `liab`: String, 负债额,仅适用于币币杠杆
|
|
|
|
|
-// /// - `liab_ccy`: String, 负债币种,仅适用于币币杠杆
|
|
|
|
|
-// /// - `liq_px`: Decimal, 预估强平价
|
|
|
|
|
-// /// - `mark_px`: Decimal, 最新标记价格
|
|
|
|
|
-// /// - `margin`: Decimal, 保证金余额,可增减,仅适用于逐仓
|
|
|
|
|
-// /// - `mgn_mode`: Decimal, 保证金模式
|
|
|
|
|
-// /// - `mgn_ratio`: Decimal, 保证金率
|
|
|
|
|
-// /// - `mmr`: Decimal, 维持保证金
|
|
|
|
|
-// /// - `notional_usd`: Decimal, 以美金价值为单位的持仓数量
|
|
|
|
|
-// /// - `opt_val`: String, 期权市值,仅适用于期权
|
|
|
|
|
-// /// - `p_time`: String,
|
|
|
|
|
-// /// - `pos`: Decimal, 持仓数量,逐仓自主划转模式下,转入保证金后会产生pos为0的仓位
|
|
|
|
|
-// /// - `pos_ccy`: String, 仓位资产币种,仅适用于币币杠杆仓位
|
|
|
|
|
-// /// - `pos_id`: Decimal, 持仓ID
|
|
|
|
|
-// /// - `pos_side`: String, 持仓方向
|
|
|
|
|
-// /// - `spot_in_use_amt`: String,
|
|
|
|
|
-// /// - `spot_in_use_ccy`: String,
|
|
|
|
|
-// /// - `theta_b_s`: String, 美金本位持仓仓位theta,仅适用于期权
|
|
|
|
|
-// /// - `theta_p_a`: String, 币本位持仓仓位theta,仅适用于期权
|
|
|
|
|
-// /// - `trade_id`: Decimal, 最新成交ID
|
|
|
|
|
-// /// - `biz_ref_id`: String, 外部业务id
|
|
|
|
|
-// /// - `biz_ref_type`: String, 外部业务类型
|
|
|
|
|
-// /// - `quote_bal`: Decimal, 计价币余额 ,适用于 币币杠杆(逐仓自主划转模式 和 一键借币模式)
|
|
|
|
|
-// /// - `base_bal`: Decimal, 交易币余额,适用于 币币杠杆(逐仓自主划转模式 和 一键借币模式)
|
|
|
|
|
-// /// - `base_borrowed`: String, 交易币已借,适用于 币币杠杆(逐仓一键借币模式)
|
|
|
|
|
-// /// - `base_interest`: String, 交易币计息,适用于 币币杠杆(逐仓一键借币模式)
|
|
|
|
|
-// /// - `quote_borrowed`: String, 计价币已借,适用于 币币杠杆(逐仓一键借币模式)
|
|
|
|
|
-// /// - `quote_interest`: String, 计价币计息,适用于 币币杠杆(逐仓一键借币模式)
|
|
|
|
|
-// /// - `u_time`: String, 最近一次持仓更新时间
|
|
|
|
|
-// /// - `upl`: Decimal, 未实现收益(以标记价格计算)
|
|
|
|
|
-// /// - `upl_last_px`: Decimal, 以最新成交价格计算的未实现收益,主要做展示使用,实际值还是 upl
|
|
|
|
|
-// /// - `upl_ratio`: Decimal, 未实现收益率(以标记价格计算
|
|
|
|
|
-// /// - `upl_ratio_last_px`: Decimal, 以最新成交价格计算的未实现收益率
|
|
|
|
|
-// /// - `vega_b_s`: String, 美金本位持仓仓位vega,仅适用于期权
|
|
|
|
|
-// /// - `vega_p_a`: String, 币本位持仓仓位vega,仅适用于期权
|
|
|
|
|
-// /// - `realized_pnl`: Decimal, 已实现收益
|
|
|
|
|
-// /// - `pnl`: Decimal, 平仓订单累计收益额
|
|
|
|
|
-// /// - `fee`: Decimal, 累计手续费金额,正数代表平台返佣 ,负数代表平台扣除
|
|
|
|
|
-// /// - `funding_fee`: Decimal, 累计资金费用
|
|
|
|
|
-// /// - `liq_penalty`: Decimal, 累计爆仓罚金,有值时为负数。
|
|
|
|
|
-// /// - `close_order_algo`: Vec<SwapPositionCloseOrderAlgo>, 平仓策略委托订单
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapPositionCloseOrderAlgo
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// - `algo_id`: String, 策略委托单ID
|
|
|
|
|
-// /// - `sl_trigger_px`: Decimal, 止损触发价
|
|
|
|
|
-// /// - `sl_trigger_px_type`: String, 止损触发价类型
|
|
|
|
|
-// /// - `tp_trigger_px`: Decimal, 止盈委托价
|
|
|
|
|
-// /// - `tp_trigger_px_type`: String, 止盈触发价类型
|
|
|
|
|
-// /// - `close_fraction`: Decimal, 策略委托触发时
|
|
|
|
|
-// #[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// pub struct SwapPosition {
|
|
|
|
|
-// pub adl: String,
|
|
|
|
|
-// pub avail_pos: String,
|
|
|
|
|
-// pub avg_px: Decimal,
|
|
|
|
|
-// pub c_time: String,
|
|
|
|
|
-// pub ccy: String,
|
|
|
|
|
-// pub delta_b_s: String,
|
|
|
|
|
-// pub delta_p_a: String,
|
|
|
|
|
-// pub gamma_b_s: String,
|
|
|
|
|
-// pub gamma_p_a: String,
|
|
|
|
|
-// pub imr: String,
|
|
|
|
|
-// pub inst_id: String,
|
|
|
|
|
-// pub inst_type: String,
|
|
|
|
|
-// pub interest: String,
|
|
|
|
|
-// pub idx_px: String,
|
|
|
|
|
-// pub last: String,
|
|
|
|
|
-// pub usd_px: String,
|
|
|
|
|
-// pub be_px: String,
|
|
|
|
|
-// pub lever: Decimal,
|
|
|
|
|
-// pub liab: String,
|
|
|
|
|
-// pub liab_ccy: String,
|
|
|
|
|
-// pub liq_px: String,
|
|
|
|
|
-// pub mark_px: String,
|
|
|
|
|
-// pub margin: String,
|
|
|
|
|
-// pub mgn_mode: String,
|
|
|
|
|
-// pub mgn_ratio: String,
|
|
|
|
|
-// pub mmr: String,
|
|
|
|
|
-// pub notional_usd: String,
|
|
|
|
|
-// pub opt_val: String,
|
|
|
|
|
-// pub pos: Decimal,
|
|
|
|
|
-// pub pos_ccy: String,
|
|
|
|
|
-// pub pos_id: String,
|
|
|
|
|
-// pub pos_side: String,
|
|
|
|
|
-// pub spot_in_use_amt: String,
|
|
|
|
|
-// pub spot_in_use_ccy: String,
|
|
|
|
|
-// pub theta_b_s: String,
|
|
|
|
|
-// pub theta_p_a: String,
|
|
|
|
|
-// pub trade_id: String,
|
|
|
|
|
-// pub biz_ref_id: String,
|
|
|
|
|
-// pub biz_ref_type: String,
|
|
|
|
|
-// pub quote_bal: String,
|
|
|
|
|
-// pub base_bal: String,
|
|
|
|
|
-// pub base_borrowed: String,
|
|
|
|
|
-// pub base_interest: String,
|
|
|
|
|
-// pub quote_borrowed: String,
|
|
|
|
|
-// pub quote_interest: String,
|
|
|
|
|
-// pub u_time: String,
|
|
|
|
|
-// pub upl: Decimal,
|
|
|
|
|
-// pub upl_last_px: String,
|
|
|
|
|
-// pub upl_ratio: String,
|
|
|
|
|
-// pub upl_ratio_last_px: String,
|
|
|
|
|
-// pub vega_b_s: String,
|
|
|
|
|
-// pub vega_p_a: String,
|
|
|
|
|
-// pub realized_pnl: String,
|
|
|
|
|
-// pub pnl: String,
|
|
|
|
|
-// pub fee: String,
|
|
|
|
|
-// pub funding_fee: String,
|
|
|
|
|
-// pub liq_penalty: String,
|
|
|
|
|
-// pub close_order_algo: Vec<SwapPositionCloseOrderAlgo>,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// #[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// pub struct SwapPositionCloseOrderAlgo {
|
|
|
|
|
-// pub algo_id: String,
|
|
|
|
|
-// pub sl_trigger_px: String,
|
|
|
|
|
-// pub sl_trigger_px_type: String,
|
|
|
|
|
-// pub tp_trigger_px: String,
|
|
|
|
|
-// pub tp_trigger_px_type: String,
|
|
|
|
|
-// pub close_fraction: String,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// /// Okx交易所行情信息请求数据结构
|
|
|
|
|
-// /// - 接口`"/api/v5/market/ticker"`
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapTicker
|
|
|
|
|
-// /// - `inst_type`: String, 产品类型
|
|
|
|
|
-// /// - `inst_id`: String, 产品ID
|
|
|
|
|
-// /// - `last`: Decimal, 最新成交价
|
|
|
|
|
-// /// - `last_sz`: Decimal, 最新成交的数量
|
|
|
|
|
-// /// - `ask_px`: Decimal, 卖一价
|
|
|
|
|
-// /// - `ask_sz`: Decimal, 卖一价的挂单数数量
|
|
|
|
|
-// /// - `bid_px`: Decimal, 买一价
|
|
|
|
|
-// /// - `bid_sz`: Decimal, 买一价的挂单数量
|
|
|
|
|
-// /// - `open24h`: Decimal, 24小时开盘价
|
|
|
|
|
-// /// - `high24h`: Decimal, 24小时最高价
|
|
|
|
|
-// /// - `low24h`: Decimal, 24小时最低价
|
|
|
|
|
-// /// - `vol_ccy24h`: Decimal, 24小时成交量,以币为单位
|
|
|
|
|
-// /// - `vol24h`: Decimal, 24小时成交量,以张为单位
|
|
|
|
|
-// /// - `ts`: String, ticker数据产生时间
|
|
|
|
|
-// /// - `sod_utc0`: Decimal, UTC 0 时开盘价
|
|
|
|
|
-// /// - `sod_utc8`: Decimal, UTC+8 时开盘价
|
|
|
|
|
-// #[derive(Debug, Clone, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// struct SwapTicker {
|
|
|
|
|
-// inst_type: String,
|
|
|
|
|
-// inst_id: String,
|
|
|
|
|
-// last: Decimal,
|
|
|
|
|
-// last_sz: Decimal,
|
|
|
|
|
-// ask_px: Decimal,
|
|
|
|
|
-// ask_sz: Decimal,
|
|
|
|
|
-// bid_px: Decimal,
|
|
|
|
|
-// bid_sz: Decimal,
|
|
|
|
|
-// open24h: Decimal,
|
|
|
|
|
-// high24h: Decimal,
|
|
|
|
|
-// low24h: Decimal,
|
|
|
|
|
-// vol_ccy24h: Decimal,
|
|
|
|
|
-// vol24h: Decimal,
|
|
|
|
|
-// ts: String,
|
|
|
|
|
-// sod_utc0: Decimal,
|
|
|
|
|
-// sod_utc8: Decimal,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// /// Okx交易所市场信息请求数据结构
|
|
|
|
|
-// /// - 接口`"/api/v5/public/instruments"`
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapMarket
|
|
|
|
|
-// /// - `alias`: String,
|
|
|
|
|
-// /// - `base_ccy`: String,
|
|
|
|
|
-// /// - `category`: String,
|
|
|
|
|
-// /// - `ct_mult`: Decimal,
|
|
|
|
|
-// /// - `ct_type`: String,
|
|
|
|
|
-// /// - `ct_val`: Decimal,
|
|
|
|
|
-// /// - `ct_val_ccy`: String,
|
|
|
|
|
-// /// - `exp_time`: String,
|
|
|
|
|
-// /// - `inst_family`: String,
|
|
|
|
|
-// /// - `inst_id`: String,
|
|
|
|
|
-// /// - `inst_type`: String,
|
|
|
|
|
-// /// - `lever`: Decimal,
|
|
|
|
|
-// /// - `list_time`: String,
|
|
|
|
|
-// /// - `lot_sz`: Decimal,
|
|
|
|
|
-// /// - `max_iceberg_sz`: Decimal,
|
|
|
|
|
-// /// - `max_lmt_sz`: Decimal,
|
|
|
|
|
-// /// - `max_mkt_sz`: Decimal,
|
|
|
|
|
-// /// - `max_stop_sz`: Decimal,
|
|
|
|
|
-// /// - `max_trigger_sz`: Decimal,
|
|
|
|
|
-// /// - `max_twap_sz`: Decimal,
|
|
|
|
|
-// /// - `min_sz`: Decimal,
|
|
|
|
|
-// /// - `opt_type`: String,
|
|
|
|
|
-// /// - `quote_ccy`: String,
|
|
|
|
|
-// /// - `settle_ccy`: String,
|
|
|
|
|
-// /// - `state`: String,
|
|
|
|
|
-// /// - `stk`: String,
|
|
|
|
|
-// /// - `tick_sz`: Decimal,
|
|
|
|
|
-// /// - `uly`: String,
|
|
|
|
|
-// #[derive(Debug, Clone, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// struct SwapMarket {
|
|
|
|
|
-// alias: String,
|
|
|
|
|
-// base_ccy: String,
|
|
|
|
|
-// category: String,
|
|
|
|
|
-// ct_mult: Decimal,
|
|
|
|
|
-// ct_type: String,
|
|
|
|
|
-// ct_val: Decimal,
|
|
|
|
|
-// ct_val_ccy: String,
|
|
|
|
|
-// exp_time: String,
|
|
|
|
|
-// inst_family: String,
|
|
|
|
|
-// inst_id: String,
|
|
|
|
|
-// inst_type: String,
|
|
|
|
|
-// lever: Decimal,
|
|
|
|
|
-// list_time: String,
|
|
|
|
|
-// lot_sz: Decimal,
|
|
|
|
|
-// max_iceberg_sz: Decimal,
|
|
|
|
|
-// max_lmt_sz: Decimal,
|
|
|
|
|
-// max_mkt_sz: Decimal,
|
|
|
|
|
-// max_stop_sz: Decimal,
|
|
|
|
|
-// max_trigger_sz: Decimal,
|
|
|
|
|
-// max_twap_sz: Decimal,
|
|
|
|
|
-// min_sz: Decimal,
|
|
|
|
|
-// opt_type: String,
|
|
|
|
|
-// quote_ccy: String,
|
|
|
|
|
-// settle_ccy: String,
|
|
|
|
|
-// state: String,
|
|
|
|
|
-// stk: String,
|
|
|
|
|
-// tick_sz: Decimal,
|
|
|
|
|
-// uly: String,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// /// Okx交易所订单信息请求数据结构
|
|
|
|
|
-// /// - 接口`"/api/v5/trade/order"`
|
|
|
|
|
-// ///
|
|
|
|
|
-// /// struct SwapOrder
|
|
|
|
|
-// /// - `inst_type`: String, 产品类型
|
|
|
|
|
-// /// - `inst_id`: String, 产品ID
|
|
|
|
|
-// /// - `ccy`: String, 保证金币种
|
|
|
|
|
-// /// - `ord_id`: String, 订单ID
|
|
|
|
|
-// /// - `cl_ord_id`: String, 客户自定义订单ID
|
|
|
|
|
-// /// - `tag`: String, 订单标签
|
|
|
|
|
-// /// - `px`: Decimal, 委托价格
|
|
|
|
|
-// /// - `px_usd`: String, 期权价格
|
|
|
|
|
-// /// - `px_vol`: String, 期权订单的隐含波动率
|
|
|
|
|
-// /// - `px_type`: String, 期权的价格类型
|
|
|
|
|
-// /// - `sz`: Decimal, 委托数量
|
|
|
|
|
-// /// - `pnl`: Decimal, 收益
|
|
|
|
|
-// /// - `ord_type`: String, 订单类型
|
|
|
|
|
-// /// - `side`: String, 订单方向
|
|
|
|
|
-// /// - `pos_side`: String, 持仓方向
|
|
|
|
|
-// /// - `td_mode`: String, 交易模式
|
|
|
|
|
-// /// - `acc_fill_sz`: Decimal, 累计成交数量
|
|
|
|
|
-// /// - `fill_px`: String, 最新成交价格,如果成交数量为0,该字段为""
|
|
|
|
|
-// /// - `trade_id`: String, 最新成交ID
|
|
|
|
|
-// /// - `fill_sz`: Decimal, 最新成交数量
|
|
|
|
|
-// /// - `fill_time`: String, 最新成交时间
|
|
|
|
|
-// /// - `source`: String, 订单来源
|
|
|
|
|
-// /// - `state`: String, 订单状态
|
|
|
|
|
-// /// - `avg_px`: Decimal, 成交均价,如果成交数量为0,该字段也为""
|
|
|
|
|
-// /// - `lever`: Decimal, 杠杆倍数
|
|
|
|
|
-// /// - `attach_algo_cl_ord_id`: String, 下单附带止盈止损时,客户自定义的策略订单ID
|
|
|
|
|
-// /// - `tp_trigger_px`: Decimal, 止盈触发价
|
|
|
|
|
-// /// - `tp_trigger_px_type`: String, 止盈触发价类型
|
|
|
|
|
-// /// - `tp_ord_px`: Decimal, 止盈委托价
|
|
|
|
|
-// /// - `sl_trigger_px`: Decimal, 止损触发价
|
|
|
|
|
-// /// - `sl_trigger_px_type`: String, 止损触发价类型
|
|
|
|
|
-// /// - `sl_ord_px`: Decimal, 止损委托价
|
|
|
|
|
-// /// - `stp_id`: String, 自成交保护ID
|
|
|
|
|
-// /// - `stp_mode`: String, 自成交保护模式
|
|
|
|
|
-// /// - `fee_ccy`: String, 交易手续费币种
|
|
|
|
|
-// /// - `fee`: Decimal, 手续费与返佣
|
|
|
|
|
-// /// - `rebate_ccy`: String, 返佣金币种
|
|
|
|
|
-// /// - `rebate`: String, 返佣金额,仅适用于币币和杠杆
|
|
|
|
|
-// /// - `tgt_ccy`: String, 币币市价单委托数量sz的单位
|
|
|
|
|
-// /// - `category`: String, 订单种类
|
|
|
|
|
-// /// - `reduce_only`: String, 是否只减仓
|
|
|
|
|
-// /// - `cancel_source`: String, 订单取消来源的原因枚举值代码
|
|
|
|
|
-// /// - `cancel_source_reason`: String, 订单取消来源的对应具体原因
|
|
|
|
|
-// /// - `quick_mgn_type`: String, 一键借币类型,仅适用于杠杆逐仓的一键借币模式
|
|
|
|
|
-// /// - `algo_cl_ord_id`: String, 客户自定义策略订单ID
|
|
|
|
|
-// /// - `algo_id`: String, 策略委托单ID,策略订单触发时有值,否则为""
|
|
|
|
|
-// /// - `u_time`: String, 订单状态更新时间
|
|
|
|
|
-// /// - `c_time`: String, 订单创建时间
|
|
|
|
|
-// #[derive(Debug, Clone, Deserialize, Serialize)]
|
|
|
|
|
-// #[serde(rename_all = "camelCase")]
|
|
|
|
|
-// pub struct SwapOrder {
|
|
|
|
|
-// inst_type: String,
|
|
|
|
|
-// inst_id: String,
|
|
|
|
|
-// ccy: String,
|
|
|
|
|
-// ord_id: String,
|
|
|
|
|
-// cl_ord_id: String,
|
|
|
|
|
-// tag: String,
|
|
|
|
|
-// px: Decimal,
|
|
|
|
|
-// px_usd: String,
|
|
|
|
|
-// px_vol: String,
|
|
|
|
|
-// px_type: String,
|
|
|
|
|
-// sz: Decimal,
|
|
|
|
|
-// pnl: String,
|
|
|
|
|
-// ord_type: String,
|
|
|
|
|
-// side: String,
|
|
|
|
|
-// pos_side: String,
|
|
|
|
|
-// td_mode: String,
|
|
|
|
|
-// acc_fill_sz: Decimal,
|
|
|
|
|
-// fill_px: String,
|
|
|
|
|
-// trade_id: String,
|
|
|
|
|
-// fill_sz: String,
|
|
|
|
|
-// fill_time: String,
|
|
|
|
|
-// source: String,
|
|
|
|
|
-// state: String,
|
|
|
|
|
-// avg_px: String,
|
|
|
|
|
-// lever: String,
|
|
|
|
|
-// attach_algo_cl_ord_id: String,
|
|
|
|
|
-// tp_trigger_px: String,
|
|
|
|
|
-// tp_trigger_px_type: String,
|
|
|
|
|
-// tp_ord_px: String,
|
|
|
|
|
-// sl_trigger_px: String,
|
|
|
|
|
-// sl_trigger_px_type: String,
|
|
|
|
|
-// sl_ord_px: String,
|
|
|
|
|
-// stp_id: String,
|
|
|
|
|
-// stp_mode: String,
|
|
|
|
|
-// fee_ccy: String,
|
|
|
|
|
-// fee: String,
|
|
|
|
|
-// rebate_ccy: String,
|
|
|
|
|
-// rebate: String,
|
|
|
|
|
-// tgt_ccy: String,
|
|
|
|
|
-// category: String,
|
|
|
|
|
-// reduce_only: String,
|
|
|
|
|
-// cancel_source: String,
|
|
|
|
|
-// cancel_source_reason: String,
|
|
|
|
|
-// quick_mgn_type: String,
|
|
|
|
|
-// algo_cl_ord_id: String,
|
|
|
|
|
-// algo_id: String,
|
|
|
|
|
-// u_time: String,
|
|
|
|
|
-// c_time: String,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// #[allow(dead_code)]
|
|
|
|
|
-// #[derive(Clone)]
|
|
|
|
|
-// pub struct OkxSwap {
|
|
|
|
|
-// exchange: ExchangeEnum,
|
|
|
|
|
-// symbol: String,
|
|
|
|
|
-// is_colo: bool,
|
|
|
|
|
-// params: BTreeMap<String, String>,
|
|
|
|
|
-// request: OkxSwapRest,
|
|
|
|
|
-// market: Market,
|
|
|
|
|
-// order_sender: Sender<Order>,
|
|
|
|
|
-// error_sender: Sender<Error>,
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// impl OkxSwap {
|
|
|
|
|
-// pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> OkxSwap {
|
|
|
|
|
-// let market = Market::new();
|
|
|
|
|
-// let mut okx_swap = OkxSwap {
|
|
|
|
|
-// exchange: ExchangeEnum::OkxSwap,
|
|
|
|
|
-// symbol: symbol.to_uppercase(),
|
|
|
|
|
-// is_colo,
|
|
|
|
|
-// params: params.clone(),
|
|
|
|
|
-// request: OkxSwapRest::new(is_colo, params.clone()),
|
|
|
|
|
-// market,
|
|
|
|
|
-// order_sender,
|
|
|
|
|
-// error_sender,
|
|
|
|
|
-// };
|
|
|
|
|
-// okx_swap.market = OkxSwap::get_market(&mut okx_swap).await.unwrap_or(okx_swap.market);
|
|
|
|
|
-// return okx_swap;
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// #[async_trait]
|
|
|
|
|
-// impl Platform for OkxSwap {
|
|
|
|
|
-// fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_self_exchange(&self) -> ExchangeEnum { ExchangeEnum::OkxSwap }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_self_symbol(&self) -> String { self.symbol.clone() }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_self_is_colo(&self) -> bool { self.is_colo }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_self_params(&self) -> BTreeMap<String, String> { self.params.clone() }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_self_market(&self) -> Market { self.market.clone() }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_request_delays(&self) -> Vec<i64> { self.request.get_delays() }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_request_avg_delay(&self) -> Decimal { self.request.get_avg_delay() }
|
|
|
|
|
-//
|
|
|
|
|
-// fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_server_time(&mut self) -> Result<String, Error> {
|
|
|
|
|
-// let res_data = self.request.get_server_time().await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let result = res_data_json[0]["ts"].as_str().unwrap().to_string();
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_account(&mut self) -> Result<Account, Error> {
|
|
|
|
|
-// let symbol_array: Vec<&str> = self.symbol.split("_").collect();
|
|
|
|
|
-// let res_data = self.request.get_balance(symbol_array[1].to_string()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let balance_info_list: Vec<SwapAccount> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let detail = balance_info_list[0].details.iter().find(|&item| item.ccy == symbol_array[1]);
|
|
|
|
|
-// match detail {
|
|
|
|
|
-// None => {
|
|
|
|
|
-// error!("Okx:获取Account信息错误!\nhandle_swap_account:res_data={:?}", res_data);
|
|
|
|
|
-// panic!("Okx:获取Account信息错误!\nhandle_swap_account:res_data={:?}", res_data)
|
|
|
|
|
-// }
|
|
|
|
|
-// Some(value) => {
|
|
|
|
|
-// let result = Account {
|
|
|
|
|
-// coin: value.ccy.to_uppercase(),
|
|
|
|
|
-// balance: value.avail_bal + value.fixed_bal,
|
|
|
|
|
-// available_balance: value.avail_bal,
|
|
|
|
|
-// frozen_balance: value.fixed_bal,
|
|
|
|
|
-// stocks: Decimal::ZERO,
|
|
|
|
|
-// available_stocks: Decimal::ZERO,
|
|
|
|
|
-// frozen_stocks: Decimal::ZERO,
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_spot_account(&mut self) -> Result<Vec<Account>, Error> {
|
|
|
|
|
-// Err(Error::new(ErrorKind::NotFound, "okx_swap:该交易所方法未实现".to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_position(&mut self) -> Result<Vec<Position>, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.to_string(), "-"));
|
|
|
|
|
-// let ct_val = self.market.ct_val;
|
|
|
|
|
-// let res_data = self.request.get_positions("SWAP".to_string()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let data_list: Vec<SwapPosition> = serde_json::from_str(&res_data_str).unwrap();
|
|
|
|
|
-// let position_info: Vec<&SwapPosition> = data_list.iter().filter(|item| item.inst_id == symbol_format).collect();
|
|
|
|
|
-// let result = position_info.iter().map(|item| format_position_item(item, ct_val)).collect();
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
|
|
|
|
|
-// let res_data = self.request.get_positions("SWAP".to_string()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let data_list: Vec<SwapPosition> = serde_json::from_str(&res_data_str).unwrap();
|
|
|
|
|
-// let result = data_list.iter().map(|item| format_position_item(item, Decimal::ONE)).collect();
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_ticker(&mut self) -> Result<Ticker, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.clone(), "-"));
|
|
|
|
|
-// let res_data = self.request.get_ticker(symbol_format.clone()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let ticker_info_list: Vec<SwapTicker> = serde_json::from_str(&res_data_str).unwrap();
|
|
|
|
|
-// let ticker_info = ticker_info_list.iter().find(|item| item.inst_id == symbol_format);
|
|
|
|
|
-// match ticker_info {
|
|
|
|
|
-// None => {
|
|
|
|
|
-// error!("okx_swap:获取Ticker信息错误!\nget_ticker:res_data={:?}", res_data_str);
|
|
|
|
|
-// panic!("okx_swap:获取Ticker信息错误!\nget_ticker:res_data={:?}", res_data_str)
|
|
|
|
|
-// }
|
|
|
|
|
-// Some(value) => {
|
|
|
|
|
-// let result = Ticker {
|
|
|
|
|
-// time: value.ts.parse().unwrap(),
|
|
|
|
|
-// high: value.high24h,
|
|
|
|
|
-// low: value.low24h,
|
|
|
|
|
-// sell: value.ask_px,
|
|
|
|
|
-// buy: value.bid_px,
|
|
|
|
|
-// last: value.last,
|
|
|
|
|
-// volume: value.last_sz,
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(symbol.clone(), "-"));
|
|
|
|
|
-// let res_data = self.request.get_ticker(symbol_format.clone()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let ticker_info_list: Vec<SwapTicker> = serde_json::from_str(&res_data_str).unwrap();
|
|
|
|
|
-// let ticker_info = ticker_info_list.iter().find(|item| item.inst_id == symbol_format);
|
|
|
|
|
-// match ticker_info {
|
|
|
|
|
-// None => {
|
|
|
|
|
-// error!("okx_swap:获取Ticker信息错误!\nget_ticker:res_data={:?}", res_data_str);
|
|
|
|
|
-// panic!("okx_swap:获取Ticker信息错误!\nget_ticker:res_data={:?}", res_data_str)
|
|
|
|
|
-// }
|
|
|
|
|
-// Some(value) => {
|
|
|
|
|
-// let result = Ticker {
|
|
|
|
|
-// time: value.ts.parse().unwrap(),
|
|
|
|
|
-// high: value.high24h,
|
|
|
|
|
-// low: value.low24h,
|
|
|
|
|
-// sell: value.ask_px,
|
|
|
|
|
-// buy: value.bid_px,
|
|
|
|
|
-// last: value.last,
|
|
|
|
|
-// volume: value.last_sz,
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_market(&mut self) -> Result<Market, Error> {
|
|
|
|
|
-// let symbol_format = utils::format_symbol(self.symbol.clone(), "-");
|
|
|
|
|
-// let res_data = self.request.get_instruments().await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<SwapMarket> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let market_info = res_data_json.iter().find(|item| item.inst_id == format!("{}-SWAP", symbol_format));
|
|
|
|
|
-// match market_info {
|
|
|
|
|
-// None => {
|
|
|
|
|
-// error!("okx_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data_str);
|
|
|
|
|
-// panic!("okx_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data_str)
|
|
|
|
|
-// }
|
|
|
|
|
-// Some(value) => {
|
|
|
|
|
-// println!("{:?}", value);
|
|
|
|
|
-// let symbol_array: Vec<&str> = value.inst_family.split("-").collect();
|
|
|
|
|
-// let result = Market {
|
|
|
|
|
-// symbol: format!("{}_{}", symbol_array[0], symbol_array[1]),
|
|
|
|
|
-// base_asset: symbol_array[0].to_string(),
|
|
|
|
|
-// quote_asset: symbol_array[1].to_string(),
|
|
|
|
|
-// tick_size: value.tick_sz,
|
|
|
|
|
-// amount_size: value.min_sz * value.ct_val,
|
|
|
|
|
-// price_precision: Decimal::from_u32(value.tick_sz.scale()).unwrap(),
|
|
|
|
|
-// amount_precision: Decimal::from_u32((value.min_sz * value.ct_val).scale()).unwrap(),
|
|
|
|
|
-// min_qty: value.min_sz,
|
|
|
|
|
-// max_qty: value.max_lmt_sz,
|
|
|
|
|
-// min_notional: value.min_sz * value.ct_val,
|
|
|
|
|
-// max_notional: value.max_lmt_sz * value.ct_val,
|
|
|
|
|
-// ct_val: value.ct_val,
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
|
|
|
|
|
-// let symbol_format = utils::format_symbol(symbol.clone(), "-");
|
|
|
|
|
-// let res_data = self.request.get_instruments().await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<SwapMarket> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let market_info = res_data_json.iter().find(|item| item.inst_id == format!("{}-SWAP", symbol_format));
|
|
|
|
|
-// match market_info {
|
|
|
|
|
-// None => {
|
|
|
|
|
-// error!("okx_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data_str);
|
|
|
|
|
-// panic!("okx_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data_str)
|
|
|
|
|
-// }
|
|
|
|
|
-// Some(value) => {
|
|
|
|
|
-// let symbol_array: Vec<&str> = value.inst_family.split("-").collect();
|
|
|
|
|
-// let result = Market {
|
|
|
|
|
-// symbol: format!("{}_{}", symbol_array[0], symbol_array[1]),
|
|
|
|
|
-// base_asset: symbol_array[0].to_string(),
|
|
|
|
|
-// quote_asset: symbol_array[1].to_string(),
|
|
|
|
|
-// tick_size: value.tick_sz,
|
|
|
|
|
-// amount_size: value.min_sz * value.ct_val,
|
|
|
|
|
-// price_precision: Decimal::from_u32(value.tick_sz.scale()).unwrap(),
|
|
|
|
|
-// amount_precision: Decimal::from_u32((value.min_sz * value.ct_val).scale()).unwrap(),
|
|
|
|
|
-// min_qty: value.min_sz,
|
|
|
|
|
-// max_qty: value.max_lmt_sz,
|
|
|
|
|
-// min_notional: value.min_sz * value.ct_val,
|
|
|
|
|
-// max_notional: value.max_lmt_sz * value.ct_val,
|
|
|
|
|
-// ct_val: value.ct_mult,
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.clone(), "-"));
|
|
|
|
|
-// let ct_val = self.market.ct_val;
|
|
|
|
|
-// let res_data = self.request.get_order(symbol_format, order_id.to_string(), custom_id.to_string()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<SwapOrder> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let order_info = res_data_json[0].clone();
|
|
|
|
|
-// let result = format_order_item(order_info, ct_val);
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.clone(), "-"));
|
|
|
|
|
-// let ct_val = self.market.ct_val;
|
|
|
|
|
-// let res_data = self.request.get_incomplete_order(symbol_format.clone()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<SwapOrder> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let result = res_data_json.iter().map(|item| format_order_item(item.clone(), ct_val)).collect();
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.clone(), "-"));
|
|
|
|
|
-// let ct_val = self.market.ct_val;
|
|
|
|
|
-// let mut params = json!({
|
|
|
|
|
-// "tdMode": "cross",
|
|
|
|
|
-// "clOrdId": custom_id.to_string(),
|
|
|
|
|
-// "instId": symbol_format,
|
|
|
|
|
-// "px": price.to_string(),
|
|
|
|
|
-// });
|
|
|
|
|
-// params["ordType"] = if price.eq(&Decimal::ZERO) { json!("market") } else { json!("limit") };
|
|
|
|
|
-// let size = (amount / ct_val).floor();
|
|
|
|
|
-// params["sz"] = json!(size);
|
|
|
|
|
-// match origin_side {
|
|
|
|
|
-// "kd" => {
|
|
|
|
|
-// params["side"] = json!("buy");
|
|
|
|
|
-// params["posSide"] = json!("long");
|
|
|
|
|
-// }
|
|
|
|
|
-// "pd" => {
|
|
|
|
|
-// params["side"] = json!("sell");
|
|
|
|
|
-// params["posSide"] = json!("long");
|
|
|
|
|
-// }
|
|
|
|
|
-// "kk" => {
|
|
|
|
|
-// params["side"] = json!("sell");
|
|
|
|
|
-// params["posSide"] = json!("short");
|
|
|
|
|
-// }
|
|
|
|
|
-// "pk" => {
|
|
|
|
|
-// params["side"] = json!("buy");
|
|
|
|
|
-// params["posSide"] = json!("short");
|
|
|
|
|
-// }
|
|
|
|
|
-// _ => { error!("下单参数错误"); }
|
|
|
|
|
-// };
|
|
|
|
|
-// let res_data = self.request.swap_order(params).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let order_info = res_data_json[0].clone();
|
|
|
|
|
-// let id = order_info["ordId"].as_str().unwrap().to_string();
|
|
|
|
|
-// let custom_id = order_info["clOrdId"].as_str().unwrap().to_string();
|
|
|
|
|
-// let result = Order {
|
|
|
|
|
-// id,
|
|
|
|
|
-// custom_id,
|
|
|
|
|
-// price,
|
|
|
|
|
-// amount,
|
|
|
|
|
-// deal_amount: Decimal::ZERO,
|
|
|
|
|
-// avg_price: Decimal::ZERO,
|
|
|
|
|
-// status: "NEW".to_string(),
|
|
|
|
|
-// order_type: "".to_string(),
|
|
|
|
|
-// trace_stack: TraceStack::new(0, Instant::now()).on_special("799 okx_swap".to_string()),
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn take_order_symbol(&mut self, symbol: String, ct_val: Decimal, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(symbol.clone(), "-"));
|
|
|
|
|
-// let mut params = json!({
|
|
|
|
|
-// "tdMode": "cross",
|
|
|
|
|
-// "clOrdId": custom_id.to_string(),
|
|
|
|
|
-// "instId": symbol_format,
|
|
|
|
|
-// "px": price.to_string(),
|
|
|
|
|
-// });
|
|
|
|
|
-// params["ordType"] = if price.eq(&Decimal::ZERO) { json!("market") } else { json!("limit") };
|
|
|
|
|
-// let size = (amount / ct_val).floor();
|
|
|
|
|
-// params["sz"] = json!(size);
|
|
|
|
|
-// match origin_side {
|
|
|
|
|
-// "kd" => {
|
|
|
|
|
-// params["side"] = json!("buy");
|
|
|
|
|
-// params["posSide"] = json!("long");
|
|
|
|
|
-// }
|
|
|
|
|
-// "pd" => {
|
|
|
|
|
-// params["side"] = json!("sell");
|
|
|
|
|
-// params["posSide"] = json!("long");
|
|
|
|
|
-// }
|
|
|
|
|
-// "kk" => {
|
|
|
|
|
-// params["side"] = json!("sell");
|
|
|
|
|
-// params["posSide"] = json!("short");
|
|
|
|
|
-// }
|
|
|
|
|
-// "pk" => {
|
|
|
|
|
-// params["side"] = json!("buy");
|
|
|
|
|
-// params["posSide"] = json!("short");
|
|
|
|
|
-// }
|
|
|
|
|
-// _ => { error!("下单参数错误"); }
|
|
|
|
|
-// };
|
|
|
|
|
-// let res_data = self.request.swap_order(params).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let order_info = res_data_json[0].clone();
|
|
|
|
|
-// let id = order_info["ordId"].as_str().unwrap().to_string();
|
|
|
|
|
-// let custom_id = order_info["clOrdId"].as_str().unwrap().to_string();
|
|
|
|
|
-// let result = Order {
|
|
|
|
|
-// id,
|
|
|
|
|
-// custom_id,
|
|
|
|
|
-// price,
|
|
|
|
|
-// amount,
|
|
|
|
|
-// deal_amount: Decimal::ZERO,
|
|
|
|
|
-// avg_price: Decimal::ZERO,
|
|
|
|
|
-// status: "NEW".to_string(),
|
|
|
|
|
-// order_type: "".to_string(),
|
|
|
|
|
-// trace_stack: TraceStack::new(0, Instant::now()).on_special("853 okx_swap".to_string()),
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.clone(), "-"));
|
|
|
|
|
-// let res_data = self.request.cancel_order(symbol_format, order_id.to_string(), custom_id.to_string()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
|
|
-// let order_info = res_data_json[0].clone();
|
|
|
|
|
-// let id = order_info["ordId"].as_str().unwrap().to_string();
|
|
|
|
|
-// let custom_id = order_info["clOrdId"].as_str().unwrap().to_string();
|
|
|
|
|
-// let result = Order {
|
|
|
|
|
-// id,
|
|
|
|
|
-// custom_id,
|
|
|
|
|
-// price: Decimal::ZERO,
|
|
|
|
|
-// amount: Decimal::ZERO,
|
|
|
|
|
-// deal_amount: Decimal::ZERO,
|
|
|
|
|
-// avg_price: Decimal::ZERO,
|
|
|
|
|
-// status: "REMOVE".to_string(),
|
|
|
|
|
-// order_type: "".to_string(),
|
|
|
|
|
-// trace_stack: TraceStack::new(0, Instant::now()).on_special("879 okx_swap".to_string()),
|
|
|
|
|
-// };
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
|
|
|
|
|
-// Err(Error::new(ErrorKind::NotFound, "okx_swap:该交易所方法未实现".to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
|
|
|
|
|
-// Err(Error::new(ErrorKind::NotFound, "okx_swap:该交易所方法未实现".to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> {
|
|
|
|
|
-// let res_data = self.request.set_position_mode().await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let result = res_data_str.clone();
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn set_dual_leverage(&mut self, leverage: &str) -> Result<String, Error> {
|
|
|
|
|
-// let symbol_format = format!("{}-SWAP", utils::format_symbol(self.symbol.clone(), "-"));
|
|
|
|
|
-// let res_data = self.request.set_leverage(symbol_format, leverage.to_string()).await;
|
|
|
|
|
-// if res_data.code == "200" {
|
|
|
|
|
-// let res_data_str = &res_data.data;
|
|
|
|
|
-// let result = res_data_str.clone();
|
|
|
|
|
-// Ok(result)
|
|
|
|
|
-// } else {
|
|
|
|
|
-// Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "okx_swap:该交易所方法未实现".to_string())) }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "okx_swap:该交易所方法未实现".to_string())) }
|
|
|
|
|
-//
|
|
|
|
|
-// async fn command_order(&mut self, order_command: OrderCommand, trace_stack: TraceStack) {
|
|
|
|
|
-// let mut handles = vec![];
|
|
|
|
|
-// // 撤销订单
|
|
|
|
|
-// let cancel = order_command.cancel;
|
|
|
|
|
-// for item in cancel.keys() {
|
|
|
|
|
-// let mut self_clone = self.clone();
|
|
|
|
|
-// let cancel_clone = cancel.clone();
|
|
|
|
|
-// let item_clone = item.clone();
|
|
|
|
|
-// let order_id = cancel_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
|
|
|
|
|
-// let custom_id = cancel_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
|
|
|
|
|
-// let result_sd = self.order_sender.clone();
|
|
|
|
|
-// let err_sd = self.error_sender.clone();
|
|
|
|
|
-// let handle = tokio::spawn(async move {
|
|
|
|
|
-// if order_id != "" {
|
|
|
|
|
-// let result = self_clone.cancel_order(&order_id, &custom_id).await;
|
|
|
|
|
-// match result {
|
|
|
|
|
-// Ok(_) => {
|
|
|
|
|
-// // result_sd.send(result).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// Err(error) => {
|
|
|
|
|
-// // 取消失败去查订单。
|
|
|
|
|
-// let query_rst = self_clone.get_order_detail(&order_id, &custom_id).await;
|
|
|
|
|
-// match query_rst {
|
|
|
|
|
-// Ok(order) => {
|
|
|
|
|
-// result_sd.send(order).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// Err(query_err) => {
|
|
|
|
|
-// error!(?query_err);
|
|
|
|
|
-// error!("撤单失败,而且查单也失败了,okx_swap,oid={}, cid={}。", order_id.clone(), custom_id.clone());
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// err_sd.send(error).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-// handles.push(handle)
|
|
|
|
|
-// }
|
|
|
|
|
-// // 下单指令
|
|
|
|
|
-// let mut limits = HashMap::new();
|
|
|
|
|
-// limits.extend(order_command.limits_open);
|
|
|
|
|
-// limits.extend(order_command.limits_close);
|
|
|
|
|
-// for item in limits.keys() {
|
|
|
|
|
-// let mut self_clone = self.clone();
|
|
|
|
|
-// let limits_clone = limits.clone();
|
|
|
|
|
-// let item_clone = item.clone();
|
|
|
|
|
-// let result_sd = self.order_sender.clone();
|
|
|
|
|
-// let err_sd = self.error_sender.clone();
|
|
|
|
|
-// let ts = trace_stack.clone();
|
|
|
|
|
-//
|
|
|
|
|
-// let handle = tokio::spawn(async move {
|
|
|
|
|
-// let value = limits_clone[&item_clone].clone();
|
|
|
|
|
-// let amount = Decimal::from_str(value.get(0).unwrap_or(&"0".to_string())).unwrap();
|
|
|
|
|
-// let side = value.get(1).unwrap();
|
|
|
|
|
-// let price = Decimal::from_str(value.get(2).unwrap_or(&"0".to_string())).unwrap();
|
|
|
|
|
-// let cid = value.get(3).unwrap();
|
|
|
|
|
-//
|
|
|
|
|
-// // order_name: [数量,方向,价格,c_id]
|
|
|
|
|
-// let result = self_clone.take_order(cid, side, price, amount).await;
|
|
|
|
|
-// match result {
|
|
|
|
|
-// Ok(mut result) => {
|
|
|
|
|
-// // ts.on_after_send();
|
|
|
|
|
-// result.trace_stack = ts.clone();
|
|
|
|
|
-//
|
|
|
|
|
-// result_sd.send(result).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// Err(error) => {
|
|
|
|
|
-// let mut err_order = Order::new();
|
|
|
|
|
-// err_order.custom_id = cid.clone();
|
|
|
|
|
-// err_order.status = "REMOVE".to_string();
|
|
|
|
|
-//
|
|
|
|
|
-// result_sd.send(err_order).await.unwrap();
|
|
|
|
|
-// err_sd.send(error).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-// handles.push(handle)
|
|
|
|
|
-// }
|
|
|
|
|
-// // 检查订单指令
|
|
|
|
|
-// let check = order_command.check;
|
|
|
|
|
-// for item in check.keys() {
|
|
|
|
|
-// let mut self_clone = self.clone();
|
|
|
|
|
-// let check_clone = check.clone();
|
|
|
|
|
-// let item_clone = item.clone();
|
|
|
|
|
-// let order_id = check_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
|
|
|
|
|
-// let custom_id = check_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
|
|
|
|
|
-// let result_sd = self.order_sender.clone();
|
|
|
|
|
-// let err_sd = self.error_sender.clone();
|
|
|
|
|
-// let handle = tokio::spawn(async move {
|
|
|
|
|
-// let result = self_clone.get_order_detail(&order_id, &custom_id).await;
|
|
|
|
|
-// match result {
|
|
|
|
|
-// Ok(result) => {
|
|
|
|
|
-// result_sd.send(result).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// Err(error) => {
|
|
|
|
|
-// err_sd.send(error).await.unwrap();
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-// handles.push(handle)
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// let futures = FuturesUnordered::from_iter(handles);
|
|
|
|
|
-// let _: Result<Vec<_>, _> = futures.try_collect().await;
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// pub fn format_order_item(data: SwapOrder, ct_val: Decimal) -> Order {
|
|
|
|
|
-// debug!("format-order-start, okx_swap");
|
|
|
|
|
-// debug!(?data);
|
|
|
|
|
-// let custom_status = if ["canceled", "filled", "mmp_canceled"].contains(&data.state.as_str()) {
|
|
|
|
|
-// "REMOVE".to_string()
|
|
|
|
|
-// } else if ["live", "partially_filled"].contains(&data.state.as_str()) {
|
|
|
|
|
-// "NEW".to_string()
|
|
|
|
|
-// } else {
|
|
|
|
|
-// "NULL".to_string()
|
|
|
|
|
-// };
|
|
|
|
|
-//
|
|
|
|
|
-// let result = Order {
|
|
|
|
|
-// id: data.ord_id,
|
|
|
|
|
-// custom_id: data.cl_ord_id,
|
|
|
|
|
-// price: data.px,
|
|
|
|
|
-// amount: data.sz * ct_val,
|
|
|
|
|
-// deal_amount: data.acc_fill_sz * ct_val,
|
|
|
|
|
-// avg_price: if data.avg_px != "" { Decimal::from_str(&data.avg_px).unwrap() } else { Decimal::ZERO },
|
|
|
|
|
-// status: custom_status,
|
|
|
|
|
-// order_type: data.ord_type,
|
|
|
|
|
-// trace_stack: TraceStack::new(0, Instant::now()).on_special("1049 okx_swap".to_string()),
|
|
|
|
|
-// };
|
|
|
|
|
-// debug!(?result);
|
|
|
|
|
-// debug!("format-order-end, okx_swap");
|
|
|
|
|
-// result
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// pub fn format_position_item(value: &SwapPosition, ct_val: Decimal) -> Position {
|
|
|
|
|
-// let position_mode = match value.pos_side.as_str() {
|
|
|
|
|
-// "long" => { PositionModeEnum::Long }
|
|
|
|
|
-// "short" => { PositionModeEnum::Short }
|
|
|
|
|
-// _ => { PositionModeEnum::Both }
|
|
|
|
|
-// };
|
|
|
|
|
-// Position {
|
|
|
|
|
-// symbol: value.inst_id.replace("-SWAP", ""),
|
|
|
|
|
-// margin_level: value.lever,
|
|
|
|
|
-// amount: value.pos * ct_val,
|
|
|
|
|
-// frozen_amount: Decimal::ZERO,
|
|
|
|
|
-// price: value.avg_px,
|
|
|
|
|
-// profit: value.upl,
|
|
|
|
|
-// position_mode,
|
|
|
|
|
-// margin: if value.margin != "" { Decimal::from_str(&value.margin).unwrap() } else { Decimal::ZERO },
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|