import akshare as ak
import plotly
import plotly.offline as plyo # 保存图表,相当于plotly.plotly as py,同时增加了离线功能
import plotly.graph_objects as go # 创建各类图表
import plotly.figure_factory as ff # 创建table
ak_stock_code = 'sh000300'
ak_stock_name = '沪深300'
ak_date_start = '2015-01-01'
ak_date_end = '2021-12-30'
window = 25
stdev_n = 2
cost = 0.6/10000
# 获取stock_code每日行情
stock_zh_index_daily_df = ak.stock_zh_index_daily(symbol=ak_stock_code)
stock_zh_index_daily_df['date'] = pd.to_datetime(stock_zh_index_daily_df['date'])
stock_zh_index_daily_df = stock_zh_index_daily_df.set_index('date')
index_value_hist_funddb_df = ak.index_value_hist_funddb(symbol=ak_stock_name, indicator="市盈率")
index_value_hist_funddb_df.rename (columns={'市盈率':'pe'},inplace=True)
index_value_hist_funddb_df.rename (columns={'日期':'date'},inplace=True)
index_value_hist_funddb_df['date'] = pd.to_datetime(index_value_hist_funddb_df['date'])
index_value_hist_funddb_df = index_value_hist_funddb_df.set_index('date')
index_daily_df = pd.merge(stock_zh_index_daily_df, index_value_hist_funddb_df[['pe']], on='date', how='outer')
# 北向资金流入
time.sleep(3)
shanghai_stock_connect_df = ak.stock_hsgt_hist_em(symbol="沪股通")
shenzhen_stock_connect_df = ak.stock_hsgt_hist_em(symbol="深股通")
shanghai_stock_connect_df.rename(columns={'日期':'date'}, inplace=True)
shanghai_stock_connect_df.rename(columns={'当日成交净买额':'Northbound_Purchase'}, inplace=True)
shenzhen_stock_connect_df.rename(columns={'日期':'date'}, inplace=True)
shenzhen_stock_connect_df.rename(columns={'当日成交净买额':'Northbound_Purchase'}, inplace=True)
northbound_purchase_df = pd.DataFrame()
northbound_purchase_df['date'] = shanghai_stock_connect_df.date
northbound_purchase_df['Northbound_Purchase'] = shanghai_stock_connect_df.Northbound_Purchase + shenzhen_stock_connect_df.Northbound_Purchase
northbound_purchase_df['date'] = pd.to_datetime(northbound_purchase_df['date'])
northbound_purchase_df = northbound_purchase_df.set_index('date')
northbound_purchase_df.head()
# 运算
def performance(ret, benchmark, rf=0.04):
max_drawdown = empyrical.max_drawdown(ret)
total_return = empyrical.cum_returns_final (ret)
annual_return = empyrical.annual_return(ret)
sharpe_ratio = empyrical.sharpe_ratio(ret,risk_free=((1+rf)** (1/252) - 1))
alpha,beta = empyrical.alpha_beta(ret, benchmark)
return {'total_return':total_return,
'annual_return':annual_return,
'max_drawdown':max_drawdown,
'sharpe-ratio':sharpe_ratio,
'alpha':alpha,
'beta':beta}
data = pd.merge(northbound_purchase_df, index_daily_df, on='date', how='left')
data['Northbound_Purchase'] = [float(x) for x in data['Northbound_Purchase'].values]
data = data.iloc[::-1]
data['mid'] = data['Northbound_Purchase'].rolling(window).mean()
stdev = data['Northbound_Purchase'].rolling(window).std()
data['upper'] = data['mid'] + stdev_n * stdev
data['lower'] = data['mid'] - stdev_n * stdev
data['ret'] = data.close/data.close.shift(1) - 1
data.loc[data['Northbound_Purchase'] > data.upper, 'signal'] = 1
data.loc[data['Northbound_Purchase'] < data.upper, 'signal'] = 0
data['position'] = data['signal'].shift(1)
data['position'].fillna(method='ffill', inplace=True)
data['position'].fillna(0, inplace=True)
data.loc[data.index[0], 'capital_ret'] = 0
data.loc[data.index[0], 'capital_ret_without_fee'] = 0
data.loc[data['position'] > data['position'].shift(1), 'capital_ret'] = data.close/(data.open*(1+cost)) - 1
data.loc[data['position'] > data['position'].shift(1), 'capital_ret_winthout_fee'] = data.close/data.open - 1
data.loc[data['position'] < data['position'].shift(1), 'capital_ret'] = (data.open/data.close.shift(1))*(1-cost) - 1
data.loc[data['position'] < data['position'].shift(1), 'capital_ret_winthout_fee'] = data.open/data.close.shift(1) - 1
data.loc[data['position'] == data['position'].shift(1), 'capital_ret'] = data['ret'] * data['position']
data.loc[data['position'] == data['position'].shift(1), 'capital_ret_winthout_fee'] = data['ret'] * data['position']
data['strate_gyvalue'] = [round(x, 2) for x in (data.capital_ret+1.0).cumprod()]
data['strate_gy_values_without_fees'] = [round(x, 2) for x in (data.capital_ret_winthout_fee+1.0).cumprod()]
data['index_value'] = [round(x, 2) for x in (data.ret+1.0).cumprod()]
df = data['2021':'2022']
p1 = performance(df.ret, df.ret)
p2 = performance(df.capital_ret, df.ret)
p3 = performance (df.capital_ret_without_fee, df.ret)
print (f"target : {ak_stock_name}({ak_stock_code})")
print (f"date range : {ak_date_start}~{ak_date_end}")
print (f"total_return : strategy: {round(p2['total_return']*100,2)}% strategy(no_cost):{round(p3['total_return']*100,2)}%、{ak_stock_name}: {round(p1['total_return'],2) }%")
print (f"annual_return: strategy: {round(p2['annual_return']*100,2)}% strategy(no_cost):{round(p3['annual_return']*100,2)}%、{ak_stock_name}: {round(p1['annual_return'],2)}%")
print (f"max_drawdown : strategy: {round(p2['max_drawdown']*100,2)}% strategy(no_cost):{round(p3['max_drawdown']*100,2) }%、{ak_stock_name}: {round(p1['max_drawdown'],2)}%")
print (f"sharpe : strategy:{round(p2['sharpe-ratio'],2)} strategy(no_cost):{round(p3['sharpe-ratio'],2)}、{ak_stock_name}: {round(p1['sharpe-ratio'],2)}")
print (f"Alpha : strategy:{round(p2['alpha'],2)} strategy(no_cost):{round(p3['alpha'],2 )}、{ak_stock_name}: {round(p1['alpha'],2)}")
print (f"Beta : strategy: {round(p2['beta'],2)} strategy(no_cost):{round(p3['beta'],2)}、{ak_stock_name}: {round(p1['beta'],2)}")
df.head()
# 图形可视化
k_hq = go.Candlestick(
x = df.index,
open = df.open,
high = df.high,
low = df.low,
close = df.close,
increasing_line_color = 'red',
decreasing_line_color = 'green'
)
trace0 = go.Scatter(
x = df.index,
y = df.upper,
mode = 'lines',
name = 'upper(买点)'
)
trace1 = go.Scatter(
x = df.index,
y = df.lower,
mode = 'lines',
name = 'lower(卖点)'
)
trace2 = go.Scatter(
x = df.index,
y = df.Northbound_Purchase,
mode = 'lines',
name = 'Northbound_Purchase'
)
trace3 = go.Scatter(
x = df.index,
y = df.capital_ret,
mode = 'lines',
name = 'capital_ret'
)
trace4 = go.Scatter(
x = df.index,
y = df.ret,
mode = 'lines',
name = 'ret'
)
# fig = go.Figure(data=[])
# fig.show()
data = [trace0, trace1, trace2]
plyo.iplot(data)