import os
import importlib
import traceback
from datetime import datetime
from pathlib import Path
from server_api.api.tqz_tushare_api import TQZTushareClient
from tqz_strategy.template import CtaTemplate
from public_module.tqz_extern.tools.position_operator.position_operator import TQZJsonOperator
from public_module.tqz_extern.tools.file_path_operator.file_path_operator import TQZFilePathOperator
from public_module.tqz_extern.tools.pandas_operator.pandas_operator import pandas
from back_tester_core.tqz_constant import TQZBackTesterSettingType, TQZStrategyCombinationType, TQZStockPoolExcelType
from public_module.tqz_extern.tqz_constant import TQZStockIntervalType
class BackTesterDataCore:
__back_tester_setting: dict = None
# --- future part ---
# --- stock part ---
__stock_pools_df_map: dict = None
__stock_bars_map: dict = None
@classmethod
def load_strategy_classes(cls, strategy_combination_type: TQZStrategyCombinationType) -> dict:
""" """
all_strategies_classes = cls.__get_all_strategy_classes(strategy_combination_type=strategy_combination_type)
strategies_setting = TQZJsonOperator.tqz_load_jsonfile(
jsonfile=cls.__strategies_setting_path(
strategy_combination_type=strategy_combination_type
)
)
_strategy_classes = {}
for value in strategies_setting.values():
if value["class_name"] in all_strategies_classes.keys() and value["class_name"] not in _strategy_classes.keys() and f'{value["class_name"]}.xlsx' in cls.__get_back_tester_stock_pools():
_strategy_classes[value["class_name"]] = {
"strategy_class": all_strategies_classes[value["class_name"]],
"strategy_setting": value["setting"]
}
return _strategy_classes
@classmethod
def load_stockPoolsMap_and_barsMap(cls) -> (dict, dict):
""" """
if cls.__stock_pools_df_map is None:
cls.__stock_pools_df_map = {}
for dirpath, dirnames, filenames in os.walk(cls.__stock_pools_path()):
for filename in filenames:
if filename.endswith('.xlsx') and filename in cls.__get_back_tester_stock_pools():
cls.__stock_pools_df_map[filename] = pandas.read_excel(f'{dirpath}/{filename}', sheet_name=TQZStockPoolExcelType.SHEET_NAME.value)
if cls.__stock_bars_map is None:
back_tester_setting = cls.__get_back_tester_setting(strategy_combination_type=TQZStrategyCombinationType.STOCK)
merge_stocks = []
for stock_pool_dataframe in cls.__stock_pools_df_map.values():
merge_stocks += stock_pool_dataframe[TQZStockPoolExcelType.STOCKS_COLUMN.value].values.tolist()
cls.__stock_bars_map = TQZTushareClient.query_multi_stocks_history_bars(
stock_list=list(set(merge_stocks)),
start=datetime.strptime(back_tester_setting[TQZBackTesterSettingType.START_DATE.value], '%Y-%m-%d'),
end=datetime.strptime(back_tester_setting[TQZBackTesterSettingType.END_DATE.value], '%Y-%m-%d'),
interval=cls.__get_current_interval()
)
return cls.__stock_pools_df_map, cls.__stock_bars_map
@classmethod
def get_slippage(cls, strategy_combination_type: TQZStrategyCombinationType):
return cls.__get_back_tester_setting(
strategy_combination_type=strategy_combination_type
)[TQZBackTesterSettingType.SLIPPAGE.value]
@classmethod
def get_fee_ratio(cls, strategy_combination_type: TQZStrategyCombinationType):
return cls.__get_back_tester_setting(
strategy_combination_type=strategy_combination_type
)[TQZBackTesterSettingType.FEE_RATIO.value]
@classmethod
def get_tick_value(cls, strategy_combination_type: TQZStrategyCombinationType):
return cls.__get_back_tester_setting(
strategy_combination_type=strategy_combination_type
)[TQZBackTesterSettingType.TICK_VALUE.value]
# --- private part ---
@classmethod
def __get_back_tester_stock_pools(cls):
return cls.__get_back_tester_setting(
strategy_combination_type=TQZStrategyCombinationType.STOCK
)[TQZBackTesterSettingType.BACK_TESTER_STOCK_POOLS.value]
@classmethod
def __get_current_interval(cls) -> TQZStockIntervalType:
interval_str = cls.__get_back_tester_setting(strategy_combination_type=TQZStrategyCombinationType.STOCK)[TQZBackTesterSettingType.INTERVAL.value]
if interval_str in [TQZStockIntervalType.DAILY.value]:
interval = TQZStockIntervalType.DAILY
elif interval_str in [TQZStockIntervalType.WEEKLY.value]:
interval = TQZStockIntervalType.WEEKLY
elif interval_str in [TQZStockIntervalType.MONTHLY.value]:
interval = TQZStockIntervalType.MONTHLY
else:
assert False, f'bad interval_str {interval_str}'
return interval
@classmethod
def __get_back_tester_setting(cls, strategy_combination_type: TQZStrategyCombinationType):
if cls.__back_tester_setting is None:
cls.__back_tester_setting = TQZJsonOperator.tqz_load_jsonfile(
jsonfile=cls.__back_tester_setting_path(strategy_combination_type=strategy_combination_type)
)
return cls.__back_tester_setting
@classmethod
def __get_all_strategy_classes(cls, strategy_combination_type: TQZStrategyCombinationType) -> dict:
""" """
root = Path(__file__).parent.parent
stock_strategies_path = root.joinpath("tqz_strategy", f'{strategy_combination_type.STOCK.value}', "strategies")
module_name = f'tqz_strategy.{strategy_combination_type.STOCK.value}.strategies'
strategies_classes = {}
for dirpath, dirnames, filenames in os.walk(stock_strategies_path):
for filename in filenames:
if filename.endswith(".py"):
strategy_module_name = ".".join(
[module_name, filename.replace(".py", "")])
try:
module = importlib.import_module(strategy_module_name)
importlib.reload(module)
for name in dir(module):
value = getattr(module, name)
if isinstance(value, type) and issubclass(value, CtaTemplate) and value is not CtaTemplate:
strategies_classes[value.__name__] = value
except: # noqa
assert False, f"策略文件{module_name}加载失败,触发异常:\n{traceback.format_exc()}"
return strategies_classes
@classmethod
def __back_tester_setting_path(cls, strategy_combination_type: TQZStrategyCombinationType) -> str:
return TQZFilePathOperator.grandfather_path(
source_path=TQZFilePathOperator.current_file_path(file=__file__)
) + f'/back_tester_config/{strategy_combination_type.value}/back_tester_setting.json'
@classmethod
def __strategies_setting_path(cls, strategy_combination_type: TQZStrategyCombinationType) -> str:
return TQZFilePathOperator.grandfather_path(
source_path=TQZFilePathOperator.current_file_path(file=__file__)
) + f'/back_tester_config/{strategy_combination_type.value}/strategies_setting.json'
@classmethod
def __stock_pools_path(cls) -> str:
return TQZFilePathOperator.grandfather_path(
source_path=TQZFilePathOperator.current_file_path(file=__file__)
) + f'/back_tester_config/stock/stock_pools'
if __name__ == '__main__':
stock_pools_map, history_bars_map = BackTesterDataCore.load_stockPoolsMap_and_barsMap()
strategy_classes = BackTesterDataCore.load_strategy_classes(strategy_combination_type=TQZStrategyCombinationType.STOCK) # strategy_name strategy_classes
print("stock_pools_map: " + str(stock_pools_map))
print("history_bars_map: " + str(history_bars_map))
print("strategy_classes: " + str(strategy_classes))
量化交易之回测篇 - 股票回测数据源(back_tester_source_data)
最新推荐文章于 2024-04-21 10:43:10 发布