股債輪動Python實現

https://xueqiu.com/1884493065/126934263

1.策略介紹

在這裏插入圖片描述

2.數據庫表設計

在這裏插入圖片描述

3.數據導入

http://quotes.money.163.com/trade/lsjysj_zhishu_399300.html

去網易財經下載指數歷史數據,導入到mysql中
在這裏插入圖片描述

4. 策略回測代碼

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# import talib
import pymysql
import datetime
import matplotlib.dates as dates
import logging



from matplotlib import dates as mdates

# 通過下面的方式進行簡單配置輸出方式與日誌級別
logging.basicConfig(filename='logger1.log', level=logging.INFO)

start_date =  '2005-01-04'

connect = pymysql.connect(
            host = '127.0.0.1',
            db = 'blog',
            user = 'root',
            passwd = '123456',
            charset = 'utf8',
            use_unicode = True
        )
cursor = connect.cursor()
 
select_sql = "select date,open,high,low,adj_close from tmp_stock where code ='399300' and date > '%s' order by date asc" % start_date
data_300 = pd.read_sql(select_sql, con=connect)
data_300 = data_300.set_index('date')
data_300

select_sql = "select date,open,high,low,adj_close from tmp_stock where code ='399905' and date > '%s' order by date asc" % start_date
data_500 = pd.read_sql(select_sql, con=connect)
data_500 = data_500.set_index('date')
data_500

select_sql = "select date,open,high,low,adj_close from tmp_stock where code ='000852' and date > '%s' order by date asc" % start_date
data_1000 = pd.read_sql(select_sql, con=connect)
data_1000 = data_1000.set_index('date')
data_1000

select_sql = "select date,open,high,low,adj_close from tmp_stock where code ='399330' and date > '%s' order by date asc" % start_date
data_100 = pd.read_sql(select_sql, con=connect)
data_100 = data_100.set_index('date')
data_100

select_sql = "select date,open,high,low,adj_close from tmp_stock where code ='399006' and date > '%s' order by date asc" % start_date
data_cyb = pd.read_sql(select_sql, con=connect)
data_cyb = data_cyb.set_index('date')
data_cyb

def MaxDrawdown(return_list):
    '''最大回撤率'''
    i = np.argmax((np.maximum.accumulate(return_list) - return_list) / np.maximum.accumulate(return_list))  # 結束位置
    if i == 0:
        return 0
    j = np.argmax(return_list[:i])  # 開始位置
    return (return_list[j] - return_list[i]) / (return_list[j])
all_date = list(data_300.index.values)
import datetime

def is_high_average(input_dataframe, date, day_count):
    all_date_array = list(input_dataframe.index.values)
    try:
        date_index = all_date_array.index(date) + 1
    except ValueError:
        date_index = -1
#     print(date_index)
    if date_index-day_count >= 0:
        close = input_dataframe['adj_close'][date_index-day_count:date_index]
#         print(close)
#         print(close.sum())
        return (close[-1] > (close.sum() / day_count) )
    else:
        return False

def get_rise_percent(input_dataframe, date, day_count):
    all_date_array = list(input_dataframe.index.values)
    try:
        date_index = all_date_array.index(date) + 1
    except ValueError:
        date_index = -1
        
    if date_index-day_count >= 0:
        close = input_dataframe['adj_close'][date_index-day_count:date_index]
        return close[-1] / close[0] - 1
    else:
        return -10
all_stock = {'hs300':data_300, 'zz500':data_500, 'zz1000':data_1000, 'sz100':data_100, 'cyb':data_cyb}
#貨幣基金年化
hb_percent = 0.04
def get_profit(percent_day_count=12, is_high_average_day_count=15, log=False):

    
#     percent_day_count = 12
#     is_high_average_day_count = 15
    is_buy = False
    buy_stock = 'hs300'
    start_hb_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
    profit = 1
    log_profit = 1
    win_profit = []
    loss_profit = []
    profit_list = []
    profit_date = []
    for date in all_date:
        stock_rise_percent = {}
        max_stock = None
        for stock in all_stock.keys():
            stock_rise_percent[stock] = get_rise_percent(all_stock[stock], date, percent_day_count)
        
        max_stock_rise_percent = -10
        for stock in stock_rise_percent.keys():
            if stock_rise_percent[stock] >= max_stock_rise_percent:
                max_stock_rise_percent = stock_rise_percent[stock]
                max_stock = stock
            
        is_high = is_high_average(all_stock[max_stock], date, is_high_average_day_count)
        if is_high and is_buy is False:
            current_date_time = datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d")
            day_count = (current_date_time - start_hb_date).days
            #算上空倉的貨幣基金收益
            profit *= 1 + ((day_count / 365) * hb_percent)
            
            is_buy = True
            buy_stock = max_stock
            buy_price = all_stock[max_stock]['adj_close'][date]
            if log:
                print("buy:" + max_stock + " date:" + str(date) + " price:" + str(buy_price))
                
        if is_buy and log:
            date_index = list(all_stock[buy_stock].index.values).index(date)
            log_profit = log_profit * (all_stock[buy_stock]['adj_close'][date_index] / all_stock[buy_stock]['adj_close'][date_index - 1])
        
        if is_buy is True and (max_stock != buy_stock or is_high is False):
            is_buy = False
            start_hb_date = datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d")
            sell_price = all_stock[buy_stock]['adj_close'][date]
            current_profit = (sell_price / buy_price) 
            profit *= current_profit
            #算上買賣成本
            profit *= 0.9985
            log_profit = profit
            if current_profit >=1:
                win_profit.append(current_profit - 1)
            else:
                loss_profit.append(current_profit - 1)
            if log:
                print("sell:" + buy_stock + " date:" + str(date) + " price:" + str(sell_price) + " profit:" + str(profit))
            if is_high:
                is_buy = True
                buy_stock = max_stock
                buy_price = all_stock[max_stock]['adj_close'][date]
                if log:
                    print("change buy:" + max_stock + " date:" + str(date) + " price:" + str(buy_price))
        profit_list.append(log_profit)
        profit_date.append(date)


    if log:
        print('淨值:' + str(profit))
        print('盈利次數:' + str(len(win_profit)))
        print('虧損次數:' + str(len(loss_profit)))
        winPercent = len(win_profit) /  float(len(win_profit) + len(loss_profit))
        print('勝率:' + str( winPercent) ) 
        averangeWinPercent = np.sum(win_profit) /  float(len(win_profit))
        print('平均每次盈利:' + str(averangeWinPercent ) ) 
        averageLossPerent = np.sum(loss_profit) /  float(len(loss_profit))
        print('平均每次虧損:' + str(averageLossPerent ) ) 
        kali = winPercent - (1 - winPercent) / (averangeWinPercent / abs(averageLossPerent));
        print('盈虧比:' + str(abs(averangeWinPercent / averageLossPerent)))
        print('凱利最佳倉位:' + str(kali))
        max_down = MaxDrawdown(profit_list)
        print('最大回撤:' + str(max_down))
    return profit, profit_list, profit_date

profit, profit_list, profit_date = get_profit(10, 16, True)
x = profit_date
y = profit_list
plt.figure(figsize=(15,8)) #創建繪圖對象
plt.plot(x,y,"b",linewidth=1)   #在當前繪圖對象繪圖(X軸,Y軸,藍色,線寬度)
# plt.plot(x,hs_profit_list,"r",linewidth=1)
plt.xlabel("Date") #X軸標籤
plt.ylabel("Profit")  #Y軸標籤
plt.title("Lundong") #圖標題
plt.show()  #顯示圖

5. 策略輸出

在這裏插入圖片描述

6.策略淨值走勢

在這裏插入圖片描述

感覺跟原文的回測結果不一樣,我再花點時間檢查下看,哪裏出了問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章