Giter Club home page Giter Club logo

backtra's Introduction

DEPRECATED

Backtra

Backtra is an advanced futures backtesting framework where we loop through kline (ohlcv) data on a specific way to acheive more realistic results.

This is a futures backtesting framework but it can also be used for spot backtesting.

More in-depth documentation is coming soon!

Getting Started

Install

git clone https://github.com/AlgoQ/backtra
cd backtra
pip install -r requirements

We will be backtesting a simple golden cross strategy with a stoploss and take profit based on the ATR. The leverage is also based on the ATR and the max percentage you are willing to lose per trade.

Golden Cross

  1. Config

Rename the exampleConfig.json file to config.json and update the parameters if wanted.

{
    "capital": 10000,
    "makerFee": -0.0025,
    "takerFee": 0.0075,
    "reduceAmount": 0
}
  1. Strategy

Create a strategy named GoldenCross.py and add it into the strategies folder.

More info about creating a strategy will be added soon.

from strategies.BaseStrategy import BaseStrategy

import numpy as np
import pandas as pd

# TODO: Import needed indicators
from talib import SMA

class GoldenCross(BaseStrategy):
    def __init__(self, strategyName, symbol, params, timeFrames, ohlcvs, tradeLogs=True):
        # Changeable values
        self.strategyName = strategyName
        self.symbol       = symbol
        self.params       = params
        self.timeFrames   = timeFrames
        self.ohlcvs       = ohlcvs
        self.tradeLogs    = tradeLogs
        
        # Fixed values
        self.configData      = self._getConfigData()
        self.capital         = self.configData['capital']
        self.makerFee        = self.configData['makerFee']
        self.takerFee        = self.configData['takerFee']
        self.reduceAmount    = self.configData['reduceAmount']
        self.capitalFollowup = [[self.ohlcvs[self.timeFrames[0]].index[1], self.capital]]
        self.openTradesL     = {}
        self.closedTradesL   = []
    
    def run(self):
        print('Trading started...')
        minKlines = max(201, self._calcMinKlines())
        
        for i in range(minKlines, len(self.ohlcvs[self.timeFrames[0]])):
            tempDf = self.ohlcvs[self.timeFrames[0]].iloc[i-minKlines:i+1].copy()
            
            # Indicators
            sma1 = SMA(tempDf['close'], self.params['sma1'])
            sma2 = SMA(tempDf['close'], self.params['sma2'])

            if sma1[-2] < sma2[-2]: # Long condition 1
                prevClose = tempDf['close'][-1]
                tempDf.loc[tempDf.index[-1], 'close'] = tempDf['high'][-1]
                sma1 = SMA(tempDf['close'], self.params['sma1'])
                sma2 = SMA(tempDf['close'], self.params['sma2'])
                
                if sma1[-1] > sma2[-1]: # Long condition 2
                    tempDf.loc[tempDf.index[-1], 'close'] = prevClose
                    for i in np.arange(tempDf['open'][-1], tempDf['high'][-1] + self.ohlcvs['pip'], self.ohlcvs['pip']):
                        openPrice = round(i, self.ohlcvs['precision'])
                        tempDf.loc[tempDf.index[-1], 'close'] = openPrice

                        # Indicators
                        sma1 = SMA(tempDf['close'], self.params['sma1'])
                        sma2 = SMA(tempDf['close'], self.params['sma2'])

                        if sma1[-1] > sma2[-1]: # Long condition 2
                            if len(self.openTradesL) != 0:
                                self.closeTrade(
                                    id = '1',
                                    time = tempDf.index[-1],
                                    tradeType = 'market',
                                    closePrice = openPrice)
                            
                            self.openTrade(
                                id = '1',
                                time = tempDf.index[-1],
                                side = 'long',
                                tradeType = 'market',
                                leverage = self.params['leverage'],
                                amount = self.capital,
                                openPrice = openPrice)
                            break
            
            elif sma1[-2] > sma2[-2]: # Short condition 1
                prevClose = tempDf['close'][-1]
                tempDf.loc[tempDf.index[-1], 'close'] = tempDf['low'][-1]
                sma1 = SMA(tempDf['close'], self.params['sma1'])
                sma2 = SMA(tempDf['close'], self.params['sma2'])
                
                if sma1[-1] < sma2[-1]: # Short condition 2
                    tempDf.loc[tempDf.index[-1], 'close'] = prevClose
                    for i in np.arange(tempDf['open'][-1], tempDf['low'][-1] - self.ohlcvs['pip'], self.ohlcvs['pip'] * -1):
                        openPrice = round(i, self.ohlcvs['precision'])
                        tempDf.loc[tempDf.index[-1], 'close'] = openPrice
                        
                        # Indicators
                        sma1 = SMA(tempDf['close'], self.params['sma1'])
                        sma2 = SMA(tempDf['close'], self.params['sma2'])

                        if sma1[-1] < sma2[-1]: # Short condition 2
                            if len(self.openTradesL) != 0:
                                self.closeTrade(
                                    id='1',
                                    time = tempDf.index[-1],
                                    tradeType = 'market',
                                    closePrice = openPrice)
                            
                            self.openTrade(
                                id = '1',
                                time = tempDf.index[-1],
                                side = 'short',
                                tradeType = 'market',
                                leverage = self.params['leverage'],
                                amount = self.capital,
                                openPrice = openPrice)
                            break
  1. Main File

Now we will create a main file that connects/runs our strategy. I this file we send all variable values through the params, select timeframe and link your data. Create mainGoldenCross.py in the main folder:

from strategies.GoldenCross import GoldenCross
from utils import jsonToOhlcv
import quantstats as qs

params = {'sma1': 50, 'sma2': 200, 'leverage': 1}

timeframe = '4h'

ohlcv = jsonToOhlcv(r'/media/kobe/D/feda/data/ohlcv_ftx_BTCUSD_784days.json', timeframe)

# precision = round(ohlcv['close'].apply(lambda x: len(str(x).split('.')[-1])).mean())

precision = 0
if precision > 0:
    pip = float('0.' + ('0' * (precision - 1)) + '1')
else:
    pip = 1

ohlcvs = {}
ohlcvs['precision'] = precision
ohlcvs['pip'] = pip
ohlcvs[timeframe] = ohlcv

goldenCross = GoldenCross(
    strategyName = 'Golden Cross',
    symbol = 'BTC/USD',
    params = params,
    ohlcvs = ohlcvs,
    timeFrames = [timeframe],
    tradeLogs = True
)

goldenCross.run()

results, percChange = goldenCross.calcResults()
goldenCross.showResults(results)

qs.plots.snapshot(percChange, title=f'Results', savefig=f'Results')
  1. Output
Strategy               Golden Cross
Symbol                 BTC/USD
Timeframes             ['4h']
Parameters             {'sma1': 50, 'sma2': 200, 'leverage': 1}
Start                  2019-08-20 16:00:00
End                    2021-10-12 12:00:00
Duration (days)        783
Equity Start [$]       10000
Equity Final [$]       58406.2285
Equity Max [$]         89791.4633
Return [%]             484.06
Max. Drawdown [%]      -39.86
Win rate [%]           54.17
Buy & Hold [%]         424.69
Total trades           24
Avg. trade [%]         12.52
Avg. winning trade [%] 31.36
Avg. losing trade [%]  -9.74
Avg. long trade [%]    24.64
Avg. short trade [%]   0.4

Snapshot: Golden Cross

If you don't have any ohlcv/kline data you can always fetch crypto kline data with FEDA.

Upcoming

  • More in-depth documentation
  • Slippage parameter in the config
  • Optimization

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.