- ago
So, I’ve found a way for using Advanced Pos Sizer – Spread Equity Equally for my strategy on Daily – I use Strategy window to generate signals. I can also use prioritization using weights. What I need is to get top signals out of signals generated (according to weights) and spread the equity between them only. So the strategy generate let's say 100 signal, I always need TOP 25 signals. And I need equity to be spreaded between 25, not 100.

Is there a way I can do it now?
0
474
Solved
20 Replies

Reply

Bookmark

Sort
- ago
#1
Make the strategy generate 25 signals.
0
- ago
#2
Hm. The question is how. There is a dataset (500 symbols). It can be 0-500 signals out of it per candle (Daily). I can't control the final number. I can select TOP 25, but the quantities are already set by that moment.
0
- ago
#3
Here's how, for example:
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { 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) {             PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } } public override void BacktestComplete() {          //last bar          if (Backtester.Orders.Count > 0)          {             WriteToDebugLog(string.Format("Signals: {0}", Backtester.Orders.Count));             WriteToDebugLog("Removing last signal...");             Backtester.Orders.RemoveAt(Backtester.Orders.Count - 1);             WriteToDebugLog(string.Format("Signals now: {0}", Backtester.Orders.Count));          } } } }
0
Glitch8
 ( 10.31% )
- ago
#4
Hmmm, presumably you'd want to perform some kind of sort first to get the TOP 25 Orders?

Also, the Orders property gives both Entry and Exit Signals, where Replicant wants to filter only the top 25 Entries.
0
- ago
#5
You're right, the example is missing a check for IsEntry:

CODE:
using System.Linq; ... public override void BacktestComplete() {          var s = Backtester.Orders.Where(o => o.IsEntry).ToList();          //last bar          if (s.Count > 0)          {                         WriteToDebugLog(string.Format("Signals: {0}", s.Count));             WriteToDebugLog("Removing last signal...");             Backtester.Orders.RemoveAt(s.Count - 1);             WriteToDebugLog(string.Format("Signals now: {0}", Backtester.Orders.Where(o => o.IsEntry).ToList().Count));          } }
0
Glitch8
 ( 10.31% )
- ago
#6
Here's a complete, minimal example that keeps the top 5 entries each bar and discards the rest. Also keeps all the exits.

I assign a Weight, and have to sort the Orders because the Backtester doesn't sort the next bar Signals by Weight.

Doing this process in PostExecute also lets you see the effects during the entire backtest, rather than just on the last bar of data, which is what would happen if you did this in BacktestComplete.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { public class MyStrategy : UserStrategyBase { //Initialize public override void Initialize(BarHistory bars) {          rsi = RSI.Series(bars.Close, 20); } //Execute public override void Execute(BarHistory bars, int idx) {          if (idx == bars.Count - 1)          {             Transaction t = PlaceTrade(bars, TransactionType.Buy, OrderType.Market);             t.Weight = rsi[idx];          } } //remove unwanted signals public override void PostExecute(DateTime dt, List<BarHistory> participants) {          //Keep top 5 Orders          Backtester.Orders.Sort((a, b) => a.Weight.CompareTo(b.Weight));          List<Transaction> top5 = new List<Transaction>();          foreach (Transaction t in Backtester.Orders)          {             if (t.IsEntry)                if (top5.Count < 5)                   top5.Add(t);          }          //Remove entries that are not in the Top 5          for (int n = Backtester.Orders.Count - 1; n >= 0; n--)          {             Transaction t = Backtester.Orders[n];             if (t.IsEntry && !top5.Contains(t))                Backtester.Orders.RemoveAt(n);          } } //private members private RSI rsi; } }
0
mjj38
- ago
#7
I've been doing this type of order filtering in PreExecute. Which approach do you guys think is better? and why?
0
- ago
#8
Wow! Thanks guys.

Glitch special thanks for your example – with sorting and all this stuff (as I’m not a native programmer it will help me a lot).

And being able to do this in PostExecute() is also a very good news.
Looks like I am one step to being able to use advanced pos sizers logic on Daily with Strategy Monitor. So I need to get equity value somewhere, using manually filled txt file is a good start for this. So I get the equity, I select orders needed, I recalculate quantities, I set new quantities.
0
- ago
#9
My strategy with such PostExecute() generates top 5 opening orders and much much more closing orders). What am I doing wrong?) Looks like the strategy doesn’t know I deleted those orders).
0
Glitch8
 ( 10.31% )
- ago
#10
Just because you limit the Strategy to 5 open ORDERS per bar, doesn't mean it cannot accumulate more than 5 open open positions at once, therefore perhaps giving you more than 5 exit orders. Without seeing the full Strategy (or a minimal example of the issue) I can only speculate.
0
- ago
#11
You are right.

Here are some details:

CODE:
if (isLongOpening) { double something = 0; PlaceTrade(bars, TransactionType.Buy, OrderType.Limit, bars.Low[idx] - something / 4); PlaceTrade(bars, TransactionType.Buy, OrderType.Limit, bars.Low[idx] - something); PlaceTrade(bars, TransactionType.Buy, OrderType.Limit, bars.Low[idx] - something * 2); PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose, signalName: "sellCloseMarketclose_candleCLose"); PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose, signalName: "sellCloseMarketclose_candleCLose"); PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose, signalName: "sellCloseMarketclose_candleCLose"); }
0
- ago
#12
So maybe it's because same bar exit is a question of adding new feature still?

I gave you a piece of code, I need to stop guessing)).
0
Glitch8
 ( 10.31% )
- ago
#13
your code is placing 3 buys and 3 sells per symbol. assuming you’re using the method i provided to keep the top 5 entries, it makes sense that you’re seeing 5 buys and a ton of sells. that’s what your code is doing 🤷🏼‍♂️
1
- ago
#14
So how can I operate withing the same bar without closing positions that were not opened?
0
Glitch8
 ( 10.31% )
- ago
#15
Here I changed things up so it would do just that. I'm using the "Tag" to match the exits with their corresponding entries, so this pattern could work even if you're submitting multiple entries for the same symbol with multiple exits.

But note that the exit signals will all be zero quantity. This is because you're placing a buy and a sell on the same bar. So, the sell does not yet have any pre-existing position on which to base its quantity on.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { public class MyStrategy : UserStrategyBase { //Initialize public override void Initialize(BarHistory bars) {          rsi = RSI.Series(bars.Close, 20); } //Execute public override void Execute(BarHistory bars, int idx) {          if (idx == bars.Count - 1)          {             Transaction t = PlaceTrade(bars, TransactionType.Buy, OrderType.Market);             t.Weight = rsi[idx];             t.Tag = counter;             t = PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose);             t.Tag = counter++;             t.Weight = 999; //to make sure exits are always weighted below entries          } } //remove unwanted signals public override void PostExecute(DateTime dt, List<BarHistory> participants) {          //Keep top 5 Orders          Backtester.Orders.Sort((a, b) => a.Weight.CompareTo(b.Weight));          List<object> top5 = new List<object>();          foreach (Transaction t in Backtester.Orders)          {             if (t.IsEntry)                if (top5.Count < 5)                   top5.Add(t.Tag);          }          //Remove entries and exits that are not in the Top 5          for (int n = Backtester.Orders.Count - 1; n >= 0; n--)          {             Transaction t = Backtester.Orders[n];             if (!top5.Contains(t.Tag))                Backtester.Orders.RemoveAt(n);          } } //private members private RSI rsi;       private static int counter = 0; } }
1
Best Answer
- ago
#16
Thanks, Glitch, I got the idea.
0
Cone8
 ( 8.04% )
- ago
#17
@mjj3
Re: Pre/Post Execute
If you're filtering in PreExecute, it's because you're also creating the trades there and most likely not using Execute. In the case show above, trades are created in Execute (run once for each symbol) and then the list of existing orders are managed in PostExecute, which is run once each bar after all symbols have finished Execute.
0
- ago
#18
QUOTE:
But note that the exit signals will all be zero quantity. This is because you're placing a buy and a sell on the same bar. So, the sell does not yet have any pre-existing position on which to base its quantity on.


So is it "the same bar exit" 's problem inly?

Looks like same bar exit is a little bit unnatural for WL7. I better not use one, right? I will not have this exit signals quantity issut if exiting after current bar, right?
0
Glitch8
 ( 10.31% )
- ago
#19
It shoudn't be a problem in backtesting, WL7 will match the exit to the position because it processes MarketClose orders last. But for trading, how can WL7 know what quantity to assign if the position isn't created yet? I guess we could get clever and look at the other entry orders in this case for a match, which is possible future enhancement?
0
- ago
#20
Yes, you can do it smart, I tried to do something like that in my library. I guess the main problem is how to trigger those closing orders?

Now if my strategy enters and exits on the same bar, the strategy generates entering and exiting signals at the same moment. So opening a position must trigger closing logic or like that.
0

Reply

Bookmark

Sort