Back to Posts
Listen to Thread

How could I implement a "Take Profit" and a "Stop Loss" in an algorithm for each trade?

How could I set a time period within which to trade (for example only allowing a trade to be placed in the London session)? - I've been getting a headache trying to do this one myself with datetime lol

Hello Adam,

There are a couple relevant algorithms from me in the thread https://www.quantopian.com/posts/simply-buy which should give you an idea on how to sell once a stock reaches a relative price limit to take a profit. The code can be modified to sell if the relative stock price drops below a limit. Let me know if you have questions/comments...no guarantee that everything is correct. When I get the chance, I can test the code again and then post it here.

Regarding trading within a specific time period, it all depends on what you need to do. For example, do you just want to trade once a day at a specified time? Or are you wanting to trade continuously within specified hours of the day?

Hi Grant,

Thanks for replying =)

I would be interested in trading within specified hours of the day (just experimenting, although from dabbling in forex I normally found it a personal bad idea to trade eur/usd outside 7am to 2pm London time, and - I don't know - but I assume different stocks have their better times of the day to trade too :P).

Adam,

Python is new to me, so perhaps an expert can chime in. I expect that one can do something like (syntax may not be correct):

if current_hour in list_of_trading_hours:  
    #code goes here

I have some examples in algorithms of how to obtain the current_hour, so let me know if you have trouble with that part.

Note that with the logic above, the backtester will still iterate over every minute (or day in the daily backtester) of the available tic data. It just won't execute the code under the if-statement if the condition is not met. One implication is that if you submit an order on the last minute of your desired trading window, it will be fulfilled outside the window (in the next tic for that security). This is a subtle point about the backtester, but order submission and order fulfillment do not occur simultaneously.

Can I clarify something? I think I may have confused myself (I blame forex ;P)

When we sell in these algorithms, can we only sell stock we have already bought? I might have got confused by the difference with the forex and stock markets (when I'm trading forex I'm trading pairs, and either go long on a position or short it lol)

*I'm pretty new to python too... Will keep trying and post if I come up with something though =)

In retrospect I would also be curious how to trade at a specified time (to limit the number of trades an algorithm makes to one a day)

You can sell stock that you don't own by placing an order with a negative number of shares.

But would you not need to buy the stock first to fulfill the sell order? :confused:

Hello Adam,

I don't have time right now to work up an example, but here's one with both long and short positions:

https://www.quantopian.com/posts/this-weeks-concept-trading-on-max-and-min

If you search the forum using the keyword "short" you'll find more. Note that there is a search box in the upper right area of the community forum page.

Grant

Adam,

Here's a sample algorithm that should show you how to buy/sell at specific dates and times. I'll need to dig through other ones to illustrate how to, for example, submit an order only at 10 am every trading day. It's a straightforward if-then statement...you just need to extract the current hour from the current datetime of the security tic of the backtest.

Grant

Clone Algorithm
9
Loading...
Backtest from to with initial capital ( data)
Cumulative performance:
Algorithm Benchmark
Custom data:
Week
Month
All
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Information Ratio
--
Benchmark Returns
--
Volatility
--
Max Drawdown
--
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
Information Ratio 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
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Thanks Grant for your help =)

One of the things confusing me about datetime is the use of a date before the time... Does that mean you can't make the algorithm run on a recurring basis, or is there a way to update the date of the datetime?

Hi Adam,

The backtester runs over every historical tic of every security that you specify. If you run the full/minutely backtester, you have access to every minute of trade data for up to 10 securities simultaneously. There is also access to a trailing window of data via the batch transform (see the help page).

Via the algorithm, you can access the datetime of every tic of every security in your backtest.

So it all depends on what you want to do. Perhaps you can provide more details. Do you want to submit a set of orders every day, once per day (e.g. upon market open)? Once I understand what you need to do, I (or somebody else) can work up an example for you to tinker with.

Just a note of caution...the backtester is designed to execute only when there is a tic in the historical database for a given security. So, for highly liquid securities (e.g. SPY), restricting order submission to a specific time (e.g. 10:00 am) will work. However, if the security does not trade every minute, some days your order might not get submitted (e.g. no tic for the security at 10:00 am would mean that your order would not get submitted). So, a more robust way to handle this is to write logic so that a flag gets set once an order gets submitted on a given day. The flag can then be used to block further orders on that day, so that you aren't buying at every minute.

Also note that once an order for a security gets submitted, it will be fulfilled in the next tic for that security (which, for a liquid security, will be the next minute of the backtest).

I tried the following code modified from things I found on the internet

import datetime

def initialize(context):  
  context.stock = sid(24)

def handle_data(context, data):  
  d = datetime.datetime.now()  
  if d.isoweekday in range(1, 5) and d.hour == 9 and d.minute == 30:  
    order(context.stock,+1)  

but found there was no trades, so out of curiosity I made a function to print d.hour, to find that every hour was counted as "1" (which is the local time on my computer...)

Hmmm... Backtester constraint?

Perhaps datetime using live time instead of the backtesters virtual time is why your algorithm above didn''t make any trades either...

Scratch that last comment lol I now notice your algo did make trades :P

Adam,

Here are some lines of code that may help you:

context.stocks = [sid(21090),sid(698),sid(6872),sid(4415),sid(6119),sid(8229),sid(39778),sid(14328),sid(630),sid(4313)]

event_hour = data[context.stocks[0]].datetime.hour
event_minute = data[context.stocks[0]].datetime.minute

The list of securities goes in def initialize(context): and you can extract the hour and minute of the event in def handle_data(context, data):. Note that the hour and minute correspond to the first security in the list, sid(21090). The backtester "loop" runs over events, not days/minutes, so datetime is associated with a specific historical event (in this case, trade data for sid(21090), Target Corporation). Note, however, that the batch transform patches up holes in the tic data, as described on the help page...a shortcoming that will eventually be fixed, I'm told.

If you want to get a feel for how the backtester handles tics and time, try these securities over various backtest periods:

context.stocks = [sid(41290),sid(41425),sid(39479),sid(33972),sid(41159)]

They don't trade every minute that the market is open.

I tried the above code, but things still seem to be using local realtime rather than backtester time :/

Adam,

Here's an example...hopefully it will start to clear things up for you. Be sure to have a look at the log output of the full/minutely backtest.

Grant

Clone Algorithm
4
Loading...
Backtest from to with initial capital ( data)
Cumulative performance:
Algorithm Benchmark
Custom data:
Week
Month
All
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Information Ratio
--
Benchmark Returns
--
Volatility
--
Max Drawdown
--
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
Information Ratio 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
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Got that to work =)

For a range of hours is there a better way than below?

def initialize(context):  
  context.stock = sid(24)  
  context.open_hours = [15,16,17,18] # change to 0 for quick/daily backtest

def handle_data(context, data):  
  event_hour = data[context.stock].datetime.hour  
  event_minute = data[context.stock].datetime.minute  
  if event_hour == context.open_hours[0]:  
    order(context.stock,+10)  
    log.info('bought')  
  if event_hour == context.open_hours[1]:  
    order(context.stock,+10)  
    log.info('bought')  
  if event_hour == context.open_hours[2]:  
    order(context.stock,+10)  
    log.info('bought')  
  if event_hour == context.open_hours[3]:  
    order(context.stock,+10)  
    log.info('bought')  

Adam,

See attached for a simpler approach. There is probably a more elegant solution in Python using a built-in functionality, timedelta. I think that what you are needing to do is start trading at a specified time and then stop after a specified number of hours have elapsed. In the end, though, it might take additional lines of code to implement the timedelta approach and it would give you less control. For example, with the if event_hour in context.open_hours: approach, you could easily stop trading for an hour in the middle of the day and then resume for the remainder of the day just by modifying context.open_hours.

Clone Algorithm
4
Loading...
Backtest from to with initial capital ( data)
Cumulative performance:
Algorithm Benchmark
Custom data:
Week
Month
All
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Information Ratio
--
Benchmark Returns
--
Volatility
--
Max Drawdown
--
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
Information Ratio 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
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Hey Adam,

By the way, if you haven't already figured it out, the Quantopian backtester by design will not accept and fulfill orders outside of trading hours for a given security (although there is a trick to emulate queuing up orders overnight, for example...but perhaps a topic for new discussion thread). So if you want your algorithm to trade only when the market is open, you don't need to put in any if-statements to avoid submitting orders when the market is closed.

Thanks for the help =)

I did notice that - for example it doesn't trade on the 1 Jan - but queuing up orders sounds like a fun experiment anyway lol

Just had the interesting thought that you could use this to run a more prolonged check on market direction, such as if there was an hourly if statement checking market direction - where each hour would set it's own "going_up = True" in a bullish market and "going_up = False" in a bearish market - and the algorithm would only place a long order upon 5 consecutive bullish hours (or a short at 5 consecutive bears).

Yeah...should be able to do something like that. It's very flexible. I think you could also do a linear fit to a trailing window of data and then find the slope, which would tell you whether the trend is upward or downward. Let me know if you decide to try this and I'll provide an example of how to get the trailing tic data into a numpy vector/array using the batch transform. The batch transform is kinda slow, but so as long as you only need the data hourly or a few times a day, it'll be no problem. If you need a trailing window updated minutely, the batch transform kinda bogs down the backtester (some fixes are in the works).

I might try that later (got an exam first lol).

Been planning to try something with batch transforms (they were actually mentioned by the person who sent me to this website in the first place, as I'd been interested in correlations as well as algo trading).

Hi Adam - not sure if you cleared up your confusion with respect to selling stock that you don't already own. As Grant has pointed out above this, is totally possible in Quantopian. This follows 'real-life' equity trading where it is possible to sell a stock you do not already. The practice is called 'shorting' and effectively involves borrowing/renting the stock from someone who does own it (and paying them a rental fee for the privilege). You then use this borrowed stock to make good the delivery on the 'sell' you are making.

Dan gives some excellent Khan Academy links that explain the process really well in this post here.

Log in to reply to this thread.
Not a member? Sign up!