Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
One Trade a Day

I'm trying to limit a trade to only once a day but I'm having trouble using datetime to do it. Would anyone mind giving me a hand?

# Put any initialization logic here.  The context object will be passed to  
# the other methods in your algorithm.  
def initialize(context):  
    context.nvda = sid(24)  
    context.max_notional = 1000000.1  
    context.min_notional = -1000000.0


# Will be called on every trade event for the securities you specify.  
def handle_data(context, data):  
    # Implement your algorithm logic here.  
    theOpen = data[context.nvda].open_price  
    curPrice = data[context.nvda].price  
    #amount = 2000/curPrice  
    if curPrice > (theOpen + .08) and curPrice < (theOpen + 1.2):  
        #order(sid(19725),amount, theOpen * 1.02, (theOpen*.98))  
        order(context.nvda, 100, data[context.nvda].close_price)  

    # data[sid(X)] holds the trade event data for that security.  
    # data.portfolio holds the current portfolio state.

    # Place orders with the order(SID, amount) method.

    # TODO: implement your own logic here.  
    #order(sid(24), 50)  

I'm getting a ridiculous return (22,000%) but it's way too volatile for my liking at the moment.

16 responses

Hello Aloke,

One easy way to trade only once a day is to run your algorithm on daily data. You'll submit an order at most once per day, and it will likely get filled the next trading day.

Are you running on daily or minute data?

To avoid the crazy returns, you'll need to use the max_notional/min_notional limits (see one of the example algorithms on the help page). Without a constraint, you can just keep on buying, borrowing virtual dollars from the Bank of Quantopian.

Grant

The code below limits trading to once a day. Maybe not the most elegant way, but you can always refine it from here.

# Put any initialization logic here.  The context object will be passed to  
# the other methods in your algorithm.  
def initialize(context):  
    context.prev_day = -1  


# Will be called on every trade event for the securities you specify.  
def handle_data(context, data):  
    # Implement your algorithm logic here.

    # data[sid(X)] holds the trade event data for that security.  
    # data.portfolio holds the current portfolio state.

    # Place orders with the order(SID, amount) method.

    # TODO: implement your own logic here.  
    curr_day = data[sid(24)].datetime.day  
    if (curr_day != context.prev_day):  
        context.prev_day = curr_day  
        # your trading logic  
        order(sid(24), 50)  

isn't live trading always done in minute mode? Or is there a way to specify that I want my live algorithm to only run at the start or end of day?

Pumplerod,

Yes, live trading is always in minute mode.

To start trading at open, you can use something like this (with context.prior_datetime initialized to None):

if context.prior_datetime == None or context.prior_datetime.day != get_datetime().day:  
        context.prior_datetime = get_datetime()  
else:  
        context.prior_datetime = get_datetime()  
        return  

This is equivalent to the Rasmus post above (with explicit evaluation of the initial condition).

To trade at the end of the day is trickier, since there is no way to detect the end of the day, since once it is detected it'll be the next day! So, you have to use logic to trade after a specified time before the close. Note that sometimes the market closes early, according to a schedule. You can access the schedule from within your algorithm (see https://www.quantopian.com/posts/market-on-close-moc-orders, for example).

An implementation looks something like this:

    context.spy = sid(8554)  
    start_date = context.spy.security_start_date  
    end_date = context.spy.security_end_date  
    context.early_closes = get_early_closes(start_date,end_date).date

# skip day if early close scheduled  
    if get_datetime().date() in context.early_closes:  
        return  

Pumplerod,

Here's a handy function (originally written by Jess Stauth):

def intradingwindow_check(context):  
    # Converts all time-zones into US EST to avoid confusion  
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))  
    # if loc_dt.hour > 12 and loc_dt.hour < 15:  
    # if loc_dt.hour == 10 and loc_dt.minute == 0:  
    if loc_dt.hour > 14 and loc_dt.minute > 45:  # MOC order  
        return True  
    else:  
        return False  

Grant

Hello Grant,

In case anyone wants to use the above function they need to import 'timezone' i.e.

from pytz import timezone

def intradingwindow_check(context):  
    # Converts all time-zones into US EST to avoid confusion  
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))  
    # if loc_dt.hour > 12 and loc_dt.hour < 15:  
    # if loc_dt.hour == 10 and loc_dt.minute == 0:  
    if loc_dt.hour == 9 and loc_dt.minute == 31:  
        return True  
    else:  
        return False  

P.

I am trying to accomplish something similar. Is there a way to access how many trades have been made in a certain day for a certain security? For example, let's say I buy aapl at open and then sell it 5 minutes later.

I'm looking for something that is like
if I have bought and sold appl today:
____don't trade

if I have not bought and sold aapl today:
____trade

I'm trying to get this to work on minute data

Hello Mike,

Sounds doable. No time now to work on an example, but you need a kind of bookkeeping function that runs every minute and tracks 'bought and sold' by security as the day progresses (e.g. stored as a dictionary in context). And you'll need to sort out how to re-initialize the bookkeeping at the start of a new day.

If you are only dealing with one security, then it is a bit simpler, since you'll just need a single boolean flag (e.g. context.bought_and_sold_appl_today).

Grant

Aloke, you may want to take a look at following example and you may be able to tweak it from there.
https://www.quantopian.com/posts/5-10-20-crossover-strategy-with-leveraged-etf

@ Grant, Peter: The solution you provided trades on the same day as signal right ?

And this trades at the open of the next day, right ?

def initialize(context):  
    context.day = None

def handle_data(context, data):  
    if get_datetime().day == context.day:  
        return  
    context.day = get_datetime().day  

Darell,

There are a couple different approaches described here. You can specify a time to trade (or a window of time) or you can 'detect' a new trading day (which, for example, would allow for a late open). So, Peter's code can be used to trade based on time, on the same day:

from pytz import timezone

def intradingwindow_check(context):  
    # Converts all time-zones into US EST to avoid confusion  
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))  
    # if loc_dt.hour > 12 and loc_dt.hour < 15:  
    # if loc_dt.hour == 10 and loc_dt.minute == 0:  
    if loc_dt.hour == 9 and loc_dt.minute == 31:  
        return True  
    else:  
        return False  

The code you posted would trade every day at the open (even if the open is late), including the first day (since you initialize with context.day = None).

There is a subtlety to this (unless something has changed). The help page states that get_datetime() "Returns the current algorithm time" but I think that what it actually does is report the datetime stamp of the highest frequency sid listed in your algorithm (and possibly even ones that are commented out). So, some minutes when the market is open could be skipped. Quantopian folks, is this correct?

Grant

• That works Grant, however the transaction log shows weird trade times like 23:27, 16:32 etc, that makes sense only if its my local machine time since 16:30 my local time is 09:30 in nyc

One more:
• How can i update a trail stop from the Daily open price, but trigger/execute trades at Daily close price (or next days close price). Attached the algo that has this issue. When i run it in daily mode, behaves as it should (ie. getting a signal, executing at next days close price), however getting it to behave the same in minute mode is still a challenge. Heres what it gets on Daily mode: https://www.dropbox.com/s/ihz8x7eabps5ezn/Screen%20Shot%202014-09-06%20at%2017.30.42.png?dl=0

in short id like to have these values in minute mode:
Price = Daily close_ price
Stop = Daily open_price

Darell,

I stripped down your algorithm to see what's going on. Kinda weird that it mostly buys at 9:32 (correct behavior), but for some days it buys at 10:32 (incorrect behavior). If you sort it out, please post the solution here.

Grant

Hi Grant, may the 1h time difference occasionally, be a cause of time change, going over to winter time etc ?

If you can, please take another look at the algo, its very simple and but i need some help with controlling time still, i have set the overall run time at the open like this:

    if get_datetime().day == context.day:  
        return  
    context.day = get_datetime().day  

and this is good since it gives the .open_price value that i use for trail stop calculation (And their values, after checking several times, are same as when i run it on Daily mode, which is also good), the downside is that my .price is due to that also days .open_price but i need the days .close_price (or price at 15:59) to check if stop has been triggered and calc a new stop again of the same days .open_price.

Thanks

Hello Darell,

Here's a recent backtest of the code I posted above, and all trades are at 9:32, which is the correct behavior. Perhaps there was an actual 1 hr. delay in SPY trading year's ago, for some days?

I don't have time now, but you might look into the 'history' interface described on the help page. With the right settings (see 'Day Units' description), it will provide trailing daily bar data.

Grant

Thanks Grant, history solved the issue of getting days open price