I am trying to rewrite this code to Python:
src = input.source(close, "Source")
volStop(src) =>
var max = src
var min = src
max := math.max(max, src)
min := math.min(min, src)
[max, min]
[max, min] = volStop(src)
plot(max, "Max", style=plot.style_cross)
Precisely I have a problem with these lines:
max := math.max(max, src)
min := math.min(min, src)
In Python I have a function, leta call it func1, and I want to get the same result the Pinescript is returning.
I have only tried for loop since from what I understand calling a function in Pinescript works kind of like for loop. And I tried to replicate the calculation but I couldn't achieve the expected results.
This is the line that is being plotted on Tradingview:
And this is the line that is being plotted in Python: the area that is framed with red square is the approximate area that is visible on Tradingview screenshot.
My current code:
maxmin = pd.DataFrame()
maxmin["max"] = price_df[f"{name_var}"]
maxmin["min"] = price_df[f"{name_var}"]
for i in range(price_df.shape[0]):
maxmin["max"].iloc[i] = max(maxmin["max"].shift(1).fillna(0).iloc[i], price_df[f"{name_var}"].iloc[i])
maxmin["min"].iloc[i] = min(maxmin["min"].shift(1).fillna(0).iloc[i], price_df[f"{name_var}"].iloc[i])
The name_var variable is set to 'Close' column.
How can I rewrite the Pinescript code to Python to get the same results?
Pine Script basically runs your code on every bar and store variables into a history (series). This is why you can access old data.
I think the problem here is you should give the same input data to get the same output. The calculation starts from the 1st available bar, where bar_index is 0. You can scroll to the left to see at which time the 1st bar is. Then your input data in python should be the same. Or you can restrict your Pine Script to start calculation like this:
start_time = input.time(timestamp("1 Jan 2023 00:00 +0000"), "Date")
// ...
volStop(src) =>
var max = src
var min = src
if time >= start_time
max := math.max(max, src)
min := math.min(min, src)
[max, min]
else
[na, na]
// ...
The python code doesn't need the shift and fillna. The input data should not have na at all, because you need the same data as on TradingView, which has no na. So the for cycle and the builtin max/min do the job:
for i in range(price_df.shape[0]):
maxmin["max"].iloc[i] = max(maxmin["max"].iloc[i], price_df[f"{name_var}"].iloc[i])
maxmin["min"].iloc[i] = min(maxmin["min"].iloc[i], price_df[f"{name_var}"].iloc[i])
But it is slow because of the iteration and value access one by one. You can use pandas methods here:
maxmin['max'] = price_df[name_var].cummax()
maxmin['min'] = price_df[name_var].cummin()
Related
As contributor to WUnderground not a problem to read via API-call the JSON-outputfile with Today's values for my station.
That JSON-file has a series of numbered 'bins', with the series growing with time from 00:00.
In each numbered 'bin' an equivalent dataset reporting values.
At the end of the day a few hundred 'bins' in the JSON-file.
Avoiding setup of a local database, to find an actual survey of Extremes_Today, it is required to periodically scan the latest JSON-file from bin0 till the latest added bin in a recursive way.
It means in some way to read each numbered bin, extract&evaluate values, jump to next bin, till last bin reached & processed.
Trying the 2 approaches below in a Python-script: these 2 script-segments just should check & report that a bin exists. The scriptlines till 442 do other jobs (incl. complete read-out of bin=0 for references), already running without error.
# Line 442 = In WU JSON-Output Today's Data find & process next Bin upto/incl. last Bin
# Example call-string for ToDay-info = https://api.weather.com/v2/pws/observations/all/1day?stationId=KMAHANOV10&format=json&units=m&apiKey=yourApiKey
# Extracting contents of the JSON-file by the scriptlines below
# page = urllib.urlopen('https://api.weather.com/v2/pws/observations/all/1day?stationId=KMAHANOV10&format=json&units=m&apiKey=yourApiKey')
# content_test = page.read()
# obj_test2 = json.loads(content_test)
# Extraction of a value is like
# Epochcheck = obj_test2['observations'][Bin]['epoch']
# 'epoch' is present as element in all bins of the JSON-file (with trend related to the number of the bin) and therefore choosen as key for scan & search. If not found, then that bin not existing = passed last present bin
# Bin [0] earlier separately has been processed => initial contents at 00:00 = references for Extremes-search
# GENERAL setup of the scanning function:
# Bin = 0
# while 'epoch' exists
# Read 'epoch' & translate to CET/LocalTime
# Compare values of Extremes in that bin with earlier Extremes
# if hi_value higher than hiExtreme => new hiExtreme & adapt HiTime (= translated 'epoch')
# if low_value lower than LowExtreme => new lowExtreme & adapt LowTime (= translated 'epoch')
# Bin = Bin + 1
# Approach1
Bin = 0
Epochcheck = obj_test2['observations'][0]['epoch']
try:
Epochcheck = obj_test2['observations'][Bin]['epoch']
print(Bin)
Bin += 1
except NameError:
Epochcheck = None
# Approach2
Bin = 0
Epochcheck = obj_test2['observations'][0]['epoch']
While Epochcheck is not None:
Epochcheck = obj_test2['observations'][Bin]['epoch']
Print(Bin)
Bin += 1
Approach1 does not throw an error, but it steps out at Bin = 1.
Approach2 reports a syntax error.
File "/home/pi/domoticz/scripts/python/URL_JSON_WU_to_HWA_Start01a_0186.py", line 476
While Epochcheck is not None:
^
SyntaxError: invalid syntax
Apparently the checkline with dynamically variable contents for Bin cannot be set up in this way: the dynamic setting of variable Bin must be inserted/described in a different way.
Epochcheck = obj_test2['observations'][Bin]['epoch']
What is in Python the appropriate way to perform such JSON-scanning using a dynamic variable [Bin]?
Or simpler way of scan&extract a series of Bins in a JSON-file?
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
I have a csv file and the data pattern like this:
I am importing it from csv file. In input data, there are some whitespaces and I am handling it by using pattern as above. For output, I want to write a function that takes this file as an input and prints the lowest and highest blood pressure. Also, it will return average of all mean values. On the other side, I should not use pandas.
I wrote below code blog.
bloods=open(bloodfilename).read().split("\n")
blood_pressure=bloods[4].split(",")[1]
pattern=r"\s*(\d+)\s*\[\s*(\d+)-(\d+)\s*\]"
re.findall(pattern,blood_pressure)
#now extract mean, min and max information from the blood_pressure of each patinet and write a new file called blood_pressure_modified.csv
pattern=r"\s*(\d+)\s*\[\s*(\d+)-(\d+)\s*\]"
outputfilename="blood_pressure_modified.csv"
# create a writeable file
outputfile=open(outputfilename,"w")
for blood in bloods:
patient_id, blood_pressure=bloods.strip.split(",")
mean=re.findall(pattern,blood_pressure)[0]
blood_pressure_modified=re.sub(pattern,"",blood_pressure)
print(patient_id, blood_pressure_modified, mean, sep=",", file=outputfile)
outputfile.close()
Output should looks like this:
This is a very simple kind of answer to this. No regex, pandas or anything.
Let me know if this is working. I can try making it work better for any case it doesn't work.
bloods=open("bloodfilename.csv").read().split("\n")
means = []
'''
Also, rather than having two list of mins and maxs,
we can have just one and taking min and max from this
list later would do the same trick. But just for clarity I kept both.
'''
mins = []
maxs = []
for val in bloods[1:]: #assuming first line is header of the csv
mean, ranges = val.split(',')[1].split('[')
means.append(int(mean.strip()))
first, second = ranges.split(']')[0].split('-')
mins.append(int(first.strip()))
maxs.append(int(second.strip()))
print(f'the lowest and the highest blood pressure are: {min(mins)} {max(maxs)} respectively\naverage of mean values is {sum(means)/len(means)}')
You can also create functions to perform small small strip stuff. That's usually a better way to code. I wrote this in bit hurry, so don't mind.
Maybe this could help with your question,
Suppose you have a CSV file like this, and want to extract only the min and max values,
SN Number
1 135[113-166]
2 140[110-155]
3 132[108-180]
4 40[130-178]
5 133[118-160]
Then,
import pandas as pd
df = pd.read_csv("REPLACE_WITH_YOUR_FILE_NAME.csv")
results = df['YOUR_NUMBER_COLUMN'].apply(lambda x: x.split("[")[1].strip("]").split("-"))
with open("results.csv", mode="w") as f:
f.write("MIN," + "MAX")
f.write("\n")
for i in results:
f.write(str(i[0]) + "," + str(i[1]))
f.write("\n")
f.close()
After you ran the snippet after without any errors then in your current working directory their should be a file named results.csv Open it up and you will have the results
I want to extract all coordinates out of a table which are inside a given radius.
How do I need to set the for loop?
I use the haversine formula for this and I just enter the lat and lon values of the center point and the lat and lon values of the point to be tested if it is in the given radius.
So I thought I need a for-loop where I run the haversine formula for each row of the lat and lon column and if the cooridnates are inside the radius i save them in an list.
#Get coordinates
#Center coordinates = nearest road location
lat1 = float(lowParkingUtilization.iloc[roadIndex].toLat)
lon1 = float(lowParkingUtilization.iloc[roadIndex].toLon)
#Test coordinates = scooter coordinates
insideRadius = []
radius = 2.50 # in kilometer
for i in eScooterVOI['lat']:
lat2 = float(eScooterVOI['lat'][i])
lon2 = float(eScooterVOI['lon'][i])
a = haversine(lon1, lat1, lon2, lat2)
if a <= radius:
insideRadius += str(lon2)+","+str(lat2)
else:
With the given code I get following error message:
File "<ipython-input-574-02dadebee55c>", line 18
^
SyntaxError: unexpected EOF while parsing
The correct answer for the question "How do I need to set the for loop?" is: YOU DON'T. pandas dataframes are not for looping over their rows. What you DO need to do is the create two new columns in the dataframe, one to calculate the distance, and one to store the names in the format you want:
eScooterVOI['dist'] = eScooterVOI.apply(lambda x: haversine(lon1, lat1, x['lon'], x['lat']), axis=1)
eScooterVOI['name'] = eScooterVOI['lon'].astype(str) + ',' + eScooterVOI['lat'].astype(str)
And then, to get a list with only the names of the coordinates whose distance is less than the radius use:
insideRadius = list(eScooterVOI[eScooterVOI['dist'] <= radius]['name'])
btw: the haversine function can be built in a way that it recieves a pandas series instead of a value, and by that it could be implemented much faster than using df.apply, but that would require changing some code which is not here in the question.
The SyntaxError: unexpected EOF while parsing error message means that some of the code blocks were not completed and the end of the code has reached.
Your else block requires at least one line of code that should be in it.
For example:
else:
lots_of_code_to_write_here
You had this error because of your else block.
When Python reads it, it expects some code to be written. Python does not find any so an error occures.
Your code might be working laready, just delete the else block, you can use an if block without being bound to use an else one.
Anyway, if you absolutely want to use an else block try something like that :
if a <= radius:
insideRadius += str(lon2)+","+str(lat2)
else :
pass
But I do not think it is recommended.
I have 100s of .txt/.sed files with lots of lines in each.
Sample input file:
Time: 10:34:51.49,15:21:39.24
Box Temperature (K): 32.82,8.88,-10.07
Silicon Temperature (K): 10.90,9.88
Voltage: 7.52,7.41
Dark Mode: AUTO,AUTO
Radiometric Calibration: RADIANCE
Units: W/m^2/sr/nm
GPS Time: n/a
Satellites: n/a
Channels: 1024
Desired output:
Time 15:21:39.24
Box Temp 32.82
8.88
-10.07
Si Temp 10.90
9.88
I was trying to write the code for identifying the string and then making a list of the values and then later tackle arranging them into a DataFrame followed by writing them to a .csv file.
Sample code
testtxt = 'Temperature (K): 32.82,8.88,-10.07,32.66,8.94,-10.07'
exp = r'^Temperature (K):(\s*) ([0-9.]+)([0-9.]+), ([0-9.-]+) , (-[0-9-.]+),([0-9-.]+) , ([0-9-.]+),(-[0-9-.]+)'
regexp = re.compile(exp)
my_temp = regexp.search(txt)
print(my_temp.group(0))
ERROR:
AttributeError: 'NoneType' object has no attribute 'group'
Basically, it finds no match!
Clarification: I want an efficient way to only extract the Time and Temperature values, not the others. It would be great to be able to stop scanning the files once those are found since each file has over 500 lines and I have lots of them.
My suggestion would be to use string.startswith() to determine if the string starts with "Box Temperature (K)", or whatever. Once you find that, get the rest of the string, parse it as a CSV, and then validate each of the components. Trying to do this all with regular expressions is more trouble than it's worth.
If you want to have the code stop once it's found everything, just set flags for the things you want to find, and once all the flags are set you can exit. Something like:
foundTime = 0
foundBoxTemp = 0
foundSiTemp = 0
while (not end of file AND (foundTime == 0 || foundBoxTemp == 0 || foundSiTemp == 0))
if (line.startswith("Box Temperature (K):"))
// parse and output
else if (line.startswith("Time:"))
// parse and output
else ....