Here, you can see my code :
import datetime
DateS = datetime.datetime.strptime('30/03/2019 00:00:00',"%d/%m/%Y %H:%M:%S").timetuple().tm_hour
DateR = datetime.datetime.strptime('15/09/2019 00:00:00',"%d/%m/%Y %H:%M:%S").timetuple().tm_hour
ETP=ET0.copy()
for i in range(8760):
if i >= (DateS - 1) and i <= (DateR - 1) :
ETP[i] = ET0[i] * DB2.Kc[0]
else:
ETP[i] = ET0[i] * DB2.SolNu[0]
ETP[0] = 0
I want to get:
Date S = 2136 (day89 * 24hour = 2135)
Date R = 6192 (day258 * 24hour = 6192)
But I get:
Date S = 0
Date R = 0
When I use:
DateS = datetime.datetime.strptime('30/03/2019-00:00:00','%d/%m/%Y-%H:%M:%S').timetuple().tm_yday
DateR = datetime.datetime.strptime('15/09/2019-23:00:00','%d/%m/%Y-%H:%M:%S').timetuple().tm_yday
I get:
Date S = 89
Date R = 258
But I would like to get the 'hour step time'...
I try different datetime with strptime and timetupl but I never success.
try this code with tm_yday instead of tm_hour
DateS = datetime.datetime.strptime('30/03/2019-00:00:00','%d/%m/%Y-%H:%M:%S').timetuple().tm_yday * 24
DateR = datetime.datetime.strptime('15/09/2019-23:00:00','%d/%m/%Y-%H:%M:%S').timetuple().tm_yday * 24
and you will have the output you ask for.
Related
I would like to write a function that calculate working business hours in python, to do that I don't like to define a class and use python ready function to calculate.
I tried with following code but the code is not working well. I need to modify the code and change it for the hour instead of minutes too.
Do you have any suggestion?
def getminutes(datetime1,datetime2,worktiming=[9, 17]):
day_hours = (worktiming[1]-worktiming[0])
day_minutes = day_hours * 60 # minutes in a work day
weekends=[6, 7]
# Set initial default variables
dt_start = datetime1.datetime # datetime of start
dt_end = datetime2.datetime # datetime of end
worktime_in_seconds = 0
if dt_start.date() == dt_end.date():
# starts and ends on same workday
full_days = 0
if dt_start in [6, 7]:
return 0
else:
if dt_start.hour < worktiming[0]:
# set start time to opening hour
dt_start = datetime.datetime(
year=dt_start.year,
month=dt_start.month,
day=dt_start.day,
hour=worktiming[0],
minute=0)
if dt_start.hour >= worktiming[1] or \
dt_end.hour < worktiming[0]:
return 0
if dt_end.hour >= worktiming[1]:
dt_end = datetime.datetime(
year=dt_end.year,
month=dt_end.month,
day=dt_end.day,
hour=worktiming[1],
minute=0)
worktime_in_seconds = (dt_end-dt_start).total_seconds()
elif (dt_end-dt_start).days < 0:
# ends before start
return 0
else:
# start and ends on different days
current_day = dt_start # marker for counting workdays
while not current_day.date() == dt_end.date():
if not is_weekend(current_day):
if current_day == dt_start:
# increment hours of first day
if current_day.hour < worktiming[0]:
# starts before the work day
worktime_in_seconds += day_minutes*60 # add 1 full work day
elif current_day.hour >= worktiming[1]:
pass # no time on first day
else:
# starts during the working day
dt_currentday_close = datetime.datetime(
year=dt_start.year,
month=dt_start.month,
day=dt_start.day,
hour= worktiming[1],
minute=0)
worktime_in_seconds += (dt_currentday_close
- dt_start).total_seconds()
else:
# increment one full day
worktime_in_seconds += day_minutes*60
current_day += datetime.timedelta(days=1) # next day
# Time on the last day
if not is_weekend(dt_end):
if dt_end.hour >= worktiming[1]: # finish after close
# Add a full day
worktime_in_seconds += day_minutes*60
elif dt_end.hour < worktiming[0]: # close before opening
pass # no time added
else:
# Add time since opening
dt_end_open = datetime.datetime(
year=dt_end.year,
month=dt_end.month,
day=dt_end.day,
hour=worktiming[0],
minute=0)
worktime_in_seconds += (dt_end-dt_end_open).total_seconds()
return int(worktime_in_seconds / 60)
How can I modify the code that works with the following input ?
getminutes(2019-12-02 09:30:00,2019-12-07 12:15:00,worktiming=[9, 17])
You can use pd.bdate_range(datetime1, datetime2) to compute the number of working days. When converting worktiming to a pandas datetime, it is easy to compute the difference (in seconds) between the two datetimes:
import pandas as pd
datetime1 = "2019-12-02 09:30:00"
datetime2 = "2019-12-07 12:15:00"
def getminutes(datetime1, datetime2, worktiming=[9, 17]):
d1 = pd.to_datetime(datetime1)
d2 = pd.to_datetime(datetime2)
wd = pd.bdate_range(d1, d2) # working days
day_hours = (worktiming[1] - worktiming[0])
day_minutes = day_hours * 60 # minutes in a work day
day_seconds = day_minutes * 60 # seconds in a work day
full_days = len(wd)
day1 = datetime1[:10]
day2 = datetime2[:10]
dt1 = pd.to_datetime(day1 + " " + str(worktiming[0]) + ":00")
dt2 = pd.to_datetime(day2 + " " + str(worktiming[1]) + ":00")
ex1, ex2 = 0, 0
if day1 in wd:
ex1 = max(pd.Timedelta(d1 - dt1).seconds, 0)
if day2 in wd:
ex2 = max(pd.Timedelta(dt2 - d2).seconds, 0)
total_seconds = full_days * day_seconds - ex1 - ex2
total_minutes = total_seconds / 60
total_hours = total_minutes / 60
return int(total_minutes)
print(getminutes(datetime1, datetime2))
Output: 2370
I have a time range like this:
runtime_start = datetime.date(2021,1,1)
runtime_end = datetime.date(2022,3,1)
current_year = datetime.date.today().year
How can I calculate the number of month in the current_year?
Some Examples:
runtime_start = 2021,1,1 | runtime_end = 2022,3,1 | current_year = 2021 | output = 12
runtime_start = 2021,1,1 | runtime_end = 2021,6,1 | current_year = 2021 | output= 5
import datetime
runtime_start = datetime.date(2021,1,1)
runtime_end = datetime.date(2022,3,1)
current_year = datetime.date.today().year
def calculate_differentmonths(runtime_start, runtime_end, current_year):
if current_year == runtime_end.year:
run_months = runtime_end.month - runtime_start.month
else:
years_month = (current_year - runtime_start.year) * 12
run_months = datetime.date.today().month + years_month
return run_months
check the results:
print(calculate_differentmonths(runtime_start, runtime_end, current_year))
result 12
print(calculate_differentmonths(datetime.date(2021,1,1), datetime.date(2021,6,1), current_year))
result 5
You can estimate the amount of months by the .days of a timedelta:
import datetime
current_year = datetime.date.today().year
start_of_curr = datetime.date(current_year,1,1)
end_of_curr = datetime.date(current_year,12,31)
data = [(datetime.date(2021,1,1), datetime.date(2022,3,1), 12),
(datetime.date(2021,1,1), datetime.date(2021,6,1), 5)]
for runtime_start, runtime_end, months in data:
# limit the used start/end dates
frm = start_of_curr if runtime_start < start_of_curr else runtime_start
to = runtime_end if runtime_end <= end_of_curr else end_of_curr
print(int(round((to-frm).days / ((end_of_curr-start_of_curr).days/12),0)),
"vs expected: ", months)
Output:
12 vs expected: 12
5 vs expected: 5
I have a dataframe of OHLCV data. I would like to know if anyone knows any tutorial or any way of finding ADX(Average directional movement ) using pandas?
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import datetime as dt
import numpy as nm
start=dt.datetime.today()-dt.timedelta(59)
end=dt.datetime.today()
df=pd.DataFrame(yf.download("MSFT", start=start, end=end))
The average directional index, or ADX, is the primary technical indicator among the five indicators that make up a technical trading system developed by J. Welles Wilder, Jr. and is calculated using the other indicators that make up the trading system. The ADX is primarily used as an indicator of momentum, or trend strength, but the total ADX system is also used as a directional indicator.
Directional movement is calculated by comparing the difference between two consecutive lows with the difference between their respective highs.
For the excel calculation of ADX this is a really good video:
https://www.youtube.com/watch?v=LKDJQLrXedg&t=387s
I was playing with this a little bit and found something that can help you with the issue:
def ADX(data: pd.DataFrame, period: int):
"""
Computes the ADX indicator.
"""
df = data.copy()
alpha = 1/period
# TR
df['H-L'] = df['High'] - df['Low']
df['H-C'] = np.abs(df['High'] - df['Close'].shift(1))
df['L-C'] = np.abs(df['Low'] - df['Close'].shift(1))
df['TR'] = df[['H-L', 'H-C', 'L-C']].max(axis=1)
del df['H-L'], df['H-C'], df['L-C']
# ATR
df['ATR'] = df['TR'].ewm(alpha=alpha, adjust=False).mean()
# +-DX
df['H-pH'] = df['High'] - df['High'].shift(1)
df['pL-L'] = df['Low'].shift(1) - df['Low']
df['+DX'] = np.where(
(df['H-pH'] > df['pL-L']) & (df['H-pH']>0),
df['H-pH'],
0.0
)
df['-DX'] = np.where(
(df['H-pH'] < df['pL-L']) & (df['pL-L']>0),
df['pL-L'],
0.0
)
del df['H-pH'], df['pL-L']
# +- DMI
df['S+DM'] = df['+DX'].ewm(alpha=alpha, adjust=False).mean()
df['S-DM'] = df['-DX'].ewm(alpha=alpha, adjust=False).mean()
df['+DMI'] = (df['S+DM']/df['ATR'])*100
df['-DMI'] = (df['S-DM']/df['ATR'])*100
del df['S+DM'], df['S-DM']
# ADX
df['DX'] = (np.abs(df['+DMI'] - df['-DMI'])/(df['+DMI'] + df['-DMI']))*100
df['ADX'] = df['DX'].ewm(alpha=alpha, adjust=False).mean()
del df['DX'], df['ATR'], df['TR'], df['-DX'], df['+DX'], df['+DMI'], df['-DMI']
return df
At the beginning the values aren't correct (as always with the EWM approach) but after several computations it converges to the correct value.
Math was taken from here.
def ADX(df):
def getCDM(df):
dmpos = df["High"][-1] - df["High"][-2]
dmneg = df["Low"][-2] - df["Low"][-1]
if dmpos > dmneg:
return dmpos
else:
return dmneg
def getDMnTR(df):
DMpos = []
DMneg = []
TRarr = []
n = round(len(df)/14)
idx = n
while n <= (len(df)):
dmpos = df["High"][n-1] - df["High"][n-2]
dmneg = df["Low"][n-2] - df["Low"][n-1]
DMpos.append(dmpos)
DMneg.append(dmneg)
a1 = df["High"][n-1] - df["High"][n-2]
a2 = df["High"][n-1] - df["Close"][n-2]
a3 = df["Low"][n-1] - df["Close"][n-2]
TRarr.append(max(a1,a2,a3))
n = idx + n
return DMpos, DMneg, TRarr
def getDI(df):
DMpos, DMneg, TR = getDMnTR(df)
CDM = getCDM(df)
POSsmooth = (sum(DMpos) - sum(DMpos)/len(DMpos) + CDM)
NEGsmooth = (sum(DMneg) - sum(DMneg)/len(DMneg) + CDM)
DIpos = (POSsmooth / (sum(TR)/len(TR))) *100
DIneg = (NEGsmooth / (sum(TR)/len(TR))) *100
return DIpos, DIneg
def getADX(df):
DIpos, DIneg = getDI(df)
dx = (abs(DIpos- DIneg) / abs(DIpos + DIneg)) * 100
ADX = dx/14
return ADX
return(getADX(df))
print(ADX(df))
This gives you the exact numbers as Tradingview and Thinkorswim.
import numpy as np
def ema(arr, periods=14, weight=1, init=None):
leading_na = np.where(~np.isnan(arr))[0][0]
arr = arr[leading_na:]
alpha = weight / (periods + (weight-1))
alpha_rev = 1 - alpha
n = arr.shape[0]
pows = alpha_rev**(np.arange(n+1))
out1 = np.array([])
if 0 in pows:
out1 = ema(arr[:int(len(arr)/2)], periods)
arr = arr[int(len(arr)/2) - 1:]
init = out1[-1]
n = arr.shape[0]
pows = alpha_rev**(np.arange(n+1))
scale_arr = 1/pows[:-1]
if init:
offset = init * pows[1:]
else:
offset = arr[0]*pows[1:]
pw0 = alpha*alpha_rev**(n-1)
mult = arr*pw0*scale_arr
cumsums = mult.cumsum()
out = offset + cumsums*scale_arr[::-1]
out = out[1:] if len(out1) > 0 else out
out = np.concatenate([out1, out])
out[:periods] = np.nan
out = np.concatenate(([np.nan]*leading_na, out))
return out
def atr(highs, lows, closes, periods=14, ema_weight=1):
hi = np.array(highs)
lo = np.array(lows)
c = np.array(closes)
tr = np.vstack([np.abs(hi[1:]-c[:-1]),
np.abs(lo[1:]-c[:-1]),
(hi-lo)[1:]]).max(axis=0)
atr = ema(tr, periods=periods, weight=ema_weight)
atr = np.concatenate([[np.nan], atr])
return atr
def adx(highs, lows, closes, periods=14):
highs = np.array(highs)
lows = np.array(lows)
closes = np.array(closes)
up = highs[1:] - highs[:-1]
down = lows[:-1] - lows[1:]
up_idx = up > down
down_idx = down > up
updm = np.zeros(len(up))
updm[up_idx] = up[up_idx]
updm[updm < 0] = 0
downdm = np.zeros(len(down))
downdm[down_idx] = down[down_idx]
downdm[downdm < 0] = 0
_atr = atr(highs, lows, closes, periods)[1:]
updi = 100 * ema(updm, periods) / _atr
downdi = 100 * ema(downdm, periods) / _atr
zeros = (updi + downdi == 0)
downdi[zeros] = .0000001
adx = 100 * np.abs(updi - downdi) / (updi + downdi)
adx = ema(np.concatenate([[np.nan], adx]), periods)
return adx
I had a struggle for few days now and I really hope that someone here can help me.
I have tried everything to make this work for dates lower than year 2019 and it doesn't want to generate any date in range that is lower than year 2019.
You can try to change
tmpTo = '2018-05-31'
to
tmpTo = '2019-05-31'
and it will give output
Here is Demo code i made for preview that goes together with much more code:
from datetime import timedelta, date, datetime
import time
dateFrom = datetime.strptime('2019-01-01', "%Y-%m-%d")
dateTo = datetime.strptime('2019-01-10', "%Y-%m-%d")
plusDAYS = 0
todayPlus1 = dateFrom + timedelta(days=plusDAYS)
datesFromTo = []
visitUrl = []
def autoInput():
global dateTo
global dateFrom
tmpFrom = '2018-05-02'
tmpTo = '2018-05-31'
dateFrom = datetime.strptime(tmpFrom, "%Y-%m-%d")
dateTo = datetime.strptime(tmpTo, "%Y-%m-%d")
separator = ' * '
pausa0 = 2
pausa = 3
autoInput()
print(dateFrom)
print(dateTo)
print('----------------------------')
print('----------------------------')
def createDatesFromTo():
global datesFromTo
global todayPlus1
global plusDAYS
while dateTo >= todayPlus1:
todayPlus1 = dateFrom + timedelta(days=plusDAYS)
datesFromTo.append(todayPlus1.strftime('%Y-%m-%d'))
plusDAYS += 1
todayPlus1 = dateFrom + timedelta(days=plusDAYS)
createDatesFromTo()
print('PRINTS EVERYTHING LIST IS CONTAINING')
print(datesFromTo)
print('----------------------------')
print('----------------------------')
def createUrlForDates():
global visitUrl
#for i in range(len(datesFromTo)): # ORIGINAL
for i in range(5): # DEMO 5 ITEMS
tmp = datesFromTo[i]+"&tom="+datesFromTo[i]+""
visitUrl.append(tmp)
createUrlForDates()
for i in visitUrl:
print('URL RESULT ---> www.TEST.com/?from='+i)
I am trying to format this data monthly, but by the current date of the month.
import pandas as pd
import datetime
import quandl
import numpy as np
start = datetime.datetime(1993, 10, 2)
end = datetime.date.today()
df = quandl.get("FRED/DGS20", collapse="daily").reset_index()
df.index=np.arange(0,len(df))
print (df)
l=[]
for i in range(0,len(df)):
if (df['DATE'].loc[i]).day == (df['DATE'].loc[len(df)-1]).day:
l.append(df['DATE'].loc[i])
The issue I am running in to is if that date is on a weekend or a holiday, it skips the month. How can I get python to choose the closest applicable day of the month if the given day is N/A?
A bit long but no for loops! insert my code after your df.index=np.arange(0,len(df)) line:
years = pd.DatetimeIndex(df['DATE']).year
years_u = np.unique(years)
years_u_norm = years_u - years_u[0]
months = pd.DatetimeIndex(df['DATE']).month
months_u = np.unique(months)
months_u_norm = months_u - months_u[0]
days = pd.DatetimeIndex(df['DATE']).day
days_u = np.unique(days)
days_u_norm = days_u - days_u[0]
shp = (years_u_norm[-1]+1, months_u_norm[-1]+1, days_u_norm[-1]+1)
mat = np.full(shp, np.nan).ravel()
y_ind = years - years_u[0]
m_ind = months - months_u[0]
d_ind = days - days_u[0]
inds = np.vstack([y_ind[np.newaxis], m_ind[np.newaxis], d_ind[np.newaxis]])
inds2 = np.ravel_multi_index(inds, shp)
inds_grid = np.indices(shp)[2].ravel()
mat[inds2] = inds_grid[inds2]
start_ind = np.ravel_multi_index([[start.year - years_u[0]], [start.month - months_u[0]], [start.day - days_u[0]]], shp)
mat[:start_ind] = np.inf
end_ind = np.ravel_multi_index([[end.year - years_u[0]], [end.month - months_u[0]], [end.day - days_u[0] + 1]], shp)
mat[end_ind:] = np.inf
mat = mat.reshape(shp)
dist = np.absolute(mat - np.full(shp, end.day-1))
min_dist = np.nanargmin(dist, axis=2) + 1
inds_f = np.unique(np.ravel_multi_index(inds[:-1, :], shp[:-1]))
res_inds = np.indices(min_dist.shape)
res_y = res_inds[0].ravel()[inds_f] + years_u[0]
res_m = res_inds[1].ravel()[inds_f] + months_u[0]
res_d = min_dist.ravel()[inds_f]
df = pd.DataFrame({'year': res_y,
'month': res_m,
'day': res_d})
print(df)