from quantopian.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage
from quantopian.pipeline.filters.morningstar import Q1500US
from quantopian.pipeline.data import Fundamentals
from quantopian.pipeline.factors import CustomFactor, Returns, Latest
from quantopian.pipeline.classifiers import Classifier
def initialize(context):
## комиссию не прописываем, берем базовую
## Назначаем время переформирования портфеля (в начале каждого месяца)
schedule_function(my_rebalance,
date_rules.month_start(),
time_rules.market_open(hours=1))
# Запись данных в конце каждого дня
schedule_function(my_record_vars,
date_rules.every_day(),
time_rules.market_close())
# Создаем pipeline
my_pipe = make_pipeline()
attach_pipeline(my_pipe, 'my_pipeline')
def make_pipeline():
# Используем данные по капитализации и B/M по топ-1500 компаний в США Q1500US.
base_universe = Q1500US()
market_cap = Latest([Fundamentals.market_cap])
book_to_price = 1/Latest([Fundamentals.pb_ratio])
# Из 1500 акций берем 500 с наименьшей капитализацией
market_cap_rank = market_cap.rank(mask=Q1500US())
book_to_price_rank = book_to_price.rank(mask=market_cap_rank.bottom(500))
# Из этих 500 берем 40 с наибольшей B/M - их и покупаем на данный месяц
longs = book_to_price_rank.top(40)
securities_to_trade = (longs)
return Pipeline(
columns={
'longs': longs,
},
screen=(securities_to_trade),
)
# Рассчитываем веса - каждую акцию покупаем на 2,5% портфеля, то есть равномерно распределяем портфель по 40 акциям
def my_compute_weights(context):
long_weight = 1.0 / len(context.longs)
return long_weight
def before_trading_start(context, data):
# Применяем pipeline каждый день
context.output = pipeline_output('my_pipeline')
# Обновляем список акций для портфеля
context.longs = context.output[context.output['longs']].index.tolist()
context.long_weight = my_compute_weights(context)
Создаем функцию ребаланса, которая продает лишние и докупает нужные акции до приведения портфеля в соответствии с желаемым портфелем
def my_rebalance(context, data):
for security in context.portfolio.positions:
if security not in context.longs and data.can_trade(security):
order_target_percent(security, 0)
for security in context.longs:
if data.can_trade(security):
order_target_percent(security, context.long_weight)
# Записываем значения переменных
def my_record_vars(context, data):
longs = shorts = 0
for position in context.portfolio.positions.itervalues():
if position.amount > 0:
longs += 1
elif position.amount < 0:
shorts += 1
record(leverage=context.account.leverage, long_count=longs, short_count=shorts)