带止盈止损的量化交易订单模拟

在进行量化交易回测的过程中,我们总会遇到一些净值如何模拟的问题,尤其是带止盈止损的订单。

注:

1.本次回测的代码忽略了一些情况,是因为笔者本次不会遇到这些情况,但如果你需要,可以在此基础上稍作修改;

2.本次代码使用C++编写,如果你希望在python中实现,只需要编译为二进制文件即可(当然,如果你使用的不是python3.11,那么需要对代码进行一些修改)。

多的不说,直接上代码。

#include <iostream>
#include <vector>
#include <map>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

/*
conds的表示
+0.000:空仓
+0.010:多头持仓
-0.010:空头持仓
+0.100:多头开仓
-0.100:空头开仓
+0.001:多头平仓
-0.001:空头平仓
+0.101:多头开仓平仓(本次不考虑)
-0.101:空头开仓平仓(本次不考虑)

小数点后一位:是否有开仓动作
小数点后两位:是否全程持仓
小数点后三位:是否有平仓动作
*/

struct PLSInput{

    double principal;
    double proportion;
    double MakerFee;
    double TakerFee;
    unsigned int leverage;

    std::vector<int> signal;    //开仓信号(0,1,-1)
    std::vector<double> open;   //开仓价
    std::vector<double> close;  //收盘价
    std::vector<double> high;
    std::vector<double> low;
    std::vector<double> ps;     //止盈点
    std::vector<double> ls;     //止损点
    std::vector<size_t> remain; //最大持续时长

    bool useable(){
        if (signal.size() != open.size()) return false;
        if (signal.size() != close.size()) return false;
        if (signal.size() != ps.size()) return false;
        if (signal.size() != ls.size()) return false;
        if (signal.size() != remain.size()) return false;
        return true;
    }
};

struct result{
    std::vector<double> net_value;
    std::vector<double> conds;
};

result plsValue(PLSInput plsinput){
    
    // 初始化变量
    const size_t n = plsinput.signal.size();
    result orders;
    std::vector<double> net_value(n, plsinput.principal);
    std::vector<double> conds(n, 0.0);

    // 判断输入是否正确
    if (!plsinput.useable()){
        orders.conds = conds;
        orders.net_value = net_value;
        return orders;
    }

    // 输入正确后,处理程序
    for (size_t i=1; i<n; i++){

        double net = net_value[i - 1];

        // 无信号
        if (plsinput.signal[i] == 0){
            conds[i] = 0.000;
            net_value[i] = net;
        }

        // 多头信号
        else if (plsinput.signal[i] == 1){
            
            // 计算开仓数额,浮动与固定
            const double open_price = plsinput.open[i];
            const int quants = static_cast<int>(net * plsinput.leverage * plsinput.proportion / open_price);
            const double fixed = net - quants * open_price * plsinput.MakerFee;
            const double ps = plsinput.ps[i];
            const double ls = plsinput.ls[i];
            double floated = quants * (open_price - plsinput.close[i]);

            conds[i] = 0.100;
            net_value[i] = floated + fixed;
            size_t j = 1;

            while (j <= plsinput.remain[i]){
                if (plsinput.low[i + j] >= ls){
                    floated = quants * (ls - open_price);
                    conds[i + j] = 0.001;
                    net_value[i + j] = floated + fixed - quants * ls * (1 - plsinput.TakerFee);
                    j++;
                    break;
                }
                else if (plsinput.high[i + j] <= ps){
                    floated = quants * (ps - open_price);
                    conds[i + j] = 0.001;
                    net_value[i + j] = floated + fixed - quants * ps * (1 - plsinput.TakerFee);
                    j++;
                    break;
                }
                else{
                    floated = quants * (plsinput.close[i + j] - open_price);
                    conds[i + j] = 0.010;
                    net_value[i + j] = j < plsinput.remain[i] ? floated + fixed : floated + fixed - quants * plsinput.close[i + j] * (1 - plsinput.TakerFee);
                    j++;
                    if (i + j >= n) break;
                }
            }

            i = i + j;
        }

        // 空头信号
        else{
            
            // 计算开仓数额,浮动与固定
            const double open_price = plsinput.open[i];
            const int quants = static_cast<int>(net * plsinput.leverage * plsinput.proportion / open_price);
            const double fixed = net - quants * open_price * plsinput.MakerFee;
            const double ps = plsinput.ps[i];
            const double ls = plsinput.ls[i];
            double floated = quants * (open_price - plsinput.close[i]) * (-1.0);

            conds[i] = -0.100;
            net_value[i] = floated + fixed;
            size_t j = 1;

            while (j <= plsinput.remain[i]){
                if (plsinput.low[i + j] >= ls){
                    floated = quants * (ls - open_price) * (-1.0);
                    conds[i + j] = -0.001;
                    net_value[i + j] = floated + fixed - quants * ls * (1 - plsinput.TakerFee);
                    j++;
                    break;
                }
                else if (plsinput.high[i + j] <= ps){
                    floated = quants * (ps - open_price) * (-1.0);
                    conds[i + j] = -0.001;
                    net_value[i + j] = floated + fixed - quants * ps * (1 - plsinput.TakerFee);
                    j++;
                    break;
                }
                else{
                    floated = quants * (plsinput.close[i + j] - open_price) * (-1.0);
                    conds[i + j] = -0.010;
                    net_value[i + j] = j < plsinput.remain[i] ? floated + fixed : floated + fixed - quants * plsinput.close[i + j] * (1 - plsinput.TakerFee);
                    j++;
                    if (i + j >= n) break;
                }
            }

            i = i + j;
        }
    }

    orders.conds = conds;
    orders.net_value = net_value;
    return orders;
}


namespace py = pybind11;

PYBIND11_MODULE(plsValue, m) {
    m.def("plsValue", &plsValue, "plsValue");
}

原创代码,笔者水平有限,且目前代码还未经过大量检验,如有瑕疵,敬请谅解。如有需要,可以与笔者交流。

邮箱:ldy675391321@gmail.com

作者:DINO

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值