1-3移动均线交叉策略2
生活随笔
收集整理的這篇文章主要介紹了
1-3移动均线交叉策略2
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
第一階段、一個簡單策略入門量化投資
1-3移動均線交叉策略2
上一篇文章1-2 移動均線交叉策略1中我們最后提到:
如果我們從第一天買入股票,一直持有股票,最后一天賣出,獲得的收益是每股124.02美元,收益率為412%
如果按照我們的策略進行買賣,總共完成了21筆交易,收益為美股82.35美元,收益率為273%
仔細分析后,我發現有以下兩點需要改進:
1.回測需要使用調整后價格。
2.策略收益的計算有問題,需要充分考慮早先交易產生的收益或虧損對后續交易的收益產生的影響。
針對這兩點,修改代碼。
假設投資的初始資金為100萬,得到的資產變化圖如下:
修正后,我們的策略在截止日期的資金總額為298萬,也就是說平均收益率為198%
雖然這回收益的計算錯誤已經改正,但結果是令人沮喪的,我們使用滑動平均模型得到的收益確實比不操作要少許多。
注:由于第一次寫的博客不小心被自己蓋掉了,你看到的是重寫了一遍的,內容簡略了許多,實在是不高興再寫一遍了,見諒,各位施主直接看代碼吧。
完整代碼
import numpy as np import pandas as pd import pandas_datareader.data as web import matplotlib.pyplot as plt import datetime import timeimport draw_candle import stockdata_preProcess as preProcess##### in stock_movingAverageCross_Strategy.py # we have give a simple strategy to trade stocks called Moving Average Model # it is still imperfect and we find it is necessary to consider the adjust price # so in stock_movingAverageCross_Strategy2.py we try to improve the strategy##### read the data from csv apple=pd.read_csv(filepath_or_buffer='data_AAPL.csv') # note that some format(data type) of data we read from .csv has changed # for example the attribute 'Date' should be the index of the dataframe, and the date type changed from datetime to string # this changes would made our methods in draw_candle.py got trouble # So we need to make the following changes date_list = [] for i in range(len(apple)):date_str = apple['Date'][i]t = time.strptime(date_str, "%Y-%m-%d")temp_date = datetime.datetime(t[0], t[1], t[2])date_list.append(temp_date) apple['DateTime'] = pd.Series(date_list,apple.index) del apple['Date'] apple = apple.set_index('DateTime')##### it seems we need to consider the adjust price # yahoo only provides the adjust price of 'Close' # but it is easy to adjust the price by the proportion of 'Adj Close' and 'Close'# now we will use the adjust data apple_adj in the following code apple_adj = preProcess.ohlc_adjust(apple)##### compute the trade information like before, use adjust price apple_adj["20d"] = np.round(apple_adj["Close"].rolling(window = 20, center = False).mean(), 2) apple_adj["50d"] = np.round(apple_adj["Close"].rolling(window = 50, center = False).mean(), 2) apple_adj["200d"] = np.round(apple_adj["Close"].rolling(window = 200, center = False).mean(), 2)apple_adj['20d-50d'] = apple_adj['20d'] - apple_adj['50d']apple_adj["Regime"] = np.where(apple_adj['20d-50d'] > 0, 1, 0) apple_adj["Regime"] = np.where(apple_adj['20d-50d'] < 0, -1, apple_adj["Regime"])regime_orig = apple_adj.ix[-1, "Regime"] apple_adj.ix[-1, "Regime"] = 0 apple_adj["Signal"] = np.sign(apple_adj["Regime"] - apple_adj["Regime"].shift(1)) apple_adj.ix[-1, "Regime"] = regime_origapple_adj_signals = pd.concat([pd.DataFrame({"Price": apple_adj.loc[apple_adj["Signal"] == 1, "Close"],"Regime": apple_adj.loc[apple_adj["Signal"] == 1, "Regime"],"Signal": "Buy"}),pd.DataFrame({"Price": apple_adj.loc[apple_adj["Signal"] == -1, "Close"],"Regime": apple_adj.loc[apple_adj["Signal"] == -1, "Regime"],"Signal": "Sell"}),]) apple_adj_signals.sort_index(inplace = True)apple_adj_long_profits = pd.DataFrame({"Price": apple_adj_signals.loc[(apple_adj_signals["Signal"] == "Buy") &apple_adj_signals["Regime"] == 1, "Price"],"Profit": pd.Series(apple_adj_signals["Price"] - apple_adj_signals["Price"].shift(1)).loc[apple_adj_signals.loc[(apple_adj_signals["Signal"].shift(1) == "Buy") & (apple_adj_signals["Regime"].shift(1) == 1)].index].tolist(),"End Date": apple_adj_signals["Price"].loc[apple_adj_signals.loc[(apple_adj_signals["Signal"].shift(1) == "Buy") & (apple_adj_signals["Regime"].shift(1) == 1)].index].index}) #draw_candle.pandas_candlestick_ohlc(apple_adj, stick = 45, otherseries = ["20d", "50d", "200d"])##### take a simple analysis again # compute a rough profit (don't consider fee of the deal) rough_profit = apple_adj_long_profits['Profit'].sum() print(rough_profit)# compute the profit if we don't take any operation # (take long position at the first day and sale it on the last day of the date) no_operation_profit = apple['Adj Close'][-1]-apple['Adj Close'][0] print(no_operation_profit)tradeperiods = pd.DataFrame({"Start": apple_adj_long_profits.index,"End": apple_adj_long_profits["End Date"]})apple_adj_long_profits["Low"] = tradeperiods.apply(lambda x: min(apple_adj.loc[x["Start"]:x["End"], "Low"]), axis = 1) #print(apple_adj_long_profits)cash = 1000000 apple_backtest = pd.DataFrame({"Start Port. Value": [],"End Port. Value": [],"End Date": [],"Shares": [],"Share Price": [],"Trade Value": [],"Profit per Share": [],"Total Profit": [],"Stop-Loss Triggered": []}) port_value = 1 batch = 100 stoploss = .2 for index, row in apple_adj_long_profits.iterrows():# Maximum number of batches of stocks invested in# The arithmetic operator "//" represents an integer division that returns a maximum integer that is not greater than the resultbatches = np.floor(cash * port_value) // np.ceil(batch * row["Price"])trade_val = batches * batch * row["Price"]if row["Low"] < (1 - stoploss) * row["Price"]: # Account for the stop-loss#share_profit = np.round((1 - stoploss) * row["Price"], 2)share_profit = np.round(- stoploss * row["Price"], 2) # ??? I think this line need to be modified as left showsstop_trig = Trueelse:share_profit = row["Profit"]stop_trig = Falseprofit = share_profit * batches * batchapple_backtest = apple_backtest.append(pd.DataFrame({"Start Port. Value": cash,"End Port. Value": cash + profit,"End Date": row["End Date"],"Shares": batch * batches,"Share Price": row["Price"],"Trade Value": trade_val,"Profit per Share": share_profit,"Total Profit": profit,"Stop-Loss Triggered": stop_trig}, index = [index]))cash = max(0, cash + profit) print(apple_backtest) apple_backtest["End Port. Value"].plot() plt.show() 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的1-3移动均线交叉策略2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LwIP应用开发笔记之十:LwIP带操作
- 下一篇: 改进初学者的PID-微分冲击