zipline: target_order не выполняется в handle_data - PullRequest
0 голосов
/ 07 января 2020

Я пытаюсь разработать ежемесячную стратегию ротационной торговли с Zipline и данными из пакета Quandl. Предполагается, что стратегия удерживает количество («topn») активов с самым высоким значением импульса и удерживает их до тех пор, пока они не упадут ниже определенного ранга импульса («keepn»).

Когда я запускаю следующий код через zipline, он работает в течение нескольких месяцев, затем внезапно начинает удерживать все больше и больше позиций, неоднократно продавая одни и те же позиции, фактически не удаляя позиции из портфеля. Это происходит как с данными Quandl, так и с пользовательским пакетом.

Полагаю, в моей стратегии есть фундаментальный недостаток, но в процессе отладки я действительно не могу ее найти.

Любая помощь приветствуется! Спасибо.

Дирк

def initialize(context):
    # List of all assets to chose from  
    context.tickers = ["AAPL", "YELP", "YHOO", "MMM", 
                       "ABT", "AMD", "AMZN", "GOOG", 
                       "AXP", "AMGN", "BBY", "BLK", 
                       "CAT"]

    context.universe = [symbol(ticker) for ticker in context.tickers]
    context.momentum_lookback = 256

    # Hold (topn) 3 assets, as long as they are in the (keepn) top 5 momentum_rank
    context.topn = 3
    context.keepn = 5

    # Schedule the trading routine for once per month
    schedule_function(handle_data, date_rules.month_start(), time_rules.market_close())

    # Allow no leverage
   set_max_leverage = 1.0


def momentum_score(ts):
    # Simplified momentum score: Last price / price 256 days ago 
    return ts[-1] / ts[0]


def handle_data(context, data):
    # String with today's date for logging purposes
    today = get_datetime().date().strftime('%d/%m/%Y')

    # Create 256 days (context.momentum_lookup) history for all equities
    hist = data.history(context.universe, 
                              "close", 
                              context.momentum_lookback,
                              "1d")

    # How much to hold of each equity
    target_percent = 100 / context.topn

    # Rank ETFs by momentum score
    ranking_table = hist.apply(momentum_score).sort_values(ascending=False)
    top_assets = ranking_table[:context.topn]
    grace_assets = ranking_table[:context.keepn]

    # List of equities being held in current portfolio
    kept_positions = list(context.portfolio.positions.keys())

    # Sell logic
    # ==========
    # Sell current holdings no longer in grace assets
    for holding in context.portfolio.positions:
        if holding not in grace_assets:
            if data.can_trade(holding):
                print(today + " [Sell] "+holding.symbol)
                order_target_percent(holding, 0.0)
                kept_positions.remove(holding)

    # Buy Logic
    # =========
    # Determine how many new assets to buy
    replacements = context.topn - len(kept_positions) 

    # Remove currently held positions from the top list
    buy_list = ranking_table.loc[~ranking_table.index.isin(kept_positions)][:replacements]

    # Buy new entities and rebalance "kept_positions" to the desired weights
    new_portfolio = list(buy_list.index) + kept_positions

    # Buy/rebalance assets
    for asset in new_portfolio:
        if data.can_trade(asset):
            print(today+"[BUY] "+asset.symbol)
            order_target_percent(asset, target_percent)

1 Ответ

0 голосов
/ 07 января 2020

Хорошо, я понял, в чем проблема. Basi c математическая ошибка на моем конце. Это проблемный код:

# How much to hold of each equity  
target_percent = 100 / context.topn

Вместо него должно было быть target_percent context.topn / 100. facepalm Я предполагаю, что это приводит к ситуациям, когда ордера не выполняются должным образом, что приводит к описанному поведению.

Извлеченный урок:

  • Проверьте открытые ордера и при необходимости отмените их

  • Следите за размерами кредитного плеча и размера позиции и проверяйте ограничения в течение всего go пробега

...