def genContinuousContractPrice(id_map, price, adj_direction="前复权", adj_type="收益率不变", rollover_ahead=False): IDIndex = dict(zip(price.columns.tolist(), np.arange(price.shape[1]))) AdjPrice = price.values[ np.arange(id_map.shape[0]), list(map(lambda x: IDIndex.get(x, 0), id_map.tolist()))] AdjPrice[pd.isnull(id_map)] = np.nan if adj_type == "收益率不变": if adj_direction == "前复权": for i in range(id_map.shape[0] - 1, 0, -1): iID, iPreID = id_map.iloc[i], id_map.iloc[i - 1] if pd.isnull(iID) or pd.isnull(iPreID) or (iID == iPreID): continue iAdj = price[iID].iloc[ i - rollover_ahead] / price[iPreID].iloc[i - rollover_ahead] if pd.isnull(iAdj): iAdj = price[iID].iloc[i] / price[iPreID].iloc[i - 1] AdjPrice[:i] = AdjPrice[:i] * iAdj elif adj_direction == "后复权": for i in range(1, id_map.shape[0]): iID, iPreID = id_map.iloc[i], id_map.iloc[i - 1] if pd.isnull(iID) or pd.isnull(iPreID) or (iID == iPreID): continue iAdj = price[iPreID].iloc[ i - rollover_ahead] / price[iID].iloc[i - rollover_ahead] if pd.isnull(iAdj): iAdj = price[iPreID].iloc[i - 1] / price[iID].iloc[i] AdjPrice[i:] = AdjPrice[i:] * iAdj else: raise __QS_Error__("不支持的调整方向: '%s'" % adj_direction) elif adj_type == "价差不变": if adj_direction == "前复权": for i in range(id_map.shape[0] - 1, 0, -1): iID, iPreID = id_map.iloc[i], id_map.iloc[i - 1] if pd.isnull(iID) or pd.isnull(iPreID) or (iID == iPreID): continue iAdj = price[iPreID].iloc[ i - rollover_ahead] - price[iID].iloc[i - rollover_ahead] if pd.isnull(iAdj): iAdj = price[iPreID].iloc[i - 1] - price[iID].iloc[i] AdjPrice[:i] = AdjPrice[:i] - iAdj elif adj_direction == "后复权": for i in range(1, id_map.shape[0]): iID, iPreID = id_map.iloc[i], id_map.iloc[i - 1] if pd.isnull(iID) or pd.isnull(iPreID) or (iID == iPreID): continue iAdj = price[iPreID].iloc[ i - rollover_ahead] - price[iID].iloc[i - rollover_ahead] if pd.isnull(iAdj): iAdj = price[iPreID].iloc[i - 1] - price[iID].iloc[i] AdjPrice[i:] = AdjPrice[i:] + iAdj else: raise __QS_Error__("不支持的调整方向: '%s'" % adj_direction) elif adj_type != "价格不变": raise __QS_Error__("不支持的调整方式: '%s'" % adj_type) return pd.Series(AdjPrice, index=id_map.index)
def getDBTable(self, table_format=None): try: if self.DBType == "SQL Server": SQLStr = "SELECT Name FROM SysObjects Where XType='U'" TableField = "Name" elif self.DBType == "MySQL": SQLStr = "SELECT table_name FROM information_schema.tables WHERE table_schema='" + self.DBName + "' AND table_type='base table'" TableField = "table_name" elif self.DBType == "Oracle": SQLStr = "SELECT table_name FROM user_tables WHERE TABLESPACE_NAME IS NOT NULL AND user='******'" TableField = "table_name" elif self.DBType == "sqlite3": SQLStr = "SELECT name FROM sqlite_master WHERE type='table'" TableField = "name" else: raise __QS_Error__("不支持的数据库类型 '%s'" % self.DBType) if isinstance(table_format, str) and table_format: SQLStr += (" WHERE %s LIKE '%s' " % (TableField, table_format)) AllTables = self.fetchall(SQLStr) except Exception as e: Msg = ("'%s' 调用方法 getAllDBTable 时错误: %s" % (self.Name, str(e))) self._QS_Logger.error(Msg) raise __QS_Error__(Msg) else: return [rslt[0] for rslt in AllTables]
def renameFactor(self, table_name, old_factor_name, new_factor_name): if table_name not in self._Arctic.list_libraries(): raise __QS_Error__("表: '%s' 不存在!" % table_name) Lib = self._Arctic[table_name] FactorInfo = Lib.read(symbol="_FactorInfo").set_index(["FactorName"]) if old_factor_name not in FactorInfo.index: raise __QS_Error__("因子: '%s' 不存在!" % old_factor_name) if new_factor_name in FactorInfo.index: raise __QS_Error__("因子: '%s' 已经存在!" % new_factor_name) FactorNames = FactorInfo.index.tolist() FactorNames[FactorNames.index(old_factor_name)] = new_factor_name FactorInfo.index = FactorNames FactorInfo.index.name = "FactorName" Lib.write( "_FactorInfo", FactorInfo.reset_index(), chunker=arctic.chunkstore.passthrough_chunker.PassthroughChunker()) IDs = Lib.list_symbols() IDs.remove("_FactorInfo") for iID in IDs: iMetaData = Lib.read_metadata(iID) if old_factor_name in iMetaData["FactorNames"]: iMetaData["FactorNames"][iMetaData["FactorNames"].index( old_factor_name)] = new_factor_name Lib.write_metadata(iID, iMetaData) return 0
def loadCSVFactorData(csv_path): with open(csv_path,mode='rb') as File: if File.readline().split(b',')[0]==b'': Horizon = True else: Horizon = False if Horizon: try: CSVFactor = readCSV2Pandas(csv_path, index_col=0, header=0, encoding="utf-8", parse_dates=True, infer_datetime_format=True) except: CSVFactor = readCSV2Pandas(csv_path, detect_file_encoding=True, index_col=0, header=0, parse_dates=True, infer_datetime_format=True) else: try: CSVFactor = readCSV2Pandas(csv_path, header=0, index_col=[0,1], encoding="utf-8", parse_dates=True, infer_datetime_format=True) except: CSVFactor = readCSV2Pandas(csv_path, detect_file_encoding=True, header=0, index_col=[0,1], parse_dates=True, infer_datetime_format=True) #Columns = list(CSVFactor.columns) #CSVFactor = CSVFactor.set_index(Columns[:2])[Columns[2]] CSVFactor = Series2DataFrame(CSVFactor.iloc[:, 0]) try: if CSVFactor.index.dtype==np.dtype("O"): CSVDT = [dt.datetime.strptime(iDT, "%Y-%m-%D") for iDT in CSVFactor.index] elif CSVFactor.index.is_all_dates: CSVDT = [iDT.to_pydatetime() for iDT in CSVFactor.index] else: raise __QS_Error__("时间序列解析失败!") except: raise __QS_Error__("时间序列解析失败!") CSVID = [str(iID) for iID in CSVFactor.columns] CSVFactor = pd.DataFrame(CSVFactor.values, index=CSVDT, columns=CSVID) return CSVFactor
def getFutureID(self, future_code="IF", date=None, is_current=True): if date is None: date = dt.date.today() if is_current: CodeStr = "EndT:= {Date}T;return GetFuturesID('{FutureID}', EndT);" else: raise __QS_Error__("目前不支持提取历史 ID") CodeStr = CodeStr.format(FutureID="".join(future_code.split(".")), Date=date.strftime("%Y%m%d")) ErrorCode, Data, Msg = self._TSLPy.RemoteExecute(CodeStr, {}) if ErrorCode!=0: raise __QS_Error__("TinySoft 执行错误: "+Msg.decode("gbk")) return [iID.decode("gbk") for iID in Data]
def _initInfo(self): if self.RiskESTDTs==[]: raise __QS_Error__("没有设置计算风险数据的时点序列!") FactorNames = set(self.Config.ModelArgs["所有因子"]) if not set(self.FT.FactorNames).issuperset(FactorNames): raise __QS_Error__("因子表必须包含如下因子: %s" % FactorNames) self._genRegressDateTime() self._adjustRiskESTDateTime() if self.RiskESTDTs==[]: raise __QS_Error__("可以计算风险数据的时点序列为空!") return 0
def renameFactor(self, table_name, old_factor_name, new_factor_name): if old_factor_name==new_factor_name: return 0 OldPath = self.MainDir+os.sep+table_name+os.sep+old_factor_name+"."+self._Suffix NewPath = self.MainDir+os.sep+table_name+os.sep+new_factor_name+"."+self._Suffix with self._DataLock: if not os.path.isfile(OldPath): raise __QS_Error__("HDF5DB.renameFactor: 表 ’%s' 中不存在因子 '%s'!" % (table_name, old_factor_name)) if os.path.isfile(NewPath): raise __QS_Error__("HDF5DB.renameFactor: 表 ’%s' 中的因子 '%s' 已存在!" % (table_name, new_factor_name)) os.rename(OldPath, NewPath) return 0
def renameTable(self, old_table_name, new_table_name): if old_table_name==new_table_name: return 0 OldPath = self.MainDir+os.sep+old_table_name NewPath = self.MainDir+os.sep+new_table_name with self._DataLock: if not os.path.isdir(OldPath): raise __QS_Error__("HDF5DB.renameTable: 表: '%s' 不存在!" % old_table_name) if os.path.isdir(NewPath): raise __QS_Error__("HDF5DB.renameTable: 表 '"+new_table_name+"' 已存在!") os.rename(OldPath, NewPath) return 0
def getTradeDay(self, start_date=None, end_date=None, exchange="SSE", **kwargs): if exchange not in ("SSE", "SZSE"): raise __QS_Error__("不支持交易所: '%s' 的交易日序列!" % exchange) if start_date is None: start_date = dt.date(1900, 1, 1) if end_date is None: end_date = dt.date.today() CodeStr = "SetSysParam(pn_cycle(), cy_day());return MarketTradeDayQk(inttodate({StartDate}), inttodate({EndDate}));" CodeStr = CodeStr.format(StartDate=start_date.strftime("%Y%m%d"), EndDate=end_date.strftime("%Y%m%d")) ErrorCode, Data, Msg = self._TSLPy.RemoteExecute(CodeStr,{}) if ErrorCode!=0: raise __QS_Error__("TinySoft 执行错误: "+Msg.decode("gbk")) return list(map(lambda x: dt.date(*self._TSLPy.DecodeDate(x)), Data))
def renameTable(self, old_table_name, new_table_name): if old_table_name not in self._TableFactorDict: raise __QS_Error__("表: '%s' 不存在!" % old_table_name) if (new_table_name!=old_table_name) and (new_table_name in self._TableFactorDict): raise __QS_Error__("表: '"+new_table_name+"' 已存在!") OldPath = self.MainDir+os.sep+old_table_name NewPath = self.MainDir+os.sep+new_table_name if OldPath==NewPath: pass elif os.path.isdir(NewPath): raise __QS_Error__("目录: '%s' 被占用!" % NewPath) with self._DataLock: os.rename(OldPath, NewPath) self._TableFactorDict[new_table_name] = self._TableFactorDict.pop(old_table_name) return 0
def _QS_initOperation(self, start_dt, dt_dict, prepare_ids, id_dict): if len(self._Descriptors) > len(self.LookBack): raise __QS_Error__("面板运算因子 : '%s' 的参数'回溯期数'序列长度小于描述子个数!" % self.Name) OldStartDT = dt_dict.get(self.Name, None) DTRuler = self._OperationMode.DTRuler if (OldStartDT is None) or (start_dt < OldStartDT): StartDT = dt_dict[self.Name] = start_dt StartInd, EndInd = DTRuler.index(StartDT), DTRuler.index( self._OperationMode.DateTimes[-1]) if (self.iLookBackMode == "扩张窗口") and (self.iInitData is not None) and ( self.iInitData.shape[0] > 0): if self.iInitData.index[-1] not in self._OperationMode.DTRuler: self._QS_Logger.warning( "注意: 因子 '%s' 的初始值不在时点标尺的范围内, 初始值和时点标尺之间的时间间隔将被忽略!" % (self.Name, )) else: StartInd = min( StartInd, self._OperationMode.DTRuler.index( self.iInitData.index[-1]) + 1) DTs = DTRuler[StartInd:EndInd + 1] if self.iLookBackMode == "扩张窗口": DTPartition = [DTs ] + [[]] * (len(self._OperationMode._PIDs) - 1) else: DTPartition = partitionList(DTs, len(self._OperationMode._PIDs)) self._PID_DTs = { iPID: DTPartition[i] for i, iPID in enumerate(self._OperationMode._PIDs) } else: StartInd = DTRuler.index(OldStartDT) PrepareIDs = id_dict.setdefault(self.Name, prepare_ids) if prepare_ids != PrepareIDs: raise __QS_Error__("因子 %s 指定了不同的截面!" % self.Name) for i, iDescriptor in enumerate(self._Descriptors): iStartInd = StartInd - self.LookBack[i] if iStartInd < 0: self._QS_Logger.warning("注意: 对于因子 '%s' 的描述子 '%s', 时点标尺长度不足!" % (self.Name, iDescriptor.Name)) iStartDT = DTRuler[max(0, iStartInd)] if self.DescriptorSection[i] is None: iDescriptor._QS_initOperation(iStartDT, dt_dict, prepare_ids, id_dict) else: iDescriptor._QS_initOperation(iStartDT, dt_dict, self.DescriptorSection[i], id_dict) if (self._OperationMode.SubProcessNum > 0) and (self.Name not in self._OperationMode._Event): self._OperationMode._Event[self.Name] = (Queue(), Event())
def renameTable(self, old_table_name, new_table_name): if old_table_name not in self._TableFactorDict: raise __QS_Error__("表: '%s' 不存在!" % old_table_name) if (new_table_name != old_table_name) and (new_table_name in self._TableFactorDict): raise __QS_Error__("表: '" + new_table_name + "' 已存在!") SQLStr = "ALTER TABLE " + self.TablePrefix + self._Prefix + old_table_name + " RENAME TO " + self.TablePrefix + self._Prefix + new_table_name self.execute(SQLStr) self._TableFactorDict[new_table_name] = self._TableFactorDict.pop( old_table_name) return 0
def _adjustData(data, data_type, order="C"): if data_type=="string": return data.where(pd.notnull(data), None).values elif data_type=="double": return data.astype("float").values elif data_type=="object": if order=="C": return np.ascontiguousarray(data.applymap(lambda x: np.frombuffer(pickle.dumps(x), dtype=np.uint8)).values) elif order=="F": return np.asfortranarray(data.applymap(lambda x: np.frombuffer(pickle.dumps(x), dtype=np.uint8)).values) else: raise __QS_Error__("不支持的参数 order 值: %s" % order) else: raise __QS_Error__("不支持的数据类型: %s" % data_type)
def renameTable(self, old_table_name, new_table_name): if old_table_name not in self._TableDT: raise __QS_Error__("表: '%s' 不存在!" % old_table_name) if (new_table_name != old_table_name) and (new_table_name in self._TableDT): raise __QS_Error__("表: '%s' 已存在!" % new_table_name) with self._DataLock: os.rename( self.MainDir + os.sep + old_table_name + "." + self._Suffix, self.MainDir + os.sep + new_table_name + "." + self._Suffix) self._TableDT[new_table_name] = self._TableDT.pop(old_table_name) return 0
def renameFactor(self, table_name, old_factor_name, new_factor_name): if old_factor_name not in self._TableFactorDict[table_name]: raise __QS_Error__("因子: '%s' 不存在!" % old_factor_name) if (new_factor_name != old_factor_name) and ( new_factor_name in self._TableFactorDict[table_name]): raise __QS_Error__("表中的因子: '%s' 已存在!" % new_factor_name) SQLStr = "ALTER TABLE " + self.TablePrefix + self._Prefix + table_name SQLStr += " CHANGE COLUMN `" + old_factor_name + "` `" + new_factor_name + "`" self.execute(SQLStr) self._TableFactorDict[table_name][ new_factor_name] = self._TableFactorDict[table_name].pop( old_factor_name) return 0
def renameFactor(self, table_name, old_factor_name, new_factor_name): if old_factor_name not in self._TableFactorDict[table_name]: raise __QS_Error__("因子: '%s' 不存在!" % old_factor_name) if (new_factor_name != old_factor_name) and ( new_factor_name in self._TableFactorDict[table_name]): raise __QS_Error__("表中的因子: '%s' 已存在!" % new_factor_name) TablePath = self.MainDir + os.sep + table_name with self._DataLock: iZTable = zarr.open(self.MainDir + os.sep + table_name, mode="w") iZTable[new_factor_name] = iZTable.pop(old_factor_name) self._TableFactorDict[table_name][ new_factor_name] = self._TableFactorDict[table_name].pop( old_factor_name) return 0
def renameFactor(self, table_name, old_factor_name, new_factor_name): if old_factor_name not in self._TableFactorDict[table_name]: raise __QS_Error__("因子: '%s' 不存在!" % old_factor_name) if (new_factor_name != old_factor_name) and ( new_factor_name in self._TableFactorDict[table_name]): raise __QS_Error__("表中的因子: '%s' 已存在!" % new_factor_name) TablePath = self.MainDir + os.sep + table_name with self._DataLock: os.rename( TablePath + os.sep + old_factor_name + "." + self._Suffix, TablePath + os.sep + new_factor_name + "." + self._Suffix) self._TableFactorDict[table_name][ new_factor_name] = self._TableFactorDict[table_name].pop( old_factor_name) return 0
def _QS_initOperation(self, start_dt, dt_dict, prepare_ids, id_dict): super()._QS_initOperation(start_dt, dt_dict, prepare_ids, id_dict) if len(self._Descriptors) > len(self.LookBack): raise __QS_Error__("时间序列运算因子 : '%s' 的参数'回溯期数'序列长度小于描述子个数!" % self.Name) StartDT = dt_dict[self.Name] StartInd = self._OperationMode.DTRuler.index(StartDT) if (self.iLookBackMode == "扩张窗口") and (self.iInitData is not None) and (self.iInitData.shape[0] > 0): if self.iInitData.index[-1] not in self._OperationMode.DTRuler: self._QS_Logger.warning( "注意: 因子 '%s' 的初始值不在时点标尺的范围内, 初始值和时点标尺之间的时间间隔将被忽略!" % (self.Name, )) else: StartInd = min( StartInd, self._OperationMode.DTRuler.index(self.iInitData.index[-1]) + 1) for i, iDescriptor in enumerate(self._Descriptors): iStartInd = StartInd - self.LookBack[i] if iStartInd < 0: self._QS_Logger.warning( "注意: 对于因子 '%s' 的描述子 '%s', 时点标尺长度不足, 不足的部分将填充 nan!" % (self.Name, iDescriptor.Name)) iStartDT = self._OperationMode.DTRuler[max(0, iStartInd)] iDescriptor._QS_initOperation(iStartDT, dt_dict, prepare_ids, id_dict)
def renameFactor(self, table_name, old_factor_name, new_factor_name): if old_factor_name == new_factor_name: return 0 with self._DataLock: iZTable = zarr.open(self.MainDir + os.sep + table_name, mode="a") if old_factor_name not in iZTable: raise __QS_Error__("ZarrDB.renameFactor: 表 ’%s' 中不存在因子 '%s'!" % (table_name, old_factor_name)) if new_factor_name in iZTable: raise __QS_Error__( "ZarrDB.renameFactor: 表 ’%s' 中的因子 '%s' 已存在!" % (table_name, new_factor_name)) iZTable[new_factor_name] = iZTable.pop(old_factor_name) DataType = iZTable.attrs.get("DataType", {}) DataType[new_factor_name] = DataType.pop(old_factor_name) iZTable.attrs["DataType"] = DataType return 0
def connect(self): if not os.path.isdir(self.MainDir): raise __QS_Error__("不存在主目录: %s!" % self.MainDir) AllTables = listDirDir(self.MainDir) _TableFactorDict = {} if not os.path.isfile(self.MainDir + os.sep + "LockFile"): open(self.MainDir + os.sep + "LockFile", mode="a").close() self._LockFile = self.MainDir + os.sep + "LockFile" self._DataLock = fasteners.InterProcessLock(self._LockFile) with self._DataLock: for iTable in AllTables: iTablePath = self.MainDir + os.sep + iTable iFactors = set(listDirFile(iTablePath, suffix=self._Suffix)) if not iFactors: continue try: iDataType = readNestedDictFromHDF5( iTablePath + os.sep + "_TableInfo.h5", "/DataType") except: iDataType = None if (iDataType is None) or (iFactors != set(iDataType.index)): iDataType = {} for ijFactor in iFactors: with h5py.File(iTablePath + os.sep + ijFactor + "." + self._Suffix, mode="r") as ijDataFile: iDataType[ijFactor] = ijDataFile.attrs["DataType"] iDataType = pd.Series(iDataType) writeNestedDict2HDF5(iDataType, iTablePath + os.sep + "_TableInfo.h5", "/DataType") _TableFactorDict[iTable] = iDataType self._TableFactorDict = _TableFactorDict self._isAvailable = True return 0
def filterID(factor_data, id_filter_str): if not id_filter_str: return factor_data.index.tolist() CompiledIDFilterStr, IDFilterFactors = testIDFilterStr( id_filter_str, factor_names=factor_data.columns.tolist()) if CompiledIDFilterStr is None: raise __QS_Error__("ID 过滤字符串有误!") temp = factor_data.loc[:, IDFilterFactors] return eval("temp[" + CompiledIDFilterStr + "].index.tolist()")
def renameFactor(self, table_name, old_factor_name, new_factor_name): if old_factor_name not in self._TableFactorDict[table_name]: raise __QS_Error__("因子: '%s' 不存在!" % old_factor_name) if (new_factor_name!=old_factor_name) and (new_factor_name in self._TableFactorDict[table_name]): raise __QS_Error__("表中的因子: '%s' 已存在!" % new_factor_name) if self.DBType!="sqlite3": SQLStr = "ALTER TABLE "+self.TablePrefix+self.InnerPrefix+table_name SQLStr += " CHANGE COLUMN `"+old_factor_name+"` `"+new_factor_name+"`" self.execute(SQLStr) else: # 将表名改为临时表 SQLStr = "ALTER TABLE %s RENAME TO %s" TempTableName = genAvailableName("TempTable", self.TableNames) self.execute(SQLStr % (self.TablePrefix+self.InnerPrefix+table_name, self.TablePrefix+self.InnerPrefix+TempTableName)) # 创建新表 FieldTypes = OrderedDict() for iFactorName, iDataType in self._TableFactorDict[table_name].items(): iDataType = ("text" if iDataType=="string" else "real") if iFactorName==old_factor_name: FieldTypes[new_factor_name] = iDataType else: FieldTypes[iFactorName] = iDataType self.createTable(table_name, field_types=FieldTypes) # 导入数据 OldFactorNames = ", ".join(self._TableFactorDict[table_name].index) NewFactorNames = ", ".join(FieldTypes) SQLStr = "INSERT INTO %s (datetime, code, %s) SELECT datetime, code, %s FROM %s" Cursor = self.cursor(SQLStr % (self.TablePrefix+self.InnerPrefix+table_name, NewFactorNames, OldFactorNames, self.TablePrefix+self.InnerPrefix+TempTableName)) self._Connection.commit() # 删除临时表 Cursor.execute("DROP TABLE %s" % (self.TablePrefix+self.InnerPrefix+TempTableName, )) self._Connection.commit() Cursor.close() self._TableFactorDict[table_name][new_factor_name] = self._TableFactorDict[table_name].pop(old_factor_name) self._TableFieldDataType[table_name][new_factor_name] = self._TableFieldDataType[table_name].pop(old_factor_name) return 0
def __QS_move__(self, idt, **kwargs): if self._iDT == idt: return 0 iTradingRecord = { iAccount.Name: iAccount.__QS_move__(idt, **kwargs) for iAccount in self.Accounts } Signal = None if (not self.SignalDTs) or (idt in self.SignalDTs): Signal = self.genSignal(idt, iTradingRecord) if Signal is not None: if not isinstance(Signal, pd.Series): raise __QS_Error__("信号格式有误, 必须是 Series 类型!") if self.LongWeightAlloction.ReAllocWeight or self.ShortWeightAlloction.ReAllocWeight: LongSignal, ShortSignal = Signal[Signal > 0], Signal[ Signal < 0] if (LongSignal.shape[0] > 0) and self.LongWeightAlloction.ReAllocWeight: LongSignal = self._allocateWeight( idt, LongSignal.index.tolist(), self.TargetAccount.IDs, self.LongWeightAlloction) * LongSignal.sum() if (ShortSignal.shape[0] > 0) and self.ShortWeightAlloction.ReAllocWeight: ShortSignal = self._allocateWeight( idt, ShortSignal.index.tolist(), self.TargetAccount.IDs, self.ShortWeightAlloction) * ShortSignal.sum() Signal = LongSignal.add(ShortSignal, fill_value=0.0) self._AllSignals[idt] = Signal Signal = self._bufferSignal(Signal) self.trade(idt, iTradingRecord, Signal) for iAccount in self.Accounts: iAccount.__QS_after_move__(idt, **kwargs) return 0
def _QS_initOperation(self, start_dt, dt_dict, prepare_ids, id_dict): OldStartDT = dt_dict.get(self.Name, None) if (OldStartDT is None) or (start_dt < OldStartDT): dt_dict[self.Name] = start_dt StartInd, EndInd = self._OperationMode.DTRuler.index( dt_dict[self.Name]), self._OperationMode.DTRuler.index( self._OperationMode.DateTimes[-1]) DTs = self._OperationMode.DTRuler[StartInd:EndInd + 1] DTPartition = partitionList(DTs, len(self._OperationMode._PIDs)) self._PID_DTs = { iPID: DTPartition[i] for i, iPID in enumerate(self._OperationMode._PIDs) } PrepareIDs = id_dict.setdefault(self.Name, prepare_ids) if prepare_ids != PrepareIDs: raise __QS_Error__("因子 %s 指定了不同的截面!" % self.Name) for i, iDescriptor in enumerate(self._Descriptors): if self.DescriptorSection[i] is None: iDescriptor._QS_initOperation(start_dt, dt_dict, prepare_ids, id_dict) else: iDescriptor._QS_initOperation(start_dt, dt_dict, self.DescriptorSection[i], id_dict) if (self._OperationMode.SubProcessNum > 0) and (self.Name not in self._OperationMode._Event): self._OperationMode._Event[self.Name] = (Queue(), Event())
def getTable(self, table_name, args={}): if not os.path.isdir(self.MainDir + os.sep + table_name): raise __QS_Error__("ZarrDB.getTable: 表 '%s' 不存在!" % table_name) return _FactorTable(name=table_name, fdb=self, sys_args=args, logger=self._QS_Logger)
def getDateTime(self, ifactor_name=None, iid=None, start_dt=None, end_dt=None, args={}): if iid is None: iid = "000001.SH" CycleStr = self._genCycleStr(args.get("周期", self.Cycle), args.get("周期单位", self.CycleUnit)) if start_dt is None: start_dt = dt.datetime(1970, 1, 1) if end_dt is None: end_dt = dt.datetime.now() CodeStr = "SetSysParam(pn_cycle()," + CycleStr + ");" CodeStr += "return select " + "['date'] " CodeStr += "from markettable datekey inttodate(" + start_dt.strftime( "%Y%m%d") + ") " CodeStr += "to (inttodate(" + end_dt.strftime( "%Y%m%d") + ")+0.9999) of '{ID}' end;" ErrorCode, Data, Msg = self._FactorDB._TSLPy.RemoteExecute( CodeStr.format(ID="".join(reversed(iid.split(".")))), {}) if ErrorCode != 0: raise __QS_Error__("TinySoft 执行错误: " + Msg.decode("gbk")) DTs = np.array([ dt.datetime(*self._FactorDB._TSLPy.DecodeDateTime(iData[b"date"])) for iData in Data ], dtype="O") return DTs[(DTs >= start_dt) & (DTs <= end_dt)].tolist()
def loadCSVFilePortfolioSignal(csv_path): FileSignals = {} if not os.path.isfile(csv_path): raise __QS_Error__("文件: '%s' 不存在" % csv_path) with open(csv_path) as CSVFile: FirstLine = CSVFile.readline() if len(FirstLine.split(",")) != 3: # 横向排列 CSVDF = readCSV2Pandas(csv_path, detect_file_encoding=True) temp = list(CSVDF.columns) nCol = len(temp) AllSignalDates = [str(int(temp[i])) for i in range(0, nCol, 2)] for i in range(int(nCol / 2)): iDT = CSVDF.columns[i * 2] iSignal = CSVDF.iloc[:, i * 2:i * 2 + 2] iSignal = iSignal[pd.notnull(iSignal.iloc[:, 1])].set_index( [iDT]).iloc[:, 0] FileSignals[AllSignalDates[i]] = iSignal else: # 纵向排列 CSVDF = readCSV2Pandas(csv_path, detect_file_encoding=True, header=0) AllSignalDates = pd.unique(CSVDF.iloc[:, 0]) AllColumns = list(CSVDF.columns) for iDT in AllSignalDates: iSignal = CSVDF.iloc[:, 1:][CSVDF.iloc[:, 0] == iDT] iSignal = iSignal.set_index(AllColumns[1:2]) iSignal = iSignal[AllColumns[2]] FileSignals[str(iDT)] = iSignal return FileSignals
def cursor(self, sql_str=None): if self._Connection is None: raise __QS_Error__("%s尚未连接!" % self.__doc__) Cursor = self._Connection.cursor() if sql_str is None: return Cursor Cursor.execute(sql_str) return Cursor
def __QS_prepareRawData__(self, factor_names, ids, dts, args={}): CycleStr = self._genCycleStr(args.get("周期", self.Cycle), args.get("周期单位", self.CycleUnit)) Fields = self._FactorDB._FactorInfo["DBFieldName"].loc[ self.Name].loc[factor_names].tolist() CodeStr = "SetSysParam(pn_cycle()," + CycleStr + ");" CodeStr += "return select " + "['date'],['" + "'],['".join( Fields) + "'] " CodeStr += "from markettable datekey inttodate(" + dts[0].strftime( "%Y%m%d") + ") " CodeStr += "to (inttodate(" + dts[-1].strftime( "%Y%m%d") + ")+0.9999) of '{ID}' end;" Data = {} for iID in ids: iCodeStr = CodeStr.format(ID="".join(reversed(iID.split(".")))) ErrorCode, iData, Msg = self._FactorDB._TSLPy.RemoteExecute( iCodeStr, {}) if ErrorCode != 0: raise __QS_Error__("TinySoft 执行错误: " + Msg.decode("gbk")) if iData: Data[iID] = pd.DataFrame(iData).set_index([b"date"]) if not Data: return pd.Panel(Data) Data = pd.Panel(Data).swapaxes(0, 2) Data.major_axis = [ dt.datetime(*self._FactorDB._TSLPy.DecodeDateTime(iDT)) for iDT in Data.major_axis ] Data.items = [(iCol.decode("gbk") if isinstance(iCol, bytes) else iCol) for i, iCol in enumerate(Data.items)] Data = Data.loc[Fields] Data.items = factor_names return Data
def getTable(self, table_name, args={}): if table_name not in self._TableFactorDict: raise __QS_Error__("表 '%s' 不存在!" % table_name) return _FactorTable(name=table_name, fdb=self, data_type=self._TableFactorDict[table_name], sys_args=args)