|
@@ -0,0 +1,547 @@
|
|
|
|
|
+use std::fmt::Debug;
|
|
|
|
|
+use serde::{Deserialize, Serialize};
|
|
|
|
|
+use rust_decimal::Decimal;
|
|
|
|
|
+use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
|
|
|
|
|
+use rust_decimal_macros::dec;
|
|
|
|
|
+use tracing::error;
|
|
|
|
|
+use crate::{Account, Market, Order, Position, PositionModeEnum, Ticker, utils};
|
|
|
|
|
+use crate::ExchangeEnum::KucoinSwapRest;
|
|
|
|
|
+
|
|
|
|
|
+/// Okx交易所账户信息请求数据结构
|
|
|
|
|
+/// - 接口`"/api/v5/account/balance"`
|
|
|
|
|
+///
|
|
|
|
|
+/// struct SwapAccount
|
|
|
|
|
+/// - `adj_eq·: Decimal,
|
|
|
|
|
+/// - `borrow_froz·: Decimal,
|
|
|
|
|
+/// - `imr·: Decimal,
|
|
|
|
|
+/// - `iso_eq·: Decimal,
|
|
|
|
|
+/// - `mgn_ratio·: Decimal,
|
|
|
|
|
+/// - `mmr·: Decimal,
|
|
|
|
|
+/// - `notional_usd·: Decimal,
|
|
|
|
|
+/// - `ord_froz·: Decimal,
|
|
|
|
|
+/// - `total_eq·: Decimal,
|
|
|
|
|
+/// - `u_time·: String
|
|
|
|
|
+///
|
|
|
|
|
+/// struct SwapAccountDetails
|
|
|
|
|
+/// - `avail_bal`: Decimal,
|
|
|
|
|
+/// - `avail_eq`: Decimal,
|
|
|
|
|
+/// - `cash_bal`: Decimal,
|
|
|
|
|
+/// - `ccy`: String,
|
|
|
|
|
+/// - `cross_liab`: Decimal,
|
|
|
|
|
+/// - `dis_eq`: Decimal,
|
|
|
|
|
+/// - `eq`: Decimal,
|
|
|
|
|
+/// - `eq_usd`: Decimal,
|
|
|
|
|
+/// - `fixed_bal`: Decimal,
|
|
|
|
|
+/// - `frozen_bal`: Decimal,
|
|
|
|
|
+/// - `interest`: Decimal,
|
|
|
|
|
+/// - `iso_eq`: Decimal,
|
|
|
|
|
+/// - `iso_liab`: Decimal,
|
|
|
|
|
+/// - `iso_upl`: Decimal,
|
|
|
|
|
+/// - `liab`: Decimal,
|
|
|
|
|
+/// - `max_loan`: Decimal,
|
|
|
|
|
+/// - `mgn_ratio`: Decimal,
|
|
|
|
|
+/// - `notional_lever`: Decimal,
|
|
|
|
|
+/// - `ord_frozen`: Decimal,
|
|
|
|
|
+/// - `twap`: Decimal,
|
|
|
|
|
+/// - `u_time`: String,
|
|
|
|
|
+/// - `upl`: Decimal,
|
|
|
|
|
+/// - `upl_liab`: Decimal,
|
|
|
|
|
+/// - `stgy_eq`: Decimal,
|
|
|
|
|
+/// - `spot_in_use_amt`: Decimal,
|
|
|
|
|
+/// - `borrow_froz`: Decimal,
|
|
|
|
|
+#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
+#[serde(rename_all = "camelCase")]
|
|
|
|
|
+struct SwapAccount {
|
|
|
|
|
+ adj_eq: Decimal,
|
|
|
|
|
+ borrow_froz: Decimal,
|
|
|
|
|
+ details: SwapAccountDetails,
|
|
|
|
|
+ imr: Decimal,
|
|
|
|
|
+ iso_eq: Decimal,
|
|
|
|
|
+ mgn_ratio: Decimal,
|
|
|
|
|
+ mmr: Decimal,
|
|
|
|
|
+ notional_usd: Decimal,
|
|
|
|
|
+ ord_froz: Decimal,
|
|
|
|
|
+ total_eq: Decimal,
|
|
|
|
|
+ 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: Decimal,
|
|
|
|
|
+ dis_eq: Decimal,
|
|
|
|
|
+ eq: Decimal,
|
|
|
|
|
+ eq_usd: Decimal,
|
|
|
|
|
+ fixed_bal: Decimal,
|
|
|
|
|
+ frozen_bal: Decimal,
|
|
|
|
|
+ interest: Decimal,
|
|
|
|
|
+ iso_eq: Decimal,
|
|
|
|
|
+ iso_liab: Decimal,
|
|
|
|
|
+ iso_upl: Decimal,
|
|
|
|
|
+ liab: Decimal,
|
|
|
|
|
+ max_loan: Decimal,
|
|
|
|
|
+ mgn_ratio: Decimal,
|
|
|
|
|
+ notional_lever: Decimal,
|
|
|
|
|
+ ord_frozen: Decimal,
|
|
|
|
|
+ twap: Decimal,
|
|
|
|
|
+ u_time: String,
|
|
|
|
|
+ upl: Decimal,
|
|
|
|
|
+ upl_liab: Decimal,
|
|
|
|
|
+ stgy_eq: Decimal,
|
|
|
|
|
+ spot_in_use_amt: Decimal,
|
|
|
|
|
+ borrow_froz: Decimal,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// 处理合约本位货币账户信息
|
|
|
|
|
+///
|
|
|
|
|
+/// pub(crate) fn handle_account(data: String, symbol: String) -> Account;
|
|
|
|
|
+///
|
|
|
|
|
+/// - `data`:String, 交易所返回账户信息,JsonString
|
|
|
|
|
+/// - `symbol`:String, 交易币对
|
|
|
|
|
+pub(crate) fn handle_swap_account(data: String, _symbol: String) -> Account {
|
|
|
|
|
+ let account_info: Vec<SwapAccount> = serde_json::from_str(&data).unwrap();
|
|
|
|
|
+ let balance_info: SwapAccountDetails = account_info[0].details.clone();
|
|
|
|
|
+ Account {
|
|
|
|
|
+ coin: balance_info.currency.to_uppercase(),
|
|
|
|
|
+ balance: balance_info.account_equity,
|
|
|
|
|
+ available_balance: balance_info.available_balance,
|
|
|
|
|
+ frozen_balance: balance_info.account_equity - balance_info.available_balance,
|
|
|
|
|
+ stocks: dec!(0),
|
|
|
|
|
+ available_stocks: dec!(0),
|
|
|
|
|
+ frozen_stocks: dec!(0),
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// Kucoin交易所持仓信息请求数据结构
|
|
|
|
|
+/// - 接口`"/api/v1/position"`
|
|
|
|
|
+///
|
|
|
|
|
+/// struct SwapPosition
|
|
|
|
|
+/// - `id`: String, 仓位Id
|
|
|
|
|
+/// - `symbol`: String, 合约symbol
|
|
|
|
|
+/// - `auto_deposit`: bool, 是否自动最佳保证金
|
|
|
|
|
+/// - `maint_margin_req`: Decimal, 维持保证金率
|
|
|
|
|
+/// - `risk_limit`: Decimal, 风险限额
|
|
|
|
|
+/// - `real_leverage`: Decimal, 杠杆倍数
|
|
|
|
|
+/// - `cross_mode`: bool, 是否全仓模式
|
|
|
|
|
+/// - `delev_percentage`: Decimal, ADL分为数
|
|
|
|
|
+/// - `opening_timestamp`: i64, 开仓时间
|
|
|
|
|
+/// - `current_timestamp`: i64, 当前时间戳
|
|
|
|
|
+/// - `current_qty`: Decimal, 当前仓位数量
|
|
|
|
|
+/// - `current_cost`: Decimal, 当前仓位价值
|
|
|
|
|
+/// - `current_comm`: Decimal, 当前仓位总费用
|
|
|
|
|
+/// - `unrealised_cost`: Decimal, 为实现价值
|
|
|
|
|
+/// - `realised_gross_cost`: Decimal, 累计已实现毛利价值
|
|
|
|
|
+/// - `realised_cost`: Decimal, 累计已实现仓位价值
|
|
|
|
|
+/// - `is_open`: bool, 是否开仓
|
|
|
|
|
+/// - `mark_price`: Decimal, 标记价格
|
|
|
|
|
+/// - `mark_value`: Decimal, 标记价值
|
|
|
|
|
+/// - `pos_cost`: Decimal, 仓位价值
|
|
|
|
|
+/// - `pos_cross`:Decimal, 追加到仓位的保证金
|
|
|
|
|
+/// - `pos_init`: Decimal, 杠杆保证金
|
|
|
|
|
+/// - `pos_comm`: Decimal, 破产费用
|
|
|
|
|
+/// - `pos_loss`: Decimal, 资金费用最少的资金
|
|
|
|
|
+/// - `pos_margin`:Decimal, 仓位保证金
|
|
|
|
|
+/// - `pos_maint`: Decimal, 维持保证金
|
|
|
|
|
+/// - `maint_margin`: Decimal, 包含未实现盈亏的仓位保证金
|
|
|
|
|
+/// - `realised_gross_pnl`: Decimal, 累计已实现毛利
|
|
|
|
|
+/// - `realised_pnl`: Decimal, 已实现盈亏
|
|
|
|
|
+/// - `unrealised_pnl`: Decimal, 未实现盈亏
|
|
|
|
|
+/// - `unrealised_pnl_pcnt`:Decimal, 仓位盈亏率
|
|
|
|
|
+/// - `unrealised_roe_pcnt`:Decimal, 投资回报率
|
|
|
|
|
+/// - `avg_entry_price`: Decimal, 平均开仓价格
|
|
|
|
|
+/// - `liquidation_price`: Decimal, 强平价格
|
|
|
|
|
+/// - `bankrupt_price`: Decimal, 破产价格
|
|
|
|
|
+/// - `settle_currency`:String, 结算币种
|
|
|
|
|
+/// - `maintain_margin`: Decimal, 维持保证金率
|
|
|
|
|
+/// - `user_id`: i64,
|
|
|
|
|
+/// - `risk_limit_level`: Decimal 当前风险限额等级
|
|
|
|
|
+#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
+#[serde(rename_all = "camelCase")]
|
|
|
|
|
+struct SwapPosition {
|
|
|
|
|
+ id: String,
|
|
|
|
|
+ symbol: String,
|
|
|
|
|
+ auto_deposit: bool,
|
|
|
|
|
+ maint_margin_req: Decimal,
|
|
|
|
|
+ risk_limit: Decimal,
|
|
|
|
|
+ real_leverage: Decimal,
|
|
|
|
|
+ cross_mode: bool,
|
|
|
|
|
+ delev_percentage: Decimal,
|
|
|
|
|
+ opening_timestamp: i64,
|
|
|
|
|
+ current_timestamp: i64,
|
|
|
|
|
+ current_qty: Decimal,
|
|
|
|
|
+ current_cost: Decimal,
|
|
|
|
|
+ current_comm: Decimal,
|
|
|
|
|
+ unrealised_cost: Decimal,
|
|
|
|
|
+ realised_gross_cost: Decimal,
|
|
|
|
|
+ realised_cost: Decimal,
|
|
|
|
|
+ is_open: bool,
|
|
|
|
|
+ mark_price: Decimal,
|
|
|
|
|
+ mark_value: Decimal,
|
|
|
|
|
+ pos_cost: Decimal,
|
|
|
|
|
+ pos_cross: Decimal,
|
|
|
|
|
+ pos_init: Decimal,
|
|
|
|
|
+ pos_comm: Decimal,
|
|
|
|
|
+ pos_loss: Decimal,
|
|
|
|
|
+ pos_margin: Decimal,
|
|
|
|
|
+ pos_maint: Decimal,
|
|
|
|
|
+ maint_margin: Decimal,
|
|
|
|
|
+ realised_gross_pnl: Decimal,
|
|
|
|
|
+ realised_pnl: Decimal,
|
|
|
|
|
+ unrealised_pnl: Decimal,
|
|
|
|
|
+ unrealised_pnl_pcnt: Decimal,
|
|
|
|
|
+ unrealised_roe_pcnt: Decimal,
|
|
|
|
|
+ avg_entry_price: Decimal,
|
|
|
|
|
+ liquidation_price: Decimal,
|
|
|
|
|
+ bankrupt_price: Decimal,
|
|
|
|
|
+ settle_currency: String,
|
|
|
|
|
+ maintain_margin: Decimal,
|
|
|
|
|
+ risk_limit_level: Decimal,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// 处理合约仓位信息
|
|
|
|
|
+///
|
|
|
|
|
+/// pub(crate) fn handle_swap_position(data: String, symbol: String, ct_val: Decimal) -> Vec<Position>;
|
|
|
|
|
+///
|
|
|
|
|
+/// - `data`:String, 交易所返回账户信息,JsonString
|
|
|
|
|
+/// - `symbol`:String, 交易币对
|
|
|
|
|
+/// - `ct_val`:Decimal, 张数价值
|
|
|
|
|
+pub(crate) fn handle_swap_position(data: String, symbol: String, ct_val: Decimal) -> Vec<Position> {
|
|
|
|
|
+ let exchange_symbol = utils::symbol_mapper(KucoinSwapRest, &symbol);
|
|
|
|
|
+ let position_info: SwapPosition = serde_json::from_str(&data).unwrap();
|
|
|
|
|
+ let coin = position_info.symbol[..symbol.find(&position_info.settle_currency).unwrap() - 1].to_string();
|
|
|
|
|
+ let base_asset = if coin == exchange_symbol.base_asset.clone() { coin } else { exchange_symbol.base_asset.clone() };
|
|
|
|
|
+ vec![Position {
|
|
|
|
|
+ symbol: format!("{}_{}", base_asset, position_info.settle_currency),
|
|
|
|
|
+ margin_level: position_info.real_leverage,
|
|
|
|
|
+ amount: position_info.current_qty * ct_val,
|
|
|
|
|
+ frozen_amount: dec!(0),
|
|
|
|
|
+ price: position_info.avg_entry_price,
|
|
|
|
|
+ profit: position_info.unrealised_pnl,
|
|
|
|
|
+ position_mode: if position_info.current_qty * ct_val > dec!(0) { PositionModeEnum::Long } else { PositionModeEnum::Short },
|
|
|
|
|
+ margin: position_info.pos_margin,
|
|
|
|
|
+ }]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// Kucoin交易所行情信息请求数据结构
|
|
|
|
|
+/// - 接口`"/api/v1/ticker"`
|
|
|
|
|
+///
|
|
|
|
|
+/// struct SwapTicker
|
|
|
|
|
+/// - `sequence`: i64, 顺序号
|
|
|
|
|
+/// - `symbol`: String, 合约
|
|
|
|
|
+/// - `side`: String, 成交方向
|
|
|
|
|
+/// - `size`: Decimal, 成交数量
|
|
|
|
|
+/// - `price`: Decimal, 成交价格
|
|
|
|
|
+/// - `best_bid_size`: Decimal, 最佳买一价总量
|
|
|
|
|
+/// - `best_bid_price`: Decimal, 最佳买一价
|
|
|
|
|
+/// - `best_ask_size`: Decimal, 最佳卖一价总量
|
|
|
|
|
+/// - `best_ask_price`: Decimal, 最佳卖一价
|
|
|
|
|
+/// - `trade_id`: String, 交易号
|
|
|
|
|
+/// - `ts`: Decimal, 成交时间
|
|
|
|
|
+#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
+#[serde(rename_all = "camelCase")]
|
|
|
|
|
+struct SwapTicker {
|
|
|
|
|
+ sequence: i64,
|
|
|
|
|
+ symbol: String,
|
|
|
|
|
+ side: String,
|
|
|
|
|
+ size: Decimal,
|
|
|
|
|
+ price: Decimal,
|
|
|
|
|
+ best_bid_size: Decimal,
|
|
|
|
|
+ best_bid_price: Decimal,
|
|
|
|
|
+ best_ask_size: Decimal,
|
|
|
|
|
+ best_ask_price: Decimal,
|
|
|
|
|
+ trade_id: String,
|
|
|
|
|
+ ts: Decimal,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// 处理合约行情信息
|
|
|
|
|
+///
|
|
|
|
|
+/// pub(crate) fn handle_swap_ticker(data: String, symbol: String) -> Ticker;
|
|
|
|
|
+///
|
|
|
|
|
+/// - `data`:String, 交易所返回账户信息,JsonString
|
|
|
|
|
+/// - `symbol`:String, 交易币对
|
|
|
|
|
+pub(crate) fn handle_swap_ticker(data: String, _symbol: String) -> Ticker {
|
|
|
|
|
+ let ticker_info: SwapTicker = serde_json::from_str(&data).unwrap();
|
|
|
|
|
+ Ticker {
|
|
|
|
|
+ time: (ticker_info.ts / dec!(1000000)).to_i64().unwrap(),
|
|
|
|
|
+ high: ticker_info.best_ask_price,
|
|
|
|
|
+ low: ticker_info.best_bid_price,
|
|
|
|
|
+ sell: ticker_info.best_ask_price,
|
|
|
|
|
+ buy: ticker_info.best_bid_price,
|
|
|
|
|
+ last: ticker_info.price,
|
|
|
|
|
+ volume: ticker_info.size,
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// Kucoin交易所行情信息请求数据结构
|
|
|
|
|
+/// - 接口`/api/v1/contracts/active"`
|
|
|
|
|
+///
|
|
|
|
|
+/// struct SwapMarket
|
|
|
|
|
+/// - `symbol`: String, 合约名称
|
|
|
|
|
+/// - `root_symbol`: String, 合约系列
|
|
|
|
|
+/// - `contract_type`: String, 合约类型
|
|
|
|
|
+/// - `first_open_date`: Decimal, 首次开放时间
|
|
|
|
|
+/// - `expire_date`: Decimal, 到期日期,为Null表示永不过期
|
|
|
|
|
+/// - `settle_date`: Decimal, 结算日期,为Null表示不支持自动结算
|
|
|
|
|
+/// - `base_currency`: String, 基础货币
|
|
|
|
|
+/// - `quote_currency`: String, 计价货币
|
|
|
|
|
+/// - `settle_currency`: String, 结算币种
|
|
|
|
|
+/// - `max_order_qty`: Decimal, 最大委托数量
|
|
|
|
|
+/// - `max_price`: Decimal, 最大下单价格
|
|
|
|
|
+/// - `lot_size`: Decimal, 最小合约数量
|
|
|
|
|
+/// - `tick_size`: Decimal, 最小的价格变化
|
|
|
|
|
+/// - `index_price_tick_size`: Decimal, 指数价格变化步长
|
|
|
|
|
+/// - `multiplier`: Decimal, 合约乘数
|
|
|
|
|
+/// - `initial_margin`: Decimal, 初始保证金率
|
|
|
|
|
+/// - `maintain_margin`: Decimal, 维持保证金率
|
|
|
|
|
+/// - `max_risk_limit`: Decimal, 最大风险限额(以XBT为单位)
|
|
|
|
|
+/// - `min_risk_limit`: Decimal, 最小风险限额(以XBT为单位)
|
|
|
|
|
+/// - `risk_step`: Decimal, 风险限额递增值(以XBT为单位)
|
|
|
|
|
+/// - `maker_fee_rate`: Decimal, marker手续费
|
|
|
|
|
+/// - `taker_fee_rate`: Decimal, taker手续费
|
|
|
|
|
+/// - `settlement_fee`: Decimal, 结算手续费
|
|
|
|
|
+/// - `is_deleverage`: bool, 是否支持自动减仓
|
|
|
|
|
+/// - `is_inverse`: bool, 是否是反向合约
|
|
|
|
|
+/// - `mark_method`: String, 标记方式
|
|
|
|
|
+/// - `fair_method`: String, 合理标记方式
|
|
|
|
|
+/// - `funding_base_symbol`: String, 基础货币symbol
|
|
|
|
|
+/// - `funding_quote_symbol`: String, 计价货币symbol
|
|
|
|
|
+/// - `funding_rate_symbol`: String, 资金货币symbol
|
|
|
|
|
+/// - `index_symbol`: String, 指数symbol
|
|
|
|
|
+/// - `settlement_symbol`: String, 结算symbol
|
|
|
|
|
+/// - `status`: String, 合约状态(Init:初始、Open:已上线、BeingSettled:结算中、Settled:已结算、Paused:已暂停、Closed:已下线、CancelOnly:只能撤单)
|
|
|
|
|
+/// - `funding_fee_rate`: Decimal, 资金费率值
|
|
|
|
|
+/// - `predicted_funding_fee_rate`: Decimal, 预测资金费率值
|
|
|
|
|
+/// - `open_interest`: Decimal, 活动仓位数
|
|
|
|
|
+/// - `turnover_of24h`: Decimal, 24小时成交额
|
|
|
|
|
+/// - `volume_of24h`: Decimal, 24小时成交量
|
|
|
|
|
+/// - `mark_price`: Decimal, 标记价格
|
|
|
|
|
+/// - `index_price`: Decimal, 指数价格
|
|
|
|
|
+/// - `last_trade_price`: Decimal, 最新成交额
|
|
|
|
|
+/// - `next_funding_rate_time`: Decimal, 下次资金费率时间
|
|
|
|
|
+/// - `max_leverage`: Decimal, 最大可用杠杆
|
|
|
|
|
+/// - `source_exchanges`: Vec<String>, 该合约指数来源交易所
|
|
|
|
|
+/// - `premiums_symbol1m`: String, 溢价指数symbol(1分钟)
|
|
|
|
|
+/// - `premiums_symbol8h`: String, 溢价指数symbol(8小时)
|
|
|
|
|
+/// - `funding_base_symbol1m`: String, 基础货币利率symbol(1分钟)
|
|
|
|
|
+/// - `funding_quote_symbol1m`: String, 计价货币利率symbol(1分钟)
|
|
|
|
|
+/// - `low_price`: Decimal, 24小时最低成交价
|
|
|
|
|
+/// - `high_price`: Decimal, 24小时最高成交价
|
|
|
|
|
+/// - `price_chg_pct`: Decimal, 24小时涨跌幅
|
|
|
|
|
+/// - `price_chg`: Decimal, 24小时涨跌价格
|
|
|
|
|
+#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
+#[serde(rename_all = "camelCase")]
|
|
|
|
|
+struct SwapMarket {
|
|
|
|
|
+ symbol: String,
|
|
|
|
|
+ root_symbol: String,
|
|
|
|
|
+ #[serde(rename = "type")]
|
|
|
|
|
+ contract_type: String,
|
|
|
|
|
+ first_open_date: Option<Decimal>,
|
|
|
|
|
+ expire_date: Option<Decimal>,
|
|
|
|
|
+ settle_date: Option<Decimal>,
|
|
|
|
|
+ base_currency: String,
|
|
|
|
|
+ quote_currency: String,
|
|
|
|
|
+ settle_currency: String,
|
|
|
|
|
+ max_order_qty: Decimal,
|
|
|
|
|
+ max_price: Decimal,
|
|
|
|
|
+ lot_size: Decimal,
|
|
|
|
|
+ tick_size: Decimal,
|
|
|
|
|
+ index_price_tick_size: Decimal,
|
|
|
|
|
+ multiplier: Decimal,
|
|
|
|
|
+ initial_margin: Decimal,
|
|
|
|
|
+ maintain_margin: Decimal,
|
|
|
|
|
+ max_risk_limit: Decimal,
|
|
|
|
|
+ min_risk_limit: Decimal,
|
|
|
|
|
+ risk_step: Decimal,
|
|
|
|
|
+ maker_fee_rate: Decimal,
|
|
|
|
|
+ taker_fee_rate: Decimal,
|
|
|
|
|
+ taker_fix_fee: Decimal,
|
|
|
|
|
+ maker_fix_fee: Decimal,
|
|
|
|
|
+ settlement_fee: Option<Decimal>,
|
|
|
|
|
+ is_deleverage: bool,
|
|
|
|
|
+ is_quanto: bool,
|
|
|
|
|
+ is_inverse: bool,
|
|
|
|
|
+ mark_method: String,
|
|
|
|
|
+ fair_method: String,
|
|
|
|
|
+ funding_base_symbol: String,
|
|
|
|
|
+ funding_quote_symbol: String,
|
|
|
|
|
+ funding_rate_symbol: String,
|
|
|
|
|
+ index_symbol: String,
|
|
|
|
|
+ settlement_symbol: Option<String>,
|
|
|
|
|
+ status: String,
|
|
|
|
|
+ funding_fee_rate: Decimal,
|
|
|
|
|
+ predicted_funding_fee_rate: Decimal,
|
|
|
|
|
+ open_interest: Decimal,
|
|
|
|
|
+ turnover_of24h: Decimal,
|
|
|
|
|
+ volume_of24h: Decimal,
|
|
|
|
|
+ mark_price: Decimal,
|
|
|
|
|
+ index_price: Decimal,
|
|
|
|
|
+ last_trade_price: Decimal,
|
|
|
|
|
+ next_funding_rate_time: Decimal,
|
|
|
|
|
+ max_leverage: Decimal,
|
|
|
|
|
+ source_exchanges: Vec<String>,
|
|
|
|
|
+ premiums_symbol_1_m: String,
|
|
|
|
|
+ premiums_symbol_8_h: String,
|
|
|
|
|
+ funding_base_symbol_1_m: String,
|
|
|
|
|
+ funding_quote_symbol_1_m: String,
|
|
|
|
|
+ low_price: Decimal,
|
|
|
|
|
+ high_price: Decimal,
|
|
|
|
|
+ price_chg_pct: Decimal,
|
|
|
|
|
+ price_chg: Decimal,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// 处理合约行情信息
|
|
|
|
|
+///
|
|
|
|
|
+/// pub(crate) fn handle_swap_market(data: String, symbol: String) -> Market ;
|
|
|
|
|
+///
|
|
|
|
|
+/// - `data`:String, 交易所返回账户信息,JsonString
|
|
|
|
|
+/// - `symbol`:String, 交易币对
|
|
|
|
|
+pub(crate) fn handle_swap_market(data: String, symbol: String) -> Market {
|
|
|
|
|
+ let exchange_symbol = utils::symbol_mapper(KucoinSwapRest, &symbol);
|
|
|
|
|
+ let symbol_format = format!("{}M", utils::format_symbol(exchange_symbol.exchange_symbol.clone(), ""));
|
|
|
|
|
+ let market_info_list: Vec<SwapMarket> = serde_json::from_str(&data).unwrap();
|
|
|
|
|
+ let market_info = market_info_list.iter().find(|&item| item.symbol == symbol_format);
|
|
|
|
|
+ match market_info {
|
|
|
|
|
+ None => {
|
|
|
|
|
+ error!("Kucoin:获取Market信息错误!\nhandle_swap_market:data={:?}", data);
|
|
|
|
|
+ panic!("Kucoin:获取Market信息错误!\nhandle_swap_market:data={:?}", data)
|
|
|
|
|
+ }
|
|
|
|
|
+ Some(value) => {
|
|
|
|
|
+ let base_asset = if value.base_currency == exchange_symbol.base_asset.clone() { &value.base_currency } else { &exchange_symbol.base_asset };
|
|
|
|
|
+ Market {
|
|
|
|
|
+ symbol: format!("{}_{}", base_asset.clone(), value.quote_currency),
|
|
|
|
|
+ base_asset: base_asset.clone(),
|
|
|
|
|
+ quote_asset: value.quote_currency.clone(),
|
|
|
|
|
+ tick_size: value.tick_size.clone(),
|
|
|
|
|
+ amount_size: value.lot_size * value.multiplier,
|
|
|
|
|
+ price_precision: Decimal::from_u32(value.tick_size.scale()).unwrap(),
|
|
|
|
|
+ amount_precision: Decimal::from_u32((value.lot_size * value.multiplier).scale()).unwrap(),
|
|
|
|
|
+ min_qty: value.lot_size,
|
|
|
|
|
+ max_qty: value.max_order_qty,
|
|
|
|
|
+ min_notional: value.lot_size * value.multiplier,
|
|
|
|
|
+ max_notional: value.max_price,
|
|
|
|
|
+ ct_val: value.multiplier,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// Kucoin交易所行情信息请求数据结构
|
|
|
|
|
+/// - 接口`"/api/v1/orders/{order-id}?clientOid={client-order-id}"`
|
|
|
|
|
+///
|
|
|
|
|
+/// struct SwapOrder
|
|
|
|
|
+/// `id`: String 订单编号
|
|
|
|
|
+/// `symbol`: String, 合约编号
|
|
|
|
|
+/// `order_type`: String, 类型,市价单或限价单
|
|
|
|
|
+/// `side`: String, 买卖方向
|
|
|
|
|
+/// `price`: Decimal, 下单价格
|
|
|
|
|
+/// `size`: Decimal, 数量
|
|
|
|
|
+/// `value`: Decimal, 订单价值
|
|
|
|
|
+/// `deal_value`: Decimal, 成交价
|
|
|
|
|
+/// `deal_size`: Decimal, 成交数量
|
|
|
|
|
+/// `stp`: Option<String>, 类型
|
|
|
|
|
+/// `stop`: String, 止损订单类型
|
|
|
|
|
+/// `stop_price_type`: String, 止损订单触发价格类型
|
|
|
|
|
+/// `stop_triggered`: bool, 止损订单是否触发标志
|
|
|
|
|
+/// `stop_price`: Option<Decimal>, 止损订单触发价格
|
|
|
|
|
+/// `time_in_force`: String, timeInForce类型
|
|
|
|
|
+/// `post_only`: bool, postOnly标志
|
|
|
|
|
+/// `hidden`: bool, 隐藏单标志
|
|
|
|
|
+/// `iceberg`: bool, 冰山单标志
|
|
|
|
|
+/// `leverage`: Decimal, 杠杆倍数
|
|
|
|
|
+/// `force_hold`: bool, 强制冻结单标志
|
|
|
|
|
+/// `close_order`: bool, 平仓单标志
|
|
|
|
|
+/// `visible_size`: Option<Decimal>, 冰山单可见数量
|
|
|
|
|
+/// `client_oid`: String, 客户订单编号
|
|
|
|
|
+/// `remark`: Option<String>, 注解
|
|
|
|
|
+/// `tags`: Option<String>, 订单标签
|
|
|
|
|
+/// `is_active`: bool, 未完成订单标志
|
|
|
|
|
+/// `cancel_exist`: bool, 订单存在取消数量标志
|
|
|
|
|
+/// `created_at`: i64, 创建时间
|
|
|
|
|
+/// `updated_at`: i64, 最新更新时间
|
|
|
|
|
+/// `end_at`: Option<i64>, 截止时间
|
|
|
|
|
+/// `order_time`: i128, 下单时间纳秒
|
|
|
|
|
+/// `settle_currency`: String, 结算币种
|
|
|
|
|
+/// `status`: String, 订单状态open或done
|
|
|
|
|
+/// `filled_value`: Decimal, 已经成交订单价值
|
|
|
|
|
+/// `filled_size`: Decimal, 已经成交订单数量
|
|
|
|
|
+/// `reduce_only`: bool, 只减仓标记
|
|
|
|
|
+#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
|
+#[serde(rename_all = "camelCase")]
|
|
|
|
|
+struct SwapOrder {
|
|
|
|
|
+ id: String,
|
|
|
|
|
+ symbol: String,
|
|
|
|
|
+ #[serde(rename = "type")]
|
|
|
|
|
+ order_type: String,
|
|
|
|
|
+ side: String,
|
|
|
|
|
+ price: Decimal,
|
|
|
|
|
+ size: Decimal,
|
|
|
|
|
+ value: Decimal,
|
|
|
|
|
+ deal_value: Decimal,
|
|
|
|
|
+ deal_size: Decimal,
|
|
|
|
|
+ stp: Option<String>,
|
|
|
|
|
+ stop: String,
|
|
|
|
|
+ stop_price_type: String,
|
|
|
|
|
+ stop_triggered: bool,
|
|
|
|
|
+ stop_price: Option<Decimal>,
|
|
|
|
|
+ time_in_force: String,
|
|
|
|
|
+ post_only: bool,
|
|
|
|
|
+ hidden: bool,
|
|
|
|
|
+ iceberg: bool,
|
|
|
|
|
+ leverage: Decimal,
|
|
|
|
|
+ force_hold: bool,
|
|
|
|
|
+ close_order: bool,
|
|
|
|
|
+ visible_size: Option<Decimal>,
|
|
|
|
|
+ client_oid: String,
|
|
|
|
|
+ remark: Option<String>,
|
|
|
|
|
+ tags: Option<String>,
|
|
|
|
|
+ is_active: bool,
|
|
|
|
|
+ cancel_exist: bool,
|
|
|
|
|
+ created_at: i64,
|
|
|
|
|
+ updated_at: i64,
|
|
|
|
|
+ end_at: Option<i64>,
|
|
|
|
|
+ order_time: i128,
|
|
|
|
|
+ settle_currency: String,
|
|
|
|
|
+ status: String,
|
|
|
|
|
+ filled_value: Decimal,
|
|
|
|
|
+ filled_size: Decimal,
|
|
|
|
|
+ reduce_only: bool,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// 处理合约订单信息
|
|
|
|
|
+///
|
|
|
|
|
+/// pub(crate) fn handle_swap_order(data: String, ct_val: Decimal) -> Order;
|
|
|
|
|
+///
|
|
|
|
|
+/// - `data`:String, 交易所返回账户信息,JsonString
|
|
|
|
|
+/// - `ct_val`:Decimal, 张数价值
|
|
|
|
|
+pub(crate) fn handle_swap_order(data: String, ct_val: Decimal) -> Order {
|
|
|
|
|
+ let order_info: SwapOrder = serde_json::from_str(&data).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let status = order_info.status;
|
|
|
|
|
+ let deal_amount = order_info.filled_size * ct_val;
|
|
|
|
|
+ let avg_price = if deal_amount.is_zero() { dec!(0) } else { order_info.filled_value / deal_amount };
|
|
|
|
|
+ let custom_status = match status.as_str() {
|
|
|
|
|
+ "open" => { "NEW".to_string() }
|
|
|
|
|
+ "cancelled" => { "REMOVE".to_string() }
|
|
|
|
|
+ "closed" => { "REMOVE".to_string() }
|
|
|
|
|
+ "finished" => { "REMOVE".to_string() }
|
|
|
|
|
+ _ => {
|
|
|
|
|
+ error!("Kucoin:格式化订单状态错误!\nhandle_swap_order:status={}", status);
|
|
|
|
|
+ panic!("Kucoin:格式化订单状态错误!\nhandle_swap_order:status={}", status)
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ Order {
|
|
|
|
|
+ id: order_info.id,
|
|
|
|
|
+ custom_id: order_info.client_oid,
|
|
|
|
|
+ price: order_info.price,
|
|
|
|
|
+ amount: order_info.size * ct_val,
|
|
|
|
|
+ deal_amount,
|
|
|
|
|
+ avg_price,
|
|
|
|
|
+ status: custom_status,
|
|
|
|
|
+ order_type: order_info.order_type,
|
|
|
|
|
+ }
|
|
|
|
|
+}
|