## What will we cover in this tutorial?

Believe it or not? The there are so many promises of the best trading strategies out there.

In this one we will analyze a promising strategy and see whether it holds or not?

What is it?

This looks amazing, how can it perform this good? Well, simply said, it combines short selling and a safety margin to avoid loosing money.

On the surface, it seems to take precautions. But let’s try to examine it closer.

## Step 1: Implementing the strategy

The strategy is to have to Moving Averages a 42 days (MA42) and 252 days (MA252), then a safety margin (or safety distance) involved.

The strategy is as follows:

• When MA42 – MA252 > safety distance, then go long.
• When MA252 – MA52 > safety distance, then go short.

To analyze and implement the Strategy, we need Pandas_datareader to read the historic ticker prices.

```import pandas_datareader as pdr
from datetime import datetime
data = pdr.get_data_yahoo('^GSPC', datetime(2000, 1, 1), datetime(2020, 1, 1))
data['MA42'] = data['Adj Close'].rolling(42).mean()
data['MA252'] = data['Adj Close'].rolling(252).mean()
data['42-252'] = data['MA42'] - data['MA252']
sd = 50
data['Regime'] = np.where(data['42-252'] > sd, 1, 0)
data['Regime'] = np.where(data['42-252'] < -sd, -1, data['Regime'])
print(data['Regime'].value_counts())
```

We retrive data for S&P 500 (ticker: ^GSPC) by using pdr.get_data_yahoo(‘^GSPC’, datetime(2000, 1, 1), datetime(2020, 1, 1)) and get 20 years of data.

As you see, the moving average are calculate with data[‘Adj Close’].rolling(42).mean().

We use a safety distance (sd) is set to 50. This makes sure that we do not go long or short immediately, but only when we have some distance.

The Regime is the short and long signal. Short when -1 and long when 1. If 0, do nothing.

We can see an overview of how often we go long and short.

``` 1    2608
0    1422
-1    1001
```

## Step 2: Test the strategy

This is straight forward.

```import pandas_datareader as pdr
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt

data = pdr.get_data_yahoo('^GSPC', datetime(2000, 1, 1), datetime(2020, 1, 1))
data['MA42'] = data['Adj Close'].rolling(42).mean()
data['MA252'] = data['Adj Close'].rolling(252).mean()
data['42-252'] = data['MA42'] - data['MA252']
sd = 50
data['Regime'] = np.where(data['42-252'] > sd, 1, 0)
data['Regime'] = np.where(data['42-252'] < -sd, -1, data['Regime'])
print(data['Regime'].value_counts())
data['Market'] = np.log(data['Adj Close'] / data['Adj Close'].shift(1))
data['Strategy'] = data['Regime'].shift(1) * data['Market']
data[['Market', 'Strategy']].cumsum().apply(np.exp).plot(grid=True, figsize=(8, 5))
plt.show()
```

To test the strategy you need to compare it. We compare it against the general market (The S&P 500).

We use the log-returns, which can later be accumulated by cumsum and applied with the exponential function to get the result again.

The Strategy uses the Regime, but shifted one day, as we need a day to react on the price, hence, data[‘Regime’].shift(1) * data[‘Market’].

Finally, we plot the Strategy against the Market.

That looks good, right?

Well, let’s look at it closer.

## Step 3: Deeper analysis of the winning strategy

First a few notes on short selling in general.

As noted, the strategy utilizes short selling, which often is not advised for starting investors. First of all, it is often more expensive, as you loan.

Often there is a fee to short sell, and a interest on top of that. I have seen fees that are quite high and interest on 4% p.a. This makes it less attractive and needs to be considered.

But there is more, and this is why I always encourage people to make the analysis they see themselves. The above depends on the starting point.

Let’s take a different period: 2010-2020, then this picture arises.

Really, you might ask?

Try it yourself. Often these extremely good strategies, looking too good to be true, are only good under certain circumstances. Like, here, where it depends on the starting point.

Okay, in the past, when you start in 2000, it would have been good. But not from 2010 and forward, then it looks like a loosing strategy.

What about if you start today?

If you ask me, this is speculating.

## What is next?

Check out my popular e-book on backtesting strategies. It will teach how to make better analysis, what to look for, and how to evaluate it. This tutorial only touches a few points.

## What will we cover in this tutorial?

In this tutorial we will learn how to export Financial data from DataFrames (Pandas/Python) into an Excel sheet. It will be in multiple sheets with colored rows and charts. And of course, all automated from Python.

## Step 1: Read financial data into a DataFrame

First we need some data. We will use the data from our CSV file. Feel free to use any other data. The CSV used here is available in my GitHub.

```import pandas as pd

data = pd.read_csv("AAPL.csv", index_col=0, parse_dates=True)
```

## Step 2: Calculate the Moving Average, MACD, and Stochastic Oscillator with DataFrames

Moving Average as done previously.

```data['MA10'] = data['Close'].rolling(10).mean()
```

The MACD as calculated follows.

```exp1 = data['Close'].ewm(span=12, adjust=False).mean()
exp2 = data['Close'].ewm(span=26, adjust=False).mean()
data['MACD'] = macd = exp1 - exp2
data['Signal line'] = exp3 = macd.ewm(span=9, adjust=False).mean()
```

The Stochastic Oscillator.

```high14 = data['High'].rolling(14).max()
low14 = data['Low'].rolling(14).min()
data['%K'] = pct_k = (data['Close'] - low14)*100/(high14 - low14)
data['%D'] = pct_d = data['%K'].rolling(3).mean()
```

## Step 3: Adjust the time period and reverse the DataFrame

Adjust the time period we need. This is needed as the first calculations will not be available (NaN) or incorrect.

```data = data.loc['2020-01-01':]
data = data.iloc[::-1]
```

Also notice, we reverse the data by .iloc[::-1]. This is just to have the most recent data on the top of our Excel sheet.

## Step 4: Export DataFrame to Excel with multiple sheets and chars

The for generating our Excel sheet we need the XlsxWriter.

If you don’t have it installed already you can install it by running this in a cell: !pip install XlsxWriter

The code that generated the Excel sheet.

```writer = pd.ExcelWriter("technical.xlsx",
engine='xlsxwriter',
date_format = 'yyyy-mm-dd',
datetime_format='yyyy-mm-dd')

workbook = writer.book

# Create a format for a green cell
'bg_color': '#C6EFCE',
'font_color': '#006100'
})

# Create a format for a red cell
'bg_color': '#FFC7CE',
'font_color': '#9C0006'
})

# **
# ** MA
# **
sheet_name = 'MA10'
data[['Close', 'MA10']].to_excel(writer, sheet_name=sheet_name)
worksheet = writer.sheets[sheet_name]

# Set column width of Date
worksheet.set_column(0, 0, 15)

for col in range(1, 3):
# Create a conditional formatted of type formula
worksheet.conditional_format(1, col, len(data), col, {
'type': 'formula',
'criteria': '=B2>=C2',
'format': green_cell
})

# Create a conditional formatted of type formula
worksheet.conditional_format(1, col, len(data), col, {
'type': 'formula',
'criteria': '=B2<C2',
'format': red_cell
})

# Create a new chart object.
chart1 = workbook.add_chart({'type': 'line'})

# Add a series to the chart.
'name': 'AAPL',
'categories': [sheet_name, 1, 0, len(data), 0],
'values': [sheet_name, 1, 1, len(data), 1],
})

# Create a new chart object.
chart2 = workbook.add_chart({'type': 'line'})

# Add a series to the chart.
'name': sheet_name,
'categories': [sheet_name, 1, 0, len(data), 0],
'values': [sheet_name, 1, 2, len(data), 2],
})

# Combine and insert title, axis names
chart1.combine(chart2)
chart1.set_title({'name': sheet_name + " AAPL"})
chart1.set_x_axis({'name': 'Date'})
chart1.set_y_axis({'name': 'Price'})

# Insert the chart into the worksheet.
worksheet.insert_chart('E2', chart1)

# **
# ** MACD
# **

sheet_name = 'MACD'
data[['Close', 'MACD', 'Signal line']].to_excel(writer, sheet_name=sheet_name)
worksheet = writer.sheets[sheet_name]

# Set column width of Date
worksheet.set_column(0, 0, 15)

for col in range(1, 4):
# Create a conditional formatted of type formula
worksheet.conditional_format(1, col, len(data), col, {
'type': 'formula',
'criteria': '=C2>=D2',
'format': green_cell
})

# Create a conditional formatted of type formula
worksheet.conditional_format(1, col, len(data), col, {
'type': 'formula',
'criteria': '=C2<D2',
'format': red_cell
})

# Create a new chart object.
chart1 = workbook.add_chart({'type': 'line'})

# Add a series to the chart.
'name': 'MACD',
'categories': [sheet_name, 1, 0, len(data), 0],
'values': [sheet_name, 1, 2, len(data), 2],
})

# Create a new chart object.
chart2 = workbook.add_chart({'type': 'line'})

# Add a series to the chart.
'name': 'Signal line',
'categories': [sheet_name, 1, 0, len(data), 0],
'values': [sheet_name, 1, 3, len(data), 3],
})

# Combine and insert title, axis names
chart1.combine(chart2)
chart1.set_title({'name': sheet_name + " AAPL"})
chart1.set_x_axis({'name': 'Date'})
chart1.set_y_axis({'name': 'Value'})

# To set the labels on x axis not on 0
chart1.set_x_axis({
'label_position': 'low',
'num_font':  {'rotation': 45}
})

# Insert the chart into the worksheet.
worksheet.insert_chart('F2', chart1)

# **
# ** Stochastic
# **

sheet_name = 'Stochastic'
data[['Close', '%K', '%D']].to_excel(writer, sheet_name=sheet_name)
worksheet = writer.sheets[sheet_name]

# Set column width of Date
worksheet.set_column(0, 0, 15)

for col in range(1, 4):
# Create a conditional formatted of type formula
worksheet.conditional_format(1, col, len(data), col, {
'type': 'formula',
'criteria': '=C2>=D2',
'format': green_cell
})

# Create a conditional formatted of type formula
worksheet.conditional_format(1, col, len(data), col, {
'type': 'formula',
'criteria': '=C2<D2',
'format': red_cell
})

# Create a new chart object.
chart1 = workbook.add_chart({'type': 'line'})

# Add a series to the chart.
'name': '%K',
'categories': [sheet_name, 1, 0, len(data), 0],
'values': [sheet_name, 1, 2, len(data), 2],
})

# Create a new chart object.
chart2 = workbook.add_chart({'type': 'line'})

# Add a series to the chart.
'name': '%D',
'categories': [sheet_name, 1, 0, len(data), 0],
'values': [sheet_name, 1, 3, len(data), 3],
})

# Combine and insert title, axis names
chart1.combine(chart2)
chart1.set_title({'name': sheet_name + " AAPL"})
chart1.set_x_axis({'name': 'Date'})
chart1.set_y_axis({'name': 'Value'})

# To set the labels on x axis not on 0
chart1.set_x_axis({
'label_position': 'low',
'num_font':  {'rotation': 45}
})

# Insert the chart into the worksheet.
worksheet.insert_chart('F2', chart1)

# End of sheets

# Close
writer.close()
```

For a walkthrough of the code, please see the video to this lesson.

This will generate an Excel sheet in called technical.xlsx. It will contain 3 sheets (MA10, MACD, Stochastic Oscillator).

A sheet will look similar to this.

## Nest steps?

This is part of the FREE online course on my page. No signup required and 2 hours of free video content with code and Jupyter Notebooks available on GitHub.

## What will we cover?

In this tutorial we will show how to calculate the Stochastic Oscillator with Pandas DataFrames.

## Step 1: Retrieve the Data from CSV file with Pandas DataFrames

We first need to read the data from a CSV file into a DataFrame. You can get the CSV file from here or directly from Yahoo! Finance.

Alternatively you can you PandasDataframes as described in this tutorial.

```import pandas as pd
import matplotlib.pyplot as plt
%matplotlib notebook

data = pd.read_csv("AAPL.csv", index_col=0, parse_dates=True)
```

## Step 2: Calculate the Stochastic Oscillator with Pandas DataFrames

The Stochastic Oscillator is defined as follows.

• 14-high: Maximum of last 14 trading days
• 14-low: Minimum of last 14 trading days
• %K(Last Close – 14-low)*100 / (14-high – 14-low)
• %D: Simple Moving Average of %K

That can be done as follows.

```high14 = data['High'].rolling(14).max()
low14 = data['Low'].rolling(14).min()
data['%K'] = (data['Close'] - low14)*100/(high14 - low14)
data['%D'] = data['%K'].rolling(3).mean()
```

Notice, we only keep the %K and %D. The high14 and low14 are temporary variables to make our calculations easier to read.

## Step 3: Visualize the Stochastic Oscillator with Matplotlib

To visualize it.

```fig, ax = plt.subplots()
data[['%K', '%D']].loc['2020-11-01':].plot(ax=ax)
ax.axhline(80, c='r', alpha=0.3)
ax.axhline(20, c='r', alpha=0.3)
data['Close'].loc['2020-11-01':].plot(ax=ax, alpha=0.3, secondary_y=True)
```

Resulting in the following.