User Tools

Site Tools


backtest_w_python

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
backtest_w_python [2025/03/23 07:30] brunobacktest_w_python [2025/03/27 17:02] (current) – [Sinon] bruno
Line 1: Line 1:
-=== Deathcross ===+==== Deathcross ====
  
 <code python> <code python>
Line 107: Line 107:
 </code> </code>
  
-=== Trend following RSI ===+==== Trend following RSI ====
  
 <code python> <code python>
-# coding: utf-8 
-# coding: utf-8 
  
-import numpy as np 
-import pandas as pd 
-import talib as ta 
- 
-df = pd.read_csv('./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) 
-df['position'] = signal.where(signal != 0).ffill() > 0 
- 
-# returns 
-df['r_hodl'] = np.log( df['close'] / df['close'].shift() ) 
-df['r_strat'] = df['position'].shift() * df['r_hodl'] 
-df['r_fee'] = np.where(df['position'] != df['position'].shift(), 0.0025, 0) 
-df['r_net'] = df['r_strat'] - df['r_fee'] 
- 
-# cumulative 
-df[['R_hodl','R_strat','R_fee','R_net']] = df[['r_hodl','r_strat','r_fee','r_net']].cumsum() 
- 
-# 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((df['position'] == 1) & (df['position'].shift() == 0)), color='green', size=7) 
-p2.inverted_triangle(df['date'], df['close'].where((df['position'] == 0) & (df['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'], df['position']) 
- 
-p4 = figure(height=150, width=800, x_range=p1.x_range) 
-p4.xaxis[0].formatter = xformatter 
-p4.line(df['date'], df['r_hodl'], color='lightgray') 
-p4.line(df['date'], df['r_strat']) 
-p4.line(df['date'], df['r_fee'], color='red') 
- 
-p5 = figure(height=325, width=800, x_range=p1.x_range) 
-p5.xaxis[0].formatter = xformatter 
-p5.line(df['date'], df['R_hodl'], color='lightgray') 
-p5.line(df['date'], df['R_strat']) 
-p5.line(df['date'], df['R_net'], color='red') 
- 
-layout = column(p1, p11, p3, p31, p2, p4, p5) 
-show(layout) 
-# 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) 
-df['position'] = signal.where(signal != 0).ffill() > 0 
- 
-# returns 
-df['r_hodl'] = np.log( df['close'] / df['close'].shift() ) 
-df['r_strat'] = df['position'].shift() * df['r_hodl'] 
-df['r_fee'] = np.where(df['position'] != df['position'].shift(), 0.0025, 0) 
-df['r_net'] = df['r_strat'] - df['r_fee'] 
- 
-# cumulative 
-df[['R_hodl','R_strat','R_fee','R_net']] = df[['r_hodl','r_strat','r_fee','r_net']].cumsum() 
- 
-# 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((df['position'] == 1) & (df['position'].shift() == 0)), color='green', size=7) 
-p2.inverted_triangle(df['date'], df['close'].where((df['position'] == 0) & (df['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'], df['position']) 
- 
-p4 = figure(height=150, width=800, x_range=p1.x_range) 
-p4.xaxis[0].formatter = xformatter 
-p4.line(df['date'], df['r_hodl'], color='lightgray') 
-p4.line(df['date'], df['r_strat']) 
-p4.line(df['date'], df['r_fee'], color='red') 
- 
-p5 = figure(height=325, width=800, x_range=p1.x_range) 
-p5.xaxis[0].formatter = xformatter 
-p5.line(df['date'], df['R_hodl'], color='lightgray') 
-p5.line(df['date'], df['R_strat']) 
-p5.line(df['date'], df['R_net'], color='red') 
- 
-layout = column(p1, p11, p3, p31, p2, p4, p5) 
-show(layout) 
 # coding: utf-8 # coding: utf-8
  
Line 324: Line 176:
 p5.line(df['date'], np.exp(returns_hodl.cumsum()), color='lightgray') 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_strat.cumsum()))
-p6.line(df['date'], np.exp(returns_netto.cumsum()), color='red')+p5.line(df['date'], np.exp(returns_netto.cumsum()), color='red')
  
 layout = column(p1, p11, p3, p31, p2, p4, p5) layout = column(p1, p11, p3, p31, p2, p4, p5)
 show(layout) show(layout)
 +
 +</code>
 +
 +
 +==== Advanced trend following RSI ====
 +<code python>
 # coding: utf-8 # coding: utf-8
  
Line 339: Line 197:
 # strategy # strategy
 RSI = ta.RSI(df.close, timeperiod = 14) RSI = ta.RSI(df.close, timeperiod = 14)
-signal_buy = RSI > 70 +signal_long_buy = RSI > 80 
-signal_sell = RSI < 30+signal_long_sell = RSI < 50 
 +signal_short_sell = RSI < 20 
 +signal_short_buy = RSI > 50
  
 # position # position
-signal signal_buy.astype(int) - signal_sell.astype(int) +signal_long signal_long_buy.astype(int) - signal_long_sell.astype(int) 
-position signal.where(signal != 0).ffill() > 0+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
 returns_hodl = np.log(df.close / df.close.shift()) returns_hodl = np.log(df.close / df.close.shift())
-returns_strat = returns_hodl * (position.shift() == 1)+returns_strat = returns_hodl * position.shift()
 returns_netto = returns_strat - 0.0025 * (position != position.shift()) returns_netto = returns_strat - 0.0025 * (position != position.shift())
  
-graphs+graphic
 from bokeh.plotting import figure,show from bokeh.plotting import figure,show
 from bokeh.layouts import column,row from bokeh.layouts import column,row
 from bokeh.models import DatetimeTickFormatter from bokeh.models import DatetimeTickFormatter
  
-df['date'] = pd.to_datetime(df['time'], unit='s')+df['date'] = pd.to_datetime(df.time, unit='s')
 xformatter = DatetimeTickFormatter(hours="%H:%M", days="%d/%m", months="%m/%Y", years="%Y") xformatter = DatetimeTickFormatter(hours="%H:%M", days="%d/%m", months="%m/%Y", years="%Y")
  
 p1 = figure(height=325, width=800) p1 = figure(height=325, width=800)
 p1.xaxis[0].formatter = xformatter p1.xaxis[0].formatter = xformatter
-p1.line(df['date'], df['close'])+p1.line(df.date, df.close)
  
 p11 = figure(height=125, width=800, x_range=p1.x_range) p11 = figure(height=125, width=800, x_range=p1.x_range)
Line 370: Line 233:
 p11.line(df.date, 30, color='green') p11.line(df.date, 30, color='green')
  
-p2 = figure(height=325, width=800, x_range=p1.x_range)+p2 = figure(height=125, width=800, x_range=p1.x_range)
 p2.xaxis[0].formatter = xformatter p2.xaxis[0].formatter = xformatter
-p2.line(df['date'], df['close'], color='gray'+p2.line(df.date, position)
-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 = figure(height=325, width=800, x_range=p1.x_range)
 p3.xaxis[0].formatter = xformatter p3.xaxis[0].formatter = xformatter
-p3.line(df.date, signal+p3.line(df.date, df.close, color='gray'
- +position_long_in = df.close.where((position == 1) & (position.shift() != 1)) 
-p31 figure(height=125width=800x_range=p1.x_range+position_long_out df.close.where((position !1) & (position.shift() == 1)) 
-p31.xaxis[0].formatter xformatter +position_short_in = df.close.where((position == -1) & (position.shift() != -1)) 
-p31.line(df['date'], position)+position_short_out = df.close.where((position != -1) & (position.shift() == -1)) 
 +p3.triangle(df.dateposition_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.datenp.where(position == -1, df.close, np.nan), color='red')
  
 p4 = figure(height=150, width=800, x_range=p1.x_range) p4 = figure(height=150, width=800, x_range=p1.x_range)
Line 395: Line 262:
 p5.line(df['date'], np.exp(returns_netto.cumsum()), color='red') p5.line(df['date'], np.exp(returns_netto.cumsum()), color='red')
  
-layout = column(p1, p11, p3, p31, p2, p4, p5)+layout = column(p1, p11, p2, p3, p4, p5)
 show(layout) show(layout)
  
 </code> </code>
  
-[[https://support.kraken.com/hc/en-us/articles/360047124832]] 
  
  
  
  
-=== Sinon === 
- 
-Un vieux code de 2022 (si pas plus). Chrypowatch n'existe plus, c'est dire :-) 
- 
-<code python> 
-# coding: utf-8 
-import requests 
-import numpy as np 
-import pandas as pd 
-  
-import talib 
-  
-url = 'https://api.cryptowat.ch/markets/kraken/btceur/ohlc' 
-ohlc = requests.get(url).json()['result'][str(12*60*60)] 
-columns = ['time','open','high','low','close','volume','count'] 
-df = pd.DataFrame(ohlc, columns=columns).astype(float) 
-df = df.iloc[-1000:] 
- 
-df['RSI'] = talib.RSI(df['close'], timeperiod=14) 
-#df['RSI'] = df.RSI.fillna(value=df.RSI.loc[14]) 
-df['long'] = talib.SMA(df.close, timeperiod=200) 
-#df['long'] = df.long.fillna(value=df.long.loc[200]) 
-df['short'] = talib.SMA(df.close,timeperiod=14) 
-#df['short'] = df.short.fillna(value=df.short.loc[14]) 
-df['trend'] = df.long < df.short 
-# signal 
-df['sig_in'] = (df.RSI > 60) & df.trend 
-df['sig_out'] = (df.RSI < 40)# | 1-df.trend 
-#df['sig_in'] = (df.RSI.shift() < 70) & (df.RSI > 70) 
-#df['sig_out'] = (df.RSI.shift() > 30) & (df.RSI < 30) 
-#df['sig_in'] = (df.RSI.shift() < 25) & (df.RSI > 25) 
-#df['stoploss'] = df.low.rolling(5).min().where(df.sig_in==1).ffill() 
-#df['sig_out'] = ((df.RSI.shift() > 75) & (df.RSI < 75)) | ((df.RSI.shift()>25) & (df.RSI<25)) | (df.close < df.stoploss) 
- 
-#df['signal'] = df.sig_in.where(df.sig_in).fillna(1-df.sig_out.where(df.sig_out)).ffill() 
-#df['sig_out'].loc[0] = True 
-#df['signal'] = (1-df.sig_out.where(df.sig_out)).fillna(df.sig_in.where(df.sig_in)).ffill()# * df.trend  
- 
-df['sig_0'] = df.sig_in.astype(int) - df.sig_out.astype(int) 
-df['sig_1'] = df.sig_0.where(df.sig_0!=0).ffill() 
-df['signal'] = df.sig_1 > 0 
-# Rendements 
-df['close'] = df.close.replace(to_replace=0, method='ffill') 
-df['r_0'] = df.close / df.close.shift() 
-df['r_strat'] = np.where(df.signal.shift(), df.r_0, 1) 
-df['r_fee'] = np.where(df.signal.shift() + df.signal == 1, 1-0.0025, 1) 
-# tronquage datafame 
-#df = df.iloc[-700:] 
-# Rendement cumulé 
-df['R_net'] = (df.r_strat * df.r_fee).cumprod() 
-# Graphiques 
-from bokeh.plotting import figure,show 
-from bokeh.layouts import column,row 
-p1 = figure(height=300,width=800) 
-p1.line(df.time,df.close) 
-#p1.line(df.time,df.long,color='green') 
-#p1.line(df.time,df.short,color='red') 
-p2 =  figure(height=100,width=800,x_range=p1.x_range) 
-p2.line(df.time,df.RSI) 
-#p3_0 = figure(height=100,width=800,x_range=p1.x_range) 
-#p3_0.line(df.time,df.trend) 
-p3_1 = figure(height=100,width=800,x_range=p1.x_range) 
-p3_1.line(df.time,df.sig_in,color='green') 
-p3_2 = figure(height=100,width=800,x_range=p1.x_range) 
-p3_2.line(df.time,df.sig_out,color='red') 
-p3_3 = figure(height=100,width=800,x_range=p1.x_range) 
-p3_3.line(df.time,df.sig_0) 
-p3_3_2 = figure(height=100,width=800,x_range=p1.x_range)  
-p3_3_2.line(df.time,df.sig_1) 
-p3_4 = figure(height=100,width=800,x_range=p1.x_range) 
-p3_4.line(df.time,df.signal) 
-p4 = figure(height=150,width=800,x_range=p1.x_range) 
-p4.line(df.time,df.r_0,color='lightgray') 
-p4.line(df.time,df.r_strat) 
-p4.line(df.time,df.r_fee,color='red') 
-p5 = figure(height=300,width=800,x_range=p1.x_range) 
-p5.line(df.time,df.r_0.cumprod(),color='lightgray') 
-p5.line(df.time,df.r_strat.cumprod()) 
-p5.line(df.time,df.R_net,color='red') 
-layout = column(p1,p2,p3_1,p3_2,p3_3,p3_3_2,p3_4,p4,p5) 
-show(layout) 
-</code> 
backtest_w_python.1742715010.txt.gz · Last modified: 2025/03/23 07:30 by bruno