
美国日历
-
2023年2月18日发(作者:)zipline中扩展上交所交易⽇历SHStockCalendar
zipline中扩展上交所交易⽇历SHStockCalendar
1获取⾮固定假期
国内市场主要包含上海证券交易所、深圳证券交易所、⾹港证券交易所、全国中⼩企业股份转让系统有限公司、中国⾦融期货交易所、上海
商品期货交易所、郑州商品期货交易所、⼤连商品期货交易所等,由于国内市场的节假⽇时间信息不像美国的有⽐较明确的规则,我们通过
adhoc_holidays把所有的⾮固定假期进⾏枚举,简单有效。当然,这种枚举的⽅式要定期对数据进⾏更新以确保准确性。有兴趣的也可以
试试⾃⼰整理国内市场节假⽇的规则。
下⾯我们就以国内股票交易市场(上交所)为例。
1.1获取股票的历史⾮固定假期
我们先从万得WindPy中获取国内股票市场的交易⽇(我们要注意下结束⽇期到当前年份结束,超过的时间数据不准确,使⽤时请⾃⼰验证
下),然后通过过周⼀⾄周五的时间序列减去交易⽇,就可以得到国内市场的历史⾮固定假期。
接⼝
万得WindPy的接⼝⽤于获取区间内⽇期序列。具体信息⼤家可以参考WindPy的接⼝⼿册。
1.3参考代码
下⾯是通过WindPy的接⼝获取历史⾮固定假期的参考代码,使⽤时请对数据进⾏更新以确保cn_adhoc_内容的准确
性,代码⽂件命名为get_cn_adhoc_。
#coding=utf-8
fromWindPyimport*
simportCustomBusinessDay
importpandasaspd
#结束⽇期可以超过当前年份,但是从wind得到的数据不准确,准确数据只到当年结束
start_date=\"1990-12-19\"#1990年12⽉19⽇上海证券交易所开始正式营业
end_base=amp(\'today\',tz=\'UTC\')
end_date=end_base+lta(days=365)#结束⽇期:下⼀年的当天
()
data=(start_date,end_date,\"Trading\")#获取区间内交易⽇的⽇期序列
df=ame([0])
start_date,end_date=df[0].iloc[[0,-1]]#设置开始⽇期和结束⽇期
weekmask=\'MonTueWedThuFri\'
cbday=CustomBusinessDay(weekmask=weekmask)#⾃定义⼯作⽇:周⼀⾄周五
dts=_range(start_date,end_date,freq=cbday)#⾃定义⼯作⽇在这段交易⽇期内的时间范围
#特定时段的⾮固定假期=⾃定义⼯作⽇在这段交易⽇期内的时间范围-这段交易⽇期内的交易⽇
df_adhoc_holidays=ame({\"date\":list(set(_series())-set(df[0]))}).sort_values(\'date\')
#将国内市场的⾮固定假期写⼊cn_adhoc_
df_adhoc_holidays[\'date\'].to_csv(\'cn_adhoc_\',index=False,date_format=\'%Y%m%d\')
2⾃定义上交所交易⽇历
我们参考utilscalendarsus_futures_来⾃定义继承TradingCalendar类的上海股票市场的交易⽇历TradingCalendar类。
2.1扩展上交所规则
⾸先,我们创建utilscalendarsexchange_calendar_⽂件,根据国内外市场的差异,结合上交所来定义⼀些规则。
扩展上交所的盘前集合竞价时间:
#上交所盘前集合竞价时间
call_auction_start=time(9,15)#9:15
call_auction_end=time(9,25)#9:25
扩展上交所的午休时间:
#上海证券交易所中午休息时间
lunch_break_start=time(11,30)#11:30
lunch_break_end=time(13,1)#13:00
扩展上交所科创板的盘后交易时间:
#上交所科创板的盘后固定交易时间
after_close_time=time(15,30)#15:30
定义上交所交易⽇历的开始时间:
start_default=amp(\'1990-12-19\',tz=\'UTC\')#上海证券交易所开始正式营业时间
交易⽇历的结束时间与美国市场可以⼀致,我们使⽤trading_calendark中的end_default
g_calendarimport(
end_default
)
2.2SHStockCalendar类
我们继承TradingCalendar类⾃定义上交所股票市场的交易⽇历SHStockCalendar
classSHStockCalendar(TradingCalendar):
现在,我们增加初始化函数来进⾏基本规则的设置
def__init__(self,start=start_default,end=end_default):
super(SHStockCalendar,self).__init__(start=start,end=end)
#增加午休时间
self._lunch_break_starts=days_at_time(_all_days,lunch_break_start,,0)
self._lunch_break_ends=days_at_time(_all_days,lunch_break_end,,0)
#在sessions中扩展午休时间,每⼀个sessions中包含开盘/收盘/午休开始/午休结束
le=ame(
index=_all_days,
columns=[\'market_open\',\'market_close\',\'lunch_break_start\',\'lunch_break_end\'],
data={
\'market_open\':self._opens,
\'market_close\':self._closes,
\'call_auction_start\':self._call_auction_start,
\'call_auction_end\':self._call_auction_end,
\'lunch_break_start\':self._lunch_break_starts,
\'lunch_break_end\':self._lunch_break_ends,
\'after_close_time\':self._after_close_time
},
dtype=\'datetime64[ns]\',
)
通过名称属性定义上海证券交易所交易⽇历的名称:
@property
defname(self):
return\"cn_sh_stock\"
通过时区属性定义使⽤上海时区
@property
deftz(self):
ne(\"Asia/Shanghai\")
定义上交所的开盘时间9:31
@property
defopen_time(self):
returntime(9,31)
定义上交所的收盘时间15:00
@property
defclose_time(self):
returntime(15,0)
定义上交所的⾮固定假期:
我们把⽣成的cn_adhoc_⽂件拷贝过来,放在同⼀级⽬录。我们编写函数从这个⽂件读取⾮固定假期。
def_get_from_file(filename,use_list=False):
withopen(filename,\'r\')asf:
data=nes()
ifuse_list:
return[int_to_date(str_to_int((\'n\')))foriindata]
else:
returnset([int_to_date(str_to_int((\'n\')))foriindata])
ifuse_list:
return[]
else:
returnset([])
def_get_adhoc_holidays(use_list=False):
data_file_path=(e(__file__),\'cn_adhoc_\')
return_get_from_file(data_file_path,use_list)
@property
defadhoc_holidays(self):
return[Timestamp(t,tz=)fortin_get_adhoc_holidays(use_list=True)]
获取每⼀个session的分钟数
@lazyval
def_minutes_per_session(self):
#上午的分钟数=午休开始时间-开盘时间
diff_am=_break__open
diff_am=(\'timedelta64[m]\')
#diff_am+1
#下午的分钟数=收盘时间-午休结束时间
diff_pm=__break_end
diff_pm=(\'timedelta64[m]\')
#diff_pm+1
returndiff_am+diff_pm+2
all_minutes获取⽇历中所有分钟的时间索引
@property
@remember_last
defall_minutes(self):
\"\"\"
ReturnsaDatetimeIndexrepresentingalltheminutesinthiscalendar.
\"\"\"
opens_in_ns=
self._(\'datetime64[ns]\')
closes_in_ns=
self._(\'datetime64[ns]\')
#扩展午休时间
lunch_break_start_in_ns=
self._lunch_break_(\'datetime64[ns]\')
lunch_break_ends_in_ns=
self._lunch_break_(\'datetime64[ns]\')
deltas_before_lunch=lunch_break_start_in_ns-opens_in_ns#上午
deltas_after_lunch=closes_in_ns-lunch_break_ends_in_ns#下午
#扩展上午分钟线根数
daily_before_lunch_sizes=(deltas_before_lunch/NANOS_IN_MINUTE)+1
#扩展下午分钟线根数
daily_after_lunch_sizes=(deltas_after_lunch/NANOS_IN_MINUTE)+1、
#全天分钟线根数
daily_sizes=daily_before_lunch_sizes+daily_after_lunch_sizes
num_minutes=(daily_sizes).astype(64)
all_minutes=(num_minutes,dtype=\'datetime64[ns]\')
idx=0
forday_idx,sizeinenumerate(daily_sizes):
#lotsofsmallallocations,butit\'sfastenoughfornow.
#lta64,soweneedtointit
size_int=int(size)
#扩展上午和下午的时间索引
before_lunch_size_int=int(daily_before_lunch_sizes[day_idx])
after_lunch_size_int=int(daily_after_lunch_sizes[day_idx])
all_minutes[idx:(idx+before_lunch_size_int)]=
(
opens_in_ns[day_idx],
lunch_break_start_in_ns[day_idx]+NANOS_IN_MINUTE,
NANOS_IN_MINUTE
)
all_minutes[(idx+before_lunch_size_int):(idx+size_int)]=
(
lunch_break_ends_in_ns[day_idx],
closes_in_ns[day_idx]+NANOS_IN_MINUTE,
NANOS_IN_MINUTE
)
idx+=size_int
returnDatetimeIndex(all_minutes).tz_localize(\"UTC\")
3使⽤SHExchangeCalendar
打开utilscalendarscalendar_⽂件,我们在_default_calendar_factories中加⼊上交所交易⽇历
_default_calendar_factories={
\'NYSE\':NYSEExchangeCalendar,
\'CME\':CMEExchangeCalendar,
\'ICE\':ICEExchangeCalendar,
\'CFE\':CFEExchangeCalendar,
\'BMF\':BMFExchangeCalendar,
\'LSE\':LSEExchangeCalendar,
\'TSX\':TSXExchangeCalendar,
\'us_futures\':QuantopianUSFuturesCalendar,
\'cn_sh_stock\':SHExchangeCalendar,
}
也可以通过register_calendar来注册
register_calendar(\"cn_sh_stock\",SHExchangeCalendar(),force=True)
后⾯我们可以通过get_calendar来使⽤
cn_calendar_=get_calendar(\"cn_sh_stock\")
4通过crontab更新历史⾮固定假期
打开,我们在setup的entry_points中加⼊cn-adhoc-holidays-sync=cn__cn_adhoc_holidays
这样我们可以在crontab中增加cn-adhoc-holidays-sync来更新⽂件
setup(
name=\'zipline\',
url=\"\",
version=_version(),
cmdclass=LazyBuildExtCommandClass(_cmdclass()),
description=\'Abacktesterforfinancialalgorithms.\',
entry_points={
\'console_scripts\':[
\'zipline=zipline.__main__:main\',
\'cn-adhoc-holidays-sync=cn__cn_adhoc_holidays\',
],
},