Back to Community
[Framework] Modular Framework for trading algorithms

I noticed many quants here have ideas of strategies but they struggle to integrate them in a clean modular implementation. Here is a modular framework designed to allow separate implementation of the different functions inside a trading algo. It comes with the implementation of a basic crossover moving average strategy to illustrate how it works.

Quick explanation of the framework. The central piece of the framework is the portfolio manager that is responsible of the portfolio. It manages alpha generators that are seeking the alpha and ask the portfolio manager for allocation. The portfolio manager gets all the requests of the alpha generator and computes a target portfolio being helped by a risk manager and a transaction cost simulator. It then transmits the target to the execution handler which is responsible of the order strategy to reach the target. All these modules are independant and can easily be modified and used again in other strategies.

Clone Algorithm
Total Returns
Max Drawdown
Benchmark Returns
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
# L-Predator Analytics ( framework to design
# systematic strategies on Quantopian.
# The framework contains modules for alpha generation, risk management,
# transaction cost, portfolio management and allocation and execution. It
# allows to work on part of the trading process and uses the benefits for
# all strategies.
# The framework comes with a crossing moving average strategy.

# external libraries

import math

# abstract class to implement

# Alpha generator module is supposed to find edge on the market and ask the
# portfolio manager for allocation. Once the portfolio manager gives allocation
# to the alpha generator, ag keeps track of positions associated with it and if
# nothing change at the next portfolio reallocation the allocation it asks is
# the one associated to the positions associated to it.

class AlphaGenerator:

    def __init__(self):
        # allocation wanted
        self.alloc = dict()
        # positions associated to the strategy
        self.pos = dict()

    def compute_allocation(self, context, data):
        raise NotImplementedError()

# Execution Handler module takes care of the strategy to reach allocation
# once the portfolio manager gives a target allocation.

class ExecutionHandler(object):

    # decides which order to make
    def compute_orders(self, context, data, target_portfolio):
        raise NotImplementedError()

# Portfolio manager module manages the portfolio on the chosen frequency. It
# has alpha generators under control that get edge and ask for allocation. It
# then compute a target allocation being helped by a risk manager and a
# transaction cost model.

class PortfolioManager:

    def __init__(self):
        # target_portfolio
        self.target_portfolio = dict()
        # list of strategies
        self.list_alpha = []

    # computes the target portfolio
    def compute_target(self, context, data):
        raise NotImplementedError()

# Risk manager module help the portfolio manager to measure the risks held by
# the portfolio. It can held models of volatility or correlation and market
# models

class RiskManager:

# Transaction cost module can help the execution handler and the portfolio
# manager to make better decisions regarding the allocation and the strategy
# to put orders

class TransactionCost:

# Implementation of concrete class to illustrate the framework with a crossover
# moving average strategy. Each implementation of these module can be
# independantly used in other strategies or replaced by customed ones.

# AlphaGeneratorMa goes long if short term moving average is above long term
# moving average and short else

class AlphaGeneratorMa(AlphaGenerator):

    def __init__(self, sid_stock, len_short_ma=20, len_long_ma=50):
        # length used to compute short term ma
        self.len_short_ma = len_short_ma
        # length used to compute long term ma
        self.len_long_ma = len_long_ma
        # stock on which ma strategy is applied
        self.sid_stock = sid_stock

    def compute_allocation(self, context, data):
        # compute simple moving average
        short_ma = data[self.sid_stock].mavg(self.len_short_ma)
        long_ma = data[self.sid_stock].mavg(self.len_long_ma)
        # go long with full exposure if short ma > long ma, short
        # else
        if (short_ma > long_ma):
            self.alloc[self.sid_stock] = 1
            self.alloc[self.sid_stock] = -1

# ExecutionHandlerMarket makes market orders only to reach allocation

class ExecutionHandlerMarket(ExecutionHandler):

    def compute_orders(self, context, data, target_portfolio):
        for stock in context.securities:
            order_target_percent(stock, target_portfolio[stock])

# PortfolioManagerEquiWeight gives equal dollar allocation to each alpha
# generator in the portfolio

class PortfolioManagerEquiWeight(PortfolioManager):

    def __init__(self):

    def compute_target(self, context, data):
        # get number of alpha generators
        nb_alpha = len(self.list_alpha)
        # clear target allocation
        for stock in context.securities:
            self.target_portfolio[stock] = 0
        # for each alpha add allocation to the target
        for alpha in self.list_alpha:
            for stock in alpha.alloc:
                alloc_alpha = alpha.alloc[stock] / nb_alpha
                self.target_portfolio[stock] = self.target_portfolio[stock] + \
                # update the number of shares the alpha is responsible for
                port_value = context.portfolio.portfolio_value
                price = data[stock].price
                alpha.pos[stock] = math.floor(alloc_alpha * port_value / price)

# initialize set up the algorithm

def initialize(context):
    # set up of the universe
    context.securities = symbols('SPY')
    # first time initialization of all components of the algorithm
        context.first_time = False
        # creation of a portfolio manager
        context.p_manager = PortfolioManagerEquiWeight()
        # creation of execution handler
        context.exec_handler = ExecutionHandlerMarket()
        # creation of alpha generator
        alpha_ma_spy = AlphaGeneratorMa(sid_stock=sid(8554))
        # alpha generator is added to the portfolio manager
    # rebalance frequency
    # the portfolio will compute new allocation each day one minute before
    # close so that all orders can be executed at close
    # transaction cost
    # Quantopian default model

# handle data is called every minute

def handle_data(context, data):

# rebalance_portfolio is called at each reallocation. It computes the new
# target portfolio and organizes the order strategy to reach it

def rebalance_portfolio(context, data):
    # compute new allocation each alpha would like
    for alpha in context.p_manager.list_alpha:
        alpha.compute_allocation(context, data)
    # compute new target portfolio
    context.p_manager.compute_target(context, data)
    # compute order strategy
    target = context.p_manager.target_portfolio
    context.exec_handler.compute_orders(context, data, target)
There was a runtime error.
2 responses

Nice, there is also a nice framework for complex orders like bracket, trailing. It would be nice if we could have multiple files strategies.
Even if Quantopian compiled it into one file to deploy it would be nice to split strategies into multiple files.

can you update this for Q 2