- In this post, we will revisit most popular blue-chip stock portfolios using Python fintech libraries.
- Our objective is to optimize currently available quant trading and investing solutions for private DIY self-traders. Our trading approach consists of the following 4 steps:
- Step 1: Examine the AAPL trading signals and support/resistance regression lines.
- Step 2: Compare AAPL vs MSFT in terms of returns, volatility, covariance, and correlations.
- Step 3: Compare MA 10-20-30, daily returns, pair plots, correlations, Monte Carlo simulations, and Sharpe ratios of AAPL, AMZN, MSFT, and TSLA stocks.
- Step 4: Perform the SPY stock price analysis and FB Prophet forecast.
Let’s dive into the details below.
Table of Contents
- AAPL Trading Signals Verified
- AAPL/MSFT Risk vs ROI Analysis
- Popular 4-Stock Portfolio
- Monte-Carlo Predictions
- SPY Return/Volatility
- SPY Prophet Forecast
- Summary
- References
- Explore More
AAPL Trading Signals Verified
Let’s set the working directory YOURPATH
import osos.chdir('YOURPATH') # Set working directoryos. getcwd()
Let’s import the key libraries and define the following functions
import numpy as npimport pandas as pdfrom math import sqrtimport matplotlib.pyplot as pltimport pandas_datareader as webfrom scipy.signal import savgol_filterfrom sklearn.linear_model import LinearRegressionfrom pandas_datareader import data as pdrimport yfinance as yfinyfin.pdr_override()def pythag(pt1, pt2): a_sq = (pt2[0] - pt1[0]) ** 2 b_sq = (pt2[1] - pt1[1]) ** 2 return sqrt(a_sq + b_sq)def regression_ceof(pts): X = np.array([pt[0] for pt in pts]).reshape(-1, 1) y = np.array([pt[1] for pt in pts]) model = LinearRegression() model.fit(X, y) return model.coef_[0], model.intercept_def local_min_max(pts): local_min = [] local_max = [] prev_pts = [(0, pts[0]), (1, pts[1])] for i in range(1, len(pts) - 1): append_to = '' if pts[i-1] > pts[i] < pts[i+1]: append_to = 'min' elif pts[i-1] < pts[i] > pts[i+1]: append_to = 'max' if append_to: if local_min or local_max: prev_distance = pythag(prev_pts[0], prev_pts[1]) * 0.5 curr_distance = pythag(prev_pts[1], (i, pts[i])) if curr_distance >= prev_distance: prev_pts[0] = prev_pts[1] prev_pts[1] = (i, pts[i]) if append_to == 'min': local_min.append((i, pts[i])) else: local_max.append((i, pts[i])) else: prev_pts[0] = prev_pts[1] prev_pts[1] = (i, pts[i]) if append_to == 'min': local_min.append((i, pts[i])) else: local_max.append((i, pts[i])) return local_min, local_max
Let’s look at the smoothed version if the above plot
month_diff = series.shape[0] // 30if month_diff == 0: month_diff = 1month_diff
6
smooth = int(2 * month_diff + 3)smooth
15
pts = savgol_filter(series, smooth, 3)plt.title(symbol)plt.xlabel('Days')plt.ylabel('Prices')plt.plot(pts, label=f'Smooth {symbol}')plt.legend()
Let’s combine these two curves into the single joint plot
plt.title(symbol)plt.xlabel('Days')plt.ylabel('Prices')plt.plot(series, label=symbol)plt.plot(pts, label=f'Smooth {symbol}')plt.legend()
Let’s generate the trading signals using the smoothed price curve
local_min, local_max = local_min_max(pts)plt.title(symbol)plt.xlabel('Days')plt.ylabel('Prices')plt.plot(pts, label=f'Smooth {symbol}')for pt in local_min: plt.scatter(pt[0], pt[1], c='r')for pt in local_max: plt.scatter(pt[0], pt[1], c='g')plt.legend()
Let’s calculate the local support and resistance lines using the regression_ceof function
local_min_slope, local_min_int = regression_ceof(local_min)local_max_slope, local_max_int = regression_ceof(local_max)support = (local_min_slope * np.array(series.index)) + local_min_intresistance = (local_max_slope * np.array(series.index)) + local_max_int
plt.title(symbol)plt.xlabel('Days')plt.ylabel('Prices')plt.plot(pts, label=f'Smooth {symbol}')plt.plot(support, label='Support', c='r')plt.plot(resistance, label='Resistance', c='g')plt.legend()
plt.title(symbol)plt.xlabel('Days')plt.ylabel('Prices')plt.plot(series, label=symbol)plt.plot(support, label='Support', c='r')plt.plot(resistance, label='Resistance', c='g')plt.legend()
Let’s plot the AAPL Simple Moving Average (SMA) to verify the 5-year MA crossover strategy
# import modulesfrom datetime import datetimeimport yfinance as yfimport matplotlib.pyplot as plt # initialize parametersstart_date = datetime(2017, 1, 1)end_date = datetime(2023, 9, 26) # get the datadf = yf.download('AAPL', start = start_date, end = end_date)
import matplotlibfrom pylab import rcParamsmatplotlib.rcParams.update({'font.size': 18})rcParams['figure.figsize'] = 15, 6simple_ma = df["Close"].rolling(window=100).mean()plt.figure(figsize=(14,8))simple_ma.plot(label="Simple Moving Average")df["Close"].plot(label="Closing Price")plt.xticks(rotation=0)plt.title("Moving Average of Closing Price", size=22)plt.legend()plt.show(
AAPL/MSFT Risk vs ROI Analysis
Following the quant trading diversification approach, we will show how a trader can reduce the volatility of the portfolio’s returns by choosing just 2 tech stocks such as AAPL and MSFT.
# Import librariesimport pandas as pdimport numpy as npimport yfinance as yfimport statsmodels.api as smfrom statsmodels.regression.rolling import RollingOLSimport matplotlib.pyplot as pltimport plotly.express as pximport plotly.graph_objects as gofrom IPython.display import clear_output
#Download datastartdate='2023-01-01'enddate='2023-09-26'tickers = ['AAPL', 'MSFT']price = yf.download(tickers, startdate, enddate)['Close']price.tail()
[*********************100%***********************] 2 of 2 completed
We can plot these two stocks as follows
# AAPL plotplt.figure(figsize=(10,6))plt.subplot(2, 1, 1) plt.plot(price.AAPL, color='b')plt.ylabel('Price')plt.title('AAPL Daily Close Price USD')# MSFT plotplt.subplot(2, 1, 2)plt.plot(price.MSFT, color='g')plt.ylabel('Price')plt.title('MSFT Daily Close Price USD')# Use plt.tight_layout() to improve the spacing between subplotsplt.tight_layout()plt.show()
We can calculate their daily returns
returns = price.pct_change().dropna()print(returns.tail())
AAPL MSFTDate 2023-09-19 0.006181 -0.0012462023-09-20 -0.019992 -0.0239772023-09-21 -0.008889 -0.0038662023-09-22 0.004945 -0.0078872023-09-25 0.007380 0.001672
AAPLMSFTcount182.000000182.000000mean0.0019700.001689std0.0133940.016852min-0.048020-0.04374325%-0.006398-0.00841450%0.0018380.00090175%0.0093000.011763max0.0469270.072435
We can plot histograms or probabilities of their daily returns
import seaborn as snsfig = plt.figure(figsize=(10,10))# AAPL plotplt.subplot(2, 1, 1) sns.distplot(returns.AAPL, color='b');plt.xlabel('Return')plt.ylabel('Probability')plt.title('AAPL Returns')# MSFT plotplt.subplot(2, 1, 2) sns.distplot(returns.MSFT, color='g')plt.xlabel('Return')plt.ylabel('Probability')plt.title('MSFT Returns')plt.show()
It is very interesting to compare Maximum Drawdown of these 2 stocks
wealth_index = (1+returns['AAPL']).cumprod()previous_peaks_MSFT = wealth_index.cummax()drawdowns_MSFT = (wealth_index - previous_peaks_MSFT)/previous_peaks_MSFTdrawdowns_MSFT.plot.line()plt.ylabel('Drawdown')plt.title('AAPL Maximum Drawdown')drawdowns_MSFT.min(), drawdowns_MSFT.idxmin()
wealth_index = (1+returns['MSFT']).cumprod()previous_peaks_MSFT = wealth_index.cummax()drawdowns_MSFT = (wealth_index - previous_peaks_MSFT)/previous_peaks_MSFTdrawdowns_MSFT.plot.line()plt.ylabel('Drawdown')plt.title('MSFT Maximum Drawdown')drawdowns_MSFT.min(), drawdowns_MSFT.idxmin()
It is worthwhile to look at correlations of their returns
corr = returns[['AAPL', 'MSFT']].corr()print(corr)sns.scatterplot(x="AAPL", y="MSFT", data=returns)sns.regplot(x="AAPL", y="MSFT", data=returns)
AAPL MSFTAAPL 1.000000 0.532946MSFT 0.532946 1.000000
Then we can calculate their compounded growth and covariance
n_days = returns.shape[0]compounded_growth = (1+returns).prod()n_periods = returns.shape[0]ann_returns = compounded_growth**(252/n_days)-1ann_returns
AAPL 0.605810MSFT 0.477083dtype: float64
cov = returns.cov()cov
AAPLMSFTAAPL0.0001790.000120MSFT0.0001200.000284
Let’s turn our attention to the efficient frontier of our 2 assets. In doing so, we need to calculate the portfolio return-volatility
# Calculate the portfolio returndef portfolio_return(w, r): return w.T @ r# Calculate the portfolio volatility returndef portfolio_vol(w, covmat): return (w.T @ covmat @ w)**0.5
We are now ready to plot the efficient frontier curve
#Plot the efficient frontier of two assetsax=plt.figure(figsize=(14,6))n_points = 15weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)]def plot_ef2(n_points, returns, cov): weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)] rets = [portfolio_return(w, ann_returns) for w in weights] vols = [portfolio_vol(w, cov) for w in weights] ef = pd.DataFrame({ "Returns": rets, "Volatility": vols }) return ef.plot.line(x="Volatility", y="Returns", style="o-")ax = plot_ef2(n_points, ann_returns, cov)ax.plot([0.013394], [0.605810], 'o',markersize=14)ax.annotate('AAPL', xy=(0.013394, 0.605810), xytext=(0.0137, 0.60), arrowprops=dict(facecolor='black', shrink=0.05))ax.plot([0.016852], [0.477083], 'o',markersize=14)ax.annotate('MSFT', xy=(0.016852, 0.477083), xytext=(0.016, 0.5), arrowprops=dict(facecolor='black', shrink=0.05))
Popular 4-Stock Portfolio
Our current objectives are as follows:
- Build moving average of selected stocks
- Determine correlations between stock returns
- Create and validate an optimal stock portfolio
- Predict the future behavior of selected stocks
#Importimport numpy as np import pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom pandas_datareader import datafrom datetime import datetime# Setting the begining and endingtoday = datetime.now()year_ago = datetime(today.year-1, today.month, today.day)
# Four company for data extractioncompany_list = ['AAPL', 'TSLA', 'MSFT', 'AMZN']
Reading input stock data:
for company in company_list: globals()[company] = pdr.get_data_yahoo(company, year_ago, today)
[*********************100%***********************] 1 of 1 completed[*********************100%***********************] 1 of 1 completed[*********************100%***********************] 1 of 1 completed[*********************100%***********************] 1 of 1 completed
price = yf.download(company_list, startdate, enddate)['Close']price.tail()
[*********************100%***********************] 4 of 4 completed
Let’s calculate MA 10-20-30
MA_days = [10, 20, 30]for ma in MA_days: ma_str = "MA AAPL {}".format(ma) price[ma_str] = price.AAPL.rolling(ma).mean() ma_str = "MA AMZN {}".format(ma) price[ma_str] = price.AMZN.rolling(ma).mean() ma_str = "MA MSFT {}".format(ma) price[ma_str] = price.MSFT.rolling(ma).mean() ma_str = "MA TSLA {}".format(ma) price[ma_str] = price.TSLA.rolling(ma).mean()price.tail()
AAPLAMZN MSFT TSLAMA AAPL 10 MA AMZN 10MA MSFT 10 MA TSLA 10MA AAPL 20MA AMZN 20MA MSFT 20MA TSLA 20MA AAPL 30MA AMZN 30MA MSFT 30MA TSLA 30Date2023-09-19179.070007137.630005328.649994266.500000177.631001140.334001332.945999264.648001180.4320137.736501329.637001254.881998179.340000137.489334326.883334248.0609992023-09-20175.490005135.289993320.769989262.589996176.889001140.327000331.734998265.715001180.3450137.788500329.552501256.351998179.196334137.334334326.707334248.4906662023-09-21173.929993129.330002319.529999255.699997176.526001139.475000330.696997266.136000179.9855137.479000329.179001257.293998179.054333137.050334326.617334248.9409992023-09-22174.789993129.119995317.010010244.880005176.187001138.564000328.970999265.774001179.9060137.343000329.031001258.035999178.948333136.735667326.420001248.9256662023-09-25176.080002131.270004317.540009246.990005175.859001137.381000326.931000263.115002179.7795137.243501328.759001258.455999178.891334136.497667326.304335249.070333
- AAPL MA 10-20-30:
import matplotlibplt.figure(figsize=(15, 6))matplotlib.rcParams.update({'font.size': 18})plt.plot(price['AAPL'])plt.plot(price['MA AAPL 10'])plt.plot(price['MA AAPL 20'])plt.plot(price['MA AAPL 30']) plt.title('AAPL')plt.xlabel('Date')plt.ylabel('Price')plt.legend(('Close','MA: 10', 'MA: 20', 'MA:30'))plt.grid()plt.show()
- AMZN MA 10-20-30:
plt.figure(figsize=(15, 6))matplotlib.rcParams.update({'font.size': 18})plt.plot(price['AMZN'])plt.plot(price['MA AMZN 10'])plt.plot(price['MA AMZN 20'])plt.plot(price['MA AMZN 30']) plt.title('AMZN')plt.xlabel('Date')plt.ylabel('Price')plt.legend(('Close','MA: 10', 'MA: 20', 'MA:30'))plt.grid()plt.show()
- MSFT MA 10-20-30:
plt.figure(figsize=(15, 6))matplotlib.rcParams.update({'font.size': 18})plt.plot(price['MSFT'])plt.plot(price['MA MSFT 10'])plt.plot(price['MA MSFT 20'])plt.plot(price['MA MSFT 30']) plt.title('MSFT')plt.xlabel('Date')plt.ylabel('Price')plt.legend(('Close','MA: 10', 'MA: 20', 'MA:30'))plt.grid()plt.show()
- TSLA MA 10-20-30:
plt.figure(figsize=(15, 6))matplotlib.rcParams.update({'font.size': 18})plt.plot(price['TSLA'])plt.plot(price['MA TSLA 10'])plt.plot(price['MA TSLA 20'])plt.plot(price['MA TSLA 30']) plt.title('TSLA')plt.xlabel('Date')plt.ylabel('Price')plt.legend(('Close','MA: 10', 'MA: 20', 'MA:30'))plt.grid()plt.show()
Let’s calculate and plot Daily Returns of our 4 stocks
price['Daily Returns AAPL'] = price['AAPL'].pct_change()price['Daily Returns AMZN'] = price['AMZN'].pct_change()price['Daily Returns MSFT'] = price['MSFT'].pct_change()price['Daily Returns TSLA'] = price['TSLA'].pct_change()
- Daily Returns AAPL
sns.displot(price['Daily Returns AAPL'].dropna(), bins=50, color='blue', kde=True)plt.title("AAPL")plt.show()
- Daily Returns AMZN
sns.displot(price['Daily Returns AMZN'].dropna(), bins=50, color='blue', kde=True)plt.title("AMZN")plt.show()
- Daily Returns MSFT
sns.displot(price['Daily Returns MSFT'].dropna(), bins=50, color='blue', kde=True)plt.title("MSFT")plt.show()
- Daily Returns TSLA
sns.displot(price['Daily Returns TSLA'].dropna(), bins=50, color='blue', kde=True)plt.title("TSLA")plt.show()
Let’s prepare the above returns for the stock correlation analysis
stock_returns = pd.DataFrame()stock_returns['AAPL']=price['Daily Returns AAPL'].dropna() stock_returns['AMZN']=price['Daily Returns AMZN'].dropna()stock_returns['MSFT']=price['Daily Returns MSFT'].dropna()stock_returns['TSLA']=price['Daily Returns TSLA'].dropna()stock_returns.tail()
- Pair plot
sns.pairplot(stock_returns)plt.savefig('pairplot_tech.png')
- Correlation matrix
# Build correlation matrixcorr = stock_returns.corr()mask = np.triu(np.ones_like(corr, dtype=bool))plt.figure(figsize=(10, 10))sns.heatmap(corr, mask=mask, square=True, linewidths=.5, annot=True)#plt.show()plt.savefig('corrmatrix_tech.png')
- Joint plot
def draw_jointplot(data): grid = sns.PairGrid(data.dropna()) grid.map_diag(sns.histplot, bins=40, kde=True) grid.map_lower(sns.regplot) grid.map_upper(sns.kdeplot)
draw_jointplot(stock_returns)plt.savefig('stockreturns_tech.png')
Here, Row 1: AAPL, Row 2: AMZN, Row 3: MSFT, Row 4: TSLA.
Let’s calculate the mean returns and covariance of our stocks
mean_income = stock_returns.mean() # Mean income for each stockcov_returns = stock_returns.cov() # Covariation count = len(stock_returns.columns)print(mean_income, cov_returns, sep='\n')
AAPL 0.001970AMZN 0.002569MSFT 0.001689TSLA 0.005150dtype: float64
AAPL AMZN MSFT TSLAAAPL 0.000179 0.000115 0.000120 0.000215AMZN 0.000115 0.000467 0.000218 0.000301MSFT 0.000120 0.000218 0.000284 0.000207TSLA 0.000215 0.000301 0.000207 0.001217
Let’s find the maximum Sharpe ratio of our portfolio by generating random shares while plotting the efficient frontier curve as an envelope
# Function, that generate random sharesdef randomPortfolio(): share = np.exp(np.random.randn(count)) share = share / share.sum() return sharedef IncomePortfolio(Rand): return np.matmul(mean_income.values, Rand)def RiskPortfolio(Rand): return np.sqrt(np.matmul(np.matmul(Rand, cov_returns.values), Rand))
combinations = 4000risk = np.zeros(combinations)income = np.zeros(combinations)portfolio = np.zeros((combinations, count))# Function, which create new combinations of sharesfor i in range(combinations): rand = randomPortfolio() portfolio[i, :] = rand risk[i] = RiskPortfolio(rand) income[i] = IncomePortfolio(rand)
plt.figure(figsize=(15, 8))plt.scatter(risk * 100, income * 100, c="b", marker="o",s=20)plt.xlabel("Risk")plt.ylabel("Income")plt.title("Portfolios")MaxSharpRatio = np.argmax(income / risk)plt.scatter([risk[MaxSharpRatio] * 100], [income[MaxSharpRatio] * 100], s=140,c="r", marker="o", label="Max Sharp ratio")plt.legend()#plt.show()plt.savefig('efficiencycurve_portfolios.png')
Finally, we can compare the maximum Sharpe ratios of our stocks
best_port = portfolio[MaxSharpRatio]for i in range(len(company_list)): print("{} : {}".format(company_list[i], best_port[i]))
AAPL : 0.5737824378783145TSLA : 0.1887338094255849MSFT : 0.033839219286878226AMZN : 0.2036445334092224
Monte-Carlo Predictions
We will consider the 1Y forecast with the mean and STD values
days = 365dt = 1 / daysstock_returns.dropna(inplace=True)mu = stock_returns.mean()sigma = stock_returns.std()
We need the following function
def monte_carlo(start_price, days, mu, sigma): price = np.zeros(days) price[0] = start_price shock = np.zeros(days) drift = np.zeros(days) for x in range(1, days): shock[x] = np.random.normal(loc=mu * dt, scale=sigma*np.sqrt(dt)) drift[x] = mu * dt price[x] = price[x-1] + (price[x-1] * (drift[x] + shock[x])) return price
- AAPL
price['AAPL'].describe()
count 183.000000mean 168.418634std 17.755754min 125.01999725% 153.84000450% 172.69000275% 180.955002max 196.449997Name: AAPL, dtype: float64
start_price = 168.418634sim = np.zeros(1000)plt.figure(figsize=(15, 8))for i in range(1000): result = monte_carlo(start_price, days, mu['AAPL'], sigma['AAPL']) sim[i] = result[days - 1] plt.plot(result) plt.xlabel('Days')plt.ylabel('Price')plt.title('Monte Carlo Analysis for AAPL')plt.savefig('monte_aapl.png')
plt.figure(figsize=(10, 7))plt.hist(sim, bins=100)plt.figtext(0.6, 0.7, "Mean: {} \nStd: {} \nStart Price: {}".format(sim.mean(), sim.std(), start_price))#plt.show()plt.savefig('montehist_aapl.png')
- MSFT
price['MSFT'].describe()
count 183.000000mean 299.507268std 36.373372min 222.30999825% 267.14500450% 311.73999075% 330.964996max 359.489990Name: MSFT, dtype: float64
start_price = 299.507268sim = np.zeros(1000)plt.figure(figsize=(15, 8))for i in range(1000): result = monte_carlo(start_price, days, mu['MSFT'], sigma['MSFT']) sim[i] = result[days - 1] plt.plot(result) plt.xlabel('Days')plt.ylabel('Price')plt.title('Monte Carlo Analysis for MSFT')plt.savefig('monte_msft.png')
plt.figure(figsize=(10, 7))plt.hist(sim, bins=100)plt.figtext(0.6, 0.7, "Mean: {} \nStd: {} \nStart Price: {}".format(sim.mean(), sim.std(), start_price))#plt.show()plt.savefig('montehist_msft.png')
- AMZN
price['AMZN'].describe()
count 183.000000mean 114.791913std 17.026834min 83.12000325% 99.38000150% 112.91000475% 130.184998max 144.850006Name: AMZN, dtype: float64
start_price = 114.791913sim = np.zeros(1000)plt.figure(figsize=(15, 8))for i in range(1000): result = monte_carlo(start_price, days, mu['AMZN'], sigma['AMZN']) sim[i] = result[days - 1] plt.plot(result) plt.xlabel('Days')plt.ylabel('Price')plt.title('Monte Carlo Analysis for AMZN')plt.savefig('monte_amzn.png')
plt.figure(figsize=(10, 7))plt.hist(sim, bins=100)plt.figtext(0.6, 0.7, "Mean: {} \nStd: {} \nStart Price: {}".format(sim.mean(), sim.std(), start_price))#plt.show()plt.savefig('montehist_amzn.png')
- TSLA
price['TSLA'].describe()
count 183.000000mean 209.919180std 45.605744min 108.09999825% 180.29499850% 201.28999375% 254.904999max 293.339996Name: TSLA, dtype: float64
plt.figure(figsize=(10, 7))plt.hist(sim, bins=100)plt.figtext(0.6, 0.7, "Mean: {} \nStd: {} \nStart Price: {}".format(sim.mean(), sim.std(), start_price))#plt.show()plt.savefig('montehist_tsla.png')
SPY Return/Volatility
Let’s look at the SPY index in 2023
# import modulesfrom datetime import datetimeimport yfinance as yfimport matplotlib.pyplot as plt # initialize parametersstart_date = datetime(2023, 1, 1)end_date = datetime(2023, 9, 25) # get the datadata = yf.download('SPY', start = start_date, end = end_date) # displayplt.figure(figsize = (20,10))plt.title('Opening Prices from {} to {}'.format(start_date, end_date))plt.plot(data['Open'],lw=4)plt.grid(color='k', linestyle='--', linewidth=1)plt.show()
Let’s calculate the average annual SPY return and volatility
nifty=data.copy()nifty_returns=(nifty['Close']/nifty['Open'])-1volatility= np.std(nifty_returns)trading_days=len(nifty_returns)mean=nifty_returns.mean()print('Annual Average SPY return',mean)print('Annual volatility',volatility*np.sqrt(trading_days))print('Number of trading days',trading_days)
Annual Average SPY return 0.0006876400629725226Annual volatility 0.09887050147370505Number of trading days 182
The SPY daily returns are given by
daily_returns=np.random.normal(mean/trading_days,volatility,trading_days)+1index_returns=[10980] for x in daily_returns: index_returns.append(index_returns[-1]*x)plt.plot(daily_returns)plt.show()
The corresponding 1000 random simulations of daily returns are
for i in range(1000): daily_returns=np.random.normal(mean/trading_days,volatility,trading_days)+1 index_returns=[10980] for x in daily_returns: index_returns.append(index_returns[-1]*x) plt.plot(daily_returns)plt.show()
SPY Prophet Forecast
Let’s prepare the SPY stock data for the FB Prophet forecast
nifty.reset_index(inplace=True)nifty['Date']= pd.to_datetime(nifty['Date'])nifty.rename(columns={'Date':'ds','Open':'y'},inplace=True)
The forecast model is expressed as
from prophet import Prophetmodel=Prophet()model.fit(nifty)predict_df=model.make_future_dataframe(periods=252)predict_df.tail()
ds4292024-05-274302024-05-284312024-05-294322024-05-304332024-05-31
Let’s plot the forecast and its components
forecast=model.predict(predict_df)
fig1=model.plot(forecast)plt.xticks(fontsize = 15)
fig2=model.plot_components(forecast,figsize=(14,5))
Summary
- In this post, we have shown how to compute stock volatility in Python and the different measures of risk-adjusted returns based on it.
- While we continue to rank SPY as a long-term hold position, we focused our discussion on rather short-term trading strategies to see how topblue-chip stocks have now again gained positive momentum.
- The AAPL example has explained how quant traders can use various SMA and MA crossovers to identify buy and sell signals. These signals have been verified using regression support and resistance lines.
- The AAPL-MSFT example has illustrated the value of an efficient frontier graph, maximum drawdown curves, correlations of returns, covariance metrics, and the compounded growth.
- The 4-stock portfolio example has demonstrated the importance of comparing and integrating popular trading indicators, correlation plots, and Monte Carlo simulations.
- Finally, we have analyzed the SPY index in terms of volatility and average returns using both historical data and the Prophet forecast model.
- Results produced by this software have been verified by comparison to a number of well known 3rd party trading platforms such as Macroaxis, TradingView, Barchart, etc.
References
- GitHub Rep
- Volatility And Measures Of Risk-Adjusted Return With Python
- Buy and Sell Signals with the Simple Moving Average Crossover
- Scalable Time-Series Forecasting with Spark and Prophet
- How to Download historical stock prices in Python ?
- Monte Carlo Methods
- Predicting Nifty using Monte Carlo, fbprophet
Explore More
- Applying a Risk-Aware Portfolio Rebalancing Strategy to ETF, Energy, Pharma, and Aerospace/Defense Stocks in 2023
- Risk-Aware Strategies for DCA Investors
- Joint Analysis of Bitcoin, Gold and Crude Oil Prices with Optimized Risk/Return in 2023
- Towards Max(ROI/Risk) Trading
- DJI Market State Analysis using the Cruz Fitting Algorithm
- Bear vs. Bull Portfolio Risk/Return Optimization QC Analysis
- A TradeSanta’s Quick Guide to Best Swing Trading Indicators
- Stock Portfolio Risk/Return Optimization
- Risk/Return QC via Portfolio Optimization – Current Positions of The Dividend Breeder
- Portfolio Optimization Risk/Return QC – Positions of Humble Div vs Dividend Glenn
- The Qullamaggie’s TSLA Breakouts for Swing Traders
- The Qullamaggie’s OXY Swing Breakouts
- Algorithmic Testing Stock Portfolios to Optimize the Risk/Reward Ratio
- Quant Trading using Monte Carlo Predictions and 62 AI-Assisted Trading Technical Indicators (TTI)
- Are Blue-Chips Perfect for This Bear Market?
- Track All Markets with TradingView
- Stock Forecasting with FBProphet
- Predicting Trend Reversal in Algorithmic Trading using Stochastic Oscillator in Python
- Inflation-Resistant Stocks to Buy
- ML/AI Regression for Stock Prediction – AAPL Use Case
- Macroaxis Wealth Optimization
- Investment Risk Management Study
One-Time
Monthly
Yearly
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
€5.00
€15.00
€100.00
€5.00
€15.00
€100.00
€5.00
€15.00
€100.00
Or enter a custom amount
€
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.