- ago
I'm trying to code an algorithm that shorts a stock (specifically SQQQ). The strategy is to place a limit sell at 1% above each Monday's opening price. The next day, it places a 1% profit target good until that day's close. If the position profit goes below 0.5% (using that day's closing price), it changes to a breakeven exit. Also, if the position is still open at the end of the week, it exits at Friday's close.

I'm trying to model this similarly to this algorithm that does the exact opposite by going long (buying) on a stock in a similar fashion (one of the C# strategies pre-loaded in wealth lab). Below is the code that I've tried so far...

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript5 { public class MyStrategy : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) {          if (idx >= bars.Count - 1)             return;          bool isNextBarStartOfWeek = bars.DateTimes[idx + 1].DayOfWeek < bars.DateTimes[idx].DayOfWeek;          bool isNextBarLastDayOfWeek = bars.TomorrowIsLastTradingDayOfWeek(idx);          if (isNextBarStartOfWeek)          SetBackgroundColor(bars, idx + 1, WLColor.Silver.SetAlpha(32));          if (isNextBarStartOfWeek)          {             mondayOpen = bars.Open[idx + 1];             tradedThisWeek = false;          }          if (HasOpenPosition(bars, PositionType.Short))          {          double target = LastOpenPosition.EntryPrice;          if (LastOpenPosition.ProfitPctAsOf(idx) > -0.5)                target = target * 0.99;             PlaceTrade(bars, TransactionType.Buy, OrderType.Limit, target);             if (isNextBarLastDayOfWeek)             {                PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose);             }          }          else          {             if (!Double.IsNaN(mondayOpen) && !tradedThisWeek)             {                double mult = 1.01;                PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, mondayOpen * mult);                if (isNextBarLastDayOfWeek)                {                   PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose);                }             }          } }       //same bar exit public override void AssignAutoStopTargetPrices(Transaction t, double basisPrice, double executionPrice) {          //t.AutoProfitTargetPrice = executionPrice * 0.99;          tradedThisWeek = true; } //declare private variables below private double mondayOpen = Double.NaN;       bool tradedThisWeek = false; } }
0
1,324
Solved
17 Replies

Reply

Bookmark

Sort
Cone8
 ( 25.44% )
- ago
#1
First, let's quickly modify the original strategy (TQQQ long) to use ExecuteSessionOpen() so that you can run it even on Monday morning and get a signal.

One Percent a Week - ExecuteSessionOpen, TQQQ long
CODE:
   using WealthLab.Backtest;    using System;    using WealthLab.Core;    using WealthLab.Indicators;    using System.Collections.Generic;        namespace WealthScript14    {       public class MyStrategy : UserStrategyBase       {          public override void Initialize(BarHistory bars)          {          }                 public override void Execute(BarHistory bars, int idx)          {          }                    public override void ExecuteSessionOpen(BarHistory bars, int idx, double sessionOpenPrice)          {             bool NextBarIsStartOfWeek = _lastBarofWeek == idx;             bool NextBarIsLastDayOfWeek = bars.TomorrowIsLastTradingDayOfWeek(idx);             if (NextBarIsLastDayOfWeek)                _lastBarofWeek = idx + 1;             if (idx - 1 == _lastBarofWeek)                SetBackgroundColor(bars, idx, WLColor.Silver.SetAlpha(32));                          if (NextBarIsStartOfWeek)             {                mondayOpen = sessionOpenPrice;                tradedThisWeek = false;             }                          if (HasOpenPosition(bars, PositionType.Long))             {                double target = LastOpenPosition.EntryPrice;                if (LastOpenPosition.ProfitPctAsOf(idx) > -0.5)                   target = target * 1.01;                PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, target);                if (NextBarIsLastDayOfWeek)                {                   PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose);                }             }             else             {                if (!Double.IsNaN(mondayOpen) && !tradedThisWeek)                {                   double mult = 0.99;                   PlaceTrade(bars, TransactionType.Buy, OrderType.Limit, mondayOpen * mult);                   if (NextBarIsLastDayOfWeek)                   {                      PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose);                   }                }             }          }             //same bar exit     public override void AssignAutoStopTargetPrices(Transaction t, double basisPrice, double executionPrice)          {             //t.AutoProfitTargetPrice = executionPrice * 1.01;             tradedThisWeek = true;          }              //declare private variables below          private double mondayOpen = Double.NaN;          bool tradedThisWeek = false;          int _lastBarofWeek = -1;       }    }


Now, as long as I didn't make a mistake, your SQQQ idea seems to do EVEN BETTER!

One Percent a Week - ExecuteSessionOpen, SQQQ short
CODE:
   using WealthLab.Backtest;    using System;    using WealthLab.Core;    using WealthLab.Indicators;    using System.Collections.Generic;        namespace WealthScript13    {       public class MyStrategy : UserStrategyBase       {          public override void Initialize(BarHistory bars)          {          }                 public override void Execute(BarHistory bars, int idx)          {          }                    public override void ExecuteSessionOpen(BarHistory bars, int idx, double sessionOpenPrice)          {             bool NextBarIsStartOfWeek = _lastBarofWeek == idx;             bool NextBarIsLastDayOfWeek = bars.TomorrowIsLastTradingDayOfWeek(idx);             if (NextBarIsLastDayOfWeek)                _lastBarofWeek = idx + 1;             if (idx - 1 == _lastBarofWeek)                SetBackgroundColor(bars, idx, WLColor.Silver.SetAlpha(32));                          if (NextBarIsStartOfWeek)             {                mondayOpen = sessionOpenPrice;                tradedThisWeek = false;             }                          if (HasOpenPosition(bars, PositionType.Short))             {                double target = LastOpenPosition.EntryPrice;                if (LastOpenPosition.ProfitPctAsOf(idx) > -0.5)                   target = target * 0.99;                PlaceTrade(bars, TransactionType.Cover, OrderType.Limit, target);                if (NextBarIsLastDayOfWeek)                {                   PlaceTrade(bars, TransactionType.Cover, OrderType.MarketClose);                }             }             else             {                if (!Double.IsNaN(mondayOpen) && !tradedThisWeek)                {                   double mult = 1.01;                   PlaceTrade(bars, TransactionType.Short, OrderType.Limit, mondayOpen * mult);                   if (NextBarIsLastDayOfWeek)                   {                      PlaceTrade(bars, TransactionType.Cover, OrderType.MarketClose);                                        }                }             }          }             //same bar exit     public override void AssignAutoStopTargetPrices(Transaction t, double basisPrice, double executionPrice)          {             //t.AutoProfitTargetPrice = executionPrice * 0.99;             tradedThisWeek = true;          }              //declare private variables below          private double mondayOpen = Double.NaN;          bool tradedThisWeek = false;          int _lastBarofWeek = -1;       }    }
2
Cone8
 ( 25.44% )
- ago
#2
Note!
After all the reverse splits, the SQQQ series starts at over $500k/share in 2010. Increase starting equity to at least $1,000,000 to get trades near the start... the results are even better.

I'm stunned. Need to look for peeking....

Edit ..
After thinking about it, it makes sense. Short SQQQ is about the same as Long TQQQ, but also takes advantage of the "volatility decay" effect of these leveraged ETFs. Good thinking!
2
- ago
#3
Thanks for your help! The most confusing part of all of this is determining how much Interactive Brokers is going to charge for commissions and fees. Anyone know if they are the lowest cost place (other than RH & WeBull) to trade TQQQ or SQQQ?

Does anyone have experience using Alpaca as a brokerage? It appears they do not have fees for US-based ETFs. Please correct me if I'm wrong.
0
Cone8
 ( 25.44% )
- ago
#4
Most brokers do not charge trading commissions. IB still does - half penny per share, or $5 for 1000 shares, but $1 min. Since SQQQ is about half the price of TQQQ, you'll be buying twice the shares, so about twice the commissions.

If you're trading a large allocation, say $100K, a SQQQ round trip will cost about $50, or about $200/month ($2,400/year) for this strategy.

Note!
WealthLab does not currently consider splits when calculating commissions. SQQQ has many reverse splits resulting in astronomical historical prices, which would result in astronomical commission charges for per share pricing. Until that's changed, pick a typical fixed commission for your typical allocation, like $25 for $100k

How, consider interest on cash too:
https://www.interactivebrokers.com/en/index.php?f=46385

This strategy is in cash more than half the time, and depending on the "settled date" and broker policies, it may pay to pay the commissions and collect interest.
1
- ago
#5
I thought it was 1% of trade value max. So, if I was doing $10k on SQQQ, I’d be looking at $100/order (buy) + $100/order (sell) = $200/roundtrip. Is that incorrect?

You said it might be worth considering just paying the commissions because the overall strategy is profitable, but why do that when I can just avoid that cost by using another broker (e.g. alpaca). Maybe I’m unaware of an obvious advantage by using IB.
0
Cone8
 ( 25.44% )
- ago
#6
QUOTE:
I thought it was 1% of trade value max.
No need to guess - https://www.interactivebrokers.com/en/pricing/commissions-home.php. 1% max is correct, but that's a lot of commission and will only give you a break when buying big lots of low-priced stocks.

QUOTE:
So, if I was doing $10k on SQQQ, I’d be looking at $100/order (buy) + $100/order (sell) = $200/roundtrip. Is that incorrect?
Nope. $10K / $20/shr = 500 shares @ $0.005/share = $2.50 per trade.

QUOTE:
You said it might be worth considering just paying the commissions because the overall strategy is profitable, but why do that when I can just avoid that cost by using another broker (e.g. alpaca).
Let's break it down.

Assume you're holding a position half the time and the other half of the time you're in cash drawing interest at a 4.5% rate. For $10K you'd earn roughly 2.25% * 10K = $250 in interest for the year. Assume you're average commission is $2.50/trade. For this strategy, that's a maximum of $2.5 x 2 x 52 = $260 in commissions. Given those assumptions, it would cost $10 more nominally to trade with IB than a commission free broker.

So if you plan to be in cash more than half the time, IB could be a better option.

Note!
If you did not elect to be a "Trader in Securities" per IRS rules, make sure you understand the Wash Sale rule before trading this or any strategy in a non-IRA account.
1
Best Answer
- ago
#7
Maybe I missed something here. I ran this script this morning to buy 1 share to see what would happen. WL sent the order to IB and it filled TQQQ at 39.34. Under Interactive Broker's "Activity" Pane where it says "Commission", it says 0.39. I thought you were saying it should be 0.005.
0
Cone8
 ( 25.44% )
- ago
#8
Don't leave out all the parts. What else did I say about commissions?
(Minimums apply - use the link right above ^^^.)

0
- ago
#9
I wasn't intentionally leaving any parts out, man. I read your post and followed the link, including the API-ordered commission link. I appreciate the help. I'm still not understanding the IB commissions. I'm just going to switch to Alpaca.
1
- ago
#10
@Cone

If I want to use ExecuteSessionOpen() in the Strategy Monitor, do I have to set the strategy to streaming (with intraday bars) or to polling (with daily bars) and execution time at 09:30 EST?
0
Cone8
 ( 25.44% )
- ago
#11
Streaming not required.

Here's the configuration that should work. (Choose your own Position Sizing and Broker.) Wealth-Data needs to be on top. For supported symbols, Wealth-Data loads immediately with the opening price, which will be the primary market opening price, if it has traded there.


1
- ago
#12
I wish there was a way to create this strategy with the Building Blocks. I'd like to do some optimization, but I don't see a way to do that with a C#-coded strategy rather than a Building Block strategy.
0
- ago
#13
That for sure is unnecessary. Optimization can easily be added to C# coded strategies - as shown in synonymous chapter of the WL8 Help > "Optimization".
0
- ago
#14
Only unnecessary if I knew how to code. :)
0
- ago
#15
Think the code can be beefed up but what do you intend to optimize exactly?
0
- ago
#16
1) Profit target
2) Changing the ‘Sell at Market on last day of week’ to selling in N Bars, which would allow me to change the strategy from the daily chart to any time frame I want..
3) Maybe throwing in a Stop Loss other than the breakeven just in case it plummets
4) Changing the Profit Percent that it tests for before it submits the breakeven sell order.
5) Building Blocks would also facilitate Multiple Positions instead of just a single position.

I would argue the Building Blocks are a large part of WealthLab’s edge. There are a ton of softwares out there that can backtest trading strategies using code. There are very few softwares out there that use drag-and-drop Building Blocks like you guys have developed. Also, there are very few software companies that are as responsive and open to new suggestions as you guys are. Seems like people suggest a new tweak or feature and, a lot of times, those features get developed really quickly. People have a question about the software, usually gets answered same-day. I think it’s brilliant.
3
- ago
#17
I've been running this strategy manually for a couple months now. What has worked well for me is having a trailing stop loss on the model after the first day, assuming you don't hit the breakeven exit.
1

Reply

Bookmark

Sort