购买低溢价可转债策略 利用python回测分析(附代码)

策略:
起始资金80万,在交易日买入收盘价排前百分之十的低溢价转债,每个200张,卖出持仓中不在百分之十内的。
交易起始时间 2018-01-01,截止时间2021-05-13

下面是每天,每七天,每14天,每30天,每60天轮动一次的数据
交易间隔 期末总资产 交易次数 交易佣金 年化收益率
1 2006550 4876 4485 44.82
7 1830552 1790 1643 38.28
14 1684799 1174 1031 32.87
30 1550693 685 602 27
60 1444754 475 443 23.95

这个收益率高得,我感觉可能我代码有问题,因为我平时工作语言不是python,这份代码是边查文档,边写的

数据库文件
链接:/s/1seEY1Sri1PIOGcBxmpB84A 加上百度网盘前缀
提取码:ckc4

def buy_lowest_premium_rate():
total_money = 800000  # 初始资金
start_date = '2018-01-01 00:00:00'  # 起始交易时间
d = datetime.datetime.strptime(start_date, '%Y-%m-%d %H:%M:%S')
bond_list = []
x = []
y = []

step = 60  # 多少天调仓一次
money_used_rate = []
trade_charge = 0
trade_count = 0
while d <= datetime.datetime.now():
    cur_date = d.strftime('%Y-%m-%d %H:%M:%S')
    db = pymysql.connect(host='*****', user="root", password="****", database="convert_bond")
    cursor = db.cursor()
    sql = 'select count(*) from bond_tmp where date="' + cur_date + '"'
    cursor.execute(sql)
    total = cursor.fetchall()[0][0]
    if total == 0:
        d = d + datetime.timedelta(days=1)  # 当天没交易,推迟到下一个交易日
        continue
    select_count = total // 10
    sel_sql = 'select * from bond_tmp where date="' + cur_date + '"' + 'order by premium_rate asc limit ' + \
              str(select_count)
    cursor.execute(sel_sql)
    results = cursor.fetchall()
    low_list_tmp = []
    for row in results:
        price = float(row[2])
        code = row[0]
        low_list_tmp.append({code: price})

    m = map(lambda i: list(i.keys())[0], bond_list)
    n = map(lambda i: list(i.keys())[0], low_list_tmp)
    print("===========================")
    print("当前持仓:" + str(sorted(list(m))))
    print("需要调仓为:" + str(sorted(list(n))))
    print("===========================")

    for item in bond_list:
        if list(item.keys())[0] in map(lambda i: list(i.keys())[0], low_list_tmp):
            continue
        else:  # 卖出不符合条件的持仓
            price_sql = 'select close from bond_tmp where date="' + cur_date + '"' + 'and code=' + \
                        str(list(item.keys())[0])
            cursor.execute(price_sql)
            price = cursor.fetchone()
            print("sell:" + list(item.keys())[0])
            if price is not None:
                total_money = total_money + 200 * float(price[0])
                trade_count += 1
                if list(item.keys())[0].startswith('11'):  # 沪市
                    trade_charge += 200 * float(price[0]) * (5 / 1000000)
                    total_money = total_money - 200 * float(price[0]) * (5 / 1000000)
                else:  # 深市
                    trade_charge += 200 * float(price[0]) * (5 / 100000)
                    total_money = total_money - 200 * float(price[0]) * (5 / 100000)
                continue

            last_day_sql = 'select count(*) from bond_tmp where date>"' + cur_date + '"' + 'and code=' + \
                           str(list(item.keys())[0])
            cursor.execute(last_day_sql)
            c = cursor.fetchone()[0]
            if c == 0:  # 为可转债最后交易日,卖出
                print("sell:" + list(item.keys())[0])
                total_money = total_money + 200 * list(item.values())[0]
                trade_count += 1
                if list(item.keys())[0].startswith('11'):
                    trade_charge += 200 * list(item.values())[0] * (5 / 1000000)
                    total_money = total_money - 200 * list(item.values())[0] * (5 / 1000000)
                else:
                    trade_charge += 200 * list(item.values())[0] * (5 / 100000)
                    total_money = total_money - 200 * list(item.values())[0] * (5 / 100000)
                print("sell:" + list(item.keys())[0])
            else:
                low_list_tmp.append(item)

    for item in low_list_tmp:
        # 买入新符合条件的可转债
        if list(item.keys())[0] not in map(lambda i: list(i.keys())[0], bond_list):
            print("buy:" + list(item.keys())[0])
            total_money = total_money - 200 * list(item.values())[0]
            trade_count += 1
            #  扣除交易费率
            if list(item.keys())[0].startswith('11'):
                trade_charge += 200 * list(item.values())[0] * (5 / 1000000)
                total_money = total_money - 200 * list(item.values())[0] * (5 / 1000000)
            else:
                trade_charge += 200 * list(item.values())[0] * (5 / 100000)
                total_money = total_money - 200 * list(item.values())[0] * (5 / 100000)

    bond_list = low_list_tmp
    ps = list(map(lambda i: list(i.values())[0], bond_list))
    bond_total = 0
    for p in ps:
        bond_total = bond_total + 200 * p
    print(cur_date + ",total money, currency:" + str(total_money) +
          ", bond:" + str(bond_total) + ",total money:" + str(total_money + bond_total))
    x.append(cur_date[0: 10])
    y.append(total_money + bond_total)
    money_used_rate.append(bond_total / (total_money + bond_total))
    d = d + datetime.timedelta(days=step)
    cursor.close()
print("交易费总计:" + str(trade_charge))
print("交易次数总计:" + str(trade_count))
plt.plot(x, y)
# plt.plot(x, y)
plt.show()
发表时间 2021-05-18 15:01

赞同来自: ppppp74 AlanY redtide

0

时间快过去了

赞同来自:

楼主请问历史数据那里抓的
2022-08-30 21:43 来自湖南 引用
0

蝶恋火2

赞同来自:

这个数据怎么获取到? 可以从哪里抓?
2022-08-09 11:37 来自湖南 引用
0

哈哈大王123

赞同来自:

但是每一个可转债买200张,假如平均价格100-120元,那么买入低价前10的可转债,最后所用资金也才20W-24W,占资金80W的总仓位的25%-30%。
假如平均价格100-120元,那么买入低价前20的可转债,最后所用资金也才40W-48W,占资金80W的总仓位的50-60%。

所以应该是买600张左右吧1
2021-06-29 11:51 引用
0

五蛋齐飞

赞同来自:

我今天跑了一下代码,发现一个问题,你没有计算可用是否足够。
如果将开始日期改成2021-01-01,跑出来的currency是负的。
2021-05-20 13:38 引用
0

watertyfs

赞同来自:

应该数据没问题,之前测试过类似的
2021-05-20 12:28 引用
0

五蛋齐飞

赞同来自:

感谢分享
2021-05-19 10:49 引用
0

redtide

赞同来自:

凌大实盘14/30天轮动年化~31%,和你的结果接近哦。
2021-05-18 16:27 引用

要回复问题请先登录注册

问题状态

  • 最新活动: 2022-08-30 21:43
  • 浏览: 7065
  • 关注: 17