I have an application implementing RESTful API. I have two methods create_order and order_status. The first method creates order and persists it with the current time in the order.time field:
order.time = Time.now
The second method responds with a hardcoded value:
:eta => 20.minutes.from_now.to_i
Instead of returning the hardcoded 20 minutes, how can I return the relative value that decreases with elapsed time (depending on the time when status request was made)?
At the beginning of the order, they are the same (20.minutes.from_now.to_i), but if the request is made after 5 mins, it should be 15.minutes.from_now.to_i.
I would save some other attribute along with order.time
For example : order.eta = Time.now + 1200
Or else : order.processing_time = 1200 and then order.eta could be calculated.
I like the second solution better, enabling different processing times for different orders.
Related
Good morning,
I have a little problem there.
I would like work with data from two different time interval.
for example, BTC (1 day time interval) and BTC (4 hour time interval) chart.
The main time interval is the 4 hour. The value "HA_C", this is the close value of "BTC 1 Day".
The "close BTC 1 Day time interval" value displayed correct in the 4 hour chart.
But the value "test" with a simple arithmetic problem differs greatly and is wrong.
You can test this as follows:
Loads the strategy in "BTC", time interval "1 Day",
note from one day the "BTC Close" value and the "test" value.
Then switch to "BTC" 4 hour time interval.
You will see, that the "HA_C Close" from the 1 hour time interval is the correct value,
but the "test" value is displayed incorrectly.
Why is the "test" value after a calculation incorrectly, although the "Close" value is correct ???
I have find out, that the problem is the "ta.ema (source, length)" function. Can someone give me a formula, that calculates the same value as the "ta.ema (source, length)" function.
**// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © flashpit
//#version=5
strategy("TEST", process_orders_on_close=true, overlay=true, calc_on_every_tick=true, pyramiding=30)
varip test = 0.0
HA_Symbol = ticker.heikinashi("BINANCE:BTCUSDT")
HA_C = request.security(HA_Symbol, "1D", close)
test:= ta.ema(HA_C, 7) * 1.05
plot (HA_C)
plot (test)**
I have finde the correct code. Here is it:
c2_1D = request.security(ticker.heikinashi('BINANCE:BTCUSDT'), "1D", t3_D (close, T3Length_1D, T3FactorCalc_1D))
It is due to the context you have called the ema function. If your chart is H4 and you perform your test calculation in the global scope, it is using 7 x H4 bars of HA_C. On BTCUSDT, over the last 7 H4 bars, it would have been 7 bars made up of multiples of only 2 daily values, hence the incorrect result.
When you change the chart to D1, it shows the correct result because now the global context of the script is now operating in the same timeframe as the security call.
If you want the correct value from the ema using 7 x 1D bars it has to be done within the context of the security call. For example :
test = request.security(ticker.heikinashi("BINANCE:BTCUSDT"), "D", ta.ema(close, 7))
If you need to perform multiple operations using the same ticker, you can also wrap them in a function and just pass the one function to a single security call. For example, this will return the daily close and the daily ema 7 :
f_ema_and_close(_src, _len) =>
_ema = ta.ema(_src, _len)
[_src, _ema]
[D1_close, D1_ema7] = request.security(ticker.heikinashi("BINANCE:BTCUSDT"), "D", f_ema_and_close(close, 7))
plot(D1_close, color = color.yellow)
plot(D1_ema7, color = color.red)
I am working with an API and I am trying to develop a simple pagination from scratch in Sinatra
This is my Sinatra route - it performs the API Call and returns 25 matters with the limit: 25 parameter and stores the resulting array in #matter -
get '/matters' do
#matter = client.matters.list(limit: 25)
slim :matters
end
My plan to get additional matters is
get '/next_matters' do
#matter = client.matters.next_page
slim :matters
end
Which supposedly returns the next 25 matters
This is my slim code at the bottom of the list of matters:
a href= "/next_matters" Next
This does not work - It returns nothing - I am sure this is because when I call next_matters is does not remember the state from client.matters.list(limit: 25).
Do I need a helper method for this?
When I try:
get '/matters' do
#matter = client.matters.list(limit: 25)
#matter2 = client.matters.next_page
slim :matters
end
I can list 50 matters - some how I need to pass the fact that I have called list previously
How do I do this?
You would do this by passing in an offset to the database as part of the query.
i.e.:
SELECT * FROM matters LIMIT 25;
Then on requesting the next page, you would do:
SELECT * FROM matters LIMIT 25 OFFSET 25;
Therefore, the next_page method needs to accept at least 1 parameter; an offset.
Pseudo code:
def next_page(offset)
# first page offset would be 0
# second page offset would be 25
# ...
limit(25).offset(offset)
end
Suppose I want to run a task once per hour, but at a variable time during the hour. It doesn't have to be truly random; I just don't want to do it at the top of the hour every hour, for example. And I want to do it once per hour only.
This eliminates several obvious approaches, such as sleeping a random amount of time between 30 and 90 minutes, then sleeping again. It would be possible (and pretty likely) for the task to run several times in a row with a sleep of little more than 30 minutes.
The approach I'm thinking about looks like this: every hour, hash the Unix timestamp of the hour, and mod the result by 3600. Add the result to the Unix timestamp of the hour, and that's the moment when the task should run. In pseudocode:
while now = clock.tick; do
// now = a unix timestamp
hour = now - now % 3600;
hash = md5sum(hour);
the_time = hour + hash % 3600;
if now == the_time; then
do_the_work();
end
end
I'm sure this will meet my requirements, but I thought it would be fun to throw this question out and see what ideas other people have!
For the next hour to do work in, just pick a random minute within that hour.
That is, pick a random time for the next interval to do work in; this might be the same interval (hour) as the current interval (hour) if work has carried over from the previous interval.
The "time to sleep" is simply the time until then. This could also be execute "immediately" on a carry-over situation if the random time was before now: this will ensure that a random time is picked each hour, unless work takes more than an hour.
Don't make it more complex than it has to be - there is no reason to hash or otherwise muck with random here. This is how "Enterprise" solutions like SharePoint Timers (with an Hourly Schedule) work.
Schedule your task (with cron or the like) to run at the top of every hour.
At the beginning of your task, sleep for a random amount of time, from 0 to (60 - (the estimated running time of your task + a fudge factor)) minutes.
If you don't want your task to run twice simultaneously, you can use a pid file. The task can check - after sleeping - for this file and wait for the currently running task to finish before starting again.
I've deployed my suggested solution and it is working very well. For example, once per minute I sample some information from a process I'm monitoring, but I do it at variable times during the minute. I created a method of a Timestamp type, called RandomlyWithin, as follows, in Go code:
func (t Timestamp) RandomlyWithin(dur Timestamp, entropy ...uint32) Timestamp {
intervalStart := t - t % dur
toHash := uint32(intervalStart)
if len(entropy) > 0 {
toHash += entropy[0]
}
md5hasher.Reset()
md5hasher.Write([]byte{
uint8(toHash >> 24 & 255),
uint8(toHash >> 16 & 255),
uint8(toHash >> 8 & 255),
uint8(toHash & 255)})
randomNum := binary.BigEndian.Uint32(md5hasher.Sum(nil)[0:4])
result := intervalStart + Timestamp(randomNum)%dur
return result
}
I'm using a task and the spreadsheet gem to read in an excel spreadsheet into my database. One of the columns I'm reading in is "start_time." To do this, I'm forming an array of values, then passing in each of these array values, one by one.
cnum_array = [] # for start times
sheet1.each 3 do |row|
unless row[9].blank?
time = Time.parse(row[9])
cnum_array << time.utc
end
end
count = 0
for course in Course.all
course.update_attribute :start_time, cnum_array[count]
count += 1
end
This seems to work fine. If I insert a "puts course.start_time" statement within this last loop, it prints off the right time. Like so:
count = 0
for course in Course.all
course.update_attribute :start_time, cnum_array[count]
puts course.start_time
count += 1
end
This gives me the right time, e.g. "2012-01-23 15:30:00."
But when I look up the course time later (e.g. via my console's Course.find(1).start_time), it gives me "2000-01-01 15:20:00." So the time of day is right, but the day itself goes back to 2000-01-01.
Does anyone know why this is happening, and how I can fix it? Thanks!
You are using the Time class. This class deals with times, not dates. My guess is that your database column is of type time as well.
I recommend you use a datetime (or possibly timestamp) column type.
I'm wishing to figure out how many milliseconds a particular function uses. So I looked high and low, but could not find a way to get the time in Ruby with millisecond precision.
How do you do this? In most programming languages its just something like
start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start
You can use ruby's Time class. For example:
t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds
Now, delta is a float object and you can get as fine grain a result as the class will provide.
You can also use the built-in Benchmark.measure function:
require "benchmark"
puts(Benchmark.measure { sleep 0.5 })
Prints:
0.000000 0.000000 0.000000 ( 0.501134)
Using Time.now (which returns the wall-clock time) as base-lines has a couple of issues which can result in unexpected behavior. This is caused by the fact that the wallclock time is subject to changes like inserted leap-seconds or time slewing to adjust the local time to a reference time.
If there is e.g. a leap second inserted during measurement, it will be off by a second. Similarly, depending on local system conditions, you might have to deal with daylight-saving-times, quicker or slower running clocks, or the clock even jumping back in time, resulting in a negative duration, and many other issues.
A solution to this issue is to use a different time of clock: a monotonic clock. This type of clock has different properties than the wall clock.
It increments monitonically, i.e. never goes back and increases at a constant rate. With that, it does not represent the wall-clock (i.e. the time you read from a clock on your wall) but a timestamp you can compare with a later timestamp to get a difference.
In Ruby, you can use such a timestamp with Process.clock_gettime(Process::CLOCK_MONOTONIC) like follows:
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63988.576809828
sleep 1.5 # do some work
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63990.08359163
delta = t2 - t1
# => 1.5067818019961123
delta_in_milliseconds = delta * 1000
# => 1506.7818019961123
The Process.clock_gettime method returns a timestamp as a float with fractional seconds. The actual number returned has no defined meaning (that you should rely on). However, you can be sure that the next call will return a larger number and by comparing the values, you can get the real time difference.
These attributes make the method a prime candidate for measuring time differences without seeing your program fail in the least opportune times (e.g. at midnight at New Year's Eve when there is another leap-second inserted).
The Process::CLOCK_MONOTONIC constant used here is available on all modern Linux, BSD, and macOS systems as well as the Linux Subsystem for Windows. It is however not yet available for "raw" Windows systems. There, you can use the GetTickCount64 system call instead of Process.clock_gettime which also returns a timer value in millisecond granularity on Windows (>= Windows Vista, Windows Server 2008).
With Ruby, you can call this function like this:
require 'fiddle'
# Get a reference to the function once
GetTickCount64 = Fiddle::Function.new(
Fiddle.dlopen('kernel32.dll')['GetTickCount64'],
[],
-Fiddle::TYPE_LONG_LONG # unsigned long long
)
timestamp = GetTickCount64.call / 1000.0
# => 63988.576809828
You should take a look at the benchmark module to perform benchmarks. However, as a quick and dirty timing method you can use something like this:
def time
now = Time.now.to_f
yield
endd = Time.now.to_f
endd - now
end
Note the use of Time.now.to_f, which unlike to_i, won't truncate to seconds.
Also we can create simple function to log any block of code:
def log_time
start_at = Time.now
yield if block_given?
execution_time = (Time.now - start_at).round(2)
puts "Execution time: #{execution_time}s"
end
log_time { sleep(2.545) } # Execution time: 2.55s
Use Time.now.to_f
The absolute_time gem is a drop-in replacement for Benchmark, but uses native instructions to be far more accurate.
If you use
date = Time.now.to_i
You're obtaining time in seconds, that is far from accurate, specially if you are timing little chunks of code.
The use of Time.now.to_i return the second passed from 1970/01/01. Knowing this you can do
date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1
With this you will have difference in second magnitude. If you want it in milliseconds, just add to the code
diff = diff * 1000
I've a gem which can profile your ruby method (instance or class) - https://github.com/igorkasyanchuk/benchmark_methods.
No more code like this:
t = Time.now
user.calculate_report
puts Time.now - t
Now you can do:
benchmark :calculate_report # in class
And just call your method
user.calculate_report