kernc / backtesting.py

:mag_right: :chart_with_upwards_trend: :snake: :moneybag: Backtest trading strategies in Python.
https://kernc.github.io/backtesting.py/
GNU Affero General Public License v3.0
5.04k stars 987 forks source link

BokehDeprecationWarning: Passing lists of formats for DatetimeTickFormatter scales was deprecated in Bokeh 3.0. Configure a single string format for each scale #1087

Open jolinmaj opened 7 months ago

jolinmaj commented 7 months ago

Expected Behavior

Chart wiht no warnings

Actual Behavior

DatetimeFormatter scales now only accept a single format. Using the first provided: '%d %b' DatetimeFormatter scales now only accept a single format. Using the first provided: '%m/%Y'

from backtesting import Strategy from backtesting.lib import crossover from backtesting import Backtest

class SmaCross(Strategy): n1 = 91 # Moving average period

def init(self):
    # Precompute the moving average
    self.sma1 = self.I(SMA, self.data.Close, self.n1)

def next(self):
    # If close price is 2% above sma1, close any existing
    # long trades, and sell the asset to create a short position
    if self.data.Close[-1] > self.sma1[-1] * 1.015:
        if self.position.is_long:
            self.position.close()
        self.sell()

    # Else, if close price crosses below sma1, close any existing
    # short trades
    elif self.data.Close[-1] < self.sma1[-1]:
        if self.position.is_short:
            self.position.close()

    # Else, if close price is 4% below sma1, close any existing
    # short trades, and buy the asset
    elif self.data.Close[-1] < self.sma1[-1] * 0.95:
        if self.position.is_short:
            self.position.close()
        self.buy()

    # Else, if close price crosses above sma1, close any existing
    # long trades
    elif self.data.Close[-1] > self.sma1[-1]:
        if self.position.is_long:
            self.position.close()

Run the backtest with the new parameters

bt = Backtest(df, SmaCross, cash=10_000_000, commission=.002)

stats = bt.optimize(n1=range(50, 100, 200),

                #n2=range(60, 90, 120),
                #maximize='Equity Final [$]',)
                #constraint=lambda param: param.n1 < param.n2)

print(f"Best parameters: n1={stats._strategy.n1}")

stats = bt.run()

bt.plot()

Now plot the results

bt.plot() stats

RaccoonTrading commented 5 months ago

Issue:

BokehDeprecationWarning: Passing lists of formats for DatetimeTickFormatter scales was deprecated in Bokeh 3.0. Configure a single string format for each scale /Users/administrator/PycharmProjects/Trading UI/venv/lib/python3.10/site-packages/backtesting/_plotting.py:250: UserWarning: DatetimeFormatter scales now only accept a single format. Using the first provided: '%m/%Y' formatter=DatetimeTickFormatter(days=['%d %b', '%a %d'],

Go to Code in plotting.py (line 250)

  if is_datetime_index:
        fig_ohlc.xaxis.formatter = CustomJSTickFormatter(
            args=dict(axis=fig_ohlc.xaxis[0],
                      formatter=DatetimeTickFormatter(days=['%d %b', '%a %d'],
                                                      months=['%m/%Y', "%b'%y"]),
                      source=source),
            code='''

Replace with:

if is_datetime_index:
    fig_ohlc.xaxis.formatter = CustomJSTickFormatter(
        args=dict(axis=fig_ohlc.xaxis[0],
                  formatter=DatetimeTickFormatter(days='%m/%d', months='%m/%Y'),
                  source=source),
        code='''...'''
    )

See: (https://docs.bokeh.org/en/latest/docs/reference/models/formatters.html#bokeh.models.DatetimeTickFormatter)