How to mark High of today if it has a particular decimal say ".55" at end for a 5m interval chart in Tradingview using Pine script - plot

What I want to do is to mark the candle in 5m chart for the current day if it meets following two condition:
1) The candle should be highest of the day and it's high=1234.75 (at end ".75" decimal)
2) The candle should be lowest of the day and it's low=900.25 (at end "0.25" decimal)
I could mark a candle if it's high value consist of ".75" decimal at end and low value consist of ".25" decimal behind any value using below code but it shows all candles whose high ends with "0.75". I want to mark only Day high candle if it meets 0.75 criteria. Please refer and help me out.. Thank you in advance
// This source code is subject to the terms of the Mozilla Public License 2.0 at
https://mozilla.org/MPL/2.0/
//#version=4
study("(75-25)", overlay=true)
ch = high[0]
cl = low[0]
truncate(number, decimals) =>
factor = pow(10, decimals)
int(number * factor) / factor
chA = truncate(ch,0)
chB = ch - chA
data = chB == 0.75
clA = truncate(cl,0)
clB = cl - clA
data1 = clB == 0.25
plotshape(data, style=shape.triangledown, size=size.small, location=location.abovebar,
color=color.red)
plotshape(data1, style=shape.triangleup, size=size.small, location=location.belowbar,
color=color.green)

You can use the security() function to get the daily high and lows. However, you would miss the intraday actions for backtesting. What you need I believe is, if the price is the daily high/low from the session start until that specific bar.
You can use the following method the keep track of the daily high/low and update the values if a new high/low forms.
var dailyHigh = high
var dailyLow = low
t = time("1440", session.regular) // Get the session open
isSessionFirstBar = na(t[1]) and not na(t) or t[1] < t // True: If first bar in the session
dailyHigh := iff(isSessionFirstBar, high, iff(high > dailyHigh, high, dailyHigh))
dailyLow := iff(isSessionFirstBar, low, iff(low < dailyLow, low, dailyLow))
Then you should combine this with your data and data1 variables.
data = (chB == 0.75) and (close == dailyHigh)
data1 = (clB == 0.25) and (close == dailyLow)

Related

How to plot line only on first value of crossover condition met in Pine Script

I need help in Pine script coding, i want to plot the first crossover value alone not entire series of values for whole day. so if crossover condition is true for 1st or 2nd or 3rd or n times, i need to plot the line from the first condition met to end of day and ignore 2nd or 3rd or 4th or nth series values to plot. how to do it? and i don't want to use line.new() since i want to backtest in tradingview.com, for historical bars i want to use Plot(). so kindly help me with the code.
Strategy im trying: Added 30pts above from 5mins High-Low, if 5 mins candle crossover the 30pts at first time from High need to plot line, ignore if condition met again in a day.
`
//#version=5
indicator(title="Crossover", shorttitle="Crossover", overlay=true)
//*5Mins High Low calculation*//
inputMax = input(5, title= "ORB total time (minutes)")
sess = input("0915-0920", title="Session Time")
t = time(timeframe.period, sess + ":1234567")
hide = timeframe.isintraday and timeframe.multiplier <= inputMax
is_newbar(res) => ta.change(time(res)) != 0
in_session = not na(t)
is_first = in_session and not in_session[1]
orb_high = float(na)
orb_low = float(na)
if is_first
orb_high := high
orb_low := low
else
orb_high := orb_high[1]
orb_low := orb_low[1]
if high > orb_high and in_session
orb_high := high
if low < orb_low and in_session
orb_low := low
plot(hide ? orb_high : na , style=plot.style_line, color=orb_high[1] != orb_high ? na : color.green , title="ORB High", linewidth=3)
plot(hide ? orb_low : na , style=plot.style_line, color=orb_low[1] != orb_low ? na : color.red, title="ORB Low", linewidth=3)
//*Crossover condition*//
var Up = 0.0
Up := orb_high + 30
var b_i = 0.0
cross_over_happened = if(ta.crossover(close, Up)) and barstate.isconfirmed
1
else
0
b_i := ta.valuewhen(cross_over_happened, close, 0)
plot(b_i, color = color.black, linewidth = 2)
`
the above code will plot whenever condition met, but i need to plot only the first value of crossover condition, not for entire series. Kindly help with the code.
I would go about this in a slightly different way (which is very close to what you have done). I would add a bool that will check if a cross already happened today, and will change the value of b_i only when the cross and the new bool are true.
First set the variables that we're going to need:
var float orb_high = na
var float orb_low = na
var bool already_had_crossover_today = false
var float b_i = na
Second, reset those variables on each new day:
if ta.change(time("D"))
orb_high := high
orb_low := low
already_had_crossover_today := false
b_i := na
Third, we'll check for the crossover, regardless if it's the first one on the day or not:
Up = orb_high + 30
cross_over_happened = ta.crossover(close, Up)
And lastly, we'll check if we had a crossover and during the day a crossover hasn't happened yet:
if cross_over_happened and not already_had_crossover_today
b_i := close
already_had_crossover_today := true
Than we can just use plot, and for better visualization use the style parameter:
plot(b_i, style = plot.style_linebr)

How to calculate the number of day-off trading like weekend, holidays?

Good Morning All!
The question in Pinescript,
Is there any trick to let my code determines whether the day before (yesterday) was day-off trading?
For example, I want my code to calculate the number of days-off.
I've coded this one, but it doesn't work perfectly at running data especially on the first day after off-market, but it works fine at historical data.
T=security(syminfo.tickerid, "1440", time)
fun()=>
NumDays= change(T)/86400000
Please Help!
This should work.
//#version=4
study("StackOverflow", overlay=true, max_labels_count=500)
daysBetween = change(dayofmonth(time))
if daysBetween > 1
label.new(bar_index, high, tostring(daysBetween) + " days", yloc=yloc.abovebar)
Edit: New code example.
This should work better.
I've actually asked a question about this myself recently.
See Detecting session breaks
//#version=4
study("NewSession", overlay=true)
var int days_off = na
var float change_in_ms = na
var int ms_per_day = 24 * 60 * 60 * 1000
change_in_ms := change(time("D"))
if change_in_ms
days_off := int(change_in_ms / ms_per_day)-1
bgcolor(change_in_ms ? color.yellow : na, 60)
plotchar(days_off, "days_off", "")

Axibase Time Series Database - filter out negative values on time chart

I am using Axibase Time Series Database Community Edition, version 10552, to store my photovoltaic and sun altitude data. Sun altitude values are negative during the night time and I don't want to see them on my graphs.
How can I view only the positive values? Anyone know a setting or a trick that can acheive this?
Here is my current Time Chart widget configuration:
[widget]
type = chart
title = PV power
timespan = 3 day
entity = pvout.25630
[series]
label = Sun Altitude at (-35.3089, 149.2004)
metric = sun_altitude
color = orange
[tags]
lat = -35.3089
lon = 149.2004
Here is a screenshot of what I am actually seeing at the moment:
Here is an example in Chart Lab:
https://axibase.com/chartlab/3170e35d/2/
Good question.
There are several ways to hide or filter out the negative values:
replace-value setting uses an expression to modify or filter series values:
[widget]
type = chart
title = PV power
timespan = 3 day
entity = pvout.25630
[series]
label = Sun Altitude at (-35.3089, 149.2004)
metric = sun_altitude
color = orange
replace-value = value < 0 ? null : value
[tags]
lat=-35.3089
lon=149.2004
This expression will filter out all values that are less than 0 from the series.
Results: https://axibase.com/chartlab/3170e35d/3/
min-range-force setting can be used to set the minimum range of the y-axis:
[widget]
type = chart
title = PV power
timespan = 3 day
entity = pvout.25630
min-range-force = 0
[series]
label = Sun Altitude at (-35.3089, 149.2004)
metric = sun_altitude
color = orange
[tags]
lat=-35.3089
lon=149.2004
Results: https://axibase.com/chartlab/3170e35d/4/
If you are using a script to calculate the Sun Altitude, then you can use the Math.max function:
[widget]
type = chart
title = PV power
timespan = 3 day
[series]
label = Altitude
#API: SunCalc.getPosition = function (date, lat, lng)
value = var pos = SunCalc.getPosition(new Date(time), -35.3089, 149.2004);
value = return Math.max(0, pos.altitude)
frequency = 30 minute
color = orange
Results: https://axibase.com/chartlab/3170e35d/5/
value equation can be used to create a computed series, excluding the negative values:
[widget]
type = chart
title = PV power
timespan = 3 day
entity = pvout.25630
[series]
metric = sun_altitude
display = false
alias = sun_alt
[tags]
lat=-35.3089
lon=149.2004
[series]
label = Sun Altitude at (-35.3089, 149.2004)
value = Math.max(0, value('sun_alt'))
color = orange
In this case, we hide the original series and assign an alias, then we use the value = Math.max(0, value('sun_alt')) equation to create a new computed series without the negative values.
Results: https://axibase.com/chartlab/3170e35d/6/

ADC transfer function

I took over the project from someone who had gone a long time ago.
I am now looking at ADC modules, but I don't get what the codes mean by.
MCU: LM3S9B96
ADC: AD7609 ( 18bit/8 channel)
Instrumentation Amp : INA114
Process: Reading volts(0 ~ +10v) --> Amplifier(INA114) --> AD7609.
Here is codes for that:
After complete conversion of 8 channels which stored in data[9]
Convert data to micro volts??
//convert to microvolts and store the readings
// unsigned long temp[], data[]
temp[0] = ((data[0]<<2)& 0x3FFFC) + ((data[1]>>14)& 0x0003);
temp[1] = ((data[1]<<4)& 0x3FFF0) + ((data[2]>>12)& 0x000F);
temp[2] = ((data[2]<<6)& 0x3FFC0) + ((data[3]>>10)& 0x003F);
temp[3] = ((data[3]<<8)& 0x3FF00) + ((data[4]>>8)& 0x00FF);
temp[4] = ((data[4]<<10)& 0x3FC00) + ((data[5]>>6)& 0x03FF);
temp[5] = ((data[5]<<12) & 0x3F000) + ((data[6]>>4)& 0x0FFF);
temp[6] = ((data[6]<<14)& 0x3FFF0) + ((data[7]>>2)& 0x3FFF);
temp[7] = ((data[7]<<16)& 0x3FFFC) + (data[8]& 0xFFFF);
I don't get what these codes are doing...? I know it shifts but how they become micro data format?
transfer function
//store the final value in the raw data array adstor[]
adstor[i] = (signed long)(((temp[i]*2000)/131072)*10000);
131072 = 2^(18-1) but I don't know where other values come from
AD7609 datasheet says The FSR for the AD7609 is 40 V for the ±10 V range and 20 V for the ±5 V range, so I guessed he chose 20vdescribed in the above and it somehow turned to be 2000???
Does anyone have any clues??
Thanks
-------------------Updated question from here ---------------------
I don't get how 18bit concatenated value of data[0] + 16bit concatenated value of data[1] turn to be microvolt after ADC transfer function.
data[9]
+---+---+--- +---+---+---+---+---+---++---+---+---++---+---+---++
analog volts | 1.902v | 1.921v | 1.887v | 1.934v |
+-----------++-----------+------------+------------+------------+
digital value| 12,464 | 12,589 | 12,366 | 12,674 |
+---+---+---++---+---+---++---+---+---++---+---+---++---+---+---+
I just make an example from data[3:0]
1 resolution = 20v/2^17-1 = 152.59 uV/bit and 1.902v/152.59uv = 12,464
Now get thru concatenation:
temp[0] = ((data[0]<<2)& 0x3FFFC) + ((data[1]>>14)& 0x0003) = C2C0
temp[1] = ((data[1]<<4)& 0x3FFF0) + ((data[2]>>12)& 0x000F) = 312D3
temp[2] = ((data[1]<<6)& 0x3FFC0) + ((data[3]>>10)& 0x003F) = 138C
Then put those into transfer function and get microvolts
adstor[i] = (signed long)(((temp[i]*2000)/131072)*10000);
adstor[0]= 7,607,421 with temp[0] !=1.902*e6
adstor[1]= 30,735,321 with temp[1] != 1.921*e6
adstor[2]= 763,549 with temp[2]
As you notice, they are quite different from the analog value in table.
I don't understand why data need to bit-shifting and <<,>> and added up with two data[]??
Thanks,
Please note that the maximum 18-bit value is 2^18-1 = $3FFFF = 262143
For [2] it appears that s/he splits 18-bit word concatenated values into longs for easier manipulation by step [3].
[3]: Regarding adstor[i] = (signed long)(((temp[i]*2000)/131072)*10000);
To convert from raw A/D reading to volts s/he multiplies with the expected volts and divides by the maximum possible A/D value (in this case, $3FFFF) so there seems to be an error in the code as s/he divides by 2^17-1 and not 2^18-1. Another possibility is s/he uses half the range of the A/D and compensates for that this way.
If you want 20V to become microvolts you need to multiply it by 1e6. But to avoid overflow of the long s/he splits the multiplication into two parts (*2000 and *10000). Because of the intermediate division the number gets small enough to be multiplied at the end by 10000 without overflowing at the expense of possibly losing some least significant bit(s) of the result.
P.S. (I use $ as equivalent to 0x due to many years of habit in certain assembly languages)

Find current value of a variable that depreciates linearly over time

Let's say we have an empty bathtub. We've lost the plug, so once water is added it will drain away at a constant rate of 2 liters pr. minute. We add water to the tub in increments. 60 liters at 10:51, 30 liters at 11:54 and 50 liters at 13:18.
So, the question is: How can I find out how much water is in the bathtub at any given time?
water_in_tub(t) = if (t<10:51) then
0
else if (10:51<t<11:54) then
min(60-2*(minutes since 10:51),0)
and so forth
And of course, as I'm sure others will point out, your model of water flowing out of a bath is inaccurate, Toricelli's Law is much more accurate.
Assuming you're modelling a continuous process...
var waterIn = Vbath
var startTime = now()
procedure add_water(var liters) {
waterIn = how_much_water();
waterIn = waterIn + liters
startTime = now()
}
function how_much_water() {
var waterNow = waterIn - (now() - startTime) * leakSpeed
if waterNow < 0 return 0 else return waterNow
}

Resources