- ago
Let's start a discussion for Buy At Close in Blocks and move post(s) from an inappropriate topic.
0
1,088
Solved
27 Replies

Reply

Bookmark

Sort
- ago
#1
Eugeni,

I didn't find the "buy at close" Rule-based strategies (Blocks), similar to WL6.
Today is it possible?
0
- ago
#2
At the moment we're not including them in Blocks but code-based strategies are enabled with MarketClose orders. Order execution at close is not something easy to achieve, especially intraday (where it just doesn't make any sense because a market order is one tick away).

WL7 doesn't show you the partial daily bar (unless you're using a streaming chart or streaming bars in Strategy Monitor). So, even the awkward workaround of running a strategy prior to the market close as in WL6 with Yahoo provider is not supported.
1
Best Answer
- ago
#3
Rodrigo,

You could make WL6 buy at close on the same bar with Rules. The backtester in WL7 works differently so this is no longer possible. Using at close orders implies a code based strategy and peeking ahead at the next bar.
1
- ago
#4
Hi Eugene,
I thought I saw something recently about how Wealth Lab has made it possible to buy at close with building block strategies, but I just looked at the newest WL7 release and couldn't find a way to do this with a strategy running on daily bars. Has this feature been added, or did I misunderstand?
0
- ago
#5
From reading your comment from last year here: https://www.wealth-lab.com/Discussion/Buy-at-Close-5640

...if I understand correctly, the best way to use building blocks to buy at close is to convert to open as a C# coded strategy, then find the line where the order type is specified and write it like this:

CODE:
_transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose, 0, 0, "Buy At Market (1)");


Looking at a chart, this appears to work correctly but I just wanted to check with you to be sure, in case I'm missing a comma or something that may be required in the newest version of WL7
0
- ago
#6
Hi Joe,

Your understanding is correct. And since it's on our FAQ, there's another topic that may come helpful in this context: "How can my strategy from Blocks enter or exit at close?"
1
- ago
#7
Great. Thanks very much for your help.
0
fred99997
 ( 14.11% )
- ago
#8
Did I understand correctly that in WL8 at the moment there is no way to make a "BuyAtClose" entry on the current bar, since "OrderType.MarketClose" is the entry at the next bar close?
0
- ago
#9
You can issue MarketClose orders on the current bar in C# code. With Blocks (using the PowerPack) you can do it on the next bar, right.
0
fred99997
 ( 14.11% )
- ago
#10
For example, let's take the code - buy on Monday at the close. But he buys on the next bar, on Tuesday at the close.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript1 { public class MyStrategy : UserStrategyBase {     public MyStrategy() : base() { StartIndex = 1; } public override void Initialize(BarHistory bars) { } public override void Execute(BarHistory bars, int idx) {          int index = idx;          Position foundPosition0 = FindOpenPosition(0);          bool condition0;          if (foundPosition0 == null)          {             condition0 = false;             {                if (bars.DateTimes[index].DayOfWeek == DayOfWeek.Monday)                                   {                      condition0 = true;                   }                             }             if (condition0)             {                _transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose, 0, 0, "Buy At Market (1)");             }          }          else          {             condition0 = false;             {                condition0 = true;             }             if (condition0)             {                Backtester.CancelationCode = 93;                ClosePosition(foundPosition0, OrderType.MarketClose, 0, "Sell At Market (1)");             }          } } public override void NewWFOInterval(BarHistory bars) {           }       private Transaction _transaction; } }
0
Cone7
 ( 35.55% )
- ago
#11
You cannot buy the Close of a bar that's already closed. Remember, Strategies run with the complete bar data. So if you check for Monday in a Daily chart, the Monday session is closed.

The rule is that all signals execute on the next bar. Change the logic to check for Friday (although "last trading day of the week" would be better in case Friday is a holiday, if only there were a rule for that).
0
fred99997
 ( 14.11% )
- ago
#12
That is, it is impossible to test the condition BuyAtClose on the current bar in WL8. This is what I wanted to know. Thank you.
1
Glitch7
 ( 83.25% )
- ago
#13
It's certainly not impossible. Here's a minimal example that buys at the close on the VERY BAR that the RSI14 crosses below 35, and then sells at the close on the VERY BAR that the RSI14 crosses above 65.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; 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) {          rsi14 = RSI.Series(bars.Close, 14);          PlotIndicator(rsi14); } //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; //because we're looking 1 bar ahead - thus no signals     if (!HasOpenPosition(bars, PositionType.Long)) {    if (rsi14[idx + 1] < 35)                PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose); } else { if (rsi14[idx + 1] > 65)                PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose); } }       //declare private variables below       private RSI rsi14; } }
0
Cone7
 ( 35.55% )
- ago
#14
Yah, impossible is a dirty word around here. However, let's add that the peeking required to accomplish this will never be possible using the building blocks. (Crud, I think I just said "impossible"!)
0
Glitch7
 ( 83.25% )
- ago
#15
I threw out the idea to add a Qualifier in Power Pack that would adjust the bar index ahead, making it possible.
0
- ago
#16
Re # 15 Threw it out, as in offered it as a work around, or threw it away as not possible?
0
- ago
#17
#13 thanks for the C# example ..That helps.
0
Cone7
 ( 35.55% )
- ago
#18
QUOTE:
I threw out the idea to add a Qualifier in Power Pack that would adjust the bar index ahead, making it possible.
Okay then. Never say "never"!
0
fred99997
 ( 14.11% )
- ago
#19
CODE:
if (rsi14[idx + 1] < 35) PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose);


It's still possible! Thanks, that's what I need :)
0
Glitch7
 ( 83.25% )
- ago
#20
Threw the idea out as in offered it up as a solution.
0
- ago
#21
I'm not looking for a "block" that will offer signals, as I realize you can't trade the past. Just one that allows me to simulate the ideas.
0
Glitch7
 ( 83.25% )
- ago
#22
The impossible is arriving in the next Power Pack release ...

0
- ago
#23
Hooorray! You guys are impossibly great!
0
Glitch7
 ( 83.25% )
- ago
#24
Sometimes it's faster to just do something than to keep talking about doing it :D
1
MIH7
- ago
#25
Be careful with this. You need to be sure that the information you use in a condition or as reference is known before.

CODE:
if (!HasOpenPosition(bars, PositionType.Long)) { if (rsi14[idx + 1] < 35) PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose); } else { if (rsi14[idx + 1] > 65) PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose); }


The example is ok because after the signal bar is closed, the rsi14[idx+1] can be calculated and the information is available for the next day. So you know the rsi for the next day before the next day starts.

When playing with the variables, tuning the code, it is essential to avoid careless mistakes like rsi14[idx+2]. If you close the signal bar, the following day is still future and cannot be applied to calculate idx+2. (in contrast to idx+1 which includes the previous bars and the signal bar after it closed)

In general, when using idx+n expressions you always need to think if the data you use is known, thinking backwards from the future index to the signal bar.

Positive example: You always know at the signal bar which days will follow (idx+1,idx+3)
CODE:
            if(bars.DateTimes[idx+1].DayOfWeek == DayOfWeek.Monday)                PlaceTrade(bars, TransactionType.Buy,OrderType.MarketClose);             if(bars.DateTimes[idx+3].DayOfWeek == DayOfWeek.Friday)                PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose);


Positive example: if the opening of tomorrow is below todays close. Although we do not know the opening price at the signal bar, we will know it just in time when the market opens to check the condition. (looking ahead in the backtest is ok, because it goes hand in hand with the live trading providing the opening price)

CODE:
            if (bars.Open[idx+1] <= bars.Close[idx] * 0.99)             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Limit,bars.Close[idx] * 0.99,-1,"LOO");             }


Negative Example: Pretty obvious that we do not know if it will be a green bar with a delta of more than 20. When we start trading tomorrow, we know the open (just in time) and the delta but the close of tomorrow will be unknown.

CODE:
            if (bars.Close[idx+1] - bars.Open[idx+1] > 20)             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Limit,bars.Close[idx] * 0.99,-1,"LOO");             }


Negative Example: using multiple conditions. Here the idx+3 is use twice which happens pretty quickly. You could use the ema20[idx+1], it can be computed when the signal bar closes. At that time you can not know something about idx+2 and idx+3 to place a signal. You can use idx+3 for the day because we know the current day at the signal bar, so we know the day relative to it.

CODE:
            if (bars.DateTimes[idx+3].DayOfWeek == DayOfWeek.Monday && ema20[idx+3] > bars.High[idx])             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Limit,bars.Close[idx] * 0.99,-1,"LOO");             }


It does not matter whether it is coded or used as a block qualifier. Working with dates after the current date can quickly lead to unwanted test results that are not correct if you accidentally look into the future. Sometimes it is very obvious and sometimes it is hidden while you are enjoying your money machine :).
1
Glitch7
 ( 83.25% )
- ago
#26
My opinion is that it's still not OK, even my example, because it's calculating an RSI based on the closing price of that bar, and then buying at the close on that VERY BAR.

Sure, you can try to put the order in a minute before the close, but what happens if the market suddenly turns around and the RSI really doesn't close at that level? So, there's a certain amount of risk here, which is why I've been so reluctant to make this available in blocks.

But the demand is quite high, people really want to model these kinds of strategies, so I can't impose my own bias on what users want to do.

Putting this in Power Pack somewhat mitigates it, since that extension is ostensibly for advanced users. And we'll document the dangers in the help as well.
0

Reply

Bookmark

Sort