import hashlib import json import importlib as im from datetime import datetime, timedelta class base_Quant_api(): def __init__(self, type, portfolioDataPath="", assetClassPath="", now=""): mod = im.import_module('lib.' + type + "_api_agent") api_agent = getattr(mod, "Api_agent") self.__default_msg = {'errorCode': '0', 'errorMsg': ''} self.__pt_keys = ["pt_id", "recomm_id", "rp_id", "last_tx_date", "last_recomm_date", "create_date", "fas", "last_check_date"] self.__fas_keys = ["fund_id", "weight"] self.__api = api_agent(portfolioDataPath, assetClassPath) self.__portfolios = {} self.__fund_metadata = {} self.__debug_info = {} self.nowstr = now def now(self): if self.nowstr == "": return datetime.now() else: return datetime(int(self.nowstr[:4]), int(self.nowstr[4:6]), int(self.nowstr[6:8])) def __debug(self, msg): self.__debug_info[datetime.now()] = msg return True def __gen_rcv_no(self, recomm_id, numbers): return "%s-%s-%s" % (datetime.now().strftime("%Y%m%d%H%M%S"), recomm_id, numbers) def __verify_pt_data(self, data): para = ["fas", "last_recomm_date", "last_tx_date", "pt_id", "recomm_id", "rp_id"] for parameter in para: if not parameter in data.keys(): return False if len(data["fas"]) == 0: return False return True def __verify_pt_data_dividend(self, data): para = ["pt_id", "total_in", "asset"] for parameter in para: if not parameter in data.keys(): return False if len(data["asset"]) == 0: return False return True def get_latest_portfolio(self, recomm_id, query_date = ''): #self.__debug("Getting portfolio data: %s" % query_key) portfolio_data = self.__api.get_latest_portfolio(recomm_id, query_date) #self.__debug("%s: %s" % (portfolio_id, json.dumps(portfolio_data))) if portfolio_data != None: return portfolio_data return None def get_portfolio_by_rpid(self, rp_id): #self.__debug("Getting portfolio data: %s" % query_key) portfolio_data = self.__api.get_portfolio_by_rpid(rp_id) #self.__debug("%s: %s" % (portfolio_id, json.dumps(portfolio_data))) if portfolio_data != None: return portfolio_data return None def get_fund_asset_class(self, fund_id): self.__debug("Getting fund asset class: %s" % fund_id) data = self.__api.get_fund_metadata(fund_id) if data != None: return data return None def _rebalance(self, pt): pass def _dividend(self, pt): pass def show_debug_info(self): if not bool(self.__debug_info): return True for exec_time in sorted(self.__debug_info): print("[%s] %s" % (exec_time.strftime("%Y-%m-%d %H:%M:%S.%f"), self.__debug_info[exec_time])) self.__debug_info = {} return True def rebalance(self, pts): self.__default_msg = {'errorCode': '0', 'errorMsg': 'Success', 'rebs':[]} pt_len = len(pts) if pt_len == 0: return self.__default_msg self.__default_msg['rcv_no'] = self.__gen_rcv_no(pts[0]["recomm_id"], pt_len) # it need to be confirmed. for pt in pts: if not self.__verify_pt_data(pt): self.__debug("Failed to verify pt data") self.__default_msg['errorCode'] ="1001" self.__default_msg['errorMsg'] = "Failed to verify pts data." self.__default_msg['rebs']= [] break else : #self._rebalance(pt) res = self._rebalance(pt) #(rp_id, reason) = self._rebalance(pt) if res == 0: rp_id = '0' reason = '符合所有條件,無需REB' last_busi_date = None rec_reason = None else: (rp_id, reason,last_busi_date,rec_reason) = res self.__default_msg['rebs'].append({"pt_id":pt["pt_id"], "rp_id":rp_id, "reason":reason, "last_busi_date":last_busi_date , "rec_reason":rec_reason}) #self.__default_msg['rebs'].append({"pt_id":pt["pt_id"], "rp_id": self._rebalance(pt)}) return self.__default_msg def dividend(self, pts): self.__default_msg = {'errorCode': '0', 'errorMsg': 'Success', 'dividends':[]} pt_len = len(pts) if pt_len == 0: return self.__default_msg for pt in pts: if not self.__verify_pt_data_dividend(pt): self.__debug("Failed to verify pt data") self.__default_msg['errorCode'] ="1001" self.__default_msg['errorMsg'] = "Failed to verify pts data." self.__default_msg['rebs']= [] break else : res = self._dividend(pt) self.__default_msg['dividends'].append({"pt_id":pt["pt_id"], "redeem":res }) #self.__default_msg['rebs'].append({"pt_id":pt["pt_id"], "rp_id": self._rebalance(pt)}) return self.__default_msg