Often there are times in trading when we receive a signal but do not wish to act on it straight away. A classic example of this is waiting to confirm a signal before entering a position. In this post, we will take a look at how to open a window, keep it open and also close it appropriately when either the window expires or we enter a position.
Opening a window is as easy as entering a position. We just check if conditions to open it are
true. The trickier part is to keep it open and then close it properly when the window is no longer valid/needed. We shall achieve this with a ternary conditional operator (confusing term? click the link!)
This post may not be suitable for absolute beginners. It assumes a certain level of knowledge in pine script. For example, further explanation is provided only the code related to opening and closing a window. If you are completely new to pine script, check out the getting started page.
To give some context to the window, a little introduction to the strategy is required. The example code below will implement a crude breakout strategy. It will attempt to enter a position only after price has retraced by a given amount AND then bounced back to continue the uptrend/downtrend. Additionally, it needs to do this all within a certain time limit from a pivot. The reasoning for a time limit is that a quick recovery from a good size retracement might indicate strong sentiment.
To meet this objective, our code shall need to be able to:
- Identify pivots/swings in price
- Track how far price retraces from the swing/high low
- Open a window if price retraces by x% or more
- Catch a break above/below the swing high/low.
- Catch the break within a given bar limit otherwise, close the window.
Note: This code is not intended to be used as a strategy in its own right. It does not have any exit, position management or sizing strategy. It will simply flip back and forth, reversing on the opposite signal. As such, this example should just be treated as a technical exercise.
//@version=3 strategy("Opening A Window Post", overlay=true) FromYear = input(defval = 2018, title = "From Year", minval = 2017) FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12) FromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31) ToYear = input(defval = 9999, title = "To Year", minval = 2017) ToMonth = input(defval = 1, title = "To Month", minval = 1, maxval = 12) ToDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31) start = timestamp(FromYear, FromMonth, FromDay, 00, 00) // backtest start window finish = timestamp(ToYear, ToMonth, ToDay, 23, 59) // backtest finish window trade_window = time >= start and time <= finish ? true : false // create function "within window of time" left_bars = input(10, title='Pivot Detection: Left Bars') right_bars = input(3, title='Pivot Detection: Right Bars') min_retracement = input(0.5, type=float, title='Min Retracement from pivot')/100 breakout_limit = input(50, title='Breakout Window: Max bars from pivot to breakout') // Get the most recent swings and their values at that time. pivot_high = pivothigh(high, left_bars,right_bars) pivot_low = pivotlow(low, left_bars, right_bars) pivot_high_value = valuewhen(pivot_high, high[right_bars], 0) pivot_low_value = valuewhen(pivot_low, low[right_bars], 0) // We need to check whether the pivot high or low triggered first. // Because we don't want to be triggering a short window when we are looking for // a long setup. since_pivot_high = barssince(pivot_high) since_pivot_low = barssince(pivot_low) // Calc retracement from high/low // long_retracement = since_pivot_high < since_pivot_low ? (close - pivot_high_value)/pivot_high_value : na // short_retracement = since_pivot_low < since_pivot_high ? (close - pivot_low_value)/pivot_low_value : na long_retracement = since_pivot_high < since_pivot_low ? (close - pivot_high_value)/pivot_high_value : na short_retracement = since_pivot_low < since_pivot_high ? (close - pivot_low_value)/pivot_low_value : na // Open and close the windows. // Close When: // - A new position is opened // - A new pivot is detected (reset) // - Pass the breakout limit buy_window = false sell_window = false buy_window := strategy.position_size > 0 ? false : pivot_high ? false : since_pivot_high > breakout_limit ? false: long_retracement <= -min_retracement ? true : buy_window sell_window := strategy.position_size < 0 ? false : pivot_low ? false : since_pivot_low > breakout_limit ? false: short_retracement >= min_retracement ? true : sell_window // Entries longCondition = close > pivot_high_value and buy_window and trade_window if (longCondition) strategy.entry("Long", strategy.long) shortCondition = close < pivot_low_value and sell_window and trade_window if (shortCondition) strategy.entry("Short", strategy.short) plotshape(pivot_high, style=shape.arrowdown, location=location.abovebar, color=purple, title='Pivot High', offset=-right_bars) plotshape(pivot_low, style=shape.arrowup, location=location.belowbar, color=purple, title='Pivot Low', offset=-right_bars) bgcolor(buy_window and sell_window ? orange : buy_window ? lime : sell_window ? red : na, transp=80) position_color = strategy.position_size > 0 ? green : strategy.position_size < 0 ? red : silver plotshape(true, style=shape.circle, location=location.bottom, color=position_color, title='Position Indicator') // Test Plots //plot(long_retracement, style=linebr) //plot(short_retracement, color=red, style=linebr)
The key part of the code that focuses on the opening and closing of the window is contained in the following lines:
buy_window = false sell_window = false buy_window := strategy.position_size > 0 ? false : pivot_high ? false : since_pivot_high > breakout_limit ? false: long_retracement <= -min_retracement ? true : buy_window sell_window := strategy.position_size < 0 ? false : pivot_low ? false : since_pivot_low > breakout_limit ? false: short_retracement >= min_retracement ? true : sell_window
Since the example uses version 3 of pinescript, we need to declare the
false to begin with. This allows us to reference itself in the following lines e.g.
Following this, we dive into the window logic. We do this with the ternary conditional operator mentioned at the start of this post. Because a ternary conditional operator will take the value of the first condition that is true, we need to create condition checks in the correct order. In this case, we shall put anything that should close the window first.
buy_windowas an example, we first check to see if we are in a long trade. If so, we close the long window. It is no longer needed. This is something to be aware of if you look at the charts and wonder why a window is not opening. It is likely you are already in a trade. To assist with this we plot some circles at the bottom of the chart to tell you if the strategy is in a long, short or flat position.
Next, we see if there is a new pivot. If there is, we reset the window because our breakout and retracement measurement levels will change. They are always measured from the most recent pivot in this example.
The final close check we make before we consider opening the window is to check whether we are within our breakout time limit. If not, we close the window again!
Assuming none of these are true, then we check to see our retracement level (the percentage price has moved from the pivot) is met. If so we have the conditions to open the window. Following this, the window should now stay open until any of the close conditions are met. The reason for this is thanks to the value is assigned to the window when NONE of the conditions described above are met. When no conditions are met (open or close), we simply pass it the previous bar’s value e.g
buy_window. So if it was open, it stays open, if it was closed, it stays closed!
On the Charts
Once up and running, you should see something which looks like the following image.
Let us know if you have any difficulty with this post in the comments below!
Find This Post Useful?
If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny.
Backtest Rookies is a registered with Brave publisher!
Brave users can drop us a tip.
Alternatively, support us by switching to Brave using this referral link and we will receive some BAT!
Enjoying the content and thinking of subscribing to Tradingview? Support this site by clicking the referral link before you sign up!