Golden Cross / Death Cross S&P 500 index (^GSPC)

1. sma50>sma200, buy
2. sma50<sma200, sell your long position.

In [1]:
import pandas as pd
import matplotlib.pyplot as plt
import datetime
from talib.abstract import *

import pinkfish as pf

# format price data
pd.options.display.float_format = '{:0.2f}'.format

%matplotlib inline

In [2]:
# set size of inline plots
'''note: rcParams can't be in same cell as import matplotlib
   or %matplotlib inline
   
   %matplotlib notebook: will lead to interactive plots embedded within
   the notebook, you can zoom and resize the figure
   
   %matplotlib inline: only draw static images in the notebook
'''
plt.rcParams["figure.figsize"] = (10, 7)

Some global data


In [3]:
symbol = 'SPY'
capital = 10000
start = datetime.datetime(1900, 1, 1)
end = datetime.datetime.now()
use_adj=True

Prepare timeseries


In [4]:
# fetch and select timeseries
ts = pf.fetch_timeseries(symbol)
ts = pf.select_tradeperiod(ts, start, end, use_adj=use_adj)

# Add technical indicator: day sma regime filter
ts['regime'] = \
    pf.CROSSOVER(ts, timeperiod_fast=50, timeperiod_slow=200)

# Finalize the time series before implementing trading strategy
ts, start = pf.finalize_timeseries(ts, start)

# Create Trade Log (tlog); Create Daily Balance (dbal)
tlog = pf.TradeLog(symbol)
dbal = pf.DailyBal()

Algo: Buy when 50 day ma crosses above 200 day ma. Sell when 50 day ma crosses below 200 day ma.


In [5]:
pf.TradeLog.cash = capital

for i, row in enumerate(ts.itertuples()):

    date = row.Index.to_pydatetime()
    high = row.high; low = row.low; close = row.close; 
    end_flag = pf.is_last_row(ts, i)

    # buy
    if tlog.shares == 0 and row.regime > 0 and ts['regime'][i-1] < 0:
        tlog.buy(date, close)  
    # sell
    elif tlog.shares > 0 and (row.regime < 0 or end_flag):
        tlog.sell(date, close)

    # record daily balance
    dbal.append(date, high, low, close)

Retrieve logs


In [6]:
tlog = tlog.get_log()
dbal = dbal.get_log(tlog)

Generate strategy stats - display all available stats


In [7]:
stats = pf.stats(ts, tlog, dbal, capital)
pf.print_full(stats)


start                                                  1993-11-11
end                                                    2020-07-15
beginning_balance                                           10000
ending_balance                                           98196.94
total_net_profit                                         88196.94
gross_profit                                            102090.99
gross_loss                                              -13894.04
profit_factor                                                7.35
return_on_initial_capital                                  881.97
annual_return_rate                                           8.94
trading_period                           26 years 8 months 4 days
pct_time_in_market                                          74.08
margin                                                          1
avg_leverage                                                 1.00
max_leverage                                                 1.00
min_leverage                                                 1.00
total_num_trades                                               13
trades_per_year                                              0.49
num_winning_trades                                             10
num_losing_trades                                               3
num_even_trades                                                 0
pct_profitable_trades                                       76.92
avg_profit_per_trade                                      6784.38
avg_profit_per_winning_trade                             10209.10
avg_loss_per_losing_trade                                -4631.35
ratio_avg_profit_win_loss                                    2.20
largest_profit_winning_trade                             31551.42
largest_loss_losing_trade                                -6765.93
num_winning_points                                         247.19
num_losing_points                                          -33.98
total_net_points                                           213.21
avg_points                                                  16.40
largest_points_winning_trade                                66.01
largest_points_losing_trade                                -17.66
avg_pct_gain_per_trade                                      22.97
largest_pct_winning_trade                                  125.67
largest_pct_losing_trade                                    -7.99
max_consecutive_winning_trades                                  6
max_consecutive_losing_trades                                   1
avg_bars_winning_trades                                    468.30
avg_bars_losing_trades                                     101.33
max_closed_out_drawdown                                    -33.65
max_closed_out_drawdown_start_date                     2020-02-19
max_closed_out_drawdown_end_date                       2020-03-23
max_closed_out_drawdown_recovery_date           Not Recovered Yet
drawdown_recovery                                           -0.09
drawdown_annualized_return                                  -3.76
max_intra_day_drawdown                                     -35.19
avg_yearly_closed_out_drawdown                              -8.95
max_yearly_closed_out_drawdown                             -33.65
avg_monthly_closed_out_drawdown                             -2.54
max_monthly_closed_out_drawdown                            -30.93
avg_weekly_closed_out_drawdown                              -1.01
max_weekly_closed_out_drawdown                             -17.93
avg_yearly_closed_out_runup                                 18.32
max_yearly_closed_out_runup                                 55.64
avg_monthly_closed_out_runup                                 3.23
max_monthly_closed_out_runup                                17.31
avg_weekly_closed_out_runup                                  1.21
max_weekly_closed_out_runup                                 17.31
pct_profitable_years                                        76.25
best_year                                                   53.26
worst_year                                                 -19.03
avg_year                                                    10.34
annual_std                                                  11.90
pct_profitable_months                                       51.81
best_month                                                  15.56
worst_month                                                -30.93
avg_month                                                    0.73
monthly_std                                                  3.26
pct_profitable_weeks                                        44.75
best_week                                                   17.31
worst_week                                                 -17.93
avg_week                                                     0.19
weekly_std                                                   1.78
sharpe_ratio                                                 0.69
sortino_ratio                                                0.74
dtype: object

Benchmark: Run, retrieve logs, generate stats


In [8]:
benchmark = pf.Benchmark(symbol, capital, start, end, use_adj=use_adj)
benchmark.run()
benchmark.tlog, benchmark.dbal = benchmark.get_logs()
benchmark.stats = benchmark.get_stats()


1993-11-11 00:00:00 BUY  355 SPY @ 28.14
2020-07-15 00:00:00 SELL 355 SPY @ 321.85

Plot Equity Curves: Strategy vs Benchmark


In [9]:
pf.plot_equity_curve(dbal, benchmark=benchmark.dbal)


Plot Trades


In [10]:
pf.plot_trades(dbal, benchmark=benchmark.dbal)


Strategy vs Benchmark


In [11]:
df = pf.summary(stats, benchmark.stats, metrics=pf.currency_metrics)
df


Out[11]:
strategy benchmark
beginning_balance $10,000.00 $10,000.00
ending_balance $98,196.94 $114,267.69
total_net_profit $88,196.94 $104,267.69
gross_profit $102,090.99 $104,267.69
gross_loss -$13,894.04 $0.00

In [12]:
extras = ('avg_month',)

df = pf.plot_bar_graph(stats, benchmark.stats, extras=extras)
df


Out[12]:
strategy benchmark
annual_return_rate 8.94 9.56
max_closed_out_drawdown -33.65 -55.18
drawdown_annualized_return -3.76 -5.77
drawdown_recovery -0.09 -1.42
best_month 15.56 23.61
worst_month -30.93 -30.98
sharpe_ratio 0.69 0.57
sortino_ratio 0.74 0.73
monthly_std 3.26 4.55
avg_month 0.73 0.83

In [ ]: