Back to Community
[Help Request] Min/Max functions not working as expected in pipeline

In the attached backtest, on line 47 I am trying to find max(0, current_liabilities-current_assets). However I see in the debugger that I am consistently getting negative excess cash when I expect positive values or 0.

Does anyone have insight into this or have a suggestion of what I should do?

Clone Algorithm
1
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 597e015ae6091e4f27944580
There was a runtime error.
2 responses

The problem is with the 'max' method. Factors can only be manipulated with a small set of methods and operators (see the list here https://www.quantopian.com/help#quantopian_pipeline_factors_Factor ). Remember that when defining factors one is really just defining the data which pipeline should fetch. The factors aren't the data. They are simply the definitions. One can't use a method like 'max' which expects numbers.

However, not to worry. Any calculations that prove too cumbersome to define inside the pipeline can always be done once the pipeline runs. The pipeline output is a pandas dataframe. Do any calculations one wants to do with that dataframe.

So, take the calculations out of the pipeline definition. Commented out here.

    # Can't use the 'max' method with factor objects  
    # Do this calc after the pipeline runs  
    # e = max(0, current_liabilities-current_assets)  
    # pipe.add(e, "e")  
    # excess_cash = cash-e  
    # pipe.add(excess_cash, "excess_cash")  
    #total_ev = market_cap+debt_value-excess_cash  
    # total_ev = excess_cash/(market_cap+debt_value)  
    # pipe.add(total_ev, "equity_value")  

Once the pipeline runs, simply add any new columns and/or calculations to the returned dataframe.

def before_trading_start(context,data):  
    context.output = pipeline_output('ev')  
    # Add other columns to the output dataframe  
    # Do the calculations we want  
    context.output['e'] = (context.output.liabilities - context.output.assets).clip(lower=0)  
    context.output['excess_cash'] = context.output.cash - context.output.e  
    context.output['total_ev'] = context.output.excess_cash / (context.output.market_cap + context.output.debt_value)  

I used the '.clip' method to ensure that e is never negative. Maybe could be done with a 'max' method but this was just personal preference.

See attached backtest.

Clone Algorithm
1
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 597f23330974dc4f24b64ad8
There was a runtime error.

Thanks Dan.