<jupyter_start><jupyter_text>Case 10: Backtesting Investment Strategies (US Stocks)  Importing the Data<jupyter_code>import pandas as pd
pd.read_csv("dji.csv").info()
data = pd.read_csv("dji.csv", parse_dates = ["Date"], index_col = "Date")<jupyter_output><empty_output><jupyter_text>Se a gente utilizar a data como indice, é possível selecionar intervalos temporais utilizando o iloc:<jupyter_code>df = data.loc["2010-01-01": "2020-03-31", "Close"].to_frame()
df<jupyter_output><empty_output><jupyter_text>Data Visualization & Returns<jupyter_code>import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
plt.style.use("seaborn")
df.describe()
df.plot(figsize = (20, 12), fontsize = 15)
plt.legend(fontsize = 15)
plt.show()
df["Return"] = df.pct_change()
df.plot(y='Return')
df
df.dropna(inplace = True)
df
df.plot(figsize = (20, 12), secondary_y = "Return", mark_right = True, fontsize = 15)
plt.show()
df.rename(columns = {"Close":"DJI_Close", "Return":"DJI_Return"}, inplace = True)
df<jupyter_output><empty_output><jupyter_text>Backtesting a simple Momentum Strategy __Positions__: +1: Investing in DJI (__long__ position) -1: Short Selling DJI (__short__ position)0: No position (__neutral__) __Strategies__: -__Buy and Hold__ (Basic Strategy - passive): Initially Investing into DJI and do nothing (Position: +1 on any given day) -__Simple Momentum__ (active Strategy to be tested): __a) Investing (+1)__ into DJI tomorrow if today´s return was __positive__ __b) Short selling (-1)__ DJI tomorrow if today´s return was __negative__<jupyter_code>df
df["Position"] = np.sign(df["DJI_Return"])
df
df["Strategy_Ret"] = df["Position"].shift() * df["DJI_Return"]
df
df.Strategy_Ret.add(1, fill_value = 0).cumprod()
df["Strategy"] = df.Strategy_Ret.add(1, fill_value = 0).cumprod() * df.iloc[0, 0]
df
df[["DJI_Close", "Strategy"]].plot(figsize = (15, 10), fontsize = 15)
plt.title("Simple Momentum Strategy", fontsize = 20)
plt.legend(fontsize = 15)
plt.show()
def summary_ann(returns):
    summary = returns.agg(["mean", "std"]).T
    summary["Return"] = summary["mean"] * 252
    summary["Risk"] = summary["std"] * np.sqrt(252)
    summary.drop(columns = ["mean", "std"], inplace = True)
    return summary
summary_ann(df[["DJI_Return", "Strategy_Ret"]])<jupyter_output><empty_output><jupyter_text>Backtesting a simple Contrarian Strategy __Strategies__: -__Buy and Hold__ (Basic Strategy): Initially Investing into DJI and do nothing (Position: +1 on all days) -__Simple Contrarian__ (Strategy to be tested): __a) Short Selling (-1)__ DJI tomorrow if today´s return was __positive__ __b) Investing (+1)__ into DJI tomorrow if today´s return was __negative__<jupyter_code>data
df = data.loc["2010":, "Close"].to_frame()
df["DJI_Return"] = df.Close.pct_change()
df.columns = ["DJI_Close", "DJI_Return"]
df.dropna(inplace = True)
df
df["Position"] = -np.sign(df["DJI_Return"])
df
df["Strategy_Ret"] = df["Position"].shift() * df["DJI_Return"]
df
df["Strategy"] = df.Strategy_Ret.add(1, fill_value = 0).cumprod() * df.iloc[0, 0]
df
df[["DJI_Close", "Strategy"]].plot(figsize = (15, 10), fontsize = 15)
plt.legend(fontsize = 15)
plt.title("Simple Contrarian Strategy", fontsize = 20)
plt.show()
summary_ann(df[["DJI_Return", "Strategy_Ret"]])<jupyter_output><empty_output><jupyter_text>More complex Strategies & Backtesting vs. Fitting<jupyter_code>data
df = data.loc["2010":, "Close"].to_frame()
df["DJI_Return"] = df.Close.pct_change()
df.columns = ["DJI_Close", "DJI_Return"]
df.dropna(inplace = True)
df
df["Position"] = np.where(df["DJI_Return"] > 0.01, -1, 1)
df
df["Strategy_Ret"] = df["Position"].shift() * df["DJI_Return"]
df
df["Strategy"] = df.Strategy_Ret.add(1, fill_value = 0).cumprod() * df.iloc[0, 0]
df
df[["DJI_Close", "Strategy"]].plot(figsize = (15, 10), fontsize = 15)
plt.legend(fontsize = 15)
plt.title("Simple Contrarian Strategy", fontsize = 20)
plt.show()
summary_ann(df[["DJI_Return", "Strategy_Ret"]])<jupyter_output><empty_output><jupyter_text>Even if a Strategy __seems to outperform__ the basic Strategy, the following issues need to be considered/analyzed as well: - Backtesting vs. Fitting -> Was the Strategy __fitted__ and optimized on __historical data__? __Forward Testing__ is required!- __Transaction Costs__ -> Changing Positions trigger Cost. Include Costs!- __Tax effects__ -> Changing Positions can trigger (earlier) Tax Payments. Include Taxes!  Simple Moving Averages (Part 1)<jupyter_code>data
df = data.loc["2010":, "Close"].to_frame()
df["DJI_Return"] = df.Close.pct_change()
df.columns = ["DJI_Close", "DJI_Return"]
df.dropna(inplace = True)
df
df.DJI_Close.rolling(window = 50).mean()
df["SMA50"] = df.DJI_Close.rolling(window = 50).mean()
df[["DJI_Close", "SMA50"]].plot(figsize = (15, 10), fontsize = 15)
plt.legend(fontsize = 15)
plt.show()
df["SMA200"] = df.DJI_Close.rolling(window = 200).mean()
df
df[["SMA50", "SMA200"]].plot(figsize = (15, 10), fontsize = 15)
plt.legend(fontsize = 15)
plt.show()
df.dropna(inplace= True)
df<jupyter_output><empty_output><jupyter_text>Simple Moving Averages (Part 2) __Strategies__: -__Buy and Hold__ (Basic Strategy): Initially Investing into DJI and do nothing (Position: +1 on all days) -__SMA Crossover (Momentum)__ (Strategy to be tested): __a) Investing (+1)__: SMA50 __>__ SMA200 __b) Short Selling (-1)__: SMA50 __<__ SMA200<jupyter_code>df["Position"] = np.sign(df.SMA50.sub(df.SMA200)) 
df
df[["SMA50", "SMA200", "Position"]].plot(figsize = (15, 10), secondary_y = "Position", fontsize = 15)
plt.show()
df["Strategy_Ret"] = df["Position"].shift() * df["DJI_Return"]
df
df["Strategy"] = df.Strategy_Ret.add(1, fill_value = 0).cumprod() * df.iloc[0, 0]
df
df[["DJI_Close", "Strategy"]].plot(figsize = (15, 10), fontsize = 15)
plt.legend(fontsize = 15)
plt.title("SMA Strategy", fontsize = 20)
plt.show()
summary_ann(df[["DJI_Return", "Strategy_Ret"]])
df["Position"] = -np.sign(df.SMA50.sub(df.SMA200)) 
df
df[["SMA50", "SMA200", "Position"]].plot(figsize = (15, 10), secondary_y = "Position", fontsize = 15)
plt.show()
df["Strategy_Ret"] = df["Position"].shift() * df["DJI_Return"]
df
df["Strategy"] = df.Strategy_Ret.add(1, fill_value = 0).cumprod() * df.iloc[0, 0]
df
df[["DJI_Close", "Strategy"]].plot(figsize = (15, 10), fontsize = 15)
plt.legend(fontsize = 15)
plt.title("SMA Strategy", fontsize = 20)
plt.show()
summary_ann(df[["DJI_Return", "Strategy_Ret"]])<jupyter_output><empty_output><jupyter_text>Backtesting the Perfect Strategy (...in case you can predict the future...)<jupyter_code>data
df = data.loc["2010":, "Close"].to_frame()
df["DJI_Return"] = df.Close.pct_change()
df.columns = ["DJI_Close", "DJI_Return"]
df.dropna(inplace = True)
df
df["Position"] = np.sign(df["DJI_Return"])
df
df["Strategy_Ret"] = df["Position"] * df["DJI_Return"]
df
df["Strategy"] = df.Strategy_Ret.add(1, fill_value = 0).cumprod() * df.iloc[0, 0]
df
df[["DJI_Close", "Strategy"]].plot(figsize = (15, 10), fontsize = 15, logy = True)
plt.legend(fontsize = 15)
plt.title("The Perfect Strategy", fontsize = 20)
plt.show()
summary_ann(df[["DJI_Return", "Strategy_Ret"]])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1723895299746693, 'fraction_numerical': 0.033211370672670985, 'mean_word_length': 6.584845250800427, 'pattern_counts': {'":': 7, '<': 38, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '324287', 'license': 'MIT', 'n_tokens_mistral': 2910, 'n_tokens_neox': 2608, 'n_words': 614, 'path': 'Project_10_Materials/Project_10_Backtesting.ipynb', 'repo_name': 'emdemor/PythonDataScienceWithPandas_Exercises', 'size': '7106'}