quantopian / pyfolio

Portfolio and risk analytics in Python
https://quantopian.github.io/pyfolio
Apache License 2.0
5.69k stars 1.78k forks source link

Exception has occurred: AttributeError 'DataFrame' object has no attribute 'amount' #662

Open cmperal opened 3 years ago

cmperal commented 3 years ago

Problem Description

Dear,

I'm trying to parse my generated backtest object into 'returns', 'positions' and 'transactions' by using function 'pf.utils.extract_rets_pos_txn_from_zipline' however, when I call such function I get this error "Exception has occurred: AttributeError 'DataFrame' object has no attribute 'amount'". I have the pyfolio logic within the function "analyze" and it is called from the function "run_algorithm" (I follow the quantopian pipeline)

This is the location where I get the error:

def analyze(context, perf):
    returns, positions, transactions = pf.utils.extract_rets_pos_txn_from_zipline(perf)

This is how I call the above function:

run_algorithm(
    start=start_date, 
    end=end_date, 
    initialize=initialize, 
    handle_data=handle_data,
    analyze=analyze,
    capital_base=10000,
    data_frequency = 'daily',
    bundle='quantopian-quandl')

Thank you.

Versions

george-adams1 commented 3 years ago

@cmperal I'm having the same issue. Have you been able to solve it?

ayxemma commented 3 years ago

this probably is because your daily net positions are all zero, so during the function call the positions extract failed because there's no daily end positions.

bergen288 commented 3 years ago

I have the same issue. How to address it?

bergen288 commented 3 years ago

Ok, the root cause is that no trade is triggered in handle_data function. Try to low the trigger condition from RSI 90/10 to 80/20 to avoid the issue.

def handle_data(context, data): 
    price_hist = data.history(context.stock, ["open", "high", "low","close"], context.rolling_window, "1d")             
    stock=sdf.retype(price_hist)   
    rsi = stock.get('rsi_12')
    if rsi[-1] > 90:
        order_target_percent(context.stock, 0.0)     
    elif rsi[-1] < 10:
        order_target_percent(context.stock, 1.0)