| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- use crate::exchange_middle_ware::{Depth, Record};
- // 获取买一卖一价差(spread)、中间价
- pub fn get_spread(depth: &Depth) -> (f64, f64, f64, f64) {
- // 定义一个乘法系数,主要是防止f64精度丢失问题
- let mul = 1e6;
- let ask = depth.asks[0].price;
- let bid = depth.bids[0].price;
- let spread = (ask * mul - bid * mul) / mul;
- let price_diff = (ask * mul + bid * mul) / (2f64 * mul);
- return (spread, price_diff, ask, bid);
- }
- // 计算最近N根K线的收盘价的标准差
- pub fn std_n_by_records(records: &Vec<Record>, n: usize) -> f64 {
- let close_list: Vec<_> = records.iter().rev().take(n).map(|r| r.close).collect();
- let count = close_list.len();
- let mean = close_list.iter().sum::<f64>() / (count as f64);
- let variance = close_list.iter().map(|&value| {
- let diff = mean - value;
- diff * diff
- }).sum::<f64>() / count as f64;
- return variance.sqrt();
- }
- // 计算gamma值
- // max_spread: 最大价差
- // q: 库存价值
- // std: 标准差
- pub fn calc_gamma(max_spread: f64, q: f64, std: f64) -> f64 {
- return max_spread / ((2f64) * q * std.powf(2f64));
- }
- // 计算价格偏差范围(加权平均值)
- pub fn calc_deviation_range(max_ira: f64, spread_list: &Vec<f64>, ira: f64) -> f64 {
- let max_spread = spread_list.iter().cloned().fold(f64::NAN, f64::max);
- let min_spread = spread_list.iter().cloned().fold(f64::NAN, f64::min);
- return (max_ira - ira) * max_spread + ira * min_spread;
- }
- // 计算Reservation price(预定价格)
- // s = midprice = 当前市场中间价
- // q = 基础资产库存中的资产数量(多头/空头头寸可为正值/负值)
- // (gamma * i) = γ = 库存风险规避参数
- // σ = std = 市场波动率
- // i = 当前第几个ira
- // 1 = T-t = 关闭时间,即测量周期结束时(方便地归一化为 1),当前时间(T 归一化 = 1,因此 t 是时间分数)
- pub fn calc_rp(mid_price: f64, quantity: f64, ira: f64, gamma: f64, std: f64) -> f64 {
- return mid_price - quantity * (gamma * ira) * 1f64 * std.powf(2f64);
- }
- pub fn calc_dk(deviation_range: f64, gamma: f64, std: f64, ira: f64) -> f64 {
- return (deviation_range * (gamma * ira) - std.powf(2f64) * (gamma * ira).powf(2f64)) / 2f64;
- }
- pub fn calc_kappa(gamma: f64, dk: f64, deviation_range: f64, ira: f64) -> f64 {
- return ((gamma * ira) / ( std::f64::consts::E.powf(dk) - 1f64)) / deviation_range;
- }
- // 核心公式二 Optimal bid & ask spread 最佳买卖价差
- // δa、δb = cal_theta = 买入/卖出价差,对称 → δa=δb
- // (gamma * i) = γ = 库存风险规避参数
- // σ = std = 市场波动率
- pub fn calc_theta(gamma: f64, std: f64, kappa: f64, ira: f64) -> f64 {
- let a = (gamma * ira) * std.powf(2f64);
- let b = 2f64 / (gamma * ira) * (1f64 + (gamma * ira) / kappa).ln();
- return (a + b) / 2f64;
- }
- // 给定ira、当前库存、最大库存、买入价格、下单数量小数位数,计算合理下单数量
- // 下单数量要与ira(风险系数)、quantity(库存)成反比
- pub fn calc_order_amount(ira_max: f64, ira: f64, quantity: f64, quantity_max: f64, bid_price: f64, amount_decimal_places: usize) -> f64 {
- let eta = (ira / ira_max) / (1.0 + quantity * 2.0);
- let order_value_base = (-quantity * eta).abs();
- let order_value = (quantity_max * 1.0/50.0) * (1.0 - order_value_base / quantity_max);
- let order_amount = order_value / bid_price;
- return truncate_decimal_places(order_amount, amount_decimal_places);
- }
- // 保留指定位数的小数
- pub fn truncate_decimal_places(num: f64, decimal_places: usize) -> f64 {
- let multiplier = 10f64.powi(decimal_places as i32);
- (num * multiplier).trunc() / multiplier
- }
- // 单元测试集
- #[cfg(test)]
- mod tests {
- // use crate::exchange_middle_ware::{get_binance_depth, get_binance_klines};
- use super::*;
- // #[tokio::test]
- // async fn test_get_spread() {
- // let depth = get_binance_depth(&"BTC_USDT".to_string(), 100i32).await;
- // let ask = depth.asks[0].price;
- // let bid = depth.bids[0].price;
- //
- // println!("ask={}, bid={}", ask, bid);
- // println!("{:?}", get_spread(&depth))
- // }
- #[test]
- fn test_std_n_by_records() {
- let records = vec![
- Record{
- time: 1567736576000,
- open: 1000.0,
- high: 1500.0,
- low: 900.9,
- close: 1200.9,
- volume: 1000000.0,
- }, Record{
- time: 1567736576000,
- open: 1000.0,
- high: 1500.0,
- low: 900.9,
- close: 1219.9,
- volume: 1000000.0,
- }, Record{
- time: 1567736576000,
- open: 1000.0,
- high: 1500.0,
- low: 900.9,
- close: 1218.1,
- volume: 1000000.0,
- }];
- println!("{}", std_n_by_records(&records, 3))
- }
- #[test]
- fn test_calc_gamma() {
- println!("{}", calc_gamma(0.1, 49.0, 23.0))
- }
- #[test]
- fn test_calc_deviation_range() {
- let max_ira = 10.0;
- let ira = 0.1;
- let spread_list = vec![
- 0.1,
- 0.2,
- 0.15,
- 0.1
- ];
- println!("{}", calc_deviation_range(max_ira, &spread_list, ira));
- }
- #[test]
- fn test_calc_rp() {
- let mid_price = 1992.01;
- let quantity = 49.0;
- let ira = 0.1;
- let gamma = 1.9289379267775165e-06;
- let std = 23.0;
- println!("{}", calc_rp(mid_price, quantity, ira, gamma, std));
- }
- #[test]
- fn test_calc_dk() {
- let deviation_range = 1.9900000000000002;
- let ira = 0.1;
- let gamma = 1.9289379267775165e-06;
- let std = 23.0;
- println!("{}", calc_dk(deviation_range, gamma, std, ira));
- }
- #[test]
- fn test_calc_kappa() {
- let deviation_range = 1.9900000000000002;
- let ira = 0.1;
- let gamma = 1.9289379267775165e-06;
- let dk = 0.00000019191948219432835;
- println!("{}", calc_kappa(gamma, dk, deviation_range, ira));
- }
- #[test]
- fn test_calc_order_amount() {
- let quantity = 10.0;
- let quantity_max = 20.0;
- let bid_price = 28684.0;
- let amount_decimal_places = 8;
- let start = 0.1;
- let end = 10.0;
- let step = 0.1;
- let mut ira = start;
- while ira <= end {
- println!("ira={}, order_amount={}", ira, calc_order_amount(end, ira, quantity, quantity_max, bid_price, amount_decimal_places));
- ira += step;
- }
- }
- }
|