Back to Community
Schedule Functions independent of time.

Hi,

If I wanted to create a schedule function that did not use time as it's decision of when to execute the code, how would I do that?
I want the schedule function to execute based on parameters I set previously, not associated with time.

My sloppy code looks like this now... having syntax errors, no updated backtest...

def initialize(context):
context.security = sid(8554)

""" The problem is this schedule function situation gets called on hours, minutes, market open, market close etc... but does not execute when the conditions of the trader function are met... it executes when the hour happens, when the minute happens, when market open or market close happens etc... it needs to execute when the event occurs, in this case the crossover, the "x", formed by the mavg_1 and mavg_2 signifying a change in the market going up or down or sideways. """

"""Also I want to be able to only execute the trader function when I do not have a position, in other words I do not want to take a position if I already have a position in the underlying security, in this case SPY. The following code is an attempt to describe that situation. """

def position(context,data):

# position = context.portfolio.positions
# if position > abs(2000000):
# return True

        #do go to the trader function below

def trader(context,data):

price_hist_2 = data.history(context.security, 'price', 9, '1m')  
mavg_1 = price_hist_2.mean()  
price_hist = data.history(context.security, 'price', 18, '1m')  
mavg_2 = price_hist.mean()  

"""Here I need to calculate the changing slope of mavg_1 and mavg_2. When the slope of mavg_1 begins to become negative after the slope has been positive, a downward moving market should be coming, and the "x". When the slope of mavg_1 becomes positive after being negative, an upward moving market should be coming, and the "x". The shift in slope of the mavg_1 being positive then negative then positive then negative and so on is where you capture your profit, you're making profit in the change in location of the "x". The crossover of the moving averages indicates the long or short market... When the lines intersect, you trade. When the lines don't intersect but are still moving with coresponding slopes indicative of the direction you are positioned for, the code executes on a small percentage of profit, continuously, to capute profit. """

slope_1 = changing slope of mavg_1  
slope_2 = changing slope of mavg_2  


cost_basis = context.portfolio.positions[context.security].cost_basis  
current_price = context.portfolio.positions[context.security].last_sale_price  
account_value = context.portfolio.portfolio_value  


if mavg_2 < mavg_1 and :  
    order_percent(context.security, .10)  
    log.info("Long")  

if mavg_2 > mavg_1:  
    order_percent(context.security, -.10)  
    log.info("Short")  

"""Here is me trying to execute the small percentage change of profit by exiting all positions at a .0625 % gain"""

elif current_price >= cost_basis * 1.0625 or current_price <= cost_basis * .9375:  
    order_percent(context.security, 0.0)  
    log.info("exiting")

If you look at the transaction details in the backtest you will see it's only trading one time a day, 2 minutes after market open, rather than through out the day whenever the crossover of the moving averages occurs.

I guess my main question is, how do you program a "Schedule Function" without using time to determine when it executes, instead of using time it would use any other indicator.

Best,
Lovis

Clone Algorithm
0
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
# Backtest ID: 58082d0af9d2fe105d55fa01
There was a runtime error.
5 responses

The maximum frequency of trading on Quantopian is a per-minute basis - you can't set event based triggers. Rather, you should check every minute whether your condition has changed, and if it has, execute your trading logic.

For your use case, you can schedule a function to run every minute of the day, and at each minute check the condition and execute the appropriate logic.

To schedule a function for every minute of the day, you can use a loop like the one below in your initialize function:

def initialize(context):  
  # For every minute available (max is 6 hours and 30 minutes)  
  total_minutes = 6*60 + 30

  for i in range(1, total_minutes):  
      # This will start at 9:31AM and will run every minute  
      schedule_function(  
      myfunc,  
        date_rules.every_day(),  
        time_rules.market_open(minutes=i),  
        True  
      )  
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 Matthew,

Thanks for your post.

Wait: You're saying you CAN NOT SET EVENT based triggers?!?! What is the point of using Quantopian if you are not allowed to set event based triggers? In order to create a profitable technical analysis based trading strategy you have to use events to figure out when to trigger (to execute, entering or exiting)... that's how it works! Even if you're a human, clicking the mouse. If I'm not trading on a culmination of events, I'm just trading randomly, and that does not make sense! The whole point of technical analysis is to use indicators to determine when events are happening, when those events happen you make a trade, if and only if the event is happening. We're trying to increase the probability of winning trades, not keep that probability at 50 50... If I can't execute based on events, in the Quantopian environment, Quantopian is useless : (

? Lovis

I built a quick algo with the above criteria, as best as I could understand from the question.

The way to do criteria based trading is to set up a function that tests the criteria as frequently as you want, daily, minutely, etc...
The key is to use if statements so that the algo only initiates a trade when the criteria is met.
You can't set up an algo in Quantopian to execute a function when the criteria are met.
You have to run the function frequently (as often as you want to test the criteria), but only allow it to act/trade when the criteria are met.
Running a scheduled function and initiating trades can easily be separated. A scheduled function can run much more frequently than it trades, in this algo it checks the criteria every minute, but trades quite infrequently (I even reduced your exiting band so that it would trade a bit more often).
Hope this helps!

In this example the first function tests every minute to check the criteria:
1. Is there a current open position, if no continue evaluation, if yes, then that is the end of the function.
2. if there is no open position, check if the sign of the slope has changed. If it has not changed, then it doesn't do anything. If it has changed then it initiates the trade.

There is a second function that tests every minute with different criteria.
1. Is there an open position, if yes then continue evaluation, if no then that is the end of the function.
2. If there is an open position, the criteria for selling the position are evaluated. If the criteria are met, it closes the position. If not it doesn't do anything.

Clone Algorithm
11
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
# Backtest ID: 58096f0e44385c105e7a2f46
There was a runtime error.

Hey Cory,

I looked over your algo and it's nearly there. There's a few things that are missing like the slope of the moving average 1 and the slope of the moving average 2, independently. There's a phenomenon that I see with the difference in moving averages. In an upward market that transitions to a downward market, the 9 changes from positive slope to negative slope, while the 18 slope gets closer and closer to 0 until the 9 moving average passes below the line of the 18 moving average. It's good that you showed the previous slope and the current slope of the combined moving averages, but you can use... if mavg_1 > mavg_2, or mavg_1 < mavg_2 to show the same thing... a positive moving market (upward market) or a negative moving market (downward market). I'm trying to show the difference between the slope of the mavg_1 and the mavg_2 and execute based on that difference. One would be positive the other would be negative and vice versa.

I wrote it what I'm trying to execute on, in the logic in the criteria test.

If we can get this algo to do what it is supposed to, this will be a very profitable strategy; making money on the difference between where the moving averages cross each other and staying out of the market when there is barely slope for either of them.

Also, I found this strategy from looking at leveraged products like /es... S & P futures.

Best regards,
Lovis

def initialize(context):
#Security to trade
context.security = sid(8554)

#Global variable to keep your test criteria  
context.moving_average_test = 0  

 # For every minute available (max is 6 hours and 30 minutes)  
total_minutes = 6*60 + 30

#Function to check the trading criteria  
for i in range(1, total_minutes):  
    # This will start at 9:31AM and will run every minute  
    schedule_function(  
    criteria_test,  
    date_rules.every_day(),  
    time_rules.market_open(minutes=i),  
    True  
  )      

def criteria_test(context, data):
#Create a global variable to store the test result for comparison
#context.moving_average_test will store the previous value for the slope for comparison
previous_slope = context.moving_average_test
print("previous slope", previous_slope)

#Obtain current data  
price_hist = data.history(context.security, 'price', 18, '1m')  
mavg_2 = price_hist.mean()  

need the previous slope and current slope of mavg_2

price_hist_2 = data.history(context.security, 'price', 9, '1m')  
mavg_1 = price_hist_2.mean()  

need the previous slope and current slope of mavg_1

current_slope = ((mavg_1 - mavg_2) / mavg_2)*1000  
print("cur_sploe", current_slope)  
#Once you have obtained your data you can decide if you want to make a trade based on that information  
#Test first criteria - Is there already an open position?  

#Determine current position  
position = abs(context.portfolio.positions_value)  

#If position is zero, then continue with the criteria test  
#If you aleady have a position, then it will not make a trade  
if position == 0:  

    #If previous slope is - and current slope is -, proceed.  
    if previous_slope < 0 and current_slope < 0:  
        #If the previous condition is met, check to see if the mavg_1 is less than mavg_2  
        if mavg_1 < mavg_2:  
            #if previous_slope_mavg_1 <= -.75 and current_slope_mavg_1 >= .75:  
                #if current_slope_mavg_2 >= -.02 but < 0, and current_slope_mavg_2 <= .02 but > 0:  
                    #order(context.security, 100)  
                    #log.info("Buy")  

    #If previous slope is + and the current is +, proceed.  
    if previous_slope > 0 and current_slope > 0:  
        #If the previous condition is met, check to see if mavg_1 is greater than mavg_2, long.  
        if mavg_1 > mavg_2:  
            #if previous_slope_mavg_2 >= .75 and the current_slope_mavg_2 is <= -.75:  
                #if previous_slope_mavg_1 > .02 but < 0, and current_slope_mavg_2 < .02 but > 0:  
                    #order(context.security, -100)  
                    #log.info("short")

context.moving_average_test = current_slope  

if position != 0:  

    if previous_slope < 0 and current_slope > 0:  
        order_percent(context.security, 100)  
        log.info("exit at slope change from neg to pos")  
        print("position", position)  

    if previous_slope > 0 and current_slope < 0:  
        order_percent(context.security, -100)  
        log.info("exit at slope change from pos to neg")  
        print("position", position)  

Hi,

The biggest problem I see with the algo when backtesting it and looking at the logs, it does not do exactly what it is supposed to. I've been struggling with this problem and this algo for a quite some time now. It'll go long or short first, but when the slope changed it does not take the correct position, rather any position at all. For example the slope will be positive, it will go long, then when the slope changed back to negative it will not have exited and not go short. What's up with this and why isn't it trading correctly?
Does anyone have any hunches as to why this is?

Regards,
Lovis