Skip to content

Optimization failure: Fatal Python error: GC object already tracked #103

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

Closed
arunavo4 opened this issue Jul 12, 2020 · 7 comments
Closed
Labels
bug Something isn't working upstream Issue affects a dependency of ours

Comments

@arunavo4
Copy link

arunavo4 commented Jul 12, 2020

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

from backtesting.test import SMA, GOOG, EURUSD


class Sma4Cross(Strategy):
    n1 = 50
    n2 = 100
    n_enter = 20
    n_exit = 10

    def init(self):
        self.sma1 = self.I(SMA, self.data.Close, self.n1)
        self.sma2 = self.I(SMA, self.data.Close, self.n2)
        self.sma_enter = self.I(SMA, self.data.Close, self.n_enter)
        self.sma_exit = self.I(SMA, self.data.Close, self.n_exit)

    def next(self):

        if not self.position:

            # On upwards trend, if price closes above
            # "entry" MA, go long

            # Here, even though the operands are arrays, this
            # works by implicitly comparing the two last values
            if self.sma1 > self.sma2:
                if crossover(self.data.Close, self.sma_enter):
                    self.buy()

            # On downwards trend, if price closes below
            # "entry" MA, go short

            else:
                if crossover(self.sma_enter, self.data.Close):
                    self.sell()

        # But if we already hold a position and the price
        # closes back below (above) "exit" MA, close the position

        else:
            if (self.position.is_long and
                    crossover(self.sma_exit, self.data.Close)
                    or
                    self.position.is_short and
                    crossover(self.data.Close, self.sma_exit)):
                self.position.close()


if __name__ == '__main__':
    bt = Backtest(GOOG, Sma4Cross, commission=.002)
    stats, heatmap = bt.optimize(
        n1=range(10, 110, 10),
        n2=range(20, 210, 20),
        n_enter=range(15, 35, 5),
        n_exit=range(10, 25, 5),
        constraint=lambda p: p.n_exit < p.n_enter < p.n1 < p.n2,
        maximize='Equity Final [$]',
        return_heatmap=False)
    print(stats)
    print('*'*50)
    print(heatmap)
    print('*'*50)
    print(heatmap.sort_values().iloc[-3:])
    print('*'*50)
    hm = heatmap.groupby(['n1', 'n2']).mean().unstack()
    print(hm)
    print('*'*50)
    from backtesting.lib import plot_heatmaps

    plot_heatmaps(heatmap, agg='mean')

    # bt.plot()

This is the same code from the doc > examples for parameter optimization doc/examples/Parameter Heatmap.ipynb
Running the above code results in BrokenProcessPool @kernc any ideas on what's wrong

/home/skywalker/PycharmProjects/backtesting.py/venv/bin/python /home/skywalker/PycharmProjects/backtesting.py/backtesting/test/main_test.py
/home/skywalker/PycharmProjects/backtesting.py/backtesting/test/main_test.py:60: UserWarning: Searching best of 486 configurations.
  return_heatmap=False)
Fatal Python error: GC object already tracked

Current thread 0x00007fafd228f740 (most recent call first):
  File "/home/skywalker/PycharmProjects/backtesting.py/venv/lib/python3.7/site-packages/pandas/core/dtypes/base.py", line 273 in is_dtype
  File "/home/skywalker/PycharmProjects/backtesting.py/venv/lib/python3.7/site-packages/pandas/core/dtypes/common.py", line 572 in is_categorical_dtype
  File "/home/skywalker/PycharmProjects/backtesting.py/venv/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 295 in __new__
  File "/home/skywalker/PycharmProjects/backtesting.py/venv/lib/python3.7/site-packages/pandas/core/internals/construction.py", line 244 in init_dict
  File "/home/skywalker/PycharmProjects/backtesting.py/venv/lib/python3.7/site-packages/pandas/core/frame.py", line 435 in __init__
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 900 in _compute_stats
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 724 in run
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 879 in <genexpr>
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 877 in <listcomp>
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 879 in _mp_task
  File "/usr/lib/python3.7/concurrent/futures/process.py", line 239 in _process_worker
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99 in run
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297 in _bootstrap
  File "/usr/lib/python3.7/multiprocessing/popen_fork.py", line 74 in _launch
  File "/usr/lib/python3.7/multiprocessing/popen_fork.py", line 20 in __init__
  File "/usr/lib/python3.7/multiprocessing/context.py", line 277 in _Popen
  File "/usr/lib/python3.7/multiprocessing/process.py", line 112 in start
  File "/usr/lib/python3.7/concurrent/futures/process.py", line 607 in _adjust_process_count
  File "/usr/lib/python3.7/concurrent/futures/process.py", line 583 in _start_queue_management_thread
  File "/usr/lib/python3.7/concurrent/futures/process.py", line 641 in submit
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 844 in <listcomp>
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 844 in optimize
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/test/main_test.py", line 60 in <module>
Traceback (most recent call last):
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/test/main_test.py", line 60, in <module>
    return_heatmap=False)
  File "/home/skywalker/PycharmProjects/backtesting.py/backtesting/backtesting.py", line 846, in optimize
    batch_index, values = future.result()
  File "/usr/lib/python3.7/concurrent/futures/_base.py", line 428, in result
    return self.__get_result()
  File "/usr/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.

Process finished with exit code 1

P.S: Running Ubuntu 20.04 LTS / Python 3.7

@kernc
Copy link
Owner

kernc commented Jul 13, 2020

The real error seems to be:

Fatal Python error: GC object already tracked

What backtesting.py version is this, and have you tried master?

@arunavo4
Copy link
Author

@kernc Backtesting==0.1.7

@arunavo4
Copy link
Author

arunavo4 commented Jul 13, 2020

@kernc I tried with master same issue __version__ 0.1.8.dev7+g0739f4b

__version__ 0.1.8.dev7+g0739f4b
/home/skywalker/PycharmProjects/untitled/test.py:64: UserWarning: Searching best of 486 configurations.
  return_heatmap=False)
Traceback (most recent call last):
  File "/home/skywalker/PycharmProjects/untitled/test.py", line 64, in <module>
    return_heatmap=False)
  File "/home/skywalker/PycharmProjects/untitled/venv/lib/python3.7/site-packages/Backtesting-0.1.8.dev7+g0739f4b-py3.7.egg/backtesting/backtesting.py", line 846, in optimize
    batch_index, values = future.result()
  File "/usr/lib/python3.7/concurrent/futures/_base.py", line 428, in result
    return self.__get_result()
  File "/usr/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.

Process finished with exit code 1

@kernc
Copy link
Owner

kernc commented Jul 13, 2020

Well, the relevant traceback above (Current thread 0x00007fafd228f740 (most recent call first):)
indicates it might be a pandas issue:

df = pd.DataFrame()

What pandas version is that? Have you tried upgrading or downgrading pandas?

@arunavo4
Copy link
Author

arunavo4 commented Jul 14, 2020

What pandas version is that? Have you tried upgrading or downgrading pandas?

pandas~=1.0.4
@kernc can you run the above code on your end and do a pip freeze and paste here. The code I have given here is from your docs. doc/examples/Parameter Heatmap.ipynb

@kernc
Copy link
Owner

kernc commented Jul 14, 2020

The examples are covered in tests which do seem to pass without error, occasionally.

@kernc kernc changed the title Unable to Run Optimize from doc examples Optimization failure: Fatal Python error: GC object already tracked Jul 15, 2020
@kernc kernc added bug Something isn't working upstream Issue affects a dependency of ours labels Jul 15, 2020
@arunavo4
Copy link
Author

arunavo4 commented Aug 2, 2020

@kernc Closing this issue as I figured out the correct way of doing it. This issue #90 helped!
Here is an example for people in future, with a similar problem.

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

from backtesting.test import SMA, GOOG, EURUSD


class Sma4Cross(Strategy):
    n1 = 50
    n2 = 100
    n_enter = 20
    n_exit = 10

    def init(self):
        self.sma1 = self.I(SMA, self.data.Close, self.n1)
        self.sma2 = self.I(SMA, self.data.Close, self.n2)
        self.sma_enter = self.I(SMA, self.data.Close, self.n_enter)
        self.sma_exit = self.I(SMA, self.data.Close, self.n_exit)

    def next(self):

        if not self.position:

            # On upwards trend, if price closes above
            # "entry" MA, go long

            # Here, even though the operands are arrays, this
            # works by implicitly comparing the two last values
            if self.sma1 > self.sma2:
                if crossover(self.data.Close, self.sma_enter):
                    self.buy()

            # On downwards trend, if price closes below
            # "entry" MA, go short

            else:
                if crossover(self.sma_enter, self.data.Close):
                    self.sell()

        # But if we already hold a position and the price
        # closes back below (above) "exit" MA, close the position

        else:
            if (self.position.is_long and
                    crossover(self.sma_exit, self.data.Close)
                    or
                    self.position.is_short and
                    crossover(self.data.Close, self.sma_exit)):
                self.position.close()


def prepare_optimization(cls: type) -> dict:
    # Construct and return optimization kwargs
    return {'n1': range(5, 30, 5),
            'n2': range(10, 70, 5),
            'n_enter': range(15, 35, 5),
            'n_exit': range(10, 25, 5),
            'constraint': lambda p: p.n_exit < p.n_enter < p.n1 < p.n2,
            'maximize': 'Equity Final [$]'}


if __name__ == '__main__':
    bt = Backtest(GOOG, Sma4Cross, commission=.002)
    opt_kwargs = prepare_optimization(Sma4Cross)
    stats, heatmap = bt.optimize(**opt_kwargs, return_heatmap=True)
    print(stats)
    print('*'*50)
    print(heatmap)
    print('*'*50)
    print(heatmap.sort_values().iloc[-3:])
    print('*'*50)
    hm = heatmap.groupby(['n1', 'n2']).mean().unstack()
    print(hm)
    print('*'*50)
    from backtesting.lib import plot_heatmaps

    plot_heatmaps(heatmap, agg='mean')

    # bt.plot()

@arunavo4 arunavo4 closed this as completed Aug 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working upstream Issue affects a dependency of ours
Projects
None yet
Development

No branches or pull requests

2 participants