Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
use of random values in an algo?

The help page says:

The use of random() isn't supported because of technical limitations with our start-of-day initialization

Is it only random() that is excluded? Or is this meant to be a more general restriction on the use of random values?

For example, I am considering using:

numpy.random.randint  

Is it allowed? I can run a backtest with it in the code, but would it result in an error under live trading?

Also, specifically, what are the "technical limitations with our start-of-day initialization"? Are there usages of random values that would be compatible? I see on https://www.quantopian.com/posts/random-selection-with-ratcheting-price that perhaps the actual requirement is that repeated backtests must return the same results?

Grant

16 responses

Any guidance on this? For example, what if I use:

import numpy as np

def initialize(context):  
    np.random.seed(31415927)

def handle_data(context,data):  
    if np.random.randint(1,101) < 31:  
        return  

Would it be o.k.?

Grant

I concur. Random excluded? Why?

And why is __iter __ banned?

def iter(self):
return iter(this.stockList.values())

Code used in live trading needs to be deterministic, meaning that if you run it multiple times, it will have identical results each time. You can have a pseudo-random algo if you seed it, and then make it deterministic. Here is more info: https://www.quantopian.com/posts/random-selection-with-ratcheting-price

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 Alisa, you might consider removing the restriction on the use of random() (change to a warning?) and adding a more accurate description of the requirement to your help page. I figure that the restriction is required because you use the repeat-ability of backtests as a QC check in live trading, correct? --Grant

@Grant, does this post contradict Alisa's?

https://www.quantopian.com/posts/using-random-in-a-simple-example

As I've got this producing random ints:

record(Random = float(random.randrange(0,100)))  

Random is good for testing exit strategies. If you can place random entries, yet your exit techniques (stop loss and stop profits) handle whatever is thrown at them then your exits might be considered robust. 100 tests with random entries, and you'll know to some degree how good your exits are. We've used this technique to tune exits with some success. Of course we run hundreds of thousands of tests over thousands of securities to tune the exit parameters. Not an option here. Random is a good method to toughen one's strategies against the unknown.

def HandleEntry(context, data):  
    if (random.randrange(0, 100) > 50):  
        return  
    stockCount = float(len(data))  
    for stock in data:  
        order_target_percent(stock, 1.0 / stockCount)  

Market Tech,

As I understand it, backtests need to be deterministic for trading at IB, meaning that if you run the same backtest more than once, the results should be identical. I think that they're using backtests as Q/C checks, to make sure that code still executes identically after changes to their trading engine (or maybe every night routinely?), but I'm just speculating.

For whatever reason, they explicitly block random(), but allow other random generators.

Not sure if I answered your question. Again, just make sure your code is deterministic for real-money trading as a rule.

By the way, do you code trading systems for a living?

Grant

Depending on how random is disallowed, the new-ish get_environment() might have a chance

if get_environment('arena') == 'backtest':  
    # Do something random  
else:    # paper or live/real  
    # Not random  

@Grant, I had assumed that any "random" was blocked, that's why I was surprised to find that post, which allowed me to add a random capability to a test rig I was working out. No question really, just a discrepancy I noticed.

Sure, backtests for actual trading should be deterministic. But that's not what my post was speaking to. A stochastic process for tuning trading modules of various kinds can be quite helpful in finding errors, finding tendencies and proofing concepts. I'm glad to know that random() does indeed work.

[Yes. I've been writing trading strategies, indicators, patterns and analytics (among other things), professionally, for nearly 10 years now. Not that I'm any good at it, or have learned a profitable thing along the way...(frown)]

@Grant Im curious why you will need to create a random number.

Hello Erick,

I'd used a random number generator to pick random days to trade, in backtesting. I wanted to limit the number of trades, but not bias the simulation by arbitrarily picking a certain day (e.g. every Tuesday). I actually ended up entering the algo into the Open contest with the random trade day selection, although in retrospect, it was not the best decision, since I subsequently found that I could make a trading decision every day, without getting killed by commissions.

As Market Tech alludes to, Quantopian needs to be thinking along the lines of supporting techniques like Monte Carlo simulations (http://en.wikipedia.org/wiki/Monte_Carlo_method). I'm guessing that the folks who do this kind of thing for real (e.g. hedge funds, investment banks, etc.) have access to big ol' computer farms, and have written their code to support modern high performance computing. To date, this kind of thing has not be high on the list for Quantopian, although there has been some discussion in the context of the upcoming Research Environment. Especially in light of the fact that they'll be putting their own money into algos via the Open and the Fund, my sense is that it'd be a wise move financially to start thinking along these lines (even if it means completely re-writing big chunks of code). Say the Fund needs at least $100M capital to be a viable business for Quantopian, so a 1% boost in returns is $1M, which would buy some nice computing power. In other words, I think it would pay for itself quickly.

Grant

@Grant,

Interesting approach. Yep well think about it we are competing against big hedge funds with almost unlimited $$$. However markets in some cases doesn't seem to be so ramdom, The trick is to find those patterns/trends and get multiple algos that behave better in certain time frames or circumstances.

EG

I used a pseudo random number generator, X_{n+1} = (a X_{n} + b) mod m

When live I've considered maybe trading random minutes and varying number of shares (at least off whole numbers) to reduce predictability by possible insiders on wall street who could conceivably take advantage (knock one aside) ahead of a recognizable pattern (with help from computers) especially when volumes become a large percentage, an interesting first-world problem to have.

def rndint(): return int(str(datetime.datetime.now().microsecond)[-1])  

is a pretty good way to generate equally distributed random ints between 0 and 9

That fine bit turned into the heart of this self-contained way to trade random minutes without using random() (although these 2--current setting--arbitrary minutes per day tend to be close to each other, so not quite right yet). (I'm betting Python will only bother to take the time for the imports once so they won't slow things down much).
Give num_minutes_to_trade a value of 1 for 1 minute per day. If you set num_minutes_to_trade to 4, for example, it will pick 4 minutes each day
Maybe there is a better way. This could stand some improvement however it's something to chew on. (or for me, to save for later)

'''
Trade randomish minutes per day.  
num_minutes_to_trade currently set to 2.  
Change to 1 or 20 or whatever up to 390.  
For minute mode.  
'''
def initialize(context):  
    symbol('A')

def handle_data(context, data):

    if not ok_minutes(context):      # Designated randomish minutes per day for trading  
        return  
    print str(get_datetime().time()) # UTC

    # [strategy here]

def ok_minutes(context):  
    from pytz import timezone as t_z  
    from datetime import datetime as d_t  
    if 'date_prv' not in context:  
        context.date_prv = ''    # init  
    if 'minutes_list' not in context:  
        context.minutes_list = []  
    bar_dt     = get_datetime().astimezone(t_z('US/Eastern'))  
    date_now   = str(bar_dt.date())  
    minute_now = (bar_dt.hour * 60) + bar_dt.minute - 570  # (570=9:30a)

    if date_now != context.date_prv:  
        # Set new ok trade minutes for the day  
        num_minutes_to_trade = 2                # Number of random minutes to trade  
        context.minutes_list = []               #   (if same by chance, will be fewer)

        for i in range(0, num_minutes_to_trade):  
            ms3   = str(d_t.now().microsecond)[-3:] # ms for microseconds, 3 digits  
            jumbl = ms3[-1] + ms3[-2] + ms3[-3]     # moving last to first  
            intgr = (int(jumbl) + 1)                # 1 to 1000  
            minut = int((intgr * 390) / 1000)       # Squash those into 1 to 390  
            context.minutes_list.append(minut)

        context.date_prv = date_now  
        #print str(minute_now) + '\t' + str(minutes_list)

    if minute_now in context.minutes_list:  
        return 1  
    return 0  

Hello Gary & M. Schäfer,

In case you missed it, note that numpy includes a suite of random sampling widgets (http://docs.scipy.org/doc/numpy/reference/routines.random.html). If the generator is seeded with a custom seed (rather than letting it pick its own), presumably all of the numpy tools will be deterministic when used in a backtest. Using datetime to generate random numbers will run afoul of the Quantopian requirement for deterministic backtests, since it uses the system clock. You'd be o.k. for just backtesting, but beyond that (fake/real money trading) I gather that you'd have to rejigger your code.

Grant