Back to Community
Help I know it's possible, buy IPO first day, stop loss at 3% or exit at 50% profit

There has got to be a way to have my algo
1) find expected IPO trade day, on that day check every 15mins to see if Ask/Bid is above $1.00.
2) buy the IPO with preset capital
3) every morning check if it's down 3%, if down then exit position
4) if it's up then stay in position until it hits a user defined ceiling (i like 30%) then exit.
5) every morning rinse and repeat.

I've done a bunch of spreadsheet work to verify the theory, buy every IPO every month and sell the next morning (avoid PDT) and you will make a profit. Now I want/need to transfer this theory into an automated system. I have mild java skills and python is similar enough for me to say I'm not a complete ignoramus but learning quant algo python is a large uphill climb and any help would be appreciated.

  • there are a huge amount of websites that monitor upcoming IPOs i have even successfully imported a websites table into googlesheets. I successfully got googlesheets to text my phone when one of those table cells displays (example:"05/10/17 Priced") which says the IPO will begin trading that day but nobody knows exactly what time it will trade. So how do i incorporate this minor success into a backtest algo.

welcome to my algo journey start, respect to those that have gone before

11 responses

Ok so 2 hours in and I've successfully pulled in the csv file I discussed above and ran a backtest with no errors. Another thing I'm really big about is logs. So i've fetched the data, logged it (proof it was retrieved), and backtested.
Now I need to parse the data more precisely, or figure out how to grab the info i want/need and act on it. The column 'Expected to Trade' is what we need to watch, when it labels the date and appends it Priced. It would look like this ' 07/04/17 Priced'. that what i need the algo to watch for and when it sees it to go to the broker and start watching for trading activity. I may get this thread locked from being annoying, i hope not. i really want this, plz help

Clone Algorithm
8
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: 595bad4023b1394dd29f020c
There was a runtime error.

Does your trading thesis work only if you buy the IPO immediately when it kicks off at the open on day 1? I'm not sure I understand why having a text alert isn't enough. There aren't that many IPOs in a day. Be alerted to one being "priced" today, then set up a stock price alert on your broker's website, and just wait to be notified of actual trading action via another text. Why need an algorithm?

@Kenneth Kwan
Valid questions Ken. This endeavor has taken many turns in my effort to implement the most profitable IPO approach. Nobody knows exactly what time it will trade so you/I literally have to sit in front of the computer with the stock symbol in a watchlist and wait for ticks to start. The earliest I've seen an IPO begin active trading is 15mins after open, the longest was 3.5 hrs later. I do have to work a day job although I control my hours I still can't be in front of the computer all the time. Another variable is sometimes IPO's are delayed a day or more.
I've searched and tried many brokers that I can set up an alert prior to trading BUT an IPO is technically not an active symbol, so when you try to enter the symbol it says "Invalid Symbol". That's what got me started on this whole downward spiral. The above website that monitors 'Priced" IPOs just tells you it should be active, but you still have to wait in front of a computer until you can put it into your watchlist.
So To answer the first question is the faster you can enter the position the better of course. Missing entry by an hour may cost you significantly in profits or even cause a loss as the price fluctuations stop and it balances causing you to buy high and sell low. I succeed nearly every time if I'm sitting there and immediately buy.

SO now I'm going in a new direction, automated purchasing and I think I found a good candidate (see attached backtest)
The backtest successfully waited and then purchase on the 25th of may, the historical date the IPO released. So now my workaround would be to just change the symbol in the code the day before the expected IPO release. Abracadabra I can go to work and the IPO will be purchased. That's the hope at least. Now for tweaking and live testing.

Clone Algorithm
8
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: 595e325a0abab1522f1c3207
There was a runtime error.

Next iteration logged for future copy/paste and further development
*Monitors and enters position correctly
*Record function corrected

Things to fix
*Get working stop loss exit
*fix the damn log.info() stuff. I can't stand not having logs!

Ok so we're now in a different direction that's far more manageable. I'll just have to change the symbol the day before an IPO is expected to start trading.
EDIT:The equity being used to test is OVID as it had significant losses easily tested.So far all data matches.

Clone Algorithm
15
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: 595ef04cc6459852751c997d
There was a runtime error.

Hey Geremy,

I have recently implemented a stoploss and it works pretty well. Here is something you could try:

  • schedule this function with the same frequency you rebalance, so I guess in your case daily in the morning

  • Define percentage of loss, in your case I suppose 3:

PORTFOLIO_STOP_LOSS = 3 # percentage of loss allowed, play around to optimize  
TRAILING_STOP_LOSS = True # To update the 'buy' price if stock exceeds it  
  • define cost_basis in intitialize and add the buy price of your positions when ordering:
    in initialize:
context.cost_basis = {}  

when ordering:

 order_target_percent(security, long_weight)  
                    if security not in context.cost_basis:  
                        context.cost_basis[security] = data.current(security, 'price')  
  • Add this function:

def stoploss(context, data):  
    #Exit position[s] when position or portfolio stop loss is reached

    positions = context.portfolio.positions

    if TRAILING_STOP_LOSS:  
        # update cost basis if price goes up  
        for sec in positions:  
            if sec in context.cost_basis and \  
               data.current(sec, 'price') > context.cost_basis[sec]:  
                context.cost_basis[sec] = data.current(sec, 'price')

    # do nothing if there are open orders or no active positions  
    if not positions:  
        return


    if POSITION_STOP_LOSS:  
        for sec, pos in positions.iteritems():  
            if sec in context.cost_basis:  
                cost_basis = context.cost_basis[sec]  
                pnl = (data.current(sec, 'price') - cost_basis) / cost_basis * 100  
                if pnl < 0 and -pnl > POSITION_STOP_LOSS:  
                    log.info('position stop loss: %s, P&L: %.2f' % (pos.sid.symbol, pnl))  
                    _order(pos.sid, 0, context)  
                    if pos.sid in context.cost_basis:  
                        context.cost_basis.pop(pos.sid)  

Note that the code is not originally mine, I have just adapted it to work with one of my algo's and it tremendously improves returns and reduces drawdown.

Thank you Jens, you sent me in the right direction.
Next iteration logged for future copy/paste and further development
*Enters position late for some reason. OVID began trading on 5/5/17 at some time during that day but algo enters on the 8th (the following monday)
*Stop loss works (yay)
Things to fix
*fix entry timing
1)use custom schedule_function? if someone could look at the coding i could use the help on this one.
2)The entry function must only run ONE TIME. buy the stock and then never try to buy it again.
*fix schedulers
*fix log -can someone help me correctly log an order? i've tried numerous times and I just can't get a properly formatted order logged

Clone Algorithm
15
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: 595f8aec2879e9522ab5bd53
There was a runtime error.

I have found some activity i don't like in the backtest transactions details. something doesn't seem right can someone look into this for me and tell me what's going on? How do i program the algo to only do one buy? according to this backtest i just spent an asston on commissions for 7 separate trades. then 6 sells, Real Life doesn't act like this :/

For some reason this iteration correctly buys the full 71 shares at 9:41AM on May 5. this is what i need but I'm having trouble merging the two codes. The one that exits at stop loss and this one.
EDIT:I think i know that one code is using [symbol('OVID')] and the other is not which screws up everything because one is cycling through a list and the other is just using(expecting) one asset.

Clone Algorithm
1
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: 596005a573d33d52f8b28ae9
There was a runtime error.

New iteration
using a context.timer to avoid buying the stock again(will be useful for multiple stocks and avoiding buy codes for each stock)
still unable to get a proper exit utilizing data.history(stk, 'high', 252, '1d') which would work really well with IPO's. IPO's generally go up for the first day or two sometimes much longer. So what we want is to use the HIGH price as our base to exit.
I want it to sell once the stock hits a high and begins to drop a certain percentage but I'm getting corrupt activity.
*fix exit
ADDED: better recording
better log.info code

Clone Algorithm
3
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: 59610fec3a412e577442e742
There was a runtime error.

test
Next iteration logged for future copy/paste and further development. Has a lot of coding i want but goes corrupt at 6% returns.
*Fix -i don't know what's broken the backtest says it sold at 6% but then graph doesn't update. maybe some bug

Clone Algorithm
2
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: 596218354e2c3751e9ea0890
There was a runtime error.

SUCCESS! I had to go back to an older, more basic coding but I've finally got it to
1)monitor every 30 minutes until the stock can be bought
2)buy full amount of shares-not 2 shares,5shares,etc( i hope this holds in my other stock symbol testing)
3)every 30 minutes check for gains
4)if gains hits a set amount (8.5% in this iteration) then sell everything
5)record all the goodies
*fix
i want logs, more logs, logs with an overabundance of detail

Clone Algorithm
15
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: 5962277021f0506b5d023eac
There was a runtime error.