Intraday time window backtesting Pine script - testing

How can you backtest your strategy only within a specific time window on an intraday basis?
I'm testing a combination of MACD and BB on a timeframe of 1 minute. But I only want to enter a long or short position at UTC+2 between 10am and 1430 and 1600 and 2000 for CME listed futures.
I want to exit any open position within X minutes outside of the entry window.
In a simplified way, my code currently looks like below:
longentry = crossover(macd, signal) and src <= lowerBB
shortentry = crossunder(macd, signal) and src >= upperBB
longclose = crossunder(src, lowerBB)
shortclose = crossover(src, upperBB)
if longentry
strategy.entry("id=LONG", strategy.long)
if shortentry
strategy.entry("id=SHORT", strategy.short)
Your assistance would be much appreciated.
Thanks and best regards,
Bas

Here is an example script of how to set up a time window for your trades. Below you will see a couple inputs. One is a bool to turn our filter on and off and the other is the time we would like to trade between. We then create a condition that checks if we are outside of our time, and that we have filter trades checked off. Then we add that to our entry with "and not timeFilter". I added some background color so you can see where exemption lies.
//#version=4
strategy("My Strategy", overlay=true, margin_long=100, margin_short=100)
useTimeFilter = input(false, "Use Time Session Filter", input.bool, group="Filters")
timeSession = input("0000-0300", "Time Session To Trade In", input.session, group="Filters")
timeFilter = na(time(timeframe.period, timeSession + ":1234567", "GMT-2")) == true and useTimeFilter
longentry = crossover(sma(close, 14), sma(close, 28))
shortentry = crossunder(sma(close, 14), sma(close, 28))
longclose = crossunder(sma(close, 14), sma(close, 28))
shortclose = crossover(sma(close, 14), sma(close, 28))
if longentry and not timeFilter
strategy.entry("LONG", strategy.long)
if longclose and not timeFilter
strategy.entry("SHORT", strategy.short)
strategy.close("LONG", when=longclose, comment="Long Close")
strategy.close("SHORT", when=shortclose, comment="Short Close")
bgcolor(timeFilter ? color.red : na)
All the best,
Bjorgum

Related

How to make global variable in pinescript(Tradingview)

I am working on creating a trend indicator in tradingview to track which way the trend is going. Specifically, I want a variable that will stay the same over days, but when a certain condition is met it will change. It seems like it should be simple to do, but everytime I try I get thrown into a never ending loop and I can't seem to wrap my head around it. Variable "Trend"
///Condition
pos = close > open
neg = close < open
pos_cond = pos and pos[1]
neg_cond = neg and neg[1]
///Variables to keep track of trend
Trend = iff(***pos_cond or neg_cond not met***, Trend[1], Trend + real_trend)
trend_change_neg = iff(pos_cond, 1, 0)
trend_change_pos = iff(neg_cond, -1, 0)
real_trend = trend_change_neg + trend_change_pos
Trend = iff(Trend > 2, 2, iff(Trend < -2, -2, Trend))
/////////plots
plotshape(Trend > 0, color = color.green, location = location.top, style = shape.square, title="TrendLong")
plotshape( Trend == 0, color = color.yellow, location = location.top, style = shape.square, title = "TrendNeutral")
plotshape( Trend < 0, color = color.red, location = location.top, style = shape.square, title = "TrendShort")
So basically what I want to do is keep a running total for Trend where each time there are 2 consecutive candles against the trend it will switch to neutral, but as the trend continues to move in 1 direction it can build back up to +-2 (This was we are never more than 2 "pullbacks" away from neutral. I've racked my brain over this for days now, but if anyone has any ideas any help would be appreciated.
You need to use var.
Example:
var a = 0
a:=close>open?1:0
https://www.tradingview.com/pine-script-docs/en/v4/language/Expressions_declarations_and_statements.html

Moving average line is only shown till last ticker.id close

I am working on a moving average indicator which shows the MA line of a given time frame.
For some reason is the MA line only displaced till the last ticker.id period close. So when for example I have set the indicator to show a daily MA the line is only updated when the day closes.
(Link to image https://i.stack.imgur.com/QjkvO.jpg)
Does anyone know how my indicator will be able include data between daily closes, so the line is being updated continuously?
I think this line not being updated continuously also causes the label which is supposed to be plotted right at the MA line being plotted at the 1 point / dollar height on the chart.
I have only recently started writing code, so excuse me if this is a dumb question. I have written this code looking at other indicators and trying to fit parts into my own
This is the code of the entire indicator.
//#version=4
study(title="Custom Timeframe SMA", shorttitle="Custom TF MA", overlay=true)
res = input(title="MA Timeframe", type=input.resolution, defval="D",options=["60", "240", "D", "W"])
length1 = input(title="SMA Length", type=input.integer, defval=50)
Label=input(title="show Labels",defval=true)
sma1 = sma(close, length1)
sourceEmaSmooth1 = security(syminfo.tickerid, res, sma1, barmerge.gaps_on, barmerge.lookahead_on)
plot(sourceEmaSmooth1, style=plot.style_line, linewidth=2, title="25 period", color=#a21e7b)
plotchar((sourceEmaSmooth1 ? Label : barstate.islast and not barstate.isconfirmed) ? sourceEmaSmooth1 : na, location=location.absolute, text=" 50 SMA", textcolor=#a21e7b, offset=10, editable=false)
Using barmerge.gaps_on with security() creates holes which appear as na values at the chart's resolution, which is why your ma wasn't always showing. It wasn't apparent on historical bars because the plot() function fills the space from non-gap to non-gap (you could see it if you plotted circles instead of a line).
Using barmerge.lookahead_on with security() produces lookahead bias on historical bars. Very nasty if you don't index the value you're fetching, as is explained in this publication on how to use security() correctly: How to avoid repainting when using security().
I added show_last = 1 to you label-plotting call and fixed the conditional. Because it now only plots the last occurrence of the label, we no longer need to worry about barstates:
//#version=4
study(title="Custom Timeframe SMA", shorttitle="Custom TF MA", overlay=true)
res = input(title="MA Timeframe", type=input.resolution, defval="D",options=["60", "240", "D", "W"])
length1 = input(title="SMA Length", type=input.integer, defval=50)
Label=input(title="show Labels",defval=true)
sma1 = sma(close, length1)
sourceEmaSmooth1 = security(syminfo.tickerid, res, sma1)
plot(sourceEmaSmooth1, linewidth=2, title="25 period", color=#a21e7b)
plotchar(Label ? sourceEmaSmooth1 : na, location=location.absolute, text=" 50 SMA", textcolor=#a21e7b, offset=10, show_last = 1, editable=false)

Get phase of day based on solar altitude/azimuth

As per the skyfield documentation online, I am able to calculate whether a given time of day is day or night.
import skyfield.api
import skyfield.almanac
ts = skyfield.api.load.timescale()
ephemeris = skyfield.api.load('de421.bsp')
observer = skyfield.api.Topos(latitude_degrees=LAT, longitude_degrees=LON)
is_day_or_night = skyfield.almanac.sunrise_sunset(ephemeris, observer)
day_or_night = is_day_or_night(ts.utc(merged_df.index.to_pydatetime()))
s = pd.Series(data=['Day' if is_day else 'Night' for is_day in day_or_night],
index = merged_df.index, dtype='category')
merged_df['Day or Night'] = s
Now, I want to also categorize the morning/noon/evening phases of the day according to solar altitude/azimuth. I came up with the following.
earth, sun = ephemeris['earth'], ephemeris['sun']
observer = earth + skyfield.api.Topos(latitude_degrees=LAT,
longitude_degrees=LON)
astrometric = observer.at(ts.utc(merged_df.index.to_pydatetime())).observe(sun)
alt, az, d = astrometric.apparent().altaz()
I need help in understanding how to proceed further since I don't have the related background knowledge about astronomical calculations.
Thanks
As per Brandon's comment, I used the cosine of zenith angle to get the sunlight intensity and then hacked together the sunlight intensity with the zenith angle to form a monotonically increasing function for the duration of the day.
temp = pd.DataFrame({'zenith': 90 - alt.degrees,
'Day or Night': day_or_night},
index=merged_df.index)
temp['cos zenith'] = np.cos(np.deg2rad(temp['zenith']))
temp['feature'] = temp['cos zenith'].diff(periods=-1)*temp['zenith']
temp['Day Phase'] = None
temp.loc[temp['Day or Night'] == False, 'Day Phase'] = 'Night'
temp.loc[(temp['feature'] > -np.inf) & (temp['feature'] <= -0.035), 'Day Phase'] = 'Morning'
temp.loc[(temp['feature'] > -0.035) & (temp['feature'] <= 0.035), 'Day Phase'] = 'Noon'
temp.loc[(temp['feature'] > 0.035) & (temp['feature'] <= np.inf), 'Day Phase'] = 'Evening'
merged_df['Phase of Day'] = temp['Day Phase']
The limits can be adjusted to change the duration required for noon, etc.

Data handling on multiple Heart rate files

I have been collecting the Heart rates of 12 calves who each received an anesthetic through four different routes of administration. I now have 48 txt files of this format:
Time HRbpm
0:00:01.7 97
0:00:02.3 121
0:00:02.8 15
... ...
HR was recorded for around 2hours. The Time column was dependent of the monitor, resulting in inconsistent time intervals between two measures.
The txt files are named as follows: 6133_IM_27.00.txt
With 6133 being the ID, IM the route and 27.00 the time (min:min.s:s) at which the treatment was injected.
My first goal is to have all the HR data so I can do an outlier analysis.
Then, I would like to include all this data in a single data frame that would look like this:
data.frame(ID=c(6133,6133,6133,6133,"...",6134,6134,"..."),
Route = c("IM","IM","IM","IM","...","SC","SC","..."),
time=c(0, 10, 20, 30,"...",0,10,"..."),
HR=c(160, 150, 145, 130,"...",162,158,"..."))
Time column going from 0 to 120 in 10min increments.
Each HR of this df would represent the mean of the HR values for the preceding minute for a given time (e.g. for time = 30, HR would represent the mean between 29 and 30 minutes for a given ID/Route combination).
I'm fairly new to R, so I've been having trouble just knowing by what angle starting on that problem. Any help would be welcome.
Thanks,
Thomas
For anyone who stumbles on this post, here's what I've done, seems to be working.
library(plyr)
library(reshape)
library(ggplot2)
setwd("/directory")
filelist = list.files(pattern = ".*.txt")
datalist = lapply(filelist, read.delim)
for (i in 1:length(datalist))
{datalist[[i]][3] = filelist[i]}
df = do.call("rbind", datalist)
attach(df)
out_lowHR = quantile(HRbpm,0.25)-1.5*IQR(HRbpm)
out_highHR = quantile(HRbpm,0.75)+1.5*IQR(HRbpm) #outliers thresholds: 60 and 200
dfc = subset(df,HRbpm>=60 & HRbpm<=200)
(length(df$HRbpm)-length(dfc$HRbpm))/length(df$HRbpm)*100 #8.6% of values excluded
df = dfc
df$ID = substr(df$V3,4,7)
df$ROA = substr(df$V3,9,11)
df$ti = substr(df$V3,13,17)
df$Time = as.POSIXct(as.character(df$Time), format="%H:%M:%S")
df$ti = as.POSIXct(as.character(df$ti), format="%M.%S")
df$t = as.numeric(df$Time-df$ti)
m=60
meanHR = ddply(df, c("ROA","ID"), summarise,
mean0 = mean(HRbpm[t>-60*m & t <=0]),
mean10 = mean(HRbpm[t>9*m & t <=10*m]),
mean20 = mean(HRbpm[t>19*m & t <=20*m]),
mean30 = mean(HRbpm[t>29*m & t <=30*m]),
mean45 = mean(HRbpm[t>44*m & t <=45*m]),
mean60 = mean(HRbpm[t>59*m & t <=60*m]),
mean90 = mean(HRbpm[t>89*m & t <=90*m]),
mean120 = mean(HRbpm[t>119*m & t <=120*m]))
meanHR = melt(meanHR)
meanHR$time = as.numeric(gsub("mean", "", meanHR$variable))
ggplot(meanHR, aes(x = time, y = value, col = ROA))+
geom_smooth()+
theme_classic()

Shiny flexdashboard: download Report

i am trying to figure out if there is a possibility to download a report withing interactive flexdashboard?
We do have possibility to download a report using Shiny (downloadButton), however there is nothing mentioned in the flexdashboard documentation about downloading the report (i have seen only examples for downloading the data etc, which is quite easy).
Sample code from the examples of flexdasboard:
---
title: "Old Faithful Eruptions"
output:
flexdashboard::flex_dashboard:
orientation: rows
social: menu
source_code: embed
runtime: shiny
---
```{r global, include=FALSE}
# load data in 'global' chunk so it can be shared by all users of the dashboard
library(datasets)
data(faithful)
```
Column {.sidebar}
-----------------------------------------------------------------------
Waiting time between eruptions and the duration of the eruption for the
Old Faithful geyser in Yellowstone National Park, Wyoming, USA.
```{r}
selectInput("n_breaks", label = "Number of bins:",
choices = c(10, 20, 35, 50), selected = 20)
sliderInput("bw_adjust", label = "Bandwidth adjustment:",
min = 0.2, max = 2, value = 1, step = 0.2)
```
Column
-----------------------------------------------------------------------
### Geyser Eruption Duration
```{r}
renderPlot({
hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks),
xlab = "Duration (minutes)", main = "Geyser Eruption Duration")
dens <- density(faithful$eruptions, adjust = input$bw_adjust)
lines(dens, col = "blue")
})
```
It would be great if someone could help insert the downloadButton which is going to give a pdf report based on flexdasboard code.
There has been similat question to mine, however noone has answered it.