跳转至

教程:统计套利策略

我们将在本教程中创建一个统计套利交易应用程序。 监控同一市场不同合约的数据,当差价偏离上期平均值的一定标准差时进行套利操作。

前腿交易放在一个单一的策略 Arb1Strategy 中,后腿交易放在另一个策略 Arb2Strategy 中。

当 Arb1Strategy 完成前腿交易后,账户的整体风险将传递到后腿进行相应的套期保值操作,从而完成整个套利过程。

创建套利策略的步骤


要创建灵活的策略,您需要执行以下操作:

  1. 决定交易哪个交易所。
  2. 添加您计划交易的品种或收听市场数据。 3.增加价格模型。
  3. 添加变量以生成信号。
  4. 添加模型。
  5. 添加策略。 查看更多详细信息-> quantlib_configuration 参考

Configure

我们使用 json 文件来配置交易应用程序。 该文件包含有关 api 密钥、日志路径和策略组件的信息。 请更新以下示例配置中的 API 密钥信息:

{
    "instance": {
        "license_id":"TRAIL001",
        "license_key":"apifiny123456",
        "log_path": "/data/cc/logs",
        "name": "sim1"
    },
    "sim": {
        "ioc_only": false,
        "use_tbbo": true,
        "delay_o2a_us": 0,
        "delay_a2m_us": 0
    },
    "fees": {
        "OKEX_SWAP": {
            "make": 0.0002,
            "take": 0.0004
        },
        "OKEX": {
            "make": 0.0003,
            "take": 0.0005
        }
    },
    "players": [
        ["BSVUSDTSWAP.OKEXSWAP_Player", ["CobJsonPlayer", {"port": ["BSVUSDTSWAP", "OKEX_SWAP"], "path": "/data/cc/cob_data"}]], 
        ["BSVUSDSWAP.OKEXSWAP_Player", ["CobJsonPlayer", {"port": ["BSVUSDSWAP", "OKEX_SWAP"], "path": "/data/cc/cob_data"}]]
    ],
    "risk_formulas": [
        ["Port_Risk", ["RiskFormula", {"components": [[["BSVUSDTSWAP", "OKEX_SWAP"], 1.0], [["BSVUSDSWAP", "OKEX_SWAP"], 1.0]]}]]
    ],
    "accounts": [
        [10001, ["Account", {"risk_formulas": ["Port_Risk"], "id": 10001}]]
    ],
    "symbols": [
        {"port": ["BSVUSDTSWAP", "OKEX_SWAP"], "cid": 10001}, 
        {"port": ["BSVUSDSWAP", "OKEX_SWAP"], "cid": 10002}
    ],
    "samplers": [
        ["std_sampler", ["TimeSampler", {"halflife": 1800, "msecs": 60000}]]
    ],
    "pricing_models": [
        ["BSVUSDTSWAP.OKEX_SWAP_askpx", ["AskPx", {"port": ["BSVUSDTSWAP", "OKEX_SWAP"]}]], 
        ["BSVUSDTSWAP.OKEX_SWAP_bidpx", ["BidPx", {"port": ["BSVUSDTSWAP", "OKEX_SWAP"]}]], 
        ["BSVUSDTSWAP.OKEX_SWAP_midpx", ["MidPx", {"port": ["BSVUSDTSWAP", "OKEX_SWAP"]}]],
        ["BSVUSDSWAP.OKEX_SWAP_askpx", ["AskPx", {"port": ["BSVUSDSWAP", "OKEX_SWAP"]}]],
        ["BSVUSDSWAP.OKEX_SWAP_bidpx", ["BidPx", {"port": ["BSVUSDSWAP", "OKEX_SWAP"]}]],
        ["BSVUSDSWAP.OKEX_SWAP_midpx", ["MidPx", {"port": ["BSVUSDSWAP", "OKEX_SWAP"]}]]
    ],
    "variables": [
        ["VAR_A_askpx", ["PriceVar", {"pm": "BSVUSDTSWAP.OKEX_SWAP_askpx"}]], 
        ["VAR_A_bidpx", ["PriceVar", {"pm": "BSVUSDTSWAP.OKEX_SWAP_bidpx"}]], 
        ["VAR_A_midpx", ["PriceVar", {"pm": "BSVUSDTSWAP.OKEX_SWAP_midpx"}]], 
        ["VAR_B_askpx", ["PriceVar", {"pm": "BSVUSDSWAP.OKEX_SWAP_askpx"}]], 
        ["VAR_B_bidpx", ["PriceVar", {"pm": "BSVUSDSWAP.OKEX_SWAP_bidpx"}]],
        ["VAR_B_midpx", ["PriceVar", {"pm": "BSVUSDSWAP.OKEX_SWAP_midpx"}]],
        ["RGAP_SBBA", ["Ratio", {"v1": "VAR_B_askpx", "v2": "VAR_A_askpx"}]], 
        ["RGAP_BBSA", ["Ratio", {"v1": "VAR_B_bidpx", "v2": "VAR_A_bidpx"}]], 
        ["RM_BDA", ["Ratio", {"v1": "VAR_B_midpx", "v2": "VAR_A_midpx"}]],
        ["EMA_SBBA", ["VarEma", {"variable": "RGAP_SBBA", "sampler": "std_sampler"}]],
        ["EMA_BBSA", ["VarEma", {"variable": "RGAP_BBSA", "sampler": "std_sampler"}]],
        ["STD_SBBA", ["VarStd2", {"variable": "RGAP_SBBA", "init_var_value": 1,"init_std_value": 0.0006,"sampler": "std_sampler"}]],
        ["STD_BBSA", ["VarStd2", {"variable": "RGAP_BBSA", "init_var_value": 1,"init_std_value": 0.0006,"sampler": "std_sampler"}]],
        ["UP", ["Add", {"v1": "EMA_SBBA", "v2": "STD_SBBA"}]],  
        ["DOWN", ["Sub", {"v1": "EMA_BBSA", "v2": "STD_BBSA"}]],  
        ["SELL_UP", ["GreaterThan", {"v1": "RGAP_SBBA", "v2": "UP"}]],  
        ["BUY_DOWN", ["LessThan", {"v1": "RGAP_BBSA", "v2": "DOWN"}]]
    ],
    "models": [
        ["model_a", ["SimpleModel", {"variable": "RM_BDA"}]], 
        ["model_b", ["SimpleModel", {"variable": "RM_BDA"}]]
    ],
    "strategies": [
        ["Arb01", ["Arb1Strategy", {"symbol": "BSVUSDTSWAP", "trade_market": "OKEX_SWAP","risk_id":0, "use_margin": true, "account": 10001, "use_separate_logs": true, "model": "model_a","rbda": "RM_BDA","sell_up": "SELL_UP","buy_down": "BUY_DOWN", "order_notional": 100, "max_notional": 1000, "max_risk": 500, "start_time": "00:30:00", "end_time": "23:59:59"}]],
        ["Arb02", ["Arb2Strategy", {"symbol": "BSVUSDSWAP", "trade_market": "OKEX_SWAP","risk_id":0,  "use_margin": true, "account": 10001, "use_separate_logs": true, "model": "model_a", "max_notional": 1000, "max_risk": 500, "start_time": "00:30:00", "end_time": "23:59:59"}]]
}

统计套利原理

统计套利是在对历史数据进行统计分析的基础上,估计相关变量的概率分布,结合基本面数据进行分析,指导套利交易。 与无风险套利相比,统计套利在少量增加了一些风险,但从中获得的套利机会将是无风险套利的数倍。 统计套利的基本思想是利用统计分析工具研究分析一组相关价格之间关系的历史数据,研究该关系在历史上的稳定性,并估计其概率分布,确定价格区间内的极值区域。 分布,即负域,当真实的价格关系进入负域时,认为价格关系不能长期维持,套利者套利成功概率较高

Steps of this Statistical Arbitrage

  1. sbba = 合约 b 的卖价 / 合约 a 的卖价
  2. bbsa = 合同 b 的投标价格 / 合同 a 的投标价格
  3. sbba 代表 action 卖出 B 合约,买入等值的 A 合约
  4. bbsa代表action 买B合约,卖A合约等值
  5. sbba可以计算其过去一段时间内的ema std值,即sbba_ema, sbba_std
  6. bbsa可以计算其过去一段时间内的ema std值,即bbsa_ema, bbsa_std
  7. 当实时sbba大于sbba_ema+sbba_std时,进行sbba动作。
  8. 当实时bbsa大于bbsa_ema-bbsa_std时,做bbsa动作。

Get data and algo sdk

在 -> 下载 中获取 Sim 数据 (quantlib_data.tar.gz) 和 algo sdk

unpack algo sdk to algo_sdk/bin/xlibs unpack quantlib_data.tar.gz to /data/cc/cob_data

Run

Arb 策略依赖于多个共享库,因此您需要先设置一些环境变量。

使用 algo_sdk 的路径设置环境变量 ALGO_HOME。 例如 /data/cc/algo_sdk:

export ALGO_HOME=YOUR_ALGO_SDK_PATH

Setup other environment variables:

export TZ=UTC
export LD_LIBRARY_PATH=${ALGO_HOME}/bin:$LD_LIBRARY_PATH
export PATH=${ALGO_HOME}/bin:$PATH

You can simulate the application now. It takes one command line argument, which is the path to a json configuration file.

ccc_sim_trader ${ALGO_HOME}/examples/arbitrage/cfg/arbitrage001.json 20220705

You can visualize the simulation results of the strategy in the form of a graph.

cd ~/code/algo_sdk/scripts
python3 sim_ana.py -p /data/cc/logs -sd 20220705 -ed 20220705
The results like this