def MOEX_find_secid(**kwargs) -> str: secid = '' data = [] if 'reg_number' in kwargs: url = f"https://iss.moex.com/iss/securities.json?q={kwargs['reg_number']}&iss.meta=off&limit=10" asset_data = json.loads(get_web_data(url)) securities = asset_data['securities'] columns = securities['columns'] data = [ x for x in securities['data'] if x[columns.index('regnumber')] == kwargs['reg_number'] or x[columns.index('regnumber')] is None ] if not data and 'isin' in kwargs: url = f"https://iss.moex.com/iss/securities.json?q={kwargs['isin']}&iss.meta=off&limit=10" asset_data = json.loads(get_web_data(url)) securities = asset_data['securities'] columns = securities['columns'] data = securities[ 'data'] # take the whole list if we search by isin if data: if len(data) > 1: # remove not traded assets if there are any outdated doubles present data = [x for x in data if x[columns.index('is_traded')] == 1] if len(data) > 1: # and then check again logging.info( QApplication.translate( "MOEX", "Multiple MOEX assets found for: ") + f"{kwargs}") return secid asset_data = dict(zip(columns, data[0])) secid = asset_data['secid'] if 'secid' in asset_data else '' return secid
def CBR_DataReader(self, _asset_id, currency_code, _currency, _isin, start_timestamp, end_timestamp): date1 = datetime.utcfromtimestamp(start_timestamp).strftime('%d/%m/%Y') # add 1 day to end_timestamp as CBR sets rate are a day ahead date2 = (datetime.utcfromtimestamp(end_timestamp) + timedelta(days=1)).strftime('%d/%m/%Y') try: code = str( self.CBR_codes.loc[self.CBR_codes["ISO_name"] == currency_code, "CBR_code"].values[0]).strip() except IndexError: logging.error( self.tr("Failed to get CBR data for: " + f"{currency_code}")) return None url = f"http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1={date1}&date_req2={date2}&VAL_NM_RQ={code}" xml_root = xml_tree.fromstring(get_web_data(url)) rows = [] for node in xml_root: s_date = node.attrib['Date'] if node is not None else None s_val = node.find("Value").text if node is not None else None rows.append({"Date": s_date, "Rate": s_val}) data = pd.DataFrame(rows, columns=["Date", "Rate"]) data['Date'] = pd.to_datetime(data['Date'], format="%d.%m.%Y") data['Rate'] = [x.replace(',', '.') for x in data['Rate']] data['Rate'] = data['Rate'].astype(float) rates = data.set_index("Date") return rates
def get_shop_name_by_inn(self, inn): if len(inn) != 10 and len(inn) != 12: logging.warning( self.tr("Incorrect length of INN. Can't get company name.")) return inn region_list = "77,78,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,"\ "30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,"\ "61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,79,83,86,87,89,91,92,99" params = { 'vyp3CaptchaToken': '', 'page': '', 'query': inn, 'region': region_list, 'PreventChromeAutocomplete': '' } token_data = json.loads( post_web_data('https://egrul.nalog.ru/', params)) if 't' not in token_data: return inn result = json.loads( get_web_data('https://egrul.nalog.ru/search-result/' + token_data['t'])) try: return result['rows'][0]['c'] # Return short name if exists except: pass try: return result['rows'][0]['n'] # Return long name if exists except: logging.warning(self.tr("Can't get company name from: ") + result) return inn
def MOEX_DataReader(self, asset_id, asset_code, isin, start_timestamp, end_timestamp, update_symbol=True): asset = self.MOEX_info(symbol=asset_code, isin=isin, special=True) if (asset['engine'] is None) or (asset['market'] is None) or (asset['board'] is None): logging.warning(f"Failed to find {asset_code} on moex.com") return None if (asset['market'] == 'bonds') and (asset['board'] == 'TQCB'): asset_code = isin # Corporate bonds are quoted by ISIN if (asset['market'] == 'shares') and (asset['board'] == 'TQIF'): asset_code = isin # ETFs are quoted by ISIN isin = asset['isin'] if 'isin' in asset else '' reg_code = asset['reg_code'] if 'reg_code' in asset else '' expiry = asset['expiry'] if 'expiry' in asset else 0 if update_symbol: JalDB().update_asset_data(asset_id, new_isin=isin, new_reg=reg_code, expiry=expiry) # Get price history date1 = datetime.utcfromtimestamp(start_timestamp).strftime('%Y-%m-%d') date2 = datetime.utcfromtimestamp(end_timestamp).strftime('%Y-%m-%d') url = f"http://iss.moex.com/iss/history/engines/{asset['engine']}/markets/{asset['market']}/" \ f"boards/{asset['board']}/securities/{asset_code}.xml?from={date1}&till={date2}" xml_root = xml_tree.fromstring(get_web_data(url)) history_rows = xml_root.findall("data[@id='history']/rows/*") quotes = [] for row in history_rows: if row.attrib['CLOSE']: if 'FACEVALUE' in row.attrib: # Correction for bonds price = float(row.attrib['CLOSE']) * float( row.attrib['FACEVALUE']) / 100.0 quotes.append({ "Date": row.attrib['TRADEDATE'], "Close": price }) else: quotes.append({ "Date": row.attrib['TRADEDATE'], "Close": row.attrib['CLOSE'] }) data = pd.DataFrame(quotes, columns=["Date", "Close"]) data['Date'] = pd.to_datetime(data['Date'], format="%Y-%m-%d") data['Close'] = pd.to_numeric(data['Close']) close = data.set_index("Date") return close
def Yahoo_Downloader(self, _asset_id, asset_code, _currency, _isin, start_timestamp, end_timestamp): url = f"https://query1.finance.yahoo.com/v7/finance/download/{asset_code}?" \ f"period1={start_timestamp}&period2={end_timestamp}&interval=1d&events=history" file = StringIO(get_web_data(url)) try: data = pd.read_csv(file) except ParserError: return None data['Date'] = pd.to_datetime(data['Date'], format="%Y-%m-%d") data = data.drop( columns=['Open', 'High', 'Low', 'Adj Close', 'Volume']) close = data.set_index("Date") return close
def PrepareRussianCBReader(self): rows = [] try: xml_root = xml_tree.fromstring( get_web_data("http://www.cbr.ru/scripts/XML_valFull.asp")) for node in xml_root: code = node.find( "ParentCode").text.strip() if node is not None else None iso = node.find( "ISO_Char_Code").text if node is not None else None rows.append({"ISO_name": iso, "CBR_code": code}) except xml_tree.ParseError: pass self.CBR_codes = pd.DataFrame(rows, columns=["ISO_name", "CBR_code"])
def MOEX_find_secid(**kwargs) -> str: secid = '' try: search_key = kwargs['regcode'] if 'regcode' in kwargs else kwargs[ 'isin'] except KeyError: return secid if not search_key: return secid url = f"https://iss.moex.com/iss/securities.json?q={search_key}&iss.meta=off&limit=10" asset_data = json.loads(get_web_data(url)) securities = asset_data['securities'] columns = securities['columns'] if 'regcode' in kwargs: # Take only records that have given regnumber to get rid of additional issues data = [ x for x in securities['data'] if x[columns.index('regnumber')] == search_key or x[columns.index('regnumber')] is None ] else: data = securities[ 'data'] # take the whole list if we search by isin if data: if len(data) > 1: # remove not traded assets if there are any outdated doubles present data = [x for x in data if x[columns.index('is_traded')] == 1] if len(data) > 1: # and then check again logging.info( QApplication.translate( "MOEX", "Multiple MOEX assets found for reg.number: ") + search_key) return secid asset_data = dict(zip(columns, data[0])) secid = asset_data['secid'] if 'secid' in asset_data else '' return secid
def MOEX_download_info(asset_code, currency='') -> dict: mapping = { 'SECID': 'symbol', 'NAME': 'name', 'SHORTNAME': 'short_name', 'ISIN': 'isin', 'REGNUMBER': 'reg_number', 'FACEVALUE': 'principal', 'MATDATE': 'expiry', 'LSTDELDATE': 'expiry', 'GROUP': 'type' } asset_type = { 'stock_shares': PredefinedAsset.Stock, 'stock_dr': PredefinedAsset.Stock, 'stock_bonds': PredefinedAsset.Bond, 'stock_etf': PredefinedAsset.ETF, 'stock_ppif': PredefinedAsset.ETF, 'futures_forts': PredefinedAsset.Derivative } asset = {} if not asset_code: return asset url = f"http://iss.moex.com/iss/securities/{asset_code}.xml" xml_root = xml_tree.fromstring(get_web_data(url)) info_rows = xml_root.findall("data[@id='description']/rows/*") boards = xml_root.findall("data[@id='boards']/rows/*") if not boards: # can't find boards -> not traded asset return asset for info in info_rows: asset.update({ mapping[field]: info.attrib['value'] for field in mapping if info.attrib['name'] == field }) if 'isin' in asset: # replace symbol with short name if we have isin in place of symbol asset['symbol'] = asset['short_name'] if asset['symbol'] == asset[ 'isin'] else asset['symbol'] del asset['short_name'] # drop short name as we won't use it further if 'principal' in asset: # Convert principal into float if possible or drop otherwise try: asset['principal'] = float(asset['principal']) except ValueError: del asset['principal'] if 'expiry' in asset: # convert YYYY-MM-DD into timestamp date_value = datetime.strptime(asset['expiry'], "%Y-%m-%d") asset['expiry'] = int( date_value.replace(tzinfo=timezone.utc).timestamp()) try: asset['type'] = asset_type[asset['type']] except KeyError: logging.error( QApplication.translate("MOEX", "Unsupported MOEX security type: ") + f"{asset['type']}") return {} boards_list = [board.attrib for board in boards] primary_board = [ x for x in boards_list if "is_primary" in x and x["is_primary"] == '1' ] if primary_board: if currency == 'USD': board_id = primary_board[0]['boardid'][:-1] + 'D' elif currency == 'EUR': board_id = primary_board[0]['boardid'][:-1] + 'E' else: board_id = primary_board[0]['boardid'] board = [ x for x in boards_list if "boardid" in x and x["boardid"] == board_id ] if board: asset.update({ 'engine': board[0]['engine'], 'market': board[0]['market'], 'board': board[0]['boardid'] }) return asset