Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Finta technical indicators library #79

Closed
AlgoQ opened this issue May 27, 2020 · 4 comments
Closed

Using Finta technical indicators library #79

AlgoQ opened this issue May 27, 2020 · 4 comments
Labels
question Not a bug, but a FAQ entry

Comments

@AlgoQ
Copy link

AlgoQ commented May 27, 2020

I'm trying to use finta as techinical indicators library. But they require lowercase column names.

First I tried to rename the df when creating the indicators (self.I) and than back to first letter uppercase but then I got an error (KeyError).

Code:

# IMPORTS

# Built-in modules
import json
# Extern modules
import pandas as pd
import numpy as np
from backtesting import Strategy, Backtest
from backtesting.lib import crossover
from finta import TA

def normalize(dataPath):
    df = pd.read_csv(dataPath)
    df["Timestamp"] = pd.to_datetime(df["Timestamp"], unit="s")
    df = df.set_index("Timestamp")
    del df["Volume_(BTC)"]
    del df["Weighted_Price"]
    df = df.rename({"Close": "close", "Open": "open", "High": "high", "Low": "low", "Volume_(Currency)": "volume"}, axis=1)

    return df.ffill()

dataPath = "D:/Kobe/Prive/bitcoinBacktesting/data/bitstampUSD_1-min_data_2012-01-01_to_2020-04-22.csv"

df = normalize(dataPath)

print(TA.SMA(df, 10))

# Strategy
class SmaCross(Strategy):
    
    # Define the two MA lags as *class variables*
    # for later optimization

    timePeriod1 = 9
    timePeriod2 = 14

    def init(self):
        
        # Precompute two moving averages
        self.sma1 = self.I(TA.SMA(self.data, self.timePeriod1))
        self.sma2 = self.I(TA.SMA(self.data, self.timePeriod2))
        

    def next(self):
        # If sma1 crosses above sma2, buy the asset
        if crossover(self.sma1, self.sma2):
            self.buy()

        # Else, if sma1 crosses below sma2, sell it
        elif crossover(self.sma2, self.sma1):
            self.sell()

df = df.rename({"close": "Close", "open": "Open", "high": "High", "low": "Low", "volume": "Volume"}, axis=1)

bt = Backtest(df, SmaCross, commission=.001)
bt.run()

Error:

Exception has occurred: KeyError
'close'

File "D:\Kobe\Prive\bitcoinBacktesting\strategies\sma.py", line 40, in init
    self.sma1 = self.I(TA.SMA(self.data, self.timePeriod1))
File "D:\Kobe\Prive\bitcoinBacktesting\strategies\sma.py", line 56, in <module>
    bt.run()

Than I changed the finta source code the first letter uppercase but than I got another error (AttributeError).

Code:

# IMPORTS

# Built-in modules
import json
# Extern modules
import pandas as pd
import numpy as np
from backtesting import Strategy, Backtest
from backtesting.lib import crossover
from finta import TA

def normalize(dataPath):
    df = pd.read_csv(dataPath)
    df["Timestamp"] = pd.to_datetime(df["Timestamp"], unit="s")
    df = df.set_index("Timestamp")
    del df["Volume_(BTC)"]
    del df["Weighted_Price"]
    df = df.rename({"Volume_(Currency)": "Volume"}, axis=1)

    return df.ffill() # Fill NaN values with previous value

dataPath = "D:/Kobe/Prive/bitcoinBacktesting/data/bitstampUSD_1-min_data_2012-01-01_to_2020-04-22.csv"

df = normalize(dataPath)

print(TA.SMA(df, 10))

# Strategy
class SmaCross(Strategy):
    
    # Define the two MA lags as *class variables*
    # for later optimization

    timePeriod1 = 9
    timePeriod2 = 14

    def init(self):
        
        # Precompute two moving averages
        self.sma1 = self.I(TA.SMA(self.data, self.timePeriod1))
        self.sma2 = self.I(TA.SMA(self.data, self.timePeriod2))
        

    def next(self):
        # If sma1 crosses above sma2, buy the asset
        if crossover(self.sma1, self.sma2):
            self.buy()

        # Else, if sma1 crosses below sma2, sell it
        elif crossover(self.sma2, self.sma1):
            self.sell()

bt = Backtest(df, SmaCross, commission=.001)
bt.run()

Error:

Exception has occurred: AttributeError
'_Array' object has no attribute 'rolling'
  File "D:\Kobe\Prive\bitcoinBacktesting\strategies\sma.py", line 40, in init
    self.sma1 = self.I(TA.SMA(self.data, self.timePeriod1))
  File "D:\Kobe\Prive\bitcoinBacktesting\strategies\sma.py", line 56, in <module>
    bt.run()

Can someone help me?

  • Backtesting version: 0.1.7
@kernc
Copy link
Owner

kernc commented May 27, 2020

To precompute indicators lazily, you'd need to call I() like so:

self.sma1 = self.I(TA.SMA, self.data, self.timePeriod1)  # func with parameters

It still won't exactly work, though, due to capitalized columns, which you'd need to rename.

#47 adds data.df accessor, or you can build dataframes yourself:

df = self.data.Close.to_series().rename('close').to_frame()
self.sma1 = self.I(TA.SMA, df, self.timePeriod1)

@AlgoQ AlgoQ closed this as completed May 27, 2020
@AlgoQ
Copy link
Author

AlgoQ commented Jun 1, 2020

@kernc Sorry, but I have another question related to this topic. I'm trying to use the ATR Indicator from the Finta Indicator Library. But this indicator requires the high, low and close column (lowercase). I've tried to rename the columns but got an AtributeError.
Can you help me renaming multiple columns?

df = self.data.rename({'Open': 'open', 'High': 'high', 'Low': 'low', 'Close': 'close', 'Volume': 'volume'}, axis=1)
AttributeError                            Traceback (most recent call last)
<timed exec> in <module>

~\anaconda3\lib\site-packages\backtesting\backtesting.py in run(self, **kwargs)
    690         strategy = self._strategy(broker, data, kwargs)  # type: Strategy
    691 
--> 692         strategy.init()
    693 
    694         # Indicators used in Strategy.next()

<ipython-input-15-6fad005ad7ee> in init(self)
     20     def init(self):
     21         # Make dataframe compatible with finta
---> 22         df = self.data.rename({'Open': 'open', 'High': 'high', 'Low': 'low', 'Close': 'close', 'Volume': 'volume'}, axis=1)
     23 
     24         self.ema = self.I(TA.EMA, df, self.emaPeriod)

~\anaconda3\lib\site-packages\backtesting\_util.py in __getattr__(self, item)
    102             return self.__get_array(item)
    103         except KeyError:
--> 104             raise AttributeError("Column '{}' not in data".format(item)) from None
    105 
    106     def _set_length(self, i):

AttributeError: Column 'rename' not in data

@AlgoQ AlgoQ reopened this Jun 1, 2020
@AlgoQ AlgoQ closed this as completed Jun 1, 2020
@AlgoQ AlgoQ reopened this Jun 1, 2020
@kernc
Copy link
Owner

kernc commented Jun 1, 2020

Yeah, Strategy.data is not a DataFrame. It, namely, doesn't have a .rename() method.

After #47, you'll be able to do:

df = self.data.df.set_axis(self.data.df.columns.str.lower(), axis=1)

For now, I guess:

df = pd.DataFrame({'open': self.data.Open,
                   ...
                   'close': self.data.Close},
                  index=self.data.index)

@AlgoQ
Copy link
Author

AlgoQ commented Jun 1, 2020

Thanks. Yeah, I'm really looking forward for this pull request to be merged!

@AlgoQ AlgoQ closed this as completed Jun 1, 2020
@kernc kernc added the question Not a bug, but a FAQ entry label Jul 27, 2020
@kernc kernc changed the title Trying to use finta as techinical indicators library Using Finta technical indicators library Jul 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Not a bug, but a FAQ entry
Projects
None yet
Development

No branches or pull requests

2 participants