Skip to content

Is it possible to optimize based on multiple variables? #256

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
Gladi-iwnl opened this issue Feb 19, 2021 · 3 comments
Closed

Is it possible to optimize based on multiple variables? #256

Gladi-iwnl opened this issue Feb 19, 2021 · 3 comments
Labels
question Not a bug, but a FAQ entry

Comments

@Gladi-iwnl
Copy link

Gladi-iwnl commented Feb 19, 2021

Is it possible to optimize based on multiple variables? Or set the constraint to a value from the results?

Example:

stats = backtest.optimize(
    n1=range(10, 110, 10),
    n2=range(20, 210, 20),
    constraint=stats['Max. Drawdown [%]'] < 20,
    maximize='Return [%]]')
@kernc
Copy link
Owner

kernc commented Feb 20, 2021

Or set the constraint to a value from the results?

Constraint is a function that takes parameter combination (e.g. specific values of n1 and n2) and either marks it admissible (acceptable, valid) or not. It operates on combinations of parameters (optimization variables) way before we obtain the backtest results. So, no.

I think what you want is maximize=, which can also be a callable that takes results and returns a value, the greater the better. Like:

def maximize(stats):
    if stats['Max. Drawdown [%]'] < -20:
        return -np.inf  # i.e. worst
    return stats['Return [%]']

stats = bt.optimize(..., maximize=maximize)

@kernc kernc added the question Not a bug, but a FAQ entry label Feb 20, 2021
@Gladi-iwnl
Copy link
Author

Gladi-iwnl commented Feb 20, 2021

So if I use this maximize function, I would only get returns where the Max. Drawdown is higher than -30?

def maximize(stats):
    if stats['Max. Drawdown [%]'] > -30:
        return stats['Return [%]']

stats, heatmap = bt.optimize(
    p1=range(1,6,1),
    p2=range(1,11,1),
    p3=range(3,20,1),
    maximize=maximize,
    return_heatmap=True)

print(heatmap.sort_values().iloc[-20:])

Also, when I try to run this optimization and sort the heatmap I get a TypeError:

  File "/run/media/gladi/B204D33B04D300F1/Work/backtestingTryout/MAShiftSl.py", line 64, in <module>
    print(heatmap.sort_values().iloc[-20:])
  File "/home/gladi/.local/lib/python3.9/site-packages/pandas/core/series.py", line 3260, in sort_values
    sorted_index = nargsort(values_to_sort, kind, ascending, na_position)
  File "/home/gladi/.local/lib/python3.9/site-packages/pandas/core/sorting.py", line 379, in nargsort
    indexer = non_nan_idx[non_nans.argsort(kind=kind)]
TypeError: '<' not supported between instances of 'float' and 'str'

@kernc
Copy link
Owner

kernc commented Feb 20, 2021

def maximize(stats):
    if stats['Max. Drawdown [%]'] > -30:
        return stats['Return [%]']

No, with maximize function as above, you have an else branch you're not handling. The later TypeError is probably a consequence of implicitly returned None value. Inspect heatmap to confirm.

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