Back to Community
Informal Quantopian Jam Session in Halifax

Anyone in Halifax is welcome to join an informal Quantopian "jam session" at 7:00 this evening (Wednesday, May 3) at QRA Corp, in our new location at 6080 Young Street, Suite 101, in Halifax, NS.

QRA is a software company specializing in testing and requirements for safety-critical systems. Our technical team members have diverse backgrounds in computer science, math, physics, electrical engineering, philosophy, and so forth. We are serious about software engineering.

A number of our team members are also interested in quantitative finance, so this evening I will be giving a brief introduction to the Quantopian platform. We decided to open it up to the public, so anyone in Halifax this evening is welcome to attend.

A few things to note:
- Pizza and beverages will be provided.
- If you have a laptop, bring it along.
- The intro will be basic, most people attending have not used the Quantopian platform.
- After the introduction, people will work in small groups and amongst themselves.
- Anyone familiar with Quantopian is welcome to work in their own direction.
- I will give suggestions on how to proceed, for different Quantopian experience levels.

The idea is to kick-start a Quantopian community here in Halifax, and if some interesting characters visit QRA as a side-effect, then that's great.

I hope to see some of you this evening!

Cheers,

Doug Staple
Chief Scientist and Director of Advanced Technologies
QRA Corp

9 responses

Sounds great. I will be there.

Awesome. See you there!

Great to see this get off the ground, good luck and have fun!

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Thanks, Delaney.

Folks: Here is a trivial "hello world" example from the algorithms environment:

Clone Algorithm
3
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
def initialize(context):
    schedule_function(rebalance,
                      date_rules.month_start(),
                      time_rules.market_open(hours=1, minutes=17))

def rebalance(context, data):
    order_target_percent(sid(8554), 0.3) # SPY
    order_target_percent(sid(23921), 0.4) # TLT
    order_target_percent(sid(14517), 0.3) # EWC

def handle_data(context, data):
    pass
There was a runtime error.

For getting started with the pipeline API, the pipeline tutorial is a great resource. I also recommend reading through and understanding the sample mean reversion algorithm provided on the Quantopian home page:

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
"""
This is a sample mean-reversion algorithm on Quantopian for you to test and adapt.
This example uses a dynamic stock selector, pipeline, to select stocks to trade. 
It orders stocks from the top 1% of the previous day's dollar-volume (liquid
stocks).

Algorithm investment thesis:
Top-performing stocks from last week will do worse this week, and vice-versa.

Every Monday, we rank high dollar-volume stocks based on their previous 5 day returns.
We long the bottom 10% of stocks with the WORST returns over the past 5 days.
We short the top 10% of stocks with the BEST returns over the past 5 days.

This type of algorithm may be used in live trading and in the Quantopian Open.
"""

# Import the libraries we will use here.
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import Returns
from quantopian.pipeline.filters.morningstar import Q1500US


def initialize(context):
    """
    Called once at the start of the program. Any one-time
    startup logic goes here.
    """
    # Define context variables that can be accessed in other methods of
    # the algorithm.
    context.long_leverage = 0.5
    context.short_leverage = -0.5
    context.returns_lookback = 5

    # Rebalance on the first trading day of each week at 11AM.
    schedule_function(rebalance,
                      date_rules.week_start(days_offset=0),
                      time_rules.market_open(hours=1, minutes=30))

    # Record tracking variables at the end of each day.
    schedule_function(record_vars,
                      date_rules.every_day(),
                      time_rules.market_close(minutes=1))

    # Create and attach our pipeline (dynamic stock selector), defined below.
    attach_pipeline(make_pipeline(context), 'mean_reversion_example')


def make_pipeline(context):
    """
    A function to create our pipeline (dynamic stock selector). The pipeline is 
    used to rank stocks based on different factors, including builtin factors, 
    or custom factors that you can define. Documentation on pipeline can be 
    found here:
    https://www.quantopian.com/help#pipeline-title
    """

    # Filter for stocks in the Q1500US universe. For more detail, see this post:
    # https://www.quantopian.com/posts/the-q500us-and-q1500us
    universe = Q1500US()
    
    # Create a Returns factor with a 5-day lookback window for all 
    # securities in our Q1500US Filter.
    recent_returns = Returns(window_length=context.returns_lookback, 
                            mask=universe)

    # Define high and low returns filters to be the bottom 10% and top 10% of
    # securities in the high dollar-volume group.
    low_returns = recent_returns.percentile_between(0,10)
    high_returns = recent_returns.percentile_between(90,100)

    # Add a filter to the pipeline such that only high-return and low-return
    # securities are kept.
    securities_to_trade = (low_returns | high_returns)

    # Create a pipeline object with the defined columns and screen.
    pipe = Pipeline(
        columns={
            'low_returns': low_returns,
            'high_returns': high_returns,
        },
        screen = securities_to_trade
    )

    return pipe

def before_trading_start(context, data):
    """
    Called every day before market open. This is where we get the securities
    that made it through the pipeline.
    """

    # Pipeline_output returns a pandas DataFrame with the results of our factors
    # and filters.
    context.output = pipeline_output('mean_reversion_example')

    # Sets the list of securities we want to long as the securities with a 'True'
    # value in the low_returns column.
    context.long_secs = context.output[context.output['low_returns']]

    # Sets the list of securities we want to short as the securities with a 'True'
    # value in the high_returns column.
    context.short_secs = context.output[context.output['high_returns']]

    # A list of the securities that we want to order today.
    context.security_list = context.long_secs.index.union(context.short_secs.index).tolist()

    # A set of the same securities, sets have faster lookup.
    context.security_set = set(context.security_list)

def compute_weights(context):
    """
    Compute weights to our long and short target positions.
    """

    # Set the allocations to even weights for each long position, and even weights
    # for each short position.
    long_weight = context.long_leverage / len(context.long_secs)
    short_weight = context.short_leverage / len(context.short_secs)
    
    return long_weight, short_weight

def rebalance(context,data):
    """
    This rebalancing function is called according to our schedule_function settings.
    """

    long_weight, short_weight = compute_weights(context)

    # For each security in our universe, order long or short positions according
    # to our context.long_secs and context.short_secs lists.
    for stock in context.security_list:
        if data.can_trade(stock):
            if stock in context.long_secs.index:
                order_target_percent(stock, long_weight)
            elif stock in context.short_secs.index:
                order_target_percent(stock, short_weight)

    # Sell all previously held positions not in our new context.security_list.
    for stock in context.portfolio.positions:
        if stock not in context.security_set and data.can_trade(stock):
            order_target_percent(stock, 0)

    # Log the long and short orders each week.
    log.info("This week's longs: "+", ".join([long_.symbol for long_ in context.long_secs.index]))
    log.info("This week's shorts: "  +", ".join([short_.symbol for short_ in context.short_secs.index]))

def record_vars(context, data):
    """
    This function is called at the end of each day and plots certain variables.
    """

    # Check how many long and short positions we have.
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1

    # Record and plot the leverage of our portfolio over time as well as the
    # number of long and short positions. Even in minute mode, only the end-of-day
    # leverage is plotted.
    record(leverage = context.account.leverage, long_count=longs, short_count=shorts)
There was a runtime error.

Next, here is an example usage of get_pricing in the research environment:

Loading notebook preview...
Notebook previews are currently unavailable.

Finally, here's a bare-bones example of how to get started with the pipeline API in the research environment. Looking through these snippets, I see that the comments are really terse. This is because these are my own notes, which I didn't intend to share with anyone. The quality should be fine. Hopefully its mostly self-explanatory -- the examples are supposed to be minimal anyway, and you have me to ask questions.

Loading notebook preview...
Notebook previews are currently unavailable.

In case the front door is locked when anyone arrives, call the office at 902-422-0212 and we'll come let you in.

The next Quantopian jam session at QRA is tentatively scheduled for July 12, 2017, at 7:30. Ray Carrol will be joining us via Skype for a discussion and to answer general finance-related questions. Dr. Carrol is the Chief Investment Officer from Brenton Hill Capital -- I personally will be looking forward to asking him some questions.