Skip to content

Instantly share code, notes, and snippets.

@e7h4n
Last active November 16, 2021 10:29
Show Gist options
  • Save e7h4n/6f4b90614af4505f803c7f27d3d08469 to your computer and use it in GitHub Desktop.
Save e7h4n/6f4b90614af4505f803c7f27d3d08469 to your computer and use it in GitHub Desktop.
股债比回归验证
import tushare as ts
import numpy as np
import pandas as pd
from datetime import datetime, date
from matplotlib import pyplot as plt
start_date = date(2015, 1, 1)
hs300 = 0
start_amount = 10000000
start_index = 0
debt_amount = start_amount
latest_index_trade_date = start_date
latest_debt_trade_date = start_date
latest_ratio = 0
def rebalance(d, index):
global debt_amount, hs300, latest_index_trade_date
total = debt_amount + hs300 * index # 计算下持仓总量
target_hs300 = (total * latest_ratio) / index # 交易后的 HS300 持仓
target_debt_amount = total * (1 - latest_ratio) # 交易后的债券持仓
diff_hs300 = target_hs300 - hs300 # HS300 交易差
diff_debt_amount = target_debt_amount - debt_amount # 债券交易差
# 更新持仓
hs300 = target_hs300
debt_amount = target_debt_amount
# TODO: 计算交易手续费
# 更新交易数据
latest_index_trade_date = d
def trade(d, ratio, index):
global debt_amount, hs300, latest_index_trade_date, latest_ratio
total = debt_amount + hs300 * index # 计算下持仓总量
target_hs300 = (total * ratio) / index # 交易后的 HS300 持仓
target_debt_amount = total * (1 - ratio) # 交易后的债券持仓
diff_hs300 = target_hs300 - hs300 # HS300 交易差
diff_debt_amount = target_debt_amount - debt_amount # 债券交易差
# 更新持仓
hs300 = target_hs300
debt_amount = target_debt_amount
# TODO: 计算交易手续费
# 更新交易数据
latest_index_trade_date = d
latest_ratio = ratio
def calc_ratio(d, pe, debt):
ratio = 1.0 / pe * 100.0 / debt
ret = 0
if ratio > 2.4:
ret = 1.0
elif ratio > 2.1:
ret = 0.7
elif ratio > 1.8:
ret = 0.6
elif ratio > 1.5:
ret = 0.3
# print(d, 'pe=', pe, '风险收益率=', 1.0/pe * 100.0, '无风险收益率=', debt, '股债比=', ratio)
return ret
def get_debt_day_rate(debt):
return (1.0 + debt / 100.0) ** (1/365) - 1.0
def increase_debt(d, debt):
global latest_debt_trade_date
days = (d - latest_debt_trade_date).days
latest_debt_trade_date = d
debt_amount * np.power(1.0 + get_debt_day_rate(debt), days)
def process(d, pe, index, debt):
ratio = calc_ratio(d, pe, debt)
debt_amount = increase_debt(d, debt)
if (ratio == latest_ratio) and ((d - latest_index_trade_date).days > 180):
rebalance(d, index)
elif ratio != latest_ratio:
trade(d, ratio, index)
df_index = pd.read_csv('index.csv', index_col=0)
df_debt = pd.read_csv('debt.csv')
df = df_index.merge(df_debt, left_on='trade_date', right_on='trade_date')
df = df.sort_values(by='trade_date')
latest_print_date = date(1970, 1, 1)
result = pd.DataFrame(columns = ['trade_date', 'index_close', 'pe_close', 'debt_close', '股债比', 'debt_holding', 'index_holding', 'ratio', 'yield', 'index_yield', 'amount'])
for index, row in df.iterrows():
d = datetime.strptime(str(int(row['trade_date'])), '%Y%m%d').date()
if d <= start_date:
continue
process(d, row['pe'], row['close_x'], row['close_y'])
if start_index == 0:
start_index = row['close_x']
total = debt_amount + hs300 * row['close_x'] # 当前总资产
result = result.append({
'trade_date': d,
'index_close': row['close_x'],
'pe_close': row['pe'],
'debt_close': row['close_y'] / 100,
'股债比': 1/row['pe']/row['close_y'] * 100,
'debt_holding': debt_amount,
'index_holding': hs300 * row['close_x'],
'ratio': latest_ratio,
'yield': (total / start_amount) ** (1/((d - start_date).days / 365)) - 1,
'index_yield': (row['close_x'] / start_index) ** (1/((d - start_date).days / 365)) - 1,
'amount': total,
}, ignore_index=True)
result.to_csv('result.csv')
print(result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment