backtest_w_python | Last modified: 1744969173 | Edit | Home

Deathcross

# coding: utf-8
import numpy as np
import pandas as pd
import talib as ta

df = pd.read_csv('Téléchargements/btceur-2h.csv')
#df = pd.read_csv('https://raw.githubusercontent.com/brulint/backtesting/main/btceur-2h.csv')

# strategy
fast = ta.EMA(df['close'], timeperiod 20)
slow = ta.SMA(df['close'], timeperiod 200)

position = fast > slow

# returns
returns_hodl = np.log(df.close / df.close.shift())
returns_strat = returns_hodl * (position.shift()= 1)
returns_netto = returns_strat - 0.0025 * (position != position.shift())
print('Returns: ', np.exp(returns_netto.sum()))

# graphs
from bokeh.plotting import figure,show
from bokeh.layouts import column,row
from bokeh.models import DatetimeTickFormatter

df['date'] = pd.to_datetime(df['time'], unit='s')
xformatter = DatetimeTickFormatter(hours="%H:%M", days="%d/%m", months="%m/%Y", years="%Y")

p0 = figure(height=325, width=800)
p0.xaxis[0].formatter = xformatter
p0.line(df['date'], df['close'])

p1 = figure(height=125, width=800, x_range=p0.x_range)
p1.xaxis[0].formatter = xformatter
p1.line(df['date'], returns_hodl)

p2 = figure(height=325, width=800, x_range=p0.x_range)
p2.xaxis[0].formatter = xformatter
p2.line(df['date'], df['close'])
p2.line(df['date'], slow, color='red')
p2.line(df['date'], fast, color='green')

p3 = figure(height=125, width=800, x_range=p0.x_range)
p3.xaxis[0].formatter = xformatter
p3.line(df['date'], position)

p4 = figure(height=325, width=800, x_range=p0.x_range)
p4.xaxis[0].formatter = xformatter
p4.line(df['date'], df['close'])
p4.triangle(df['date'], df['close'].where((position == 1) & (position.shift() == 0)), color='green', size=7)
p4.inverted_triangle(df['date'], df['close'].where((position == 0) & (position.shift() == 1)), color='red', size=7)

p5 = figure(height=150, width=800, x_range=p0.x_range)
p5.xaxis[0].formatter = xformatter
p5.line(df['date'], returns_hodl, color='lightgray')
p5.line(df['date'], returns_strat)

p6 = figure(height=325, width=800, x_range=p0.x_range)
p6.xaxis[0].formatter = xformatter
p6.line(df['date'], np.exp(returns_hodl.cumsum()), color='lightgray')
p6.line(df['date'], np.exp(returns_strat.cumsum()))
p6.line(df['date'], np.exp(returns_netto.cumsum()), color='red')

layout = column(p0, p1, p2, p3, p4, p5, p6)
show(layout)

Light version

# coding: utf-8
import numpy as np
import pandas as pd
import talib as ta

 Donwload data
# https://support.kraken.com/hc/en-us/articles/360047124832
names = ['time', 'open', 'high', 'low', 'close', 'volume', 'count']
df = pd.read_csv('XBTEUR_1440.csv', names=names) 
df = df[int(-10.5*365):] # Only the X last years
df['close'] = df.close.replace(to_replace=0, method='ffill')

# Strategy begin
RSI = ta.RSI(df.close, timeperiod=14)
SIG_in = (RSI.shift() < 25) & (RSI > 25)
SIG_out = (RSI.shift() > 75) & (RSI < 75)
# Strategy end

POS = SIG_in.astype(int) - SIG_out.astype(int)
POS = POS.replace(to_replace=0, method='ffill') > 0
r_hodl = np.log(df.close / df.close.shift())
r_strat = r_hodl * (POS.shift() == 1)
r_netto = r_strat - 0.0025 * (POS != POS.shift())
print('Return: ',np.exp(r_netto.sum()))

from bokeh.plotting import figure,show
df['time'] = pd.to_datetime(df.time, unit='s')
fig = figure(height=300, x_axis_type="datetime")
fig.line(df.time, np.exp(r_hodl.cumsum()), color='lightgray')
fig.line(df.time, np.exp(r_strat.cumsum()), color='blue')
fig.line(df.time, np.exp(r_netto.cumsum()), color='red')
show(fig)

Trend following RSI


# coding: utf-8

import numpy as np
import pandas as pd
import talib as ta

df = pd.read_csv('Téléchargements/btceur-2h.csv')
#df = pd.read_csv('https://raw.githubusercontent.com/brulint/backtesting/main/btceur-2h.csv')

# strategy
RSI = ta.RSI(df.close, timeperiod 14)
signal_buy = RSI > 70
signal_sell = RSI < 30

# position
signal = signal_buy.astype(int) - signal_sell.astype(int)
position = signal.where(signal != 0).ffill() > 0

# returns
returns_hodl = np.log(df.close / df.close.shift())
returns_strat = returns_hodl * (position.shift()= 1)
returns_netto = returns_strat - 0.0025 * (position != position.shift())

# graphs
from bokeh.plotting import figure,show
from bokeh.layouts import column,row
from bokeh.models import DatetimeTickFormatter

df['date'] = pd.to_datetime(df['time'], unit='s')
xformatter = DatetimeTickFormatter(hours="%H:%M", days="%d/%m", months="%m/%Y", years="%Y")

p1 = figure(height=325, width=800)
p1.xaxis[0].formatter = xformatter
p1.line(df['date'], df['close'])

p11 = figure(height=125, width=800, x_range=p1.x_range)
p11.xaxis[0].formatter = xformatter
p11.line(df.date, RSI)
p11.line(df.date, 70, color='green')
p11.line(df.date, 50, color='red')
p11.line(df.date, 30, color='green')

p2 = figure(height=325, width=800, x_range=p1.x_range)
p2.xaxis[0].formatter = xformatter
p2.line(df['date'], df['close'], color='gray')
p2.triangle(df['date'], df['close'].where((position == 1) & (position.shift() == 0)), color='green', size=7)
p2.inverted_triangle(df['date'], df['close'].where((position == 0) & (position.shift() == 1)), color='red', size=7)

p3 = figure(height=125, width=800, x_range=p1.x_range)
p3.xaxis[0].formatter = xformatter
p3.line(df.date, signal)

p31 = figure(height=125, width=800, x_range=p1.x_range)
p31.xaxis[0].formatter = xformatter
p31.line(df['date'], position)

p4 = figure(height=150, width=800, x_range=p1.x_range)
p4.xaxis[0].formatter = xformatter
p4.line(df['date'], returns_hodl, color='lightgray')
p4.line(df['date'], returns_strat)

p5 = figure(height=325, width=800, x_range=p1.x_range)
p5.xaxis[0].formatter = xformatter
p5.line(df['date'], np.exp(returns_hodl.cumsum()), color='lightgray')
p5.line(df['date'], np.exp(returns_strat.cumsum()))
p5.line(df['date'], np.exp(returns_netto.cumsum()), color='red')

layout = column(p1, p11, p3, p31, p2, p4, p5)
show(layout)

Advanced trend following RSI

# coding: utf-8

import numpy as np
import pandas as pd
import talib as ta

df = pd.read_csv('Téléchargements/btceur-2h.csv')
#df = pd.read_csv('https://raw.githubusercontent.com/brulint/backtesting/main/btceur-2h.csv')

# strategy
RSI = ta.RSI(df.close, timeperiod 14)
signal_long_buy = RSI > 80
signal_long_sell = RSI < 50
signal_short_sell = RSI < 20
signal_short_buy = RSI > 50

# position
signal_long = signal_long_buy.astype(int) - signal_long_sell.astype(int)
signal_short = signal_short_sell.astype(int) - signal_short_buy.astype(int) 
position_long = signal_long.where(signal_long != 0).ffill() > 0
position_short = signal_short.where(signal_short != 0).ffill() > 0
position = position_long.astype(int) - position_short.astype(int)

# returns
returns_hodl = np.log(df.close / df.close.shift())
returns_strat = returns_hodl * position.shift()
returns_netto = returns_strat - 0.0025 * (position != position.shift())

# graphic
from bokeh.plotting import figure,show
from bokeh.layouts import column,row
from bokeh.models import DatetimeTickFormatter

df['date'] = pd.to_datetime(df.time, unit='s')
xformatter = DatetimeTickFormatter(hours="%H:%M", days="%d/%m", months="%m/%Y", years="%Y")

p1 = figure(height=325, width=800)
p1.xaxis[0].formatter = xformatter
p1.line(df.date, df.close)

p11 = figure(height=125, width=800, x_range=p1.x_range)
p11.xaxis[0].formatter = xformatter
p11.line(df.date, RSI)
p11.line(df.date, 70, color='green')
p11.line(df.date, 50, color='red')
p11.line(df.date, 30, color='green')

p2 = figure(height=125, width=800, x_range=p1.x_range)
p2.xaxis[0].formatter = xformatter
p2.line(df.date, position)

p3 = figure(height=325, width=800, x_range=p1.x_range)
p3.xaxis[0].formatter = xformatter
p3.line(df.date, df.close, color='gray')
position_long_in = df.close.where((position == 1) & (position.shift() != 1))
position_long_out = df.close.where((position != 1) & (position.shift()= 1))
position_short_in = df.close.where((position == -1) & (position.shift() != -1))
position_short_out = df.close.where((position != -1) & (position.shift() == -1))
p3.triangle(df.date, position_long_in, color='cyan', size=7)
p3.inverted_triangle(df.date, position_long_out, color='blue', size=7)
p3.inverted_triangle(df.date, position_short_in, color='orange', size=7)
p3.triangle(df.date, position_short_out, color='red', size=7)
p3.line(df.date, np.where(position == 1, df.close, np.nan), color='green')
p3.line(df.date, np.where(position == -1, df.close, np.nan), color='red')

p4 = figure(height=150, width=800, x_range=p1.x_range)
p4.xaxis[0].formatter = xformatter
p4.line(df['date'], returns_hodl, color='lightgray')
p4.line(df['date'], returns_strat)

p5 = figure(height=325, width=800, x_range=p1.x_range)
p5.xaxis[0].formatter = xformatter
p5.line(df['date'], np.exp(returns_hodl.cumsum()), color='lightgray')
p5.line(df['date'], np.exp(returns_strat.cumsum()))
p5.line(df['date'], np.exp(returns_netto.cumsum()), color='red')

layout = column(p1, p11, p2, p3, p4, p5)
show(layout)