- ago
If my strategy is long a position, and I use PlaceOrder to sell the position at market, and then immediately set the resulting transaction's Quantity property to a particular value then WL8 seems to ignore the Quantity property value and always utilizes the Trading preferences settings. I've tried the various combinations of trading preferences "Reduce size of exit order to match position quantity" and "Always set exit order quantity to full position quantity" to no avail.

My requirement is to sell a specific share quantity.

User Cone, in another thread, gave an example, except it was for a buy. Hence, in my code I'm doing the following for the sell:

CODE:
Transaction t = PlaceTrade(bars, TransactionType.Sell, OrderType.Market); t.Quantity = (some_calculated_quantity);

Perhaps I'm overlooking a setting? The issue occurs when running the strategy in the strategy monitor.
0
1,103
Solved
26 Replies

Reply

Bookmark

Sort
Glitch8
 ( 10.62% )
- ago
#1
Maybe you have some portfolio sync options enabled in the Trading Preferences, several of these will override the quantity of a sell order based on a broker's position or account size.
0
Glitch8
 ( 10.62% )
- ago
#2
I tried this simple test strategy in the SM, and in this case it's using the quantity of 10 that I assigned to the Transaction object. Maybe see if it works for you here and then we can see what the differences are.

CODE:
using WealthLab.Backtest; using WealthLab.Core; 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 - 50)             PlaceTrade(bars, TransactionType.Buy, OrderType.Market);          if (idx == bars.Count - 1)          {             Transaction t = PlaceTrade(bars, TransactionType.Sell, OrderType.Market);             t.Quantity = 10;          } } } }


0
- ago
#3
I have tried the various combinations of the Portfolio Sync trading preferences with no impact. The strategy, when run in the strategy monitor, always respects the Portfolio Sync settings and does utilize the Transaction.Quantity property. By the way, I'm using the dummy broker.
0
Glitch8
 ( 10.62% )
- ago
#4
Can you try my sample strategy and see if you are getting the expected sell of 10 quantity?
0
Cone8
 ( 4.98% )
- ago
#5
QUOTE:
I have tried the various combinations of the Portfolio Sync trading preferences with no impact. The strategy, when run in the strategy monitor, always respects the Portfolio Sync settings and does utilize the Transaction.Quantity property.
This is confusing. Did you mean "does not utilize"?

Let's be clear. If you want to use the t.Quantity, Reduce Size... and Always set... Portfolio Sync options should not be selected.
1
- ago
#6
NOTE: for this to work for a BUY, the Strategy Setting "Position Size" should be set to "Fixed Value". If it is set to "Percent of Equity" AND "Basis Price" is set to "Market Open Next Bar" it will not work. It will use the % Equity and show the signal in $$ instead of number of shares. Wasn't sure if this had been noted before.
0
Cone8
 ( 4.98% )
- ago
#7
Actually, it does work for that case too. The Signal will display the $dollar size amount (see Strategy Settings > Basis Price > Important Notes for Market Open Basis), but when you Place the signal with the broker, the share size you set in the strategy will be used - just like in the backtest.

For entry orders (Buy/Short), assigning a Transaction.Quantity in the Strategy always overrides the Position Sizer. It's just that for a Market Open Basis you won't see that size until you place the order with the broker.

For exit orders (Sell/Cover), assigning a Transaction.Quantity in the Strategy can sell any number of shares of the Position, but WealthLab can change the shares based on the .Portfolio Sync preferences when you Stage/Place the order.
0
- ago
#8
Thanks @Cone for the clarification. As you guessed I was relying on the misleading $$ amount for the signal. I didn't try a trade.
0
Cone8
 ( 4.98% )
- ago
#9
misleading?... I know what you mean, but keep in mind that you selected a basis price (tomorrow's open) that doesn't exist in causal reality. The idea of the feature is to give you the amount of cash available for the trade. This is a convenience for trading mutual funds, for example. There's no way to convert dollars into shares for a non-existent price, and that's why the actual basis for shares is always the last close for market orders.
0
- ago
#10
QUOTE:
Actually, it does work for that case too. The Signal will display the $dollar size amount (see Strategy Settings > Basis Price > Important Notes for Market Open Basis), but when you Place the signal with the broker, the share size you set in the strategy will be used - just like in the backtest.
(Post #7)

it appears this is not true as I have just found out, at least with the current WL release. My strategy calculates a different $$ allocation for each symbol being traded and then converts to quantity based on current symbol price. I found that if the Position Sizer is set to Percent of Equity, it will ignore the code pattern
CODE:
transaction.Quantity = tQty
and allocate equal $$ to all symbols based on the Percent of Equity Position SIzer value, ignoring the individual quantity override.
0
Glitch8
 ( 10.62% )
- ago
#12
Hmmm, OK let's test this out. I created this strategy that places one trade.

CODE:
public override void Execute(BarHistory bars, int idx) {          if (idx == bars.Count - 20)             PlaceTrade(bars, TransactionType.Buy, OrderType.Market);          if (idx == bars.Count - 2)             PlaceTrade(bars, TransactionType.Sell, OrderType.Market); }


With 100% of equity sizing, on SPY, my trade is assigned a quantity of 194.

If I modify the code like this,

CODE:
public override void Execute(BarHistory bars, int idx) {          if (idx == bars.Count - 20)          {             Transaction t = PlaceTrade(bars, TransactionType.Buy, OrderType.Market);             t.Quantity = 123;          }          if (idx == bars.Count - 2)             PlaceTrade(bars, TransactionType.Sell, OrderType.Market); }


Then the trade is assigned a quantity of 123 instead of 194.

0
- ago
#14
Are you running this test in the SM? What tab are you displaying?

I retested with quantity = 1 and equity % = 30

Quantity = 1





Equity % = 30





Note that for the buy of TNA, the correct $ amt is $8,444 (qty x current price). WL ignores the quantity set in code, leading to an incorrect sizing (which is not 30% of equity either).
0
Glitch8
 ( 10.62% )
- ago
#15
You're starting to bring up two different issues now.

1) When I change the position sizing to 1 share in the Strategy Monitor, I get a trade for 1 share as expected.



0
Glitch8
 ( 10.62% )
- ago
#16
For the second issue, I cannot see your code so it would not be fair to comment.
0
- ago
#17
I hope these snippets show the relevant flow. Note that I am setting quantity in PostExecute() by modifying the quantities in Backtester.Orders. Note also that (to be repetitive) this behavior only shows up when strategy is run in SM, not SW.

CODE:
      public override void PostExecute(DateTime dt, List<BarHistory> participants)       {          foreach (BarHistory bh in participants)          {             ...             ...             ...             ...             SetBuyQuantitiesFromAllocation();             ...             ...             ...             ...          }          if (activeAcctNum != null)          {             BrokerAccount brokerAccount = GetBrokerAccount(activeAcctNum);             if (brokerAccount != null)             {                                acctVal = brokerAccount.AccountValue;                acctCash = GetAccountCash(brokerAccount, acctIsIb);                double buyPwr = brokerAccount.BuyingPower;                acctIsIb = brokerAccount.AccountID.Substring(0, 1) == "U"                   || brokerAccount.AccountID.Substring(0, 1) == "D";                WriteToDebugLog("Broker Account is " + brokerAccount, false);                //dev33 - MT                WriteToDebugLog("Account value = " + acctVal.ToString("N2"), false);                WriteToDebugLog("Account cash = " + acctCash.ToString("N2"), false);                WriteToDebugLog("Account buying power = " + buyPwr.ToString("N2") + "\n", false);                //dev33 - MT test                WLHost.Instance.AddLogItem("Fid Broker Acct Value", acctVal.ToString("N2"), WLColor.Green); }             else WriteToDebugLog("Broker Account is null", false);          }          else WriteToDebugLog("Active Account Number is null", false);          void SetBuyQuantitiesFromAllocation()          {             //reqCash = 0;             if (debugOption) WriteToDebugLog("\nPending Purchases", false);             if (debugOption) WriteToDebugLog("Sym\tQty\tValue", false);             foreach (Transaction t in Backtester.Orders)             {                if (t.TransactionType == TransactionType.Buy)                {                   //calculate buy quantity                   int qAlloc = GetBuyQuantity(t.Symbol);                   t.Quantity = qAlloc;                   if(debugOption)                      WriteToDebugLog(t.Symbol + "\t" + t.TransactionType + "\t" + t.Quantity, false);                }             }          }          int GetBuyQuantity(string sym)          {             int qAlloc;             string Index;             double bPrice;             bPrice = GetSnapPrice(sym);             Index = li.LevSymToIndex(sym);             double alloc = indexKVolList.Where(i => i.index == Index).Select(i => i.Kw).FirstOrDefault();             qAlloc = (int)((acctVal * alloc / 100) / bPrice);             return qAlloc;          }


ADDENDUM
Some background so the code might make more sense. This strategy buy / sells leveraged ETF's based on signals for the underlyings (market index symbols) and uses an algorithm to size the positions and also to signal reallocation of the portfolio, similar to (but not exactly) a rotation strategy.

0
Glitch8
 ( 10.62% )
- ago
#18
Let's boil this down to the simplest form. Here's a Strategy that adjusts the Transaction Quantity in PostExecute to 234.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; 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 PostExecute(DateTime dt, List<BarHistory> participants) {    if (Backtester.Orders.Count > 0)             Backtester.Orders[0].Quantity = 234; } //declare private variables below } }


When I run this in the Strategy Monitor, the signal is for 234 shares, as expected.

0
Best Answer
- ago
#19
Did you set the sizing for the position in the SM for % of Equity?
0
Glitch8
 ( 10.62% )
- ago
#20
Yes

0
- ago
#21
Here's what I get when I run your test code with a 4 symbol DataSet with sizing for % Equity and Quantity. Starting Equity is $100,000.

Something is clearly broken on my side, but it's not my code.




0
Glitch8
 ( 10.62% )
- ago
#22
Make sure your Trading Preference Use Broker Account Value is not enabled.
0
- ago
#23
It was enabled (not sure why that matters). I disabled it and get a different result. Equity % is correct but Shares is whacked.



0
Glitch8
 ( 10.62% )
- ago
#24
>>not sure why that matters<<

It matters because that is processed after the strategy executes. If you are assigning a quantity manually, you'll need to turn off that option.

My code is assigning a Quantity to only the FIRST Transaction in the list. So, the result is correct, the first Transaction Quantity is adjusted to 234.

The code is in Post #18
0
- ago
#25
I see. I missed that only applied to first symbol. Let me think about whether I must run strategy with Broker Equity option enabled. In the meantime, I will use quantity sizing instead of Equity sizing. It seems to calculate quantity correctly with this setting.

Thanks for all your effort to unravel this!
0
- ago
#26
QUOTE:
If you are assigning a quantity manually, you'll need to turn off that option.

Post #24

The problem is I have multiple strategies, some of which make use this option, and others that don't. It would be helpful if Trading Preferences like these are not globally applied but could be enabled / disabled by individual strategy.
0

Reply

Bookmark

Sort