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

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 this issue Nov 7, 2023 · 1 comment

Comments

@jolinmaj
Copy link

jolinmaj commented Nov 7, 2023

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
Copy link

RaccoonTrading commented Jan 20, 2024

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants