# Copyright (c) 2022 <NAME>


"""
定义Data类

日志
2022-01-08
- 更新：Data通过调用TradeDay类来维护日期
2022-01-18
- 更新：Data类新增zdt_top矩阵，用于表示过过滤涨跌停
2022-01-20
- 更新：新增重置industry的方法，以及最大的ind数值
"""


import numpy as np
import datetime
import sys
sys.path.append('C:/Users/Administrator/Desktop/Daily-Frequency-Quant/QBG/DataLoader')
sys.path.append('C:/Users/HBG/Desktop/Repositories/Daily-Frequency-Quant/QBG/DataLoader')
from tools.trade_day import *
from tools.calculate_tools import div_2d


class Data:
    def __init__(self, code_order_dic: dict, order_code_dic: dict, date_position_dic: dict, position_date_dic: dict,
                 data_dic: dict, ret: np.array, trade_day: TradeDay, industry_dic: dict = None,
                 top_dic: dict = None, top: np.array = None, zdt_top: np.array = None):
        """
        :param code_order_dic: 股票代码到矩阵位置的字典
        :param order_code_dic: 矩阵位置到股票代码的字典
        :param date_position_dic: 日期到矩阵下标的字典
        :param data_dic: 所有的数据，形状一致
        :param ret: 使用的收益率
        :param trade_day: TradeDay类
        :param industry_dic: 使用的行业分类，是一个字典，值是一个矩阵，里面的数字就是行业分类
        :param top_dic: 字典，存储top矩阵中存储每一个交易日可选的股票
        :param top: 初始的top
        :param zdt_top：涨跌停top
        """
        self.code_order_dic = code_order_dic
        self.order_code_dic = order_code_dic
        self.date_position_dic = date_position_dic
        self.position_date_dic = position_date_dic
        self.data_dic = data_dic
        self.ret = ret
        self.industry_dic = industry_dic
        self.trade_day = trade_day
        self.top_dic = top_dic
        self.top = top
        self.zdt_top = zdt_top

        self.industry = None  # 使用的行业
        self.max_ind_code = 0  # 行业中最大的字段编号

    def set_top(self, name):
        self.top = self.top_dic[name]

    def set_ret(self, return_type: str):  # 同时更改ret和zdt_top
        length = int(return_type.split('_')[-1])
        start_name = return_type.split('_')[0]
        end_name = return_type.split('_')[1]
        ret = np.zeros(self.ret.shape)
        ret[-length:] = np.nan  # 注意要将不合法的部分全部置为nan
        ret[:-length] = div_2d(self.data_dic[end_name][length:], self.data_dic[start_name][:-length]) - 1
        self.ret = ret

        zdt_top = np.zeros(self.ret.shape)
        zdt_top[-1] = np.nan  # 注意要将不合法的部分全部置为nan
        zdt_top[:-1] = div_2d(self.data_dic[start_name][1:], self.data_dic['close'][:-1]) - 1  # 过滤涨跌停
        self.zdt_top = (~np.isnan(zdt_top)) & (np.abs(zdt_top) <= 0.099)

    def set_ind(self, name: str = 'sws'):
        self.industry = self.industry_dic[name]
        self.max_ind_code = self.industry.max()

    def get_real_date(self, date: str, direction: str = 'forward') -> int:  # 用于获取起始日期对应的真正的数据起始位置
        """
        :param date: 任意输入的结束日期
        :param direction: 方向
        :return: 返回有交易的真正的起始日期对应的下标
        """
        tmp_date = date.split('-')
        real_date = self.trade_day.get_real_date(date=datetime.date(int(tmp_date[0]), int(tmp_date[1]),
                                                                    int(tmp_date[2])), direction=direction)
        return self.date_position_dic[real_date]

# Copyright (c) 2022 <NAME>


"""
定义Data类

日志
2022-01-08
- 更新：Data通过调用TradeDay类来维护日期
2022-01-18
- 更新：Data类新增zdt_top矩阵，用于表示过过滤涨跌停
2022-01-20
- 更新：新增重置industry的方法，以及最大的ind数值
"""


import numpy as np
import datetime
import sys
sys.path.append('C:/Users/Administrator/Desktop/Daily-Frequency-Quant/QBG/DataLoader')
sys.path.append('C:/Users/HBG/Desktop/Repositories/Daily-Frequency-Quant/QBG/DataLoader')
from tools.trade_day import *
from tools.calculate_tools import div_2d


class Data:
    def __init__(self, code_order_dic: dict, order_code_dic: dict, date_position_dic: dict, position_date_dic: dict,
                 data_dic: dict, ret: np.array, trade_day: TradeDay, industry_dic: dict = None,
                 top_dic: dict = None, top: np.array = None, zdt_top: np.array = None):
        """
        :param code_order_dic: 股票代码到矩阵位置的字典
        :param order_code_dic: 矩阵位置到股票代码的字典
        :param date_position_dic: 日期到矩阵下标的字典
        :param data_dic: 所有的数据，形状一致
        :param ret: 使用的收益率
        :param trade_day: TradeDay类
        :param industry_dic: 使用的行业分类，是一个字典，值是一个矩阵，里面的数字就是行业分类
        :param top_dic: 字典，存储top矩阵中存储每一个交易日可选的股票
        :param top: 初始的top
        :param zdt_top：涨跌停top
        """
        self.code_order_dic = code_order_dic
        self.order_code_dic = order_code_dic
        self.date_position_dic = date_position_dic
        self.position_date_dic = position_date_dic
        self.data_dic = data_dic
        self.ret = ret
        self.industry_dic = industry_dic
        self.trade_day = trade_day
        self.top_dic = top_dic
        self.top = top
        self.zdt_top = zdt_top

        self.industry = None  # 使用的行业
        self.max_ind_code = 0  # 行业中最大的字段编号

    def set_top(self, name):
        self.top = self.top_dic[name]

    def set_ret(self, return_type: str):  # 同时更改ret和zdt_top
        length = int(return_type.split('_')[-1])
        start_name = return_type.split('_')[0]
        end_name = return_type.split('_')[1]
        ret = np.zeros(self.ret.shape)
        ret[-length:] = np.nan  # 注意要将不合法的部分全部置为nan
        ret[:-length] = div_2d(self.data_dic[end_name][length:], self.data_dic[start_name][:-length]) - 1
        self.ret = ret

        zdt_top = np.zeros(self.ret.shape)
        zdt_top[-1] = np.nan  # 注意要将不合法的部分全部置为nan
        zdt_top[:-1] = div_2d(self.data_dic[start_name][1:], self.data_dic['close'][:-1]) - 1  # 过滤涨跌停
        self.zdt_top = (~np.isnan(zdt_top)) & (np.abs(zdt_top) <= 0.099)

    def set_ind(self, name: str = 'sws'):
        self.industry = self.industry_dic[name]
        self.max_ind_code = self.industry.max()

    def get_real_date(self, date: str, direction: str = 'forward') -> int:  # 用于获取起始日期对应的真正的数据起始位置
        """
        :param date: 任意输入的结束日期
        :param direction: 方向
        :return: 返回有交易的真正的起始日期对应的下标
        """
        tmp_date = date.split('-')
        real_date = self.trade_day.get_real_date(date=datetime.date(int(tmp_date[0]), int(tmp_date[1]),
                                                                    int(tmp_date[2])), direction=direction)
        return self.date_position_dic[real_date]

# Copyright (c) 2022 <NAME> 定义Data类  日志 2022-01-08 - 更新：Data通过调用TradeDay类来维护日期 2022-01-18 - 更新：Data类新增zdt_top矩阵，用于表示过过滤涨跌停 2022-01-20 - 更新：新增重置industry的方法，以及最大的ind数值 :param code_order_dic: 股票代码到矩阵位置的字典         :param order_code_dic: 矩阵位置到股票代码的字典         :param date_position_dic: 日期到矩阵下标的字典         :param data_dic: 所有的数据，形状一致         :param ret: 使用的收益率         :param trade_day: TradeDay类         :param industry_dic: 使用的行业分类，是一个字典，值是一个矩阵，里面的数字就是行业分类         :param top_dic: 字典，存储top矩阵中存储每一个交易日可选的股票         :param top: 初始的top         :param zdt_top：涨跌停top # 使用的行业 # 行业中最大的字段编号 # 同时更改ret和zdt_top # 注意要将不合法的部分全部置为nan # 注意要将不合法的部分全部置为nan # 过滤涨跌停 # 用于获取起始日期对应的真正的数据起始位置 :param date: 任意输入的结束日期         :param direction: 方向         :return: 返回有交易的真正的起始日期对应的下标