[PYTHON] Try the cloud-based algorithm trading service "Quantopian"

About this article

I found "Quantopian" when I was looking for finance related information in Python, so I will try it. Quantopian

What is Quantopian

A cloud-based algorithm trading platform. Users can create trading algorithms with Python-like code and backtest using a dedicated IDE (development environment) in the browser. If you have an account with Interactive Brokers Securities, it seems that you can also connect and make real trades.

What can you trade?

It seems to hold data on US stocks / ETFs since 2002 on a minute basis.

Let's start with

account registration

Access the site. It is bright red. Register with your email address from Sign Up on the top right. quantopian_01.png

Immediately after login

The menus are lined up at the top. quantopian_02.png

You can see the ongoing / upcoming Contest (forward test) from Capital-> Leaderboard. It seems that Contest is held every 6 months. quantopian_05.png

If you follow the name, you can see what the person posted to the Community and the Algorithm he shared. quantopian_06.png

You can also see the performance and source code of the shared Algorithm and clone it for improvement. This is like GitHub. quantopian_07.png

quantopian_08.png

The algorithm is coded from Algorithm. quantopian_03.png

How do you write the code?

Let's read the sample Sample Mean Reversion Algorithm. Below, I will post the full code for the time being.

python



# This is a sample mean-reversion algorithm on Quantopian for you to test and adapt.

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

# Every Monday, we rank high-volume stocks based on their previous 5 day returns. 
# We go long the bottom 20% of stocks with the WORST returns over the past 5 days.
# We go short the top 20% 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
import numpy as np

# The initialize function is the place to set your tradable universe and define any parameters. 
def initialize(context):
    # Use the top 1% of stocks defined by average daily trading volume.
    set_universe(universe.DollarVolumeUniverse(99, 100))
    
    # Set execution cost assumptions. For live trading with Interactive Brokers 
    # we will assume a $1.00 minimum per trade fee, with a per share cost of $0.0075. 
    set_commission(commission.PerShare(cost=0.0075, min_trade_cost=1.00))
    
    # Set market impact assumptions. We limit the simulation to 
    # trade up to 2.5% of the traded volume for any one minute,
    # and  our price impact constant is 0.1. 
    set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.10))
    
    # Define the other variables
    context.long_leverage = 0.5
    context.short_leverage = -0.5
    context.lower_percentile = 20
    context.upper_percentile = 80
    context.returns_lookback = 5
           
    # Rebalance every Monday (or the first trading day if it's a holiday).
    # At 11AM ET, which is 1 hour and 30 minutes after market open.
    schedule_function(rebalance, 
                      date_rules.week_start(days_offset=0),
                      time_rules.market_open(hours = 1, minutes = 30))  

# The handle_data function is run every bar.    
def handle_data(context,data):    
    # Record and plot the leverage of our portfolio over time. 
    record(leverage = context.account.leverage)

    # We also want to monitor the number of long and short positions 
    # in our portfolio over time. This loop will check our positition sizes 
    # and add the count of longs and shorts to our plot.
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)

# This rebalancing is called according to our schedule_function settings.     
def rebalance(context,data):
    # Get the last N days of prices for every stock in our universe.
    prices = history(context.returns_lookback, '1d', 'price')
    
    # Calculate the past 5 days' returns for each security.
    returns = (prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
    
    # Remove stocks with missing prices.
    # Remove any stocks we ordered last time that still have open orders.
    # Get the cutoff return percentiles for the long and short portfolios.
    returns = returns.dropna()
    open_orders = get_open_orders()
    if open_orders:
        eligible_secs = [sec for sec in data if sec not in open_orders]
        returns = returns[eligible_secs]

    # Lower percentile is the threshhold for the bottom 20%, upper percentile is for the top 20%.
    lower, upper = np.percentile(returns, [context.lower_percentile,
                                           context.upper_percentile])
    
    # Select the X% worst performing securities to go long.
    long_secs = returns[returns <= lower]
    
    # Select the Y% best performing securities to short.
    short_secs = returns[returns >= upper]
    
    # Set the allocations to even weights in each portfolio.
    long_weight = context.long_leverage / len(long_secs)
    short_weight = context.short_leverage / len(short_secs)
    
    for security in data:
        
        # Buy/rebalance securities in the long leg of our portfolio.
        if security in long_secs:
            order_target_percent(security, long_weight)
            
        # Sell/rebalance securities in the short leg of our portfolio.
        elif security in short_secs:
            order_target_percent(security, short_weight)
            
        # Close any positions that fell out of the list of securities to long or short.
        else:
            order_target(security, 0)
            
    log.info("This week's longs: "+", ".join([long_.symbol for long_ in long_secs.index]))
    log.info("This week's shorts: "  +", ".join([short_.symbol for short_ in short_secs.index]))

Overview

The sample algorithm is aimed at so-called "return reversal" (a phenomenon in which a relative decrease is increased and an increase is decreased according to the law of mean reversion). The strategy is as follows.

--At the beginning of each week, measure the returns of the last 5 days for stocks with high transaction amounts --Long stocks in the bottom 20% of returns --Short stocks in the top 20% of returns ――Brands that did not become long or short will be closed --Both long and short holdings shall be 50% of the funds

initialize(context) I will write it first as a promise. `context``` has the role of managing parameters etc. during the trading session. In other words, it works like a global variable. Set the parameters like `context.some_property```.

python


    # Use the top 1% of stocks defined by average daily trading volume.
    set_universe(universe.DollarVolumeUniverse(99, 100))

First, define the investment universe. We have acquired 99-100% of the percentile rank of the transaction amount. In other words, it is the top 1% of the transaction amount.

python


    # Set execution cost assumptions. For live trading with Interactive Brokers 
    # we will assume a $1.00 minimum per trade fee, with a per share cost of $0.0075. 
    set_commission(commission.PerShare(cost=0.0075, min_trade_cost=1.00))

The fee is 0.75 cents per share, with a minimum of $ 1.

python


    # Set market impact assumptions. We limit the simulation to 
    # trade up to 2.5% of the traded volume for any one minute,
    # and  our price impact constant is 0.1. 
    set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.10))

Defines the impact of slippage and market impact. `volume_limit calculates` is how much you keep your order quantity against the volume on a minute basis. For example, when 100 shares are traded on a minute basis, ``` volume_limit = 0.25 With ````, it is calculated that up to 25 shares (100 * 0.25) can be executed for one minute. The actual market impact (price fluctuations due to your order) is calculated using the price_impact appropriately constant. In Quantopian, the market impact is calculated by (your order / volume) ^ 2 * constant. For example, in the above example, the price moves in the disadvantageous direction by (0.25) ^ 2 * 0.10 = 0.625% depending on your order. It becomes.

python


    # Define the other variables
    context.long_leverage = 0.5
    context.short_leverage = -0.5
    context.lower_percentile = 20
    context.upper_percentile = 80
    context.returns_lookback = 5

Definition of constants used in trading sessions. Both long / short holdings are up to 50% of the funds, defining lower / upper percentile levels and past return measurement periods.

python


    # Rebalance every Monday (or the first trading day if it's a holiday).
    # At 11AM ET, which is 1 hour and 30 minutes after market open.
    schedule_function(rebalance, 
                      date_rules.week_start(days_offset=0),
                      time_rules.market_open(hours = 1, minutes = 30))  

Describes the process to be executed periodically. On the first day of the week, 1 hour and 30 minutes after opening, the `` `rebalance``` function will be called. (The witness time of US stocks is from 9:30 to 16:00, so it will be executed at 11:00)

handle_data(context, data) Called every time a trade event (bar update) occurs. `data``` is a dictionary that stores investment universe data and whose key is the Tesicker symbol. For example, data [symbol ('GOOG')] `` to get the latest Google data.

python


# The handle_data function is run every bar.    
def handle_data(context,data):    
    # Record and plot the leverage of our portfolio over time. 
    record(leverage = context.account.leverage)

    # We also want to monitor the number of long and short positions 
    # in our portfolio over time. This loop will check our positition sizes 
    # and add the count of longs and shorts to our plot.
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)

You can use record () to record any value and output it to the chart. In this case, the leverage and the number of long / short stocks are recorded and plotted.

rebalance(context,data) It is called by schedule_function, and the gimmicks and closings are executed here.

python


# This rebalancing is called according to our schedule_function settings.     
def rebalance(context,data):
    # Get the last N days of prices for every stock in our universe.
    prices = history(context.returns_lookback, '1d', 'price')

history is a built-in function, history(bar_count, frequency, field, ffill=True)Specify. bar_Specify the position including the current foot with count, the interval with frequency, and the data to be acquired with field. In this case, you will get the price 5 days ago. The return value is pandas.In DataFrame format, the universe brands are lined up in the columns direction.




#### **`python`**
```py

    # Calculate the past 5 days' returns for each security.
    returns = (prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]

Calculate the return.

python


    # Remove stocks with missing prices.
    # Remove any stocks we ordered last time that still have open orders.
    # Get the cutoff return percentiles for the long and short portfolios.
    returns = returns.dropna()
    open_orders = get_open_orders()
    if open_orders:
        eligible_secs = [sec for sec in data if sec not in open_orders]
        returns = returns[eligible_secs]

After excluding uncalculated returns, the stocks being traded are considered as trade-eligible stocks.

python


    # Lower percentile is the threshhold for the bottom 20%, upper percentile is for the top 20%.
    lower, upper = np.percentile(returns, [context.lower_percentile,
                                           context.upper_percentile])
    
    # Select the X% worst performing securities to go long.
    long_secs = returns[returns <= lower]
    
    # Select the Y% best performing securities to short.
    short_secs = returns[returns >= upper]

Substitute the returns of the lower 20% points and the upper 20% points for lower and upper, and filter the original `` `returns``` to narrow down to long and short stocks.

python


    # Set the allocations to even weights in each portfolio.
    long_weight = context.long_leverage / len(long_secs)
    short_weight = context.short_leverage / len(short_secs)

We will determine the position size per issue for each long and short. If there are five long stocks, it means that each stock is allowed to have a position of 0.1 times the amount of funds.

python


    for security in data:
        
        # Buy/rebalance securities in the long leg of our portfolio.
        if security in long_secs:
            order_target_percent(security, long_weight)
            
        # Sell/rebalance securities in the short leg of our portfolio.
        elif security in short_secs:
            order_target_percent(security, short_weight)
            
        # Close any positions that fell out of the list of securities to long or short.
        else:
            order_target(security, 0)
            
    log.info("This week's longs: "+", ".join([long_.symbol for long_ in long_secs.index]))
    log.info("This week's shorts: "  +", ".join([short_.symbol for short_ in short_secs.index]))

For all universe stocks, we will place orders for those included in long_secs and those included in short_secs. order_target_percent is a built-in function that places an order so that the specified stock has the specified weight in the portfolio. For example, if you already have 5% of AAPL in your portfolio and you run ```order_target_percent (symbol ('AAPL'), 0.1) `` `, you will get 5% of the difference. Such a place is smart! Stocks that are neither long_secs nor short_secs will be closed with a weight of 0%.

Finally, output the log and finish.

Let's run the back test

You can run a simple backtest by pressing Ctrl + B on the editor screen. It's simple, but it takes some time. quantopian_04.png

You can see the performance compared to the S & P 500 (SPY) and the return beta drawdown. Information on long / short issues is also displayed on the log screen. You can run Full Backtest for more detailed verification. (It takes about a few minutes)

quantopian_09.png

quantopian_10.png

The return is 9.2%, which is outperforming against SPY-2.5%. This strategy is beta 0.01, so it doesn't work with SPY at all. The maximum drawdown was around 7%. You can also see the Sharpe ratio, Sortino ratio, Information ratio, etc. The leverage during the period is about 0.95-1.05, which seems to be almost market neutral.

If you look at Transaction Details, you can also see the trading history.

in conclusion

I just tried running the sample algorithm for the time being, but when I looked at the API documentation etc., I found that it was a fairly substantial algorithm trading platform. Up until now, system trading has often involved collecting data on its own, building models, and using commercially available software, but in the future it may be the time to do it in the cloud. Above all, I think that Python coding skills can be used as they are.

It seems that the same thing can be done in the local environment by using a package called zipline, but unfortunately it only supports linux and OSX, so it cannot be installed in my environment.

In the future, I would like to proceed with reading comprehension of API.

Reference site

There seems to be almost no information in Japanese yet.

Quantopian --FinTech news that allows you to create and backtest trading algorithms on your browser

Recommended Posts

Try the cloud-based algorithm trading service "Quantopian"
Try the Variational-Quantum-Eigensolver (VQE) algorithm with Blueqat
Try the Taxii server (2. Service / Collection settings)
I investigated the reinforcement learning algorithm of algorithmic trading
About the service command
Try to model a multimodal distribution using the EM algorithm