Lua - Take Multiple inputs - lua

I want to write a program that calculate the Average of all input numbers.
First it will asks "How many number you want to input"
If users type 5 then the program will take 5 inputs Then it calculates the Average of it.
I wrote a function that takes passed numbers & returns average of of it But How do we ask the user to input multiple inputs and save it in array

local num = nil;
local sum = 0;
local n = 0;
while num != 0 do
num = io.read()
sum = sum + tonumber(num)
n = n + 1;
end
print(sum / (n-1))
this code will calculate all inputs and will stop asking for input until the user types 0, when he types 0, he will print the average of the values entered

Related

How can I obtain this specific series data to calculate time-to-funding-weighted average of premium index?

I'm looking to calculate and plot the funding rate of Binance BTCUSDT Perpetual and have come across the following documentation page: https://www.binance.com/en/support/faq/360033525031
It states:
The Funding Rate formula:
"Funding Rate (F) = Average Premium Index (P) + clamp (interest rate - Premium Index (P), 0.05%, -0.05%)"
I'm obtaining the "Premium Index" just fine, just with "p = request.security("BINANCE:BTCUSDT_PREMIUM", "", close)*100"
However I'm currently struggling with how to obtain the:
"Time-to-funding weighted Average of Premium Index " which apparently is calculated with
"Average Premium Index (P) = (1 * Premium_Index_1 + 2 * Premium_Index_2 + 3 * Premium_Index_3 +···+·480 * Premium_index_480)/(1+2+3+···+480)"
(the funding period for Binance is 8 hours hence the average over 480 minutes)
My exact question is, how do I backtrack to the last funding timestamp of 00:00 / 08:00 / 16:00, then obtain an array / series data of the premium index at each of the last 480 minutes, so that I can then iterate over it to use the above formula for the time weighted average?
Thank you very much for any advice in advance. My apologies if the answer is obvious I'm very new to Pine Script.
I believe you can obtain the time weighted average premium like so:
premium = request.security("BINANCE:BTCUSDT_PREMIUM", "1", close)
new_funding_period = ta.change(time("480")) != 0
var int n = na
var float premium_sum = na
var int n_sum = na
if new_funding_period
n := 1
premium_sum := premium
n_sum := 1
else
n += 1
premium_sum += premium * n
n_sum += n
predicted_TWAP = premium_sum / n_sum
current_TWAP = ta.valuewhen(new_funding_period, predicted_TWAP[1], 0)
However, you are limited to performing the calculation on a 1 minute chart to obtain accurate results due to being unable to reliably retrieve the values from a security call from a lower timeframe when the chart is set to a higher timeframe than 1 minute.

How to slice tensors with a predefined order in torch?

I have a dataset of length 10 train = torch.range(1,10). I want to slice it in a random order defined by p = torch.randperm(10).
To get slice by ranges one can do a = train[{{1,3}}] to get elements th first three elements. But lets say I want the the 2nd, 3rd and 9th elements. Can I get this without operating a for loop like this
for i = 1,3 do
print(a[{ p[i] }])
end
where
p[1] = 2, p[2] = 3, p[3] = 9.
a = train[{{ p[{{1,3}}] }}] doesn't work.
Well, for one there's index, it however requires longTensors:
train = torch.range(1,10)
p = torch.randperm(10):long()
print(train:index(p))

Lua multiple inputs in table

I'm new to lua and I have this assignment and one of the questions I'm really stumped on is asking:
"A program that asks the user repeatedly for students' scores, will stop when the user enters a score of 999 then the program should calculate and display the number of scores entered, highest score, lowest score, and the average score. Make sure to display an error message if a score less than zero or more than 100 is entered by user. "
I've been at this all week long and still can't figure out what to do and its due at 11:59pm est. Any insight and direction would be great.
-How do I input multiple values in a growing table scores = {}? Where the size is given by the number of inputs for variable s after the user enters 999 and ends the repeat loop. This is actually my BIGGEST problem.
My Code:
local scores = {}, avg
repeat
io.write("Enter score(s)")
local s = tonumber(io.read()) --input and convert data type
print(s, type(s)) --s value, check input type
if(s < 0 or s > 100) then
print("Error.")
end
until (s == 999)
for i = 0, #s, 1 do
sum = 0
if s then
sum = sum + s
end
end
-- -----------------------------------------------------------Attemps to find a way to put s values in scores table-----------------------------------------------------------------------------------------
--[[scores[#scores+1] = s ----Attempt 1
print (scores)
for i = 0, #s, 1 do ----Attempt 2
scores{s} = s[i]
print (i, scores) --tried a multitude of different ways and
--kept getting the same number printed once or memory location of last entered number
end
for i, s in ipairs (scores) do --Attempt 3
print (i, s)
end
for i = 0, #s, 1 do
sum = 0
if s then
sum = sum + s
end
end --]]
-- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
--[[function average(myTable)
local sum = 0
for i in scores do
sum = sum + i
end
return (sum / #scores)
end
print ("The number of values in the table"..#scores)
print ("The average of the scores is "..average(s))
print ("The max value in the table is "..math.max(s))
print ("The minimum value in the table is "..math.min(s))
table.maxn(scores), table.minn(scores)
--]]
io.write("Please press enter to continue")
io.read()

Attempt to get numbers instead of NaN values when printing

I've a simple program with a for loop where i calculate some value that I print to the screen, but only the first value is printed, the rest is just NaN values. Is there any way to fix this? I suppose the numbers might have a lot of decimals thus the NaN issue.
Output from program:
0.18410
NaN
NaN
NaN
NaN
etc.
This is the code, maybe it helps:
for i=1:30
t = (100*i)*1.1*0.5;
b = factorial(round(100*i)) / (factorial(round((100*i)-t)) * factorial(round(t)));
% binomial distribution
d = b * 0.5^(t) * 0.5^(100*i-(t));
% cumulative
p = binocdf(1.1 * (100*i) * 0.5,100*i,0.5);
% >= AT LEAST
result = 1-p + d;
disp(result);
end
You could do the calculation of the fraction yourself.
Therefore you need to calculate $d$ directly. Then you can get all values of the numerators and the denominators and multiply them by hand and make sure that the result will not get too big. The following code is poorly in terms of speed and memory, but it may be a good start:
for i=1:30
t = (55*i);
b = factorial(100*i) / (factorial(100*i-t) * factorial(t));
% binomial distribution
d = b * 0.5^(t) * 0.5^(100*i-(t));
numerators = 1:(100*i);
denominators = [1:(100*i-t),1:55*i,ones(1,100*i)*2];
value = 1;
while length(numerators) > 0 || length(denominators) > 0
if length(numerators) == 0
value = value/denominators(1);
denominators(1) = [];
elseif length(denominators) == 0
value = value* numerators(1);
numerators(1) = [];
elseif value > 10000
value = value/denominators(1);
denominators(1) = [];
else
value = value* numerators(1);
numerators(1) = [];
end
end
% cumulative
p = binocdf(1.1 * (100*i) * 0.5,100*i,0.5);
% >= AT LEAST
result = 1-p + value;
disp(result);
end
output:
0.1841
0.0895
0.0470
0.0255
0.0142
0.0080
0.0045
...
Take a look at the documentation of factorial:
Note that the factorial function grows large quite quickly, and
even with double precision values overflow will occur if N > 171.
For such cases consider 'gammaln'.
On your second iteration you are already doing factorial (200) which returns Inf and then Inf/Inf returns NaN.

How can I better parse variable time stamp information in Fortran?

I am writing code in gfortran to separate a variable time stamp into its separate parts of year, month, and day. I have written this code so the user can input what the time stamp format will be (ie. YEAR/MON/DAY, DAY/MON/YEAR, etc). This creates a total of 6 possible combinations. I have written code that attempts to deal with this, but I believe it to be ugly and poorly done.
My current code uses a slew of 'if' and 'goto' statements. The user provides 'tsfo', the time stamp format. 'ts' is a character array containing the time stamp data (as many as 100,000 time stamps). 'tsdelim' is the delimiter between the year, month, and day. I must loop from 'frd' (the first time stamp) to 'nlines' (the last time stamp).
Here is the relevant code.
* Choose which case to go to.
first = INDEX(tsfo,tsdelim)
second = INDEX(tsfo(first+1:),tsdelim) + first
if (INDEX(tsfo(1:first-1),'YYYY') .ne. 0) THEN
if (INDEX(tsfo(first+1:second-1),'MM') .ne. 0) THEN
goto 1001
else
goto 1002
end if
else if (INDEX(tsfo(1:first-1),'MM') .ne. 0) THEN
if (INDEX(tsfo(first+1:second-1),'DD') .ne. 0) THEN
goto 1003
else
goto 1004
end if
else if (INDEX(tsfo(1:first-1),'DD') .ne. 0) THEN
if (INDEX(tsfo(first+1:second-1),'MM') .ne. 0) THEN
goto 1005
else
goto 1006
end if
end if
first = 0
second = 0
* Obtain the Julian Day number of each data entry.
* Acquire the year, month, and day of the time stamp.
* Find 'first' and 'second' and act accordingly.
* Case 1: YYYY/MM/DD
1001 do i = frd,nlines
first = INDEX(ts(i),tsdelim)
second = INDEX(ts(i)(first+1:),tsdelim) + first
read (ts(i)(1:first-1), '(i4)') Y
read (ts(i)(first+1:second-1), '(i2)') M
read (ts(i)(second+1:second+2), '(i2)') D
* Calculate the Julian Day number using a function.
temp1(i) = JLDYNUM(Y,M,D)
end do
goto 1200
* Case 2: YYYY/DD/MM
1002 do i = frd,nlines
first = INDEX(ts(i),tsdelim)
second = INDEX(ts(i)(first+1:),tsdelim) + first
read (ts(i)(1:first-1), '(i4)') Y
read (ts(i)(second+1:second+2), '(i2)') M
read (ts(i)(first+1:second-1), '(i2)') D
* Calculate the Julian Day number using a function.
temp1(i) = JLDYNUM(Y,M,D)
end do
goto 1200
* Onto the next part of the code
1200 blah blah blah
I believe this code will work, but I do not think it is a very good method. Is there a better way to go about this?
It is important to note that the indices 'first' and 'second' must be calculated for each time stamp as the month and day can both be represented by 1 or 2 integers. The year is always represented by 4.
With only six permutations to handle I would just build a look-up table with the whole tsfo string as the key and the positions of year, month and day (1st, 2nd or 3rd) as the values. Any unsupported formats should produce an error, which I haven't coded below. When subsequently you loop though your ts list and split an item you know which positions to cast to the year, month and day integer variables:
PROGRAM timestamp
IMPLICIT NONE
CHARACTER(len=10) :: ts1(3) = ["2000/3/4 ","2000/25/12","2000/31/07"]
CHARACTER(len=10) :: ts2(3) = ["3/4/2000 ","25/12/2000","31/07/2000"]
CALL parse("YYYY/DD/MM",ts1)
print*
CALL parse("DD/MM/YYYY",ts2)
CONTAINS
SUBROUTINE parse(tsfo,ts)
IMPLICIT NONE
CHARACTER(len=*),INTENT(in) :: tsfo, ts(:)
TYPE sti
CHARACTER(len=10) :: stamp = "1234567890"
INTEGER :: iy = -1, im = -1, id = -1
END TYPE sti
TYPE(sti),PARAMETER :: stamps(6) = [sti("YYYY/MM/DD",1,2,3), sti("YYYY/DD/MM",1,3,2),&
sti("MM/DD/YYYY",2,3,1), sti("DD/MM/YYYY",3,2,1),&
sti("MM/YYYY/DD",2,1,3), sti("DD/YYYY/MM",3,1,2)]
TYPE(sti) :: thisTsfo
INTEGER :: k, k1, k2
INTEGER :: y, m, d
CHARACTER(len=10) :: cc(3)
DO k=1,SIZE(stamps)
IF(TRIM(tsfo) == stamps(k)%stamp) THEN
thisTsfo = stamps(k)
EXIT
ENDIF
ENDDO
print*,thisTsfo
DO k=1,SIZE(ts)
k1 = INDEX(ts(k),"/")
k2 = INDEX(ts(k),"/",BACK=.TRUE.)
cc(1) = ts(k)(:k1-1)
cc(2) = ts(k)(k1+1:k2-1)
cc(3) = ts(k)(k2+1:)
READ(cc(thisTsfo%iy),'(i4)') y
READ(cc(thisTsfo%im),'(i2)') m
READ(cc(thisTsfo%id),'(i2)') d
PRINT*,ts(k),y,m,d
ENDDO
END SUBROUTINE parse
END PROGRAM timestamp
I would encode the different cases in another way, like this:
module foo
implicit none
private
public encode_datecode
contains
integer function encode_datecode(datestr, sep)
character(len=*), intent(in) :: datestr, sep
integer :: first, second
character(len=1) :: c1, c2, c3
first = index(datestr, sep)
second = index(datestr(first+1:), sep) + first
c1 = datestr(1:1)
c2 = datestr(first+1:first+1)
c3 = datestr(second+1:second+1)
foo = num(c1) + 3*num(c2) + 9*num(c3)
end function encode_datecode
integer function num(c)
character(len=1) :: c
if (c == 'Y') then
num = 0
else if (c == 'M') then
num = 1
else if (c == 'D') then
num = 2
else
stop "Illegal character"
end if
end function num
end module foo
and then handle the legal cases (21, 15, 19, 7, 11, 5) in a SELECT statement.
This takes advantage of the fact that there won't be a 'YDDY/MY/YM' format.
If you prefer better binary or decimal readability, you can also multiply by four or by 10 instead of 3.

Resources