<jupyter_start><jupyter_text>Simple strategy - Moving Average CrossoversThe **"Moving Average Crossovers"** strategy for algorithmic trading is just like the ***"Hello world"*** program for coding beginners. It serves as a good starting point to learn coding for technical analysis.  Table of Contents* [1. Implement the strategy](1.-Implement-the-strategy)* [2. Plot figure](2-Plot-figure)* [3. Backtesting](3-Backtesting)* [4. Evaluate strategy](4-Evalaute-strategy)  **Requirements:** * pandas * numpy * matplotlib  1. Implement the strategy<jupyter_code># import libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# load aapl csv file
aapl = pd.read_csv('../../database/microeconomic_data/nasdaq_ticks_day/nasdaq_AAPL.csv', header=0, index_col='Date', parse_dates=True)

# We select only the data from 2015-2019
aapl = aapl.loc[pd.Timestamp('2015-01-01'):pd.Timestamp('2019-12-31')]
# Initialize the short and long windows
short_window = 40
long_window = 100

# Initialize the `signals` DataFrame with the `signal` column
signals = pd.DataFrame(index=aapl.index)
signals['signal'] = 0.0

# Create short simple moving average over the short window
signals['short_mavg'] = aapl['Close'].rolling(window=short_window, min_periods=1, center=False).mean()

# Create long simple moving average over the long window
signals['long_mavg'] = aapl['Close'].rolling(window=long_window, min_periods=1, center=False).mean()

# Create signals
signals['signal'][short_window:] = np.where(signals['short_mavg'][short_window:] 
                                            > signals['long_mavg'][short_window:], 1.0, 0.0)   

# Generate trading orders
signals['positions'] = signals['signal'].diff()

# Print `signals`
signals.tail()<jupyter_output><empty_output><jupyter_text>2. Plot figure<jupyter_code># Initialize the plot figure
fig = plt.figure()

# Add a subplot and label for y-axis
ax1 = fig.add_subplot(111,  ylabel='Price in $')

# Plot the closing price
aapl['Close'].plot(ax=ax1, color='r', lw=2.)

# Plot the short and long moving averages
signals[['short_mavg', 'long_mavg']].plot(ax=ax1, lw=2.)

positions = (signals.positions).to_numpy()
short_mavg = (signals.short_mavg).to_numpy()
long_mavg = (signals.long_mavg).to_numpy()

# Plot the buy signals
ax1.plot(signals.loc[positions == 1.0].index, 
         short_mavg[positions == 1.0],
         '^', markersize=10, color='m')

# Plot the sell signals
ax1.plot(signals.loc[positions == -1.0].index, 
         long_mavg[positions == -1.0],
         'v', markersize=10, color='k')

# Show the plot
plt.show()<jupyter_output><empty_output><jupyter_text>3. Backtesting<jupyter_code># Set the initial capital
initial_capital= float(100000.0)

# Create a DataFrame `positions`
positions = pd.DataFrame(index=signals.index).fillna(0.0)

# Buy a 100 shares
positions['AAPL'] = 100*signals['signal']   
  
# Initialize the portfolio with value owned   
portfolio = positions.multiply(aapl['Close'], axis=0)

# Store the difference in shares owned 
pos_diff = positions.diff()

# Add `holdings` to portfolio
portfolio['holdings'] = (positions.multiply(aapl['Close'], axis=0)).sum(axis=1)

# Add `cash` to portfolio
portfolio['cash'] = initial_capital - (pos_diff.multiply(aapl['Close'], axis=0)).sum(axis=1).cumsum()   

# Add `total` to portfolio
portfolio['total'] = portfolio['cash'] + portfolio['holdings']

# Add `returns` to portfolio
portfolio['returns'] = portfolio['total'].pct_change()

# Print the last lines of `portfolio`
portfolio.tail()
# Create a figure
fig = plt.figure()

ax1 = fig.add_subplot(111, ylabel='Portfolio value in $')

# Plot the equity curve in dollars
portfolio['total'].plot(ax=ax1, lw=2.)

positions = signals.positions.to_numpy()

ax1.plot(portfolio.loc[positions == 1.0].index, 
         portfolio.total[positions == 1.0],
         '^', markersize=10, color='m')
ax1.plot(portfolio.loc[positions == -1.0].index, 
         portfolio.total[positions == -1.0],
         'v', markersize=10, color='k')

# Show the plot
plt.show()<jupyter_output><empty_output><jupyter_text>4. Evaluate strategy  4.1 Sharpe ratio<jupyter_code># Isolate the returns of your strategy
returns = portfolio['returns']

# annualized Sharpe ratio
sharpe_ratio = np.sqrt(252) * (returns.mean() / returns.std())

# Print the Sharpe ratio
print(sharpe_ratio)<jupyter_output>0.8311190106415088<jupyter_text>4.2 Maximum drawdown<jupyter_code># Define a trailing 252 trading day window
window = 252

# Calculate the max drawdown in the past window days for each day 
rolling_max = aapl['Close'].rolling(window, min_periods=1).max()
daily_drawdown = aapl['Close']/rolling_max - 1.0

# Calculate the minimum (negative) daily drawdown
max_daily_drawdown = daily_drawdown.rolling(window, min_periods=1).min()

# Plot the results
daily_drawdown.plot()
max_daily_drawdown.plot()

# Show the plot
plt.show()<jupyter_output><empty_output><jupyter_text>3. Compound Annual Growth Rate (CAGR)<jupyter_code># Get the number of days in `aapl`
days = (aapl.index[-1] - aapl.index[0]).days

# Calculate the CAGR 
cagr = ((((aapl['Close'][-1]) / aapl['Close'][1])) ** (365.0/days)) - 1

# Print the CAGR
print(cagr)<jupyter_output>0.24654176746201206
{'fraction_non_alphanumeric': 0.1435158501440922, 'fraction_numerical': 0.03342939481268011, 'mean_word_length': 5.168246445497631, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '398893', 'license': 'CC0-1.0', 'n_tokens_mistral': 1912, 'n_tokens_neox': 1763, 'n_words': 427, 'path': 'code/technical-analysis_basics/simple-strategy-ma-crossover.ipynb', 'repo_name': 'awoo424/algotrading', 'size': '5205'}