gjdatac-api 0.2.9__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gjdatac_api
3
- Version: 0.2.9
3
+ Version: 0.3.1
4
4
  Summary: 数据接口打包
5
5
  Author: yin
6
6
  Author-email: 2018209921@qq.com
@@ -11,13 +11,13 @@ import pandas as pd
11
11
  import dolphindb as ddb
12
12
 
13
13
  from .dict_data import (get_price_frequency_dict, get_price_data_type_dict, get_instruments_type_dict,
14
- future_delivery_fee_return_fields, future_delivery_fee_return_fields_rename,
15
- future_margin_ratio_return_fields, future_margin_ratio_return_fields_rename,
16
- future_limit_position_return_fields, future_limit_position_return_fields_rename,
17
- main_contract_return_fields, main_contract_return_fields_rename,
18
- tick_main_contract_return_fields, tick_main_contract_return_fields_rename,
19
- gtja_mink_main_contract_return_fields, gtja_mink_main_contract_return_fields_rename
20
- )
14
+ future_delivery_fee_return_fields, future_delivery_fee_return_fields_rename,
15
+ future_margin_ratio_return_fields, future_margin_ratio_return_fields_rename,
16
+ future_limit_position_return_fields, future_limit_position_return_fields_rename,
17
+ main_contract_return_fields, main_contract_return_fields_rename,
18
+ tick_main_contract_return_fields, tick_main_contract_return_fields_rename,
19
+ gtja_mink_main_contract_return_fields, gtja_mink_main_contract_return_fields_rename
20
+ )
21
21
  from .dolphindb_info import *
22
22
  from .instrument_class import Instrument
23
23
 
@@ -406,6 +406,69 @@ class GJDataC:
406
406
  else:
407
407
  raise TypeError("输入类型必须是 datetime、date 或 对应格式的str")
408
408
 
409
+ @staticmethod
410
+ def validate_dates(start_date, end_date):
411
+ """
412
+ 校验日期合法性并比较先后关系
413
+
414
+ 参数:
415
+ start_date: 开始日期(可以是str/datetime/date类型)
416
+ end_date: 结束日期(可以是str/datetime/date类型)
417
+
418
+ 返回:
419
+ 如果日期合法且start_date <= end_date,返回(parsed_start, parsed_end)
420
+ 否则返回None
421
+ """
422
+
423
+ def parse_date(date_obj):
424
+ """将各种类型的日期统一转换为datetime.datetime对象"""
425
+ if isinstance(date_obj, datetime.datetime):
426
+ return date_obj
427
+ if isinstance(date_obj, datetime.date):
428
+ # 将date转换为datetime,时间部分设为00:00:00
429
+ return datetime.datetime.combine(date_obj, datetime.time.min)
430
+ if not isinstance(date_obj, str):
431
+ return None
432
+
433
+ # 移除可能存在的单引号
434
+ date_str = date_obj.strip("'\"")
435
+
436
+ # 尝试匹配各种日期格式
437
+ patterns = [
438
+ r'(\d{4})[-.](\d{1,2})[-.](\d{1,2})(?:\s+(\d{1,2}):(\d{1,2}):(\d{1,2}))?', # 带时间的格式
439
+ r'(\d{4})[-.](\d{1,2})[-.](\d{1,2})', # 不带时间的格式
440
+ r'(\d{4})(\d{2})(\d{2})' # 紧凑格式
441
+ ]
442
+
443
+ for pattern in patterns:
444
+ match = re.fullmatch(pattern, date_str)
445
+ if match:
446
+ groups = match.groups()
447
+ year, month, day = map(int, groups[:3])
448
+ try:
449
+ # 如果有时间部分则解析时间,否则设为00:00:00
450
+ if len(groups) > 3 and all(groups[3:6]):
451
+ hour, minute, second = map(int, groups[3:6])
452
+ return datetime.datetime(year, month, day, hour, minute, second)
453
+ return datetime.datetime(year, month, day)
454
+ except ValueError:
455
+ return None
456
+ return None
457
+
458
+ # 解析日期(统一转换为datetime对象)
459
+ parsed_start = parse_date(start_date)
460
+ parsed_end = parse_date(end_date)
461
+
462
+ # 检查日期是否有效
463
+ if not parsed_start or not parsed_end:
464
+ return None
465
+
466
+ # 比较日期时间
467
+ if parsed_start > parsed_end:
468
+ return None
469
+
470
+ return (parsed_start, parsed_end)
471
+
409
472
  """ get_price(获取行情数据接口) """
410
473
 
411
474
  def get_price(self, order_book_ids=None, asset_type="future", frequency=None, start_date=None, end_date=None,
@@ -427,6 +490,10 @@ class GJDataC:
427
490
  # self.get_price_data = self.get_price_data.sort_values(by='datetime', ascending=True)
428
491
 
429
492
  ''' 数据校验 (先对必填参数进行校验)'''
493
+ if start_date and end_date:
494
+ if not self.validate_dates(start_date, end_date):
495
+ return None
496
+
430
497
  # 对order_book_ids进行校验
431
498
  self.get_price_validate_order_book_ids(order_book_ids)
432
499
 
@@ -1105,6 +1172,10 @@ class GJDataC:
1105
1172
  """
1106
1173
 
1107
1174
  """ 校验参数 """
1175
+ if start_date and end_date:
1176
+ if not self.validate_dates(start_date, end_date):
1177
+ return None
1178
+
1108
1179
  data = self.get_trading_dates_validate_date_n_start_end(date, n, start_date, end_date, is_include_start,
1109
1180
  is_include_end, trade_time, date_count, date_type)
1110
1181
 
@@ -1186,7 +1257,6 @@ class GJDataC:
1186
1257
  if isinstance(end_date, str):
1187
1258
  end_date = self._get_trading_dates_by_start_end(end_date)
1188
1259
 
1189
-
1190
1260
  # 筛选 trading_day_str 列在 start_date 和 end_date 之间的数据
1191
1261
  # filtered_df = trading_params_data.loc[
1192
1262
  # (trading_params_data['trading_day_str'] >= start_date) & (
@@ -1799,6 +1869,10 @@ class GJDataC:
1799
1869
  """
1800
1870
 
1801
1871
  """ 校验参数 """
1872
+ if start_date and end_date:
1873
+ if not self.validate_dates(start_date, end_date):
1874
+ return None
1875
+
1802
1876
  self.get_active_contract_validate_params(commodity, start_date, end_date, frequency, compute_type, adjust_type,
1803
1877
  adjust_method)
1804
1878
 
@@ -2004,13 +2078,7 @@ class GJDataC:
2004
2078
  # 先从数据库获取数据
2005
2079
  tick_data, db_session = self.connect_db(table_name, db_path)
2006
2080
 
2007
- # 使用 strftime 方法将 Timestamp 转换为所需格式
2008
- formatted_dates = [ts.strftime('%Y.%m.%d') for ts in data['trading_day'].tolist()]
2009
-
2010
2081
  # 根据日期筛选数据
2011
- # 将日期转换成 DolphinDB 识别的日期格式,用于筛选数据
2012
- # start_dolphin_date = self.get_active_contract_datetime_to_dolphin_time(start_date)
2013
- # end_dolphin_date = self.get_active_contract_datetime_to_dolphin_time(end_date)
2014
2082
  start_dolphin_date = self.format_date(start_date)
2015
2083
  end_dolphin_date = self.format_date(end_date)
2016
2084
  date_data = tick_data.where(f"trading_day >= {start_dolphin_date} and trading_day <= {end_dolphin_date}")
@@ -2056,8 +2124,6 @@ class GJDataC:
2056
2124
  # else:
2057
2125
  # raise ValueError("start_date or end_date type error, please enter datetime.date type")
2058
2126
 
2059
-
2060
-
2061
2127
  self.format_date(start_date)
2062
2128
  self.format_date(end_date)
2063
2129
 
@@ -2208,6 +2274,10 @@ class GJDataC:
2208
2274
  """
2209
2275
 
2210
2276
  """ 校验参数 """
2277
+ if start_date and end_date:
2278
+ if not self.validate_dates(start_date, end_date):
2279
+ return None
2280
+
2211
2281
  self.get_basic_data_validate_params(order_book_id, asset_type, start_date, end_date)
2212
2282
 
2213
2283
  """ 获取数据 """
@@ -2326,7 +2396,6 @@ class GJDataC:
2326
2396
  start_dolphin_date = self.format_date(start_date)
2327
2397
  end_dolphin_date = self.format_date(end_date)
2328
2398
 
2329
-
2330
2399
  # 此处还需要判断的原因是,因为对 dolphindb 中不同的日期数据类型查询数据的语法不同
2331
2400
  asset_type_data = product_data.where(
2332
2401
  f"data_date>={start_dolphin_date} and data_date<={end_dolphin_date}") if asset_type == '库存' \
@@ -2409,6 +2478,10 @@ class GJDataC:
2409
2478
  """
2410
2479
 
2411
2480
  """ 校验必填参数 """
2481
+ if start_date and end_date:
2482
+ if not self.validate_dates(start_date, end_date):
2483
+ return None
2484
+
2412
2485
  # 校验commodity, start_date, end_date 是否为必填参数
2413
2486
  self.get_warehouse_stocks_future_validate_required_params(commodity, start_date, end_date)
2414
2487
 
@@ -2452,8 +2525,6 @@ class GJDataC:
2452
2525
  """
2453
2526
  校验参数类型是否为str
2454
2527
  :param commodity: str--必填,期货合约品种
2455
- :param start_date: str--必填,开始日期
2456
- :param end_date: str--必填,结束日期 (默认为策略当天日期的前一天)
2457
2528
  :return: None
2458
2529
  """
2459
2530
 
@@ -2506,8 +2577,6 @@ class GJDataC:
2506
2577
  :return: 过滤后的数据
2507
2578
  """
2508
2579
 
2509
-
2510
-
2511
2580
  start_date = self._get_warehouse_stocks_future_date_conversion(start_date)
2512
2581
  end_date = self._get_warehouse_stocks_future_date_conversion(end_date)
2513
2582
 
@@ -2551,6 +2620,10 @@ class GJDataC:
2551
2620
  """
2552
2621
 
2553
2622
  """ 校验必填参数 """
2623
+ if start_date and end_date:
2624
+ if not self.validate_dates(start_date, end_date):
2625
+ return None
2626
+
2554
2627
  # 校验oder_book_ids, start_date, end_date, frequency 是否为必填参数
2555
2628
  self.get_vwap_validate_required_params(order_book_ids, start_date, end_date, frequency)
2556
2629
 
@@ -2797,6 +2870,9 @@ class GJDataC:
2797
2870
  """
2798
2871
 
2799
2872
  """ 校验必填参数 """
2873
+ if start_date and end_date:
2874
+ if not self.validate_dates(start_date, end_date):
2875
+ return None
2800
2876
  # 校验oder_book_ids, start_date, end_date, frequency 是否为必填参数
2801
2877
  self.get_twap_validate_required_params(order_book_ids, start_date, end_date, frequency)
2802
2878
 
@@ -3086,7 +3162,7 @@ class GJDataC:
3086
3162
  """
3087
3163
 
3088
3164
  def get_history_bars(self, datetime_str=None, instrument_id=None, bar_count=None,
3089
- frequency=None, fields=None, start_date=None, end_date=None):
3165
+ frequency=None, fields=None, start_date=None, end_date=None):
3090
3166
  """
3091
3167
  (此接口根据接收的参数调用不同的功能函数)
3092
3168
  查询合约指定日期时间前的行情数据
@@ -3107,7 +3183,6 @@ class GJDataC:
3107
3183
  ValueError: 参数验证失败时抛出
3108
3184
  """
3109
3185
 
3110
-
3111
3186
  ''' 根据参数的不同,调用不同的函数 '''
3112
3187
  if datetime_str and bar_count is not None:
3113
3188
  # 参数验证
@@ -3205,7 +3280,6 @@ class GJDataC:
3205
3280
  # except ValueError:
3206
3281
  # raise ValueError("Invalid datetime format, should be 'YYYY-MM-DD HH:MM:SS'")
3207
3282
 
3208
-
3209
3283
  def _get_history_bar_execute_query(self, frequency, instrument_id, datetime_str, bar_count):
3210
3284
  """
3211
3285
  执行查询
@@ -3244,7 +3318,6 @@ class GJDataC:
3244
3318
  """
3245
3319
  contract_type = self.filter_contract_type(instrument_id)
3246
3320
 
3247
-
3248
3321
  if contract_type == "future":
3249
3322
  return {
3250
3323
  "1d": (history_future_day_db_table_name, history_future_day_db_path),
@@ -3358,6 +3431,10 @@ class GJDataC:
3358
3431
  """
3359
3432
 
3360
3433
  # 校验参数
3434
+ if start_date and end_date:
3435
+ if not self.validate_dates(start_date, end_date):
3436
+ return None
3437
+
3361
3438
  self.get_history_bars_validate_params(instrument_id, start_date, end_date, frequency, fields)
3362
3439
 
3363
3440
  # 查询数据
@@ -3452,9 +3529,8 @@ class GJDataC:
3452
3529
  table_data, bars_db_session = self.connect_db(table_info[0], table_info[1])
3453
3530
 
3454
3531
  # 转换日期格式
3455
- conv_start_date = self.format_date(start_date)
3456
- conv_end_date = self.format_date(end_date)
3457
-
3532
+ conv_start_date = self.format_date(start_date)
3533
+ conv_end_date = self.format_date(end_date)
3458
3534
 
3459
3535
  # 筛选数据
3460
3536
  query_data = self._get_history_bars_filter_data(table_data, instrument_id, conv_start_date, conv_end_date)
@@ -3754,6 +3830,9 @@ class GJDataC:
3754
3830
  """
3755
3831
 
3756
3832
  """ 获取数据 """
3833
+ if start_date and end_date:
3834
+ if not self.validate_dates(start_date, end_date):
3835
+ return None
3757
3836
  result, db_session = self.get_trading__dates_get_data(start_date, end_date, is_include_start, is_include_end)
3758
3837
  db_session.close()
3759
3838
 
@@ -3811,7 +3890,6 @@ class GJDataC:
3811
3890
  # 将 trade_time 转换为 datetime 对象
3812
3891
  trade_time = self.format_date(trade_time)
3813
3892
 
3814
-
3815
3893
  # 获取交易日历数据
3816
3894
  trading_dates = self.get_trading_dates_data()
3817
3895
 
@@ -3845,7 +3923,8 @@ class GJDataC:
3845
3923
 
3846
3924
  return trading_dates
3847
3925
 
3848
- def get_trading_days(self, trading_dates, trade_time, date_count):
3926
+ @staticmethod
3927
+ def get_trading_days(trading_dates, trade_time, date_count):
3849
3928
  """
3850
3929
  查询前后 N 个交易日
3851
3930
  :param trading_dates: 交易日历数据
@@ -3896,6 +3975,20 @@ class GJDataC:
3896
3975
  end=trade_time + datetime.timedelta(minutes=abs(date_count)),
3897
3976
  freq='min') # 'T' 表示分钟频率
3898
3977
 
3978
+ def _before_trading_day(_date):
3979
+ if _date in trading_dates['trading_day'].dt.date.values:
3980
+ return _date
3981
+ else:
3982
+ _previous_date = _date - datetime.timedelta(days=1)
3983
+ return _before_trading_day(_previous_date)
3984
+
3985
+ def _after_trading_day(_date):
3986
+ if _date in trading_dates['trading_day'].dt.date.values:
3987
+ return _date
3988
+ else:
3989
+ _previous_date = _date + datetime.timedelta(days=1)
3990
+ return _after_trading_day(_previous_date)
3991
+
3899
3992
  # 将时间点转换为指定格式的字符串
3900
3993
  time_points_str = time_points.strftime('%Y.%m.%d %H:%M:%S')
3901
3994
 
@@ -3905,6 +3998,36 @@ class GJDataC:
3905
3998
  # 检查时间点是否在交易日历中
3906
3999
  if point.date() in trading_dates['trading_day'].dt.date.values:
3907
4000
  valid_time_points.append(point_str)
4001
+ else:
4002
+ if point.date() < trade_time.date():
4003
+ previous_date = point.date() - datetime.timedelta(days=1)
4004
+ trading_date = _before_trading_day(previous_date)
4005
+ elif point.date() > trade_time.date():
4006
+ previous_date = point.date() + datetime.timedelta(days=1)
4007
+ trading_date = _after_trading_day(previous_date)
4008
+ else:
4009
+ trading_date = point.date()
4010
+ datetime_obj = datetime.datetime.combine(trading_date, datetime.time.min)
4011
+
4012
+ # 获取当天的最后一秒(23:59:59)
4013
+ end_of_day = datetime.datetime.combine(datetime_obj.date(), datetime.time(23, 59, 59))
4014
+ if trading_date < trade_time.date():
4015
+ _time_points = \
4016
+ pd.date_range(start=end_of_day - datetime.timedelta(minutes=abs(date_count)),
4017
+ end=end_of_day,
4018
+ freq='min')
4019
+ elif trading_date > trade_time.date():
4020
+ _time_points = \
4021
+ pd.date_range(start=datetime_obj,
4022
+ end=datetime_obj + datetime.timedelta(minutes=abs(date_count)),
4023
+ freq='min')
4024
+ else:
4025
+ _time_points = \
4026
+ pd.date_range(start=datetime_obj,
4027
+ end=datetime_obj,
4028
+ freq='min')
4029
+ _time_points = _time_points.strftime('%Y.%m.%d %H:%M:%S')
4030
+ valid_time_points.extend(_time_points)
3908
4031
 
3909
4032
  # 根据 date_count 的正负决定查询方向
3910
4033
  if date_count < 0:
@@ -3931,7 +4054,6 @@ class GJDataC:
3931
4054
  data, db_session = self.connect_db(trading_dates_db_table_name, trading_dates_db_path)
3932
4055
  date = self.format_date(date)
3933
4056
 
3934
-
3935
4057
  # 根据条件筛选数据
3936
4058
  # 筛选 trade_flag 列等于 T 的数据(是交易日的数据)
3937
4059
  filtered_data = data.where(f"trading_day = {date}").where("trade_flag = 'T'").toDF()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gjdatac-api
3
- Version: 0.2.9
3
+ Version: 0.3.1
4
4
  Summary: 数据接口打包
5
5
  Author: yin
6
6
  Author-email: 2018209921@qq.com
@@ -5,7 +5,7 @@ with open('description_info.md', 'r', encoding='utf-8') as f:
5
5
 
6
6
  setup(
7
7
  name='gjdatac_api', # 你的包名
8
- version='0.2.9', # 版本号
8
+ version='0.3.1', # 版本号
9
9
  description='数据接口打包', # 包的简要描述
10
10
  long_description=long_description, # 包的详细描述
11
11
  long_description_content_type='text/markdown', # 描述文件的类型
File without changes