金融量化專案案例 -- 雙均線策略制定

zylyehuo發表於2023-10-01

部落格地址:https://www.cnblogs.com/zylyehuo/

開發環境

  • anaconda
    • 整合環境:整合好了資料分析和機器學習中所需要的全部環境
    • 安裝目錄不可以有中文和特殊符號
  • jupyter
    • anaconda提供的一個基於瀏覽器的視覺化開發工具

使用tushare包獲取某股票的歷史行情資料

!pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tushare
import tushare as ts
import pandas as pd
from pandas import DataFrame,Series
import numpy as np
df = pd.read_csv('./maotai.csv').drop(labels='Unnamed: 0',axis=1)
df

# 將date列轉為時間序列且將其作為源資料的行索引
df['date'] = pd.to_datetime(df['date'])
df.set_index('date',inplace=True)
df.head()

計算該股票歷史資料的5日均線和60日均線

  • 什麼是均線?
    • 對於每一個交易日,都可以計算出前N天的移動平均值,然後把這些移動平均值連起來,成為一條線,就叫做N日移動平均線。移動平均線常用線有5天、10天、30天、60天、120天和240天的指標。
      • 5天和10天的是短線操作的參照指標,稱做日均線指標;
      • 30天和60天的是中期均線指標,稱做季均線指標;
      • 120天和240天的是長期均線指標,稱做年均線指標。
    • 均線計算方法:MA=(C1+C2+C3+...+Cn)/N C:某日收盤價 N:移動平均週期(天數)
# df['close'].rolling(5)  依次取出第一個“前五天”、第二個“前五天”...
# df['close'].rolling(5).mean()  計算均值
ma5 = df['close'].rolling(5).mean()
ma30 = df['close'].rolling(30).mean()
ma5
date
2001-08-27         NaN
2001-08-28         NaN
2001-08-29         NaN
2001-08-30         NaN
2001-08-31    -162.504
                ...   
2023-09-22    1825.506
2023-09-25    1826.142
2023-09-26    1823.954
2023-09-27    1821.954
2023-09-28    1821.986
Name: close, Length: 5289, dtype: float64

視覺化歷史資料的收盤價和兩條均線

import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(ma5[50:180])
plt.plot(ma30[50:180])

[<matplotlib.lines.Line2D at 0x1f3c9adc610>]

分析輸出所有金叉日期和死叉日期

  • 股票分析技術中的金叉和死叉,可以簡單解釋為:
    • 分析指標中的兩根線,一根為短時間內的指標線,另一根為較長時間的指標線。
    • 如果短時間的指標線方向拐頭向上,並且穿過了較長時間的指標線,這種狀態叫“金叉”;
    • 如果短時間的指標線方向拐頭向下,並且穿過了較長時間的指標線,這種狀態叫“死叉”;
    • 一般情況下,出現金叉後,操作趨向買入;死叉則趨向賣出。當然,金叉和死叉只是分析指標之一,要和其他很多指標配合使用,才能增加操作的準確性。
# 過濾NaN值
ma5 = ma5[30:]
ma30 = ma30[30:]
s1 = ma5 < ma30
s2 = ma5 > ma30
df = df[30:]
death_ex = s1 & s2.shift(1)  # 判定死叉的條件 F -> T
df.loc[death_ex]  # 死叉對應的行資料
death_date = df.loc[death_ex].index
golden_ex = ~(s1 | s2.shift(1))  # 判定金叉的條件 T -> F
golden_date = df.loc[golden_ex].index  # 金叉的時間

需求

​============================================
如果我從假如我從2010年1月1日開始,初始資金為100000元,金叉儘量買入,死叉全部賣出,則到今天為止,我的炒股收益率如何?
============================================
  • 分析:
    • 買賣股票的單價使用開盤價
    • 買賣股票的時機
    • 最終手裡會有剩餘的股票沒有賣出去
      • 會有。如果最後一天為金叉,則買入股票。估量剩餘股票的價值計算到總收益。
        • 剩餘股票的單價就是用最後一天的收盤價。
s1 = Series(data=1,index=golden_date)  # 1作為金叉的標識
s2 = Series(data=0,index=death_date)  # 0作為死叉的標識

s = s1.append(s2)
s = s.sort_index()  # 儲存的是金叉和死叉對應的時間
s = s['2010':'2020']  # 儲存的是金叉和死叉對應的時間
first_money = 100000  # 本金,不變
money = first_money  # 可變的,買股票花的錢和賣股票收入的錢都從該變數中進行操作
hold = 0  # 持有股票的數量(股數:100股=1手)

for i in range(0,len(s)):  # i表示的s這個Series中的隱式索引
    # s[i] = 0 (死叉:賣) 
    # s[i] = 1(金叉:買)
    if s[i] == 1:  # 金叉的時間
        # 基於100000的本金儘可能多的去買入股票
        # 獲取股票的單價(金叉時間對應的行資料中的開盤價)
        time = s.index[i]  # 金叉的時間
        p = df.loc[time]['open']  # 股票的單價
        hand_count = money // (p*100)  # 使用100000最多買入多少手股票
        hold = hand_count * 100  # 買股票的支數
        money -= (hold * p)  # 將買股票花的錢從money中減去
    else:
        # 將買入的股票賣出去        
        # 找出賣出股票的單價
        death_time = s.index[i]
        p_death = df.loc[death_time]['open']  # 賣股票的單價
        money += (p_death * hold)  # 賣出的股票收入加入到money
        hold = 0

# 如何判定最後一天為金叉還是死叉
last_money = hold * df['close'][-1] #剩餘股票的價值

# 總收益
# >0  賺錢
# <0  虧損
money + last_money - first_money
-22684925.799999997

相關文章