Back to Community
Linking my external GARP strategy to Quantopian

I'm new to the platform was wondering if it could link to an external API to fetch data.

I have a really successful GARP strategy here https://investorsedge.net/Strategy/Definition/24459/23717 that I would like to explore setting up on the platform.

InvestorsEdge has an API/JSON which allows access to the ranking tables on a given day, so I'd like to be able to access the API, receive and parse the JSON ranking list and trade the top 10 stocks at the start of each month.

4 responses

Hi Liam,

The best way to do this is with our self-serve data api: https://www.quantopian.com/help#self_serve_data. Your full ranking can be imported as a factor in pipeline. From there you can analyze the factor in research, or use it in an algorithm.
You can use google sheets as glue to go from the InvestorsEdge JSON API to the csv format self-serve expects.

happy coding,
fawce

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.

Hi fawce,

Thanks for the info - I've had a quick read of the documents and I'm not sure if it will work (or more likely I've completely misunderstood how to use it...).
The data out of the ranking API looks like this:

{ date: '2018-07-12T00:00:00',
ranks: [
{
symbol: 'AAPL',
rank: 100.0
},
{
symbol: 'MSFT',
rank: 80.0
},
{
symbol: 'MU',
rank: 60.0
},
{
symbol: 'FB',
rank: 40.0
},
{
symbol: 'GOOG',
rank: 20.0
}
]
}

That can obviously translate to a simple csv file, but how do I use this structure within the trading logic of your platform? For instance, I may only want to consider trading stocks with a rank >= 80.

Thanks
Liam

Hi Liam,

If you can get your data into a .csv file and upload it to Quantopian using self-serve data, you can then use the Pipeline API to add that filtering logic to a research notebook or algorithm. Here's a template algorithm in which you could add your custom dataset. I added a couple of lines that would filter the universe of stocks using a rank field.

Note that the template won't do anything until you actually upload a dataset and update the algorithm code to add in your dataset.

Clone Algorithm
5
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
"""
Self-Serve Data allows you to both upload historical data as well as live-update your data on a regular basis. Because of this live-updating capability and the point-in-time capture of your data, your data can now be used in algorithms you submit to the daily Quantopian Contest.

If you want to live update a dataset, you need to establish an FTP or host a file somewhere (like Dropbox or Google Sheets) and keep it up to date. Files are checked for new data on a nightly basis. You can read more about live updating datasets in the help documentation: https://www.quantopian.com/help#self_serve_data.

For a guide on how to upload your data, check out the Introduction to Self-Serve Data notebook attached to this forum post:
https://www.quantopian.com/posts/upload-your-custom-datasets-and-signals-with-self-serve-data#5b28fffc986d4e0048148f80

Once you've uploaded your dataset and configured live updates, follow the TO-DOs in the sample algorithm below to incorporate your data and develop an algorithm for the Quantopian Contest.

This example algorithm uses your uploaded dataset and uses the resulting pipeline to make trading decisions. A pipeline screen checks that uploaded data is not more than 3 business days old.
"""

import quantopian.algorithm as algo
import quantopian.optimize as opt
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import BusinessDaysSincePreviousEvent, SimpleMovingAverage

from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.experimental import risk_loading_pipeline

from quantopian.pipeline.data import Fundamentals

# TODO: Un-comment this line to import your dataset here.
# from quantopian.pipeline.data.user_[user_id] import [dataset_name]

# Constraint Parameters
MAX_GROSS_LEVERAGE = 1.0
MAX_SHORT_POSITION_SIZE = 0.02
MAX_LONG_POSITION_SIZE = 0.02

def initialize(context):
    """
    A core function called automatically once at the beginning of a backtest.

    Use this function for initializing state or other bookkeeping.

    Parameters
    ----------
    context : AlgorithmContext
        An object that can be used to store state that you want to maintain in 
        your algorithm. context is automatically passed to initialize, 
        before_trading_start, handle_data, and any scheduled functions.
        context provides the portfolio attribute, which can be used to retrieve 
        information about current positions.
    """
    
    # TODO: Un-comment this section to enable the call to make_pipeline():
    # algo.attach_pipeline(make_pipeline(), 'my_data_template')

    # Attach the pipeline for the risk model factors that we
    # want to neutralize in the optimization step. The 'risk_factors' string is 
    # used to retrieve the output of the pipeline in before_trading_start below.
    algo.attach_pipeline(risk_loading_pipeline(), 'risk_factors')

    # TODO: Schedule your trade logic via this rebalance function.
    # algo.schedule_function(
    #     func=rebalance,
    #     date_rule=algo.date_rules.week_start(),
    #     time_rule=algo.time_rules.market_open(hours=0, minutes=30)
    # )


def make_pipeline():
    """
    A function that creates and returns our pipeline.

    We break this piece of logic out into its own function to make it easier to
    test and modify in isolation. In particular, this function can be
    copy/pasted into research and run by itself.

    Returns
    -------
    pipe : Pipeline
        Represents computation we would like to perform on the assets that make
        it through the pipeline screen.
    """
    
    base_universe = QTradableStocksUS()
    
    # TODO: Replace with your dataset name.
    days_since_last_update = BusinessDaysSincePreviousEvent(
        inputs=[[dataset_name].asof_date.latest]
    )
    
    # TODO: Replace with your dataset name and the name of your value column. In this example, we assume your value column is a number:
    my_rank = [dataset_name].rank.latest
    
    # TODO: Update threshold based on live update frequency.
    has_recent_update = (days_since_last_update < 3)
    universe = (has_recent_update & base_universe)
    high_rank = (my_rank >= 80)

    # Create pipeline
    pipe = Pipeline(
        columns={
            'factor': factor,
        },
        screen=factor.notnull() & universe & high_rank
    )
    return pipe


def before_trading_start(context, data):
    """
    Optional core function called automatically before the open of each market day.

    Parameters
    ----------
    context : AlgorithmContext
        See description above.
    data : BarData
        An object that provides methods to get price and volume data, check
        whether a security exists, and check the last time a security traded.
    """

    # TODO: Un-comment this line to store the output of your pipeline in the context variable:
    # context.pipeline_data = algo.pipeline_output('my_data_template')

    # This dataframe will contain all of our risk loadings
    context.risk_loadings = algo.pipeline_output('risk_factors')
    

def rebalance(context, data):
    """
    A function scheduled to run once every Monday at 10AM ET in order to
    rebalance the longs and shorts lists.

    Parameters
    ----------
    context : AlgorithmContext
        See description above.
    data : BarData
        See description above.
    """
    # Retrieve pipeline output.
    pipeline_data = context.pipeline_data

    # Retrieve risk model factor data.
    risk_loadings = context.risk_loadings

    # Here we define our objective for the Optimize API. In this template 
    # we use the MaximizeAlpha objective.
    objective = opt.MaximizeAlpha(pipeline_data.factor)

    # Define the list of constraints.
    constraints = []
    
    # Constrain our maximum gross leverage.
    constraints.append(opt.MaxGrossExposure(MAX_GROSS_LEVERAGE))

    # Require our algorithm to remain dollar neutral.
    constraints.append(opt.DollarNeutral())

    # Add the RiskModelExposure constraint to make use of the
    # default risk model constraints.
    neutralize_risk_factors = opt.experimental.RiskModelExposure(
        risk_model_loadings=risk_loadings,
        version=0
    )
    constraints.append(neutralize_risk_factors)

    # With this constraint we enforce that no position can make up
    # greater than MAX_SHORT_POSITION_SIZE on the short side and
    # no greater than MAX_LONG_POSITION_SIZE on the long side. This
    # ensures that we do not overly concentrate our portfolio in
    # one security or a small subset of securities.
    constraints.append(
        opt.PositionConcentration.with_equal_bounds(
            min=-MAX_SHORT_POSITION_SIZE,
            max=MAX_LONG_POSITION_SIZE
        ))

    # Put together all the pieces we defined above by passing
    # them into the algo.order_optimal_portfolio function. This handles
    # all of our ordering logic, assigning appropriate weights
    # to the securities in our universe to maximize our alpha with
    # respect to the given constraints.
    algo.order_optimal_portfolio(
        objective=objective,
        constraints=constraints
    )
There was a runtime error.
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.

Hi Jamie,
That's great - thanks for that. I'll have a look in my copious amounts of spare time!
Liam