Pine scripting: how to find the price X days ago - date

In Pine Script, how do I find the price based on a certain number of days ago? I've tried something like this...
// Find the price 90 days ago
target = time - 90 * 60 * 60 * 24 * 1000
valuewhen(time < target, close, 1)
...however time < target never seems to return true – presumably because the current bar's time cannot also be in the past at the same time. Perhaps valuewhen() wasn't designed to be used with dynamic values that change on every bar?
Do I need to use a loop instead, and scan through every past bar until I find the date I'm looking for?

Perhaps there's a better way, but the workaround I'm using currently using is a function with a for loop, scanning backwards until the appropriate date is found. Here is my function:
priceXDaysAgo(numDays) =>
targetTimestamp = time - numDays*60*60*24*1000
// Declare a result variable with a "void" value
float result = if false
1
// We'll scan backwards through the preceding bars to find the first bar
// earlier than X days ago (it might be a little greater than X days if
// there was a break in trading: weekend, public holiday, etc.)
for i = 1 to 1000
if time[i] < targetTimestamp
result := close[i]
break
result
You can then call the function anywhere in your script:
priceXDaysAgo(90)

Related

Convert unix time to month number?

Using os.time how can I get how many months have passed since the unix epoch (Unix Timestamp)
I just need it for a month ID, so any kind of number would be fine, as long as it changes every month, and it can be reversed to get the actual month.
local function GetMonth(seconds)
local dayduration,year = 3600*24
local days={31,0,31,30,31,30,31,31,30,31,30,31}
for i=1970,10000 do -- For some reason too lazy to use while
local yeardays = i%4 == 0 and i%100 ~= 0 and 366 or 365
local yearduration = dayduration * yeardays
if yearduration < seconds then
seconds = seconds - yearduration
else
year = i break
end
end
days[2]=(year%4==0) and 29 or 28
seconds = seconds%(365*24*3600)
for i=1,12 do
if seconds>days[i]*dayduration then
seconds=seconds-days[i]*dayduration
else
return --i + year*12 <-- If you want a unique ID
end
end
end
Currently, it'll give the number 2, since it's February. If you uncomment the code at the end for the unique ID, you'll get 554 instead, meaning we're currently at the 554th month since the epoch.
As Jean-Baptiste Yunès said in his answer's comments, I'm not sure if your sentence:
NOTE: This is for Lua, but I'm unable to use os.date
meant you have no os.date, or that you don't know how to use it. You have an answer for both cases, you can use the one you need.
This may do the trick:
print (os.date("*t",os.time())["month"])
os.time() gives you the current date as a number. os.date("*t",...) converts it into a table in which the month equals to the number of the month corresponding to the date.

How do I convert a decimal number representing time to actual time in Crystal Reports 2008? Ex: "1.5" represents 1:30

I'm trying to edit an existing Crystal Report that shows time allowances for work orders. Budgeted Time / Actual Time / Remaining Time type deal.
These fields show up as not properly converting time from the data field for the report. The person who made the report has some formula for it already but I'm not sure what's it doing.
Formula: Standard Time
Stringvar array Std_Time := split(replace(cstr({WOMNT_CARD.STANDARD_HOURS_DURATION}),",",""),".");
val(Std_Time[1])*60+val(Std_Time[2])
The field used in the report is Sum of #Standard Time (Number).
How do I fix this so these numbers are properly converted?
The formula that you have posted does the following:
First it converts the datatype of the {WOMNT_CARD.STANDARD_HOURS_DURATION} field to string by using the cstr function, the result is being stripped of commas with the replace function and the resulted string is being split into an array by using the dot character as the delimiter.
So, for the value 1.5 the Std_Time variable will hold the following
Std_Time[1] → 1
Std_Time[2] → 5
Finally it calculates the result by multiplying the first value of the first index with 60 and adds to it the value of the second index. The value 1.5 becomes 1 * 60 + 5 = 65
If the 1.5 must represent 1:30 then the last line must become
val(Std_Time[1]) * 60 + 60 * val(Std_Time[2]) / 10
because 60 * 5 / 10 = 30
or you can use for simplicity just the following
60 * val(replace(cstr({WOMNT_CARD.STANDARD_HOURS_DURATION}),",",""))
since 60 * 1.5 = 90

timestamp to milliseconds conversion around midnight getting messed up

I am using following function to convert timestamp in format (e.g.) 02:49:02.506 to milliseconds in perl.
sub to_millis {
my( $hours, $minutes, $seconds, $millis) = split /:/, $_[0];
$millis += 1000 * $seconds;
$millis += 1000 * 60 * $minutes;
$millis += 1000 * 60 * 60 * $hours;
return $millis;
}
I am then using the milliseconds generated from above routine to calculate the time difference between two timestamps in milliseconds. This works fine all day but gets messed up around midnight, when the timestamp changes to 00:00:00.000. So any logs generated for 1 hr (between 12am to 1am) gets me values in negative for the timestamp difference. Since my timestamp doesn't have a date in it, how do I fix this problem? I am trying to do this on a mobile device, which doesn't have many perl modules installed. So I don't have the liberty of using all the perl modules available.
If you know the ordering of your two timestamps, and if you know that they're no more than 24 hours apart, if you get a negative difference add 24 hours (86,400,000 milliseconds).
If you don't have that information, then you won't be able to distinguish between a 2-minute span and a span of 24 hours and 2 minutes.
I assume that your timestamps will never be more than 23 hours 59 minutes apart?
Let's take two time stamps A and B. I am assuming that A happens before B.
Normally, if A is less than B, I know I can get my time by subtracting A from B. However, in this case, A is bigger than B. I now have to assume that I've wrapped around midnight. What do I do?
I know that the difference between A and B is A going to midnight, PLUS B.
For example, A is 11:58:30 and B is 00:02:00
I know that A will be 90 seconds before midnight, and B will add another 120 seconds to that time. Thus, the total difference will be 90 + 120 = 210 seconds.
Using your routine:
my $midnight = to_millis( "23:59:00:000" ); # Need the time at midnight
my $a_time = to_millis( $a_timestamp );
my $b_time = to_millis( $b_timestamp );
my $time_diff;
if ( $a_time < $b_time ) { # Normal timestamp issue
$time_diff = $b_time - $a_time;
}
else { # We wrapped around midnight!
my $first_part = $midnight - $a_time; # Time from A to midnight
$time_diff = $first_part + $b_time # We add the time from midnite to B
}
You have two timestamps, A and B. If B is always conceptually "after" A but the interval from A to B could cross a date boundary, then do
if (B < A) B+=86400000
and then do the subtraction. Or equivalently
diff = B - A
if (diff < 0) diff+=86400000
If, however you are not guaranteed that B will always be "after" A, you have to decide what is the acceptable range of positive and negative values for the difference. If it's more than half a day you're out of luck, there's no way to solve the problem as you cannot tell if a negative interval represents a real negative interval or a positive one that happened to cross a day boundary.
To handle the wrap around at midnight:
$elapsed_ms = $t2_ms - $t1_ms;
if ($elapsed_ms < 0) $elapsed_ms += (24 * 60 * 60 * 1000);

KRL: Comparing two timestamps

I have two timestamps created with time:now() (one stored in an app variable from the past, one the current time). I need to find the difference between them (preferably in minutes). How do I do that?
I've tried this syntax, but the parser didn't like it:
diff = time:now() - original_time;
time:compare() doesn't give me enough information, and time:add() is the opposite of what I need. There don't seem to be any other applicable time functions documented.
The time functions return a time string, not a time object. To calculate time elapsed, you will have to convert your time string into epoch time (seconds since 1970..). Fortunately, epoch time is one of the formats supported by strftime.
foo = time:now();
efoo = time:strftime(foo,"%s);
The minus operator is actually sensitive to a leading whitespace. It's on the list of things to work out of the parser, but I just haven't had time to get to it. Here is a working rule:
rule first_rule {
select when pageview ".*" setting ()
pre {
foo = time:now();
bar = time:add(foo,{"minutes": -5});
ebar = time:strftime(bar,"%s");
efoo = time:strftime(foo,"%s");
diff = efoo-ebar;
}
notify("-5 minutes in seconds", diff) with sticky = true;
}

Unix gettimeofday() - compatible algorithm for determining week within month?

If I've got a time_t value from gettimeofday() or compatible in a Unix environment (e.g., Linux, BSD), is there a compact algorithm available that would be able to tell me the corresponding week number within the month?
Ideally the return value would work in similar to the way %W behaves in strftime() , except giving the week within the month rather than the week within the year.
I think Java has a W formatting token that does something more or less like what I'm asking.
[Everything below written after answers were posted by David Nehme, Branan, and Sparr.]
I realized that to return this result in a similar way to %W, we want to count the number of Mondays that have occurred in the month so far. If that number is zero, then 0 should be returned.
Thanks to David Nehme and Branan in particular for their solutions which started things on the right track. The bit of code returning [using Branan's variable names] ((ts->mday - 1) / 7) tells the number of complete weeks that have occurred before the current day.
However, if we're counting the number of Mondays that have occurred so far, then we want to count the number of integral weeks, including today, then consider if the fractional week left over also contains any Mondays.
To figure out whether the fractional week left after taking out the whole weeks contains a Monday, we need to consider ts->mday % 7 and compare it to the day of the week, ts->wday. This is easy to see if you write out the combinations, but if we insure the day is not Sunday (wday > 0), then anytime ts->wday <= (ts->mday % 7) we need to increment the count of Mondays by 1. This comes from considering the number of days since the start of the month, and whether, based on the current day of the week within the the first fractional week, the fractional week contains a Monday.
So I would rewrite Branan's return statement as follows:
return (ts->tm_mday / 7) + ((ts->tm_wday > 0) && (ts->tm_wday <= (ts->tm_mday % 7)));
If you define the first week to be days 1-7 of the month, the second week days 8-14, ... then the following code will work.
int week_of_month( const time_t *my_time)
{
struct tm *timeinfo;
timeinfo =localtime(my_time);
return 1 + (timeinfo->tm_mday-1) / 7;
}
Assuming your first week is week 1:
int getWeekOfMonth()
{
time_t my_time;
struct tm *ts;
my_time = time(NULL);
ts = localtime(&my_time);
return ((ts->tm_mday -1) / 7) + 1;
}
For 0-index, drop the +1 in the return statement.
Consider this pseudo-code, since I am writing it in mostly C syntax but pretending I can borrow functionality from other languages (string->int assignment, string->time conversion). Adapt or expand for your language of choice.
int week_num_in_month(time_t timestamp) {
int first_weekday_of_month, day_of_month;
day_of_month = strftime(timestamp,"%d");
first_weekday_of_month = strftime(timefstr(strftime(timestamp,"%d/%m/01")),"%w");
return (day_of_month + first_weekday_of_month - 1 ) / 7 + 1;
}
Obviously I am assuming that you want to handle weeks of the month the way the standard time functions handle weeks of the year, as opposed to just days 1-7, 8-13, etc.