python上证指数网格交易收益验证

145 阅读4分钟
# -*- coding: utf-8 -*-
# @Python  : Python3.8
"""
总结
1. 交费费用在千分之一和万分之二之间,影响甚小
2. 网格越小,则交易频次越高,收益越高,占用资金越大
3. 网格金额越大,收益越大,占用资金越大,呈正比关系,交易频次不变
4. 合适的网格在100-200之间
5. 收益不高,和银行利率相差无几

2000-4000,网格50,网格金额1万,2020-01-01至2023-12-07,收益34431,交易次数242,最大资金占用26万
2000-4000,网格100,网格金额1万,2020-01-01至2023-12-07,收益16974,交易次数86,最大资金占用13万
2000-4000,网格200,网格金额1万,2020-01-01至2023-12-07,收益9818,交易次数32,最大资金占用6万
2000-4000,网格300,网格金额1万,2020-01-01至2023-12-07,收益5697,交易次数14,最大资金占用4万
2000-4000,网格400,网格金额1万,2020-01-01至2023-12-07,收益3785,交易次数8,最大资金占用3万

2000-4000,网格50,网格金额2万,2020-01-01至2023-12-07,收益68863,交易次数242,最大资金占用52万
2000-4000,网格100,网格金额2万,2020-01-01至2023-12-07,收益33949,交易次数86,最大资金占用26万
2000-4000,网格200,网格金额2万,2020-01-01至2023-12-07,收益19636,交易次数32,最大资金占用12万
2000-4000,网格300,网格金额2万,2020-01-01至2023-12-07,收益11395,交易次数14,最大资金占用8万
2000-4000,网格400,网格金额2万,2020-01-01至2023-12-07,收益7571,交易次数8,最大资金占用6万

"""
import time
import pandas as pd


class BuyRecord:
    def __init__(self, low_index, high_index, bug_index, hold_weight):
        self.low_index = low_index
        self.high_index = high_index
        self.bug_index = bug_index
        self.hold_weight = hold_weight

    def info(self):
        print("low_index:{},high_index:{},bug_index:{},hold_weight:{}".format(self.low_index, self.high_index,
                                                                              self.bug_index, self.hold_weight))


class MyModel:
    def __init__(self, min_index: float = 2000, max_index: float = 4000, grid: float = 400.0,
                 grid_money: float = 20000.0, cost_rate: float = 0.0002):
        self.min_index = min_index
        self.max_index = max_index
        self.grid = grid
        self.grid_money = grid_money
        self.cost_rate = cost_rate
        self.income = 0
        self.buy_record = []
        self.opt_info_record = []
        self.max_money_used = 0
        self.opt_print = False
        tmp_index = min_index
        while tmp_index < max_index:
            buy_record = BuyRecord(tmp_index, tmp_index + grid, None, 0)
            self.buy_record.append(buy_record)
            tmp_index = tmp_index + grid
        # print([i.info() for i in self.buy_record])

    def set_opt_print(self, opt_print=False):
        self.opt_print = opt_print

    def opt(self, current_time, current_index):
        current_opt_info = ["{},当前指数:{}".format(current_time, current_index)]
        for record in self.buy_record:
            if record.hold_weight == 0:
                if current_index < record.low_index:
                    record.hold_weight = 1
                    record.bug_index = current_index
                    opt_info = "{},【买入】,买入阈值:{},买入值:{}".format(current_time, record.low_index, current_index)
                    current_opt_info.append(opt_info)
                    self.opt_info_record.append(opt_info)
            else:
                if current_index > record.high_index:
                    current_income = self.grid_money * (
                            (current_index - record.bug_index) / record.bug_index - self.cost_rate)
                    self.income = self.income + current_income
                    opt_info = "{},【卖出】,卖出阈值:{},买入值:{},卖出值:{},当前收益:{},总收益:{}".format(current_time, record.high_index,
                                                                                     record.bug_index,
                                                                                     current_index,
                                                                                     current_income, self.income)
                    current_opt_info.append(opt_info)
                    self.opt_info_record.append(opt_info)
                    record.hold_weight = 0
                    record.bug_index = None
        money_use = len([i for i in self.buy_record if i.hold_weight != 0]) * self.grid_money
        current_opt_info.append("当前资金占用:{}".format(money_use))
        if self.max_money_used < money_use:
            self.max_money_used = money_use
        if self.opt_print:
            print("|".join(current_opt_info))

    def clear(self, current_time, current_index):
        current_opt_info = ["【清仓】 {},当前指数:{}".format(current_time, current_index)]
        for record in self.buy_record:
            if record.hold_weight == 1:
                current_income = self.grid_money * (
                        (current_index - record.bug_index) / record.bug_index - self.cost_rate)
                self.income = self.income + current_income
                opt_info = "【清仓】 {},【卖出】,卖出阈值:{},买入值:{},卖出值:{},当前收益:{},总收益:{}".format(current_time, record.high_index,
                                                                                      record.bug_index,
                                                                                      current_index,
                                                                                      current_income, self.income)
                current_opt_info.append(opt_info)
                self.opt_info_record.append(opt_info)
                record.hold_weight = 0
                record.bug_index = None
        print("|".join(current_opt_info))

    def stat(self):
        print("-" * 120)
        print("总收益:{}".format(self.income))
        print("最大资金占用:{}".format(self.max_money_used))
        print("交易次数:{}".format(len(self.opt_info_record)))
        print("当前持有:{}".format([i.info() for i in self.buy_record if i.hold_weight != 0]))
        print("交易详情:")
        for info in self.opt_info_record:
            print(info)

    def clear_and_stat(self, current_time, current_index):
        self.clear(current_time, current_index)
        self.stat()


def test():
    df = pd.read_excel("data/shanghai_index.xlsx", engine="openpyxl")
    print("总数据量:{}".format(len(df)))
    df = df[df["日期"] > '2020/01/01']
    df = df.sort_index(ascending=False)
    start_row = df.iloc[0]
    end_row = df.iloc[-1]
    print("样本数据量:{}".format(len(df)))
    print("起始指数:{} {}".format(start_row["日期"], start_row["收盘价"]))
    print("最终指数:{} {}".format(end_row["日期"], end_row["收盘价"]))
    # print(df.head())
    m = MyModel()
    for i, row in df.iterrows():
        m.opt(row["日期"], row["收盘价"])
    m.clear_and_stat(end_row["日期"], end_row["收盘价"])


if __name__ == "__main__":
    _t1 = time.time()
    test()

    _t2 = time.time()
    print('{}\n用时:{}秒'.format('_' * 100, round((_t2 - _t1), 4)))