Crates.io | qust |
lib.rs | qust |
version | 0.1.5 |
source | src |
created_at | 2024-09-28 17:21:10.828444 |
updated_at | 2024-11-16 10:48:38.939076 |
description | A crate for finance quantative reserach |
homepage | |
repository | https://github.com/baiguoname/qust |
max_upload_size | |
id | 1390250 |
size | 337,352 |
Qust is a Rust libraries for building live-trading and back-test systems. It has the following features:
Accept kline flow, and return a target position.
Accept tick data flow, and return a target position.
Accept tick data flow, and return an order action.
Accept kline and tick flow, return a target positon or an order action.
Accept kline flow, and return a bool.(a least two of it make a strategy, one for open position, another for close)
Add filter conditions to an existed strategy.
Add algorithm method to an existed strategy.
Add order matching methods when backtest a strategy.
Add valitality manager to strategies.
Add portoflio manager to a pool of strategies. and so on.
See this notebook Example for more detail.
Add this to Cargo.toml
:
qust-derive = { version = ">=0.1" }
qust-ds = { version = ">=0.1" }
qust = { version = ">=0.1" }
qust-api = { version = ">=0.1"}
qust-io = { version = ">=0.1"}
serde = "*"
serde_json = "*"
itertools = "*"
typetag = "*"
tokio = "*"
ta = { version = "0.5.0" }
You can build a strategy basing on kline data and backtest in on kline:
use qust_derive::*;
use qust_ds::prelude::*;
use qust::prelude::*;
use qust_api::prelude::*;
use qust_io::prelude::*;
use ta::{ Next, indicators::SimpleMovingAverage as SMA };
#[ta_derive2]
pub struct TwoMaStra {
pub short_period: usize,
pub long_period: usize,
}
#[typetag::serde]
impl Ktn for TwoMaStra {
fn ktn(&self,_di: &Di) -> RetFnKtn {
let mut last_norm_hold = NormHold::No;
let mut short_ma = SMA::new(self.short_period).unwrap();
let mut long_ma = SMA::new(self.long_period).unwrap();
let mut last_short_value = 0f64;
let mut last_long_value = 0f64;
Box::new(move |di_kline| {
let c = di_kline.di.c()[di_kline.i] as f64;
let short_value = short_ma.next(c);
let long_value = long_ma.next(c);
match last_norm_hold {
NormHold::No if di_kline.i != 0 => {
if last_short_value < last_long_value && short_value >= long_value {
last_norm_hold = NormHold::Lo(1.);
}
}
NormHold::Lo(_) if short_value < long_value => {
last_norm_hold = NormHold::No;
}
_ => {}
}
last_short_value = short_value;
last_long_value = long_value;
last_norm_hold.clone()
})
}
}
#[tokio::main]
async fn main() {
let di = read_remote_kline_data().await;
let two_ma_stra = TwoMaStra { short_period: 9, long_period: 20 };
let two_ma_stra_ptm: Ptm = two_ma_stra.ktn_box().to_ktn().to_ptm();
let pnl_res_dt: PnlRes<dt> = two_ma_stra_ptm.bt_kline((&di, cs1));
pnl_res_dt.to_csv("pnl_res_dt.csv"); // save the pnl to local csv;
}
ApiBridgeBox
)都有自身的订单管理,api程序停止运行后,到下次重开程序,中间过程中如果没有手动开平仓,历史的订单会被读取