Conditional statement between today date and minus 3 months in Python - python-3.x

I am trying to insert 'NULL' values in a table depending on the date.
If the date is between todays date and 3 months backward (which will be february).
Then I want to update the 'NULL' values into each selected columns.
The Traceback is as following:
Traceback (most recent call last):
File "C:\projects\docs\script.py", line 41, in <module>
if dt < date_sql < dr3:
TypeError: '<' not supported between instances of 'datetime.datetime' and 'pyodbc.Row'
Been strugling for a long time, so really appreciate your guidance as I have tried to find a solution.
Python code is:
import pyodbc
from datetime import date, datetime
import dateutil.relativedelta
conn = pyodbc.connect(
r'DRIVER={SQL Server};'
r'SERVER=server;'
r'DATABASE=db;'
)
dt = datetime.today()
dr3 = dt - dateutil.relativedelta.relativedelta(months=3)
print(dr3)
cursor = conn.cursor()
sent_date = cursor.execute("""SELECT TOP 30 sent_date, id
FROM Department.Customer""")
def fetch_date():
for row in sent_date:
r = row
print(r)
return r
date_sql = fetch_date()
if dt < date_sql < dr3:
try:
value = None
cursor.execute("""UPDATE Department.Customer SET name=?, address=?, email=?,
phone=?""", (value, value, value, value))
cursor.commit()
except pyodbc.Error as ex:
print(str(ex))
cursor.rollback()
cursor.close()
Output from print(dr3) is:
2018-02-28 17:19:50.452290
Output from print(r) in fetch_date() function is:
(datetime.datetime(2018, 5, 22, 10, 21, 36), 1)
(datetime.datetime(2018, 5, 22, 10, 21, 36), 2)
(datetime.datetime(2018, 5, 22, 10, 21, 36), 3)
...

Related

Date Difference QuantLib

I want to calculate days difference between the dates using 360 days basis .Code is as per below but is not working
import QuantLib as ql
import pandas as pd
issueDate = ql.Date(15, 3, 2020)
maturityDate = ql.Date(15, 1, 2025)
tenor = ql.Period(ql.Semiannual)
calendar = ql.UnitedStates()
businessConvention = ql.Unadjusted
dateGeneration = ql.DateGeneration.Backward
monthEnd = False
schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, businessConvention,
businessConvention, dateGeneration, monthEnd)
dateList = list(schedule)
def calculateInterOrderTime(dateList):
result = map(lambda x: [i / np.timedelta64(1, 'D') for i in np.diff([c for c in x])[0]],dateList)
print(list(result))
I want to achieve results as per below
[120,180,180,180,180,180,180,180,180,180,180]
I will appreciate if someone can help me in achieving the results. Thanking you in advance.
For example:
dates = [*schedule]
[int(ql.Thirty360().yearFraction(start, end)*360) for start, end in zip(dates[:-1], dates[1:])]
[120, 180, 180, 180, 180, 180, 180, 180, 180, 180]

backtrader printing data feed vaues does not print hours and minues and defaults to

I'm learning to use backtrader and I've come across a problem when trying to print out the datafeed. It correctly prints the day, open, high, low, close and volume but the hour and minutes data seems to default to 23:59:59.999989 on every line.
Here is a sample of the data source:
datetime,open,high,low,close,volume,,
11/2/2020 9:30,330.187,330.188,329.947,330.038,4.79,,
11/2/2020 9:31,330.038,330.438,329.538,329.677,5.49,,
11/2/2020 9:32,329.667,330.248,329.577,330.117,5.8,,
11/2/2020 9:33,330.128,330.328,329.847,329.948,5.59,,
11/2/2020 9:34,329.967,330.308,329.647,329.698,6.24,,
and the code I use to add the data to backtrader is:
data = bt.feeds.GenericCSVData(
dataname = 'SPY_11_2020_1M.txt',
name= 'SPY',
datetime = 0,
dtformat = ('%m/%d/%Y %H:%M'),
period = bt.TimeFrame.Ticks,
compression = 1,
fromdate = params['fromdate'],
todate = params['todate'],
open = 1,
high = 2,
low = 3,
close = 4,
volume = 5,
openinterest = -1,
)
cerebro.adddata(data)
my code for the trategy, which is a simple buy and hold strategy, is:
import backtrader as bt
from datetime import datetime as dt
class BuyHold(bt.Strategy):
def __init__(self):
# self.time = self.datas[0].datetime.datetime(0),
self.open = self.datas[0].open
self.high = self.datas[0].high
self.low = self.datas[0].low
self.close = self.datas[0].close
self.volume = self.datas[0].volume
def next(self):
print('{0} {1}\t{2}\t{3}\t{4}\t{5}\t{6}'.format(
self.datas[0].datetime.date(0),
self.datas[0].datetime.time(0),
self.open[0],
self.high[0],
self.low[0],
self.close[0],
self.volume[0]
))
# print('{0}\t{1}\t{2}\t{3}\t{4}\t{5}'.format(
# self.time,
# self.open[0],
# self.high[0],
# self.low[0],
# self.close[0],
# self.volume[0]
# ))
if self.position.size == 0:
size = int(self.broker.getcash() / self.data)
self.buy(size = size)
The printout I get is as:
2020-11-02 23:59:59.999989 330.187 330.188 329.947 330.038 4.79
2020-11-02 23:59:59.999989 330.038 330.438 329.538 329.677 5.49
2020-11-02 23:59:59.999989 329.667 330.248 329.577 330.117 5.8
2020-11-02 23:59:59.999989 330.128 330.328 329.847 329.948 5.59
2020-11-02 23:59:59.999989 329.967 330.308 329.647 329.698 6.24
I also tried it with the commented out self.time with the commented out print line which provides similar result in a slightly different format as:
(datetime.datetime(2020, 11, 2, 23, 59, 59, 999989),) 330.187 330.188 329.947 330.038 4.79
(datetime.datetime(2020, 11, 2, 23, 59, 59, 999989),) 330.038 330.438 329.538 329.677 5.49
(datetime.datetime(2020, 11, 2, 23, 59, 59, 999989),) 329.667 330.248 329.577 330.117 5.8
(datetime.datetime(2020, 11, 2, 23, 59, 59, 999989),) 330.128 330.328 329.847 329.948 5.59
(datetime.datetime(2020, 11, 2, 23, 59, 59, 999989),) 329.967 330.308 329.647 329.698 6.24
(datetime.datetime(2020, 11, 2, 23, 59, 59, 999989),) 329.698 330.198 329.568 329.948 6.51
I don't know what I'm missing here.
struggle with the problem some days,i use isoformat to read the time and date
strategy
class my_strategy1(bt.Strategy):
def log(self, txt, dt=None):
''' Logging function for this strategy'''
# dt = dt or self.datas[0].datetime.date(0)
#the fellowing will print date ,that is,2021-08-06
print(self.datas[0].datetime.date(0).isoformat())
#the fellowing will print time,that is,08:09:01
print(self.datas[0].datetime.time(0).isoformat())
print(txt)
def __int__(self):
pass
def next(self):
self.log('Close, %.2f' % self.dataclose[0])
print("trend is", self.datas[0].lines.trend[0])
pass
data class
class My_CSVData(bt.feeds.GenericCSVData):
"""
如何添加格外的数据列在excel中进行处理
how to append the other data to csv
"""
lines = ('trend',)
params = (
('trend', -1),
)
def get_data_via_excel(path):
datatest=My_CSVData(
dataname=path,
timeframe=bt.TimeFrame.Minutes,
compression=60,
dtformat='%Y-%m-%d %H:%M:%S',
tmformat = '%H:%M:%S',
fromdate = datetime(2021,4,16),
todate = datetime(2021,7,30),
datetime = 0,
high=2,
open =1,
close=4,
low =3,
volume=5,
openinterest =6,
trend = 7 ,#not use -1
)
return datatest
data source
datetime,open,high,low,close,volume,openinterest,trend
2021-04-16 09:59:00,5138,5144,5109,5117,200,0,-2
2021-04-16 11:00:00,5117,5122,5089,5102,200,0,-2
2021-04-16 11:29:00,5103,5118,5096,5105,200,0,-1
2021-04-16 14:00:00,5105,5152,5105,5142,200,0,0
2021-04-16 15:00:00,5141,5142,5111,5116,200,0,1
2021-04-16 21:59:00,5122,5141,5116,5129,200,0,0
2021-04-16 23:00:00,5128,5136,5108,5120,200,0,0
This problem also took me few hours. And I find the solution from another web.
Here.
For minute data tell cerebro that you are using minute data (timeframe) and how many minutes per bar (compression).
data = bt.feeds.GenericCSVData(
dataname = 'SPY_11_2020_1M.txt',
name= 'SPY',
datetime = 0,
dtformat = ('%m/%d/%Y %H:%M'),
**timeframe=bt.TimeFrame.Minutes,**
period = bt.TimeFrame.Ticks,
compression = 1,
fromdate = params['fromdate'],
todate = params['todate'],
open = 1,
high = 2,
low = 3,
close = 4,
volume = 5,
openinterest = -1,
)

Numeric value as a string and convert to actual numeric

I found this thread how to make a variable change from the text "1m" into "1000000" in python
My string values are in a column within a pandas dataframe. The string/0bkects values are like 18M, 345K, 12.9K, 0, etc.
values = df5['Values']
multipliers = { 'k': 1e3,
'm': 1e6,
'b': 1e9,
}
pattern = r'([0-9.]+)([bkm])'
for number, suffix in re.findall(pattern, values):
number = float(number)
print(number * multipliers[suffix])
Running the code gives this error:
Traceback (most recent call last):
File "c:/Users/thebu/Documents/Python Projects/trading/screen.py", line 19, in <module>
for number, suffix in re.findall(pattern, values):
File "C:\Users\thebu\Anaconda3\envs\trading\lib\re.py", line 223, in findall
return _compile(pattern, flags).findall(string)
TypeError: expected string or bytes-like object
Thanks
Here's another way using regex:
import re
def get_word(s):
# find word
r = re.findall(r'[a-z]', s)
# find numbers
w = re.findall(r'[0-9]', s)
if len(r) > 0 and len(w) > 0:
r = r[0]
v = multipliers.get(r, None)
if v:
w = int(''.join(w))
w *= v
return round(w)
df['col2'] = df['col'].apply(get_word)
print(df)
col col2
0 10k 10000
1 20m 20000000
Sample Data
df = pd.DataFrame({'col': ['10k', '20m']})

Why is there a difference between datetime.utcnow() and datetime.now(timezone('UTC'))?

As you can see from the snippet below, there's a one hour difference between the two method. What is the reason ?
from datetime import datetime
from pytz import timezone
import time
def timestamp2date(timestamp):
# function converts a UTC timestamp into Europe/Zurich Gregorian date
DATE_TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
utcTimeStamp = datetime.fromtimestamp(int(timestamp)).replace(tzinfo=timezone('UTC'))
return utcTimeStamp.astimezone(timezone('Europe/Zurich')).strftime(DATE_TIME_FORMAT)
timeStampUTC_1 = time.mktime(datetime.utcnow().timetuple())
print(timeStampUTC_1)
print(timestamp2date(timeStampUTC_1))
timeStampUTC_2 = time.mktime(datetime.now(timezone('UTC')).timetuple())
print(timeStampUTC_2)
print(timestamp2date(timeStampUTC_2))
print(timeStampUTC_2 - timeStampUTC_1)
# 1504385450.0
# 2017-09-03 00:50:50 this the right time
# 1504389050.0
# 2017-09-03 01:50:50
# 3600.0
The reason is that datetime.timetuple() sets dst=-1 if the datetime is not offset aware and dst=0 or 1 when it is offset aware.
From the documentation:
The tm_isdst flag of the result is set according to the dst() method: tzinfo is None or dst() returns None, tm_isdst is set to -1; else if dst() returns a non-zero value, tm_isdst is set to 1; else tm_isdst is set to 0.
In []:
datetime.utcnow()
Out[]:
datetime.datetime(2017, 9, 2, 23, 9, 12, 715042)
In []:
print(datetime.utcnow().dst())
Out[]:
None
In []:
datetime.now(timezone('UTC'))
Out[]:
datetime.datetime(2017, 9, 2, 23, 9, 15, 856983, tzinfo=<UTC>)
In []:
datetime.now(timezone('UTC')).dst()
Out[]
datetime.timedelta(0)
In []:
datetime(2017, 9, 2, 23, 9, 15, 856983).timetuple()
Out[]:
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=23, tm_min=9,
tm_sec=15, tm_wday=5, tm_yday=245, tm_isdst=-1)
^^
In []:
datetime(2017, 9, 2, 23, 9, 15, 856983, timezone('UTC')).timetuple()
Out[]:
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=23, tm_min=9,
tm_sec=15, tm_wday=5, tm_yday=245, tm_isdst=0)
^
This changes the timestamp that time.mktime() generates because mktime treats -1 unknown and uses localtime, so may calculate dst=1 and hence they could be an 1 hour different (3600s):
In []:
time.mktime(datetime(2017, 9, 2, 23, 9, 15, 856983).timetuple())
Out[]:
1504411755.0
In []:
time.mktime(datetime(2017, 9, 2, 23, 9, 15, 856983, timezone('UTC')).timetuple())
Out[]:
1504415355.0
Here's the result of my further exploration of the timezone concept associated with the daylight saving time flag. The code is pretty straightforward.
To summarize the results, there's a right way to handle date/time information:
Date/time object must be localized
If localized correctly, the date/time object shows right daylight saving time information
This is reflected when you convert your localized date/time object to a UTC date/time object which is by definition DST agnostic
All those considerations are particularly relevant when, for example, you access a stock or currency historical minute rate API
code:
from datetime import datetime
from pytz import timezone
import time
print("---- Winter time (CET=Central European Time) ----")
dateStr = "2014-02-28 22:28:15"
datetimeObjUnlocalized = datetime.strptime(dateStr, "%Y-%m-%d %H:%M:%S")
print('UNL: ' + datetimeObjUnlocalized.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjUnlocalized-->tm_isdst=' + str(datetimeObjUnlocalized.timetuple()[8]))
datetimeObjZH = timezone('Europe/Zurich').localize(datetimeObjUnlocalized)
print('ZH: ' + datetimeObjZH.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjZH-->tm_isdst=' + str(datetimeObjZH.timetuple()[8]))
print("UTC: " + datetimeObjZH.astimezone(timezone('UTC')).strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print("\n---- Summer time (CEST=Central European Summer Time) ----")
dateStr = "2014-06-28 22:28:15"
datetimeObjUnlocalized = datetime.strptime(dateStr, "%Y-%m-%d %H:%M:%S")
print('UNL: ' + datetimeObjUnlocalized.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjUnlocalized-->tm_isdst=' + str(datetimeObjUnlocalized.timetuple()[8]))
datetimeObjZH = timezone('Europe/Zurich').localize(datetimeObjUnlocalized)
print('ZH: ' + datetimeObjZH.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjZH-->tm_isdst=' + str(datetimeObjZH.timetuple()[8]))
print("UTC: " + datetimeObjZH.astimezone(timezone('UTC')).strftime("%Y-%m-%d %H:%M:%S %Z%z"))

Ignore unconverted data from date-time stamp when using strptime

A third party API returns me a CSV data containing date time stamp like this:
dtval = '2016-10-14 05:09:30+00:00'
I have to convert it in the format : mm/dd/yyyy.
Here I'm not sure about last +XX:XX of directive:
datetime.datetime.strptime(dtval, "%Y-%m-%d %H:%M:%S+XX:XX").strftime('%m/%d/%Y')
I tried followings but did not work:
>>>datetime.datetime.strptime('2016-10-14 05:09:30+00:00', '%Y-%m-%d %H:%M:%S')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/_strptime.py", line 500, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "/usr/lib/python3.5/_strptime.py", line 340, in _strptime
data_string[found.end():])
ValueError: unconverted data remains: +00:00
>>>datetime.datetime.strptime('2016-10-14 05:09:30+00:00', "%Y-%m-%d %H:%M:%S%z")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/_strptime.py", line 500, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "/usr/lib/python3.5/_strptime.py", line 337, in _strptime
(data_string, format))
ValueError: time data '2016-10-14 05:09:30+00:00' does not match format '%Y-%m-%d %H:%M:%S+%z'
Is there any option in the Python3.4+'s datetime module to ignore remainging unconverted data?
I gone through this but did not find any such option
After a little bit research I found this fix in django's source code :
class FixedOffset(tzinfo):
"""
Fixed offset in minutes east from UTC. Taken from Python's docs.
Kept as close as possible to the reference version. __init__ was changed
to make its arguments optional, according to Python's requirement that
tzinfo subclasses can be instantiated without arguments.
"""
def __init__(self, offset=None, name=None):
if offset is not None:
self.__offset = timedelta(minutes=offset)
if name is not None:
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return timedelta(0)
def get_timezone(offset):
"""
Returns a tzinfo instance with a fixed offset from UTC.
"""
if isinstance(offset, timedelta):
offset = offset.seconds // 60
sign = '-' if offset < 0 else '+'
hhmm = '%02d%02d' % divmod(abs(offset), 60)
name = sign + hhmm
return FixedOffset(offset, name)
def custom_strptime(self, value):
"""Parses a string and return a datetime.datetime.
This function supports time zone offsets. When the input contains one,
the output uses a timezone with a fixed offset from UTC.
Raises ValueError if the input is well formatted but not a valid datetime.
Returns None if the input isn't well formatted.
"""
datetime_re = re.compile(
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})'
r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$'
)
match = datetime_re.match(value)
if match:
kw = match.groupdict()
if kw['microsecond']:
kw['microsecond'] = kw['microsecond'].ljust(6, '0')
tzinfo = kw.pop('tzinfo')
if tzinfo == 'Z':
tzinfo = utc
elif tzinfo is not None:
offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
offset = 60 * int(tzinfo[1:3]) + offset_mins
if tzinfo[0] == '-':
offset = -offset
tzinfo = get_timezone(offset)
kw = {k: int(v) for k, v in kw.items() if v is not None}
kw['tzinfo'] = tzinfo
return datetime.datetime(**kw)

Resources