Convert tradingview's pine script to python in VScode - python

I want to convert the following Pine script to python to calculate the value for vwap1 variable without plotting the results, I just want to calculate the value for vwap1:
...
wapScore(pds) =>
mean = sum(volume*close,pds)/sum(volume,pds)
vwapsd = sqrt(sma(pow(close-mean, 2), pds) )
(close-mean)/vwapsd
vwap1 = input(48)
plot(vwapScore(vwap1),title="ZVWAP2-48",color=#35e8ff, linewidth=2,transp=0.75)
...
I have tried the following:
...
def calculate_SMA(ser, days):
sma = ser.rolling(window=days).mean()
return sma
def calculate_Zscore(pds, volume, close):
mean = sum(volume * close, pds) / sum(volume, pds)
vwapsd = np.sqrt(calculate_SMA(pow(close - mean, 2), pds))
return (close - mean) / vwapsd
...
And I am using calculate_Zscore function to calculate the value and add it to pandas dataframe but it gives me different values rather than the values on trading view

I just wanted to comment ...but my reputation cannot allow me :)
Surely the sum of pine script (tradingview) has a different type signature than the python sum.
In particular the second parameter has a totally different meaning.
In pine script sum(x,y) tells you the sliding sum of last y values of x (sum of x for y bars back).
In python sum(x,y) sum the iterable x and if y, the second parameter has passed (optional), this value is added to the sum of items of the iterable.So if your sum(x) == 4.5 then sum(x,10) == 14.5
So your code surely need to be changed at least on the use of this method
Hoping to be helpful

Related

Review RSI function - Python

does this RSI code looks correct for you?
RSI I'm getting with this code are very often touching oscillator peaks (0 or 100) when comparing to RSIs on different market data apps (TradingView etc.) they hardly ever do that.
Does this formula looks correct? I found it in quite old book Technical Traders Guide to Computer Analysis of the Futures Market. Also it returns almost identical results as RSI=100-(100-RS) where RS=AVG GAIN/AVG LOSS. But still I'm a bit mad that results are different comparing to RSIs available on the web...
#
# Formula used:
#
# RSI(n) = 100 * (avg_up(n) / (avg_up(n)+avg_down(n)))
#
# Where:
#
# avg_up = average percentage gain from n-periods
# avg_down = average percentage loss from n-periods
# n = number of periods to calculate averages
#
def calculate_percentage_gains_and_losses(prices):
percentage = {"gains":[0.0],
"losses":[0.0]}
for i in range(len(prices)-1):
diff=((float(prices[i + 1]) / float(prices[i]))*100)-100
if diff>=0:
percentage["gains"].append(diff)
percentage["losses"].append(0.0)
else:
percentage["losses"].append(abs(diff))
percentage["gains"].append(0.0)
return percentage
def calculate_avg_percentage_gains_and_losses(prices, gains, losses, periods):
avg_percentage = {"gains":[ 0.0 for x in range(periods - 1)],
"losses":[ 0.0 for x in range(periods - 1)]}
for i in range(periods,len(prices)+1):
avg_percentage["gains"].append(sum(gains[i - periods:i]) / periods)
avg_percentage["losses"].append(sum(losses[i - periods:i]) / periods)
return avg_percentage
def calculate_relative_strength_index(prices, periods):
percentage = calculate_percentage_gains_and_losses(prices)
avg_percentage = calculate_avg_percentage_gains_and_losses(prices, percentage["gains"], percentage["losses"], periods)
rsi_list=[0.0 for x in range(periods - 1)]
for i in range(periods - 1, len(prices)):
rsi = 100 * round((avg_percentage["gains"][i] / (avg_percentage["gains"][i] + avg_percentage["losses"][i])), 2)
rsi_list.append(rsi)
return rsi_list
EDIT
Here is the code after adjustment
def calculate_percentage_gains_and_losses(prices):
percentage = {"gains":[0.0],
"losses":[0.0]}
for i in range(len(prices)-1):
diff=((float(prices[i + 1]) / float(prices[i]))*100)-100
if diff>=0:
percentage["gains"].append(diff)
percentage["losses"].append(0.0)
else:
percentage["losses"].append(abs(diff))
percentage["gains"].append(0.0)
return percentage
def calculate_smoothed_avg_percentage_gains_and_losses(prices, gains, losses, periods):
avg_percentage = {"gains":[ 0.0 if i<(periods-1) else sum(gains[:periods]) / periods for i in range(periods)],
"losses":[ 0.0 if i<(periods-1) else sum(losses[:periods]) / periods for i in range(periods)]}
for i in range(periods, len(prices)):
avg_percentage["gains"].append((gains[i] + (avg_percentage["gains"][i-1]* (periods-1))) / periods)
avg_percentage["losses"].append((losses[i] + (avg_percentage["losses"][i-1]* (periods-1))) / periods)
return avg_percentage
def calculate_relative_strength_index(prices, periods):
percentage = calculate_percentage_gains_and_losses(prices)
avg_percentage = calculate_smoothed_avg_percentage_gains_and_losses(prices, percentage["gains"], percentage["losses"], periods)
rsi=[ 0.0 if i < (periods-1) else round((100 * (avg_percentage["gains"][i] / (avg_percentage["gains"][i] + avg_percentage["losses"][i]))),2) for i in range(len(prices))]
return rsi
Firstly, issues with formula:
your RSI formula is calculated differently to the usual. As you acknowledge, RS is normally calculated as (Avg gains)/(Avg losses) yet you use (Avg gains)/((Avg gains) + (Avg losses)). While there may be strong correlation between the two, they are two different formulas and will therefore give you different answers. Furthermore you use percentage gains/losses when most charting platforms use raw gains/losses. And finally, you use a simple average of the gains/losses (known as Cutler's RSI). The much more widely used Wells Wilder RSI uses a smoothed average given by:
Avg gain = (gain + (prev gain) * (period -1))/period
The upshot is you will get very different numbers.
Secondly, your code:
While I have not scrutinized your code with a fine tooth comb, there are several issues rendering the code, at best, inefficient. If you intend on continuing to code in Python you MUST learn AND understand list comprehension and how to use it. It is what makes Python so useful and powerful. You have used it merely to initialize some lists. There are many websites and books that cover list comprehension quite extensively, just google it.
Additionally, if you intend to use python to calculate series information on chronologically ordered data, I strongly recommend you import the pandas module and use DataFrames rather than lists. DataFrames are like database records that keeps all data neatly in the row they belong two and are easily manipulated. List will get messy as you try to line up the data.
I will not provide code at this point because I think you already have plenty to think a bout and work on but will happily help once you have understood the above.

Implied volatility calculation in Python

With the comments from the answer, I rewrote the code below (math.1p(x)->math.log(x)), which now should work and give a good approximation of the volatility.
I am trying to create a short code to calculate the implied volatility of a European Call option. I wrote the code below:
from scipy.stats import norm
import math
norm.cdf(1.96)
#c_p - Call(+1) or Put(-1) option
#P - Price of option
#S - Strike price
#E - Exercise price
#T - Time to expiration
#r - Risk-free rate
#C = SN(d_1) - Ee^{-rT}N(D_2)
def implied_volatility(Price,Stock,Exercise,Time,Rf):
P = float(Price)
S = float(Stock)
E = float(Exercise)
T = float(Time)
r = float(Rf)
sigma = 0.01
print (P, S, E, T, r)
while sigma < 1:
d_1 = float(float((math.log(S/E)+(r+(sigma**2)/2)*T))/float((sigma*(math.sqrt(T)))))
d_2 = float(float((math.log(S/E)+(r-(sigma**2)/2)*T))/float((sigma*(math.sqrt(T)))))
P_implied = float(S*norm.cdf(d_1) - E*math.exp(-r*T)*norm.cdf(d_2))
if P-(P_implied) < 0.001:
return sigma
sigma +=0.001
return "could not find the right volatility"
print implied_volatility(15,100,100,1,0.05)
This yields: 0.595 volatility which should be somewhere 0.3203. That is a huge difference...
I know this is not a fast method by any means, I just want to demonstrate how the principle works, but I am not able to calculate a good approximation.
For some reason when I call the function it gives me really bad approximation of the actual implied volatility which I calculated using a Matlab Program and the following webpage: Implied Volatility. Could anyone please help me to figure out where I made the mistake?
There are two problems I see, none of which are directly python related:
You are using log1p(x), which is the natural logarithm of 1+x, while you actually want log(x), which is the natural logarithm of x (cf. Wikipedia).
An option price of 100 is way to high considering the other parameters. Try to calculate the implied volatility for a price of 10 - which should be about 0.18 both by your program and the calculator you linked.
In Python2, the result of 5 / 2 is 2. It uses floor division. To fix that, make every number a float. In your implied_volatility function, change P = Price to P = float(Price), S = Stock to S = float(Stock), etc.

Inappropriate argument value (of correct type). in JES (Python/Jython)

Hey so I am just working on some coding homework for my Python class using JES. Our assignment is to take a sound, add some white noise to the background and to add an echo as well. There is a bit more exacts but I believe I am fine with that. There are four different functions that we are making: a main, an echo equation based on a user defined length of time and amount of echos, a white noise generation function, and a function to merge the noises.
Here is what I have so far, haven't started the merging or the main yet.
#put the following line at the top of your file. This will let
#you access the random module functions
import random
#White noise Generation functiton, requires a sound to match sound length
def whiteNoiseGenerator(baseSound) :
noise = makeEmptySound(getLength(baseSound))
index = 0
for index in range(0, getLength(baseSound)) :
sample = random.randint(-500, 500)
setSampleValueAt(noise, index, sample)
return noise
def multipleEchoesGenerator(sound, delay, number) :
endSound = getLength(sound)
newEndSound = endSound +(delay * number)
len = 1 + int(newEndSound/getSamplingRate(sound))
newSound = makeEmptySound(len)
echoAmplitude = 1.0
for echoCount in range (1, number) :
echoAmplitude = echoAmplitude * 0.60
for posns1 in range (0, endSound):
posns2 = posns1 + (delay * echoCount)
values1 = getSampleValueAt(sound, posns1) * echoAmplitude
values2 = getSampleValueAt(newSound, posns2)
setSampleValueAt (newSound, posns2, values1 + values2)
return newSound
I receive this error whenever I try to load it in.
The error was:
Inappropriate argument value (of correct type).
An error occurred attempting to pass an argument to a function.
Please check line 38 of C:\Users\insanity180\Desktop\Work\Winter Sophomore\CS 140\homework3\homework_3.py
That line of code is:
setSampleValueAt (newSound, posns2, values1 + values2)
Anyone have an idea what might be happening here? Any assistance would be great since I am hoping to give myself plenty of time to finish coding this assignment. I have gotten a similar error before and it was usually a syntax error however I don't see any such errors here.
The sound is made before I run this program and I defined delay and number as values 1 and 3 respectively.
Check the arguments to setSampleValueAt; your sample value must be out of bounds (should be within -32768 - 32767). You need to do some kind of output clamping for your algorithm.
Another possibility (which indeed was the error, according to further input) is that your echo will be out of the range of the sample - that is, if your sample was 5 seconds long, and echo was 0.5 seconds long; or the posns1 + delay is beyond the length of the sample; the length of the new sound is not calculated correctly.

Significant numbers digits of value by its error

I'm in need of a function returning only the significant part of a value with respect to a given error. Meaning something like this:
def (value, error):
""" This function takes a value and determines its significant
accuracy by its error.
It returns only the scientific important part of a value and drops the rest. """
magic magic magic....
return formated value as String.
What i have written so far to show what I mean:
import numpy as np
def signigicant(value, error):
""" Returns a number in a scintific format. Meaning a value has an error
and that error determines how many digits of the
value are signifcant. e.g. value = 12.345MHz,
error = 0.1MHz => 12.3MHz because the error is at the first digit.
(in reality drop the MHz its just to show why.)"""
xx = "%E"%error # I assume this is most ineffective.
xx = xx.split("E")
xx = int(xx[1])
if error <= value: # this should be the normal case
yy = np.around(value, -xx)
if xx >= 0: # Error is 1 or bigger
return "%i"%yy
else: # Error is smaller than 1
string = "%."+str(-xx) +"f"
return string%yy
if error > value: # This should not be usual but it can happen.
return "%g"%value
What I don't want is a function like numpys around or round. Those functions take a value and want to know what part of this value is important. The point is that in general I don't know how many digits are significant. It depends in the size of the error of that value.
Another example:
value = 123, error = 12, => 120
One can drop the 3, because the error is at the size of 10. However this behaviour is not so important, because some people still write 123 for the value. Here it is okay but not perfectly right.
For big numbers the "g" string operator is a usable choice but not always what I need. For e.g.
If the error is bigger than the value.( happens e.g. when someone wants to measure something that does not exist.)
value = 10, error = 100
I still wish to keep the 10 as the value because I done know it any better. The function should return 10 then and not 0.
The stuff I have written does work more or less, but its clearly not effective or elegant in any way. Also I assume this question does concern hundreds of people because every scientist has to format numbers in that way. So I'm sure there is a ready to use solution somewhere but I haven't found it yet.
Probably my google skills aren't good enough but I wasn't able to find a solution to this in two days and now I ask here.
For testing my code I used this the following but more is needed.
errors = [0.2,1.123,1.0, 123123.1233215,0.123123123768]
values = [12.3453,123123321.4321432, 0.000321 ,321321.986123612361236,0.00001233214 ]
for value, error in zip(values, errors):
print "Teste Value: ",value, "Error:", error
print "Result: ", signigicant(value, error)
import math
def round_on_error(value, error):
significant_digits = 10**math.floor(math.log(error, 10))
return value // significant_digits * significant_digits
Example:
>>> errors = [0.2,1.123,1.0, 123123.1233215,0.123123123768]
>>> values = [12.3453,123123321.4321432, 0.000321 ,321321.986123612361236,0.00001233214 ]
>>> map(round_on_error, values, errors)
[12.3, 123123321.0, 0.0, 300000.0, 0.0]
And if you want to keep a value that is inferior to its error
if (value < error)
return value
else
def round_on_error(value, error):
significant_digits = 10**math.floor(math.log(error, 10))
return value // significant_digits * significant_digits

Changing only the calculation in a function

Is it possible to have a function where you specify a function within it as a variable.
For example, I have two functions which follow exactly the same process, except one calculaate the Average using np.mean and the other calculates the standard deviation where only np.std is different.
i.e.
it would be defined:
def calculate(function)
you would call one in the script like:
calculate(mean)
and the other
calculate(std)
I'm just wondering if it is possible to do something like this s it would greatly reduce my script length.
EDIT
Sorry I should have said that I wanted the mean and std to be the ones predefined in numpy. getattr() in Xu's answer worked
Use getattr to get the method object according to the method name:
def calculate(function):
func = getattr(np, function)
func(...) # do what you want
calculate("mean") # calculate the average number
calculate("std") # calculate the standard deviation
Yes this is possible.
Example:
def addIt(x):
return x+x
def test(fn):
for x in xrange(5):
print fn(x)
test(addIt)
Output:
0
2
4
6
8
def f1(t): return t * 2
def f2(t): return t * t
def comb(t,f): return f(t)
print comb(10, f1)
print comb(10, f2)

Categories

Resources