From efc25388281c8831129b70a9faa5a6949c37ffa7 Mon Sep 17 00:00:00 2001 From: Artem Lavrenov Date: Sun, 7 Jun 2020 11:56:14 +0300 Subject: [PATCH] Add plugin moex financeyahoo stock sipnet --- .gitignore | 2 + plugin/eur.py | 4 +- plugin/financeyahoo.py | 22 +++++++++++ plugin/moex.py | 24 ++++++++++++ plugin/sipnet.py | 48 +++++++++++++++++++++++ plugin/stock.py | 88 ++++++++++++++++++++++++++++++++++++++++++ plugin/usd.py | 4 +- readme.md | 6 +++ 8 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 plugin/financeyahoo.py create mode 100644 plugin/moex.py create mode 100644 plugin/sipnet.py create mode 100644 plugin/stock.py diff --git a/.gitignore b/.gitignore index b46dda7..7f146cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ _TKINTER_install.zip +_HLAM/* +plugin/personalsetting.py mbplugin.zip dllplugin httpserver diff --git a/plugin/eur.py b/plugin/eur.py index 8497679..c35bf91 100644 --- a/plugin/eur.py +++ b/plugin/eur.py @@ -8,8 +8,8 @@ def get_balance(login, password, storename=None): result = {} session = requests.Session() url = time.strftime("http://cbrates.rbc.ru/tsv/978/%Y/%m/%d.tsv") - response2 = session.get(url) - result['Balance'] = response2.text.split()[-1] + response = session.get(url) + result['Balance'] = response.text.split()[-1] result['userName'] = 'Курс евро от РБК' return result diff --git a/plugin/financeyahoo.py b/plugin/financeyahoo.py new file mode 100644 index 0000000..8295f76 --- /dev/null +++ b/plugin/financeyahoo.py @@ -0,0 +1,22 @@ +# -*- coding: utf8 -*- +''' Получение котировок с finance.yahoo.com в логин код ценной бумаги + https://finance.yahoo.com/quote/AAPL + https://query1.finance.yahoo.com/v8/finance/chart/AAPL ''' +import sys;sys.dont_write_bytecode = True +import os, sys, re, time, logging +import requests +import store, settings, personalsetting + +def get_balance(login, password, storename=None): + result = {} + session = requests.Session() + url = time.strftime(f'https://query1.finance.yahoo.com/v8/finance/chart/{login}') + response = session.get(url) + meta = response.json()['chart']['result'][0]['meta'] + meta['regularMarketPrice'] + result['Balance'] = meta['regularMarketPrice'] + return result + + +if __name__ == '__main__': + print('This is module finance.yahoo.com') diff --git a/plugin/moex.py b/plugin/moex.py new file mode 100644 index 0000000..bd8b24b --- /dev/null +++ b/plugin/moex.py @@ -0,0 +1,24 @@ +# -*- coding: utf8 -*- +''' Получение котировок с moex.com в логин код ценной бумаги + https://iss.moex.com/iss/engines/stock/markets/shares/securities/TATNP + https://iss.moex.com/iss/securities/TATNP.xml''' +import sys;sys.dont_write_bytecode = True +import os, sys, re, time, logging +import requests +import xml.etree.ElementTree as etree +import store, settings, personalsetting + + +def get_balance(login, password, storename=None): + result = {} + session = requests.Session() + url = time.strftime(f'https://iss.moex.com/iss/engines/stock/markets/shares/securities/{login}') + response = session.get(url) + root=etree.fromstring(response.text) + rows = root.findall('*[@id="marketdata"]/rows')[0] + result['Balance'] = [c.get('LAST') for c in rows.getchildren() if c.get('LAST')!=''][0] + return result + + +if __name__ == '__main__': + print('This is module moex') diff --git a/plugin/sipnet.py b/plugin/sipnet.py new file mode 100644 index 0000000..b949fa1 --- /dev/null +++ b/plugin/sipnet.py @@ -0,0 +1,48 @@ +# -*- coding: utf8 -*- +import sys;sys.dont_write_bytecode = True +import os, sys, re, logging +import requests +import store + +# Строка для поиска баланса на странице +re_balance = r'(?usi)Баланс.*?>.*?>.*?>(.*?) ' +# Строка для поиска тарифа +re_tariff = r'(?usi)status-work.*?>.*?>.*?>(.*?)<' +re_sipid = '(?usi)SIP ID.*?>.*?>(.*?)<' # SIP ID (лицевой счет) + + +def get_balance(login, password, storename=None): + logging.info(f'start get_balance {login}') + result = {} + url = 'https://www.sipnet.ru/cabinet/index' + session = store.load_session(storename) + if session is None: + logging.info(f'No saved session {login}') + session = requests.Session() + response1 = session.get(url) + if re.search(re_balance, response1.text): + logging.info(f'Already logoned {login}') + else: + # Логинимся + logging.info(f'relogon {login}') + data = {'CabinetAction': 'login','view': 'ru','Name': login,'Password':password,} + response1 = session.post(url, data=data) + if response1.status_code != 200: + raise RuntimeError(f'POST Login page {url} error: status_code {response2.status_code}') + + result['Balance'] = re.search(re_balance, response1.text).group(1).replace(',', '.').strip() + try: + result['TarifPlan'] = re.search(re_tariff, response1.text).group(1).replace(' ', '').strip() + except Exception: + logging.info(f'Not found {TarifPlan}') + try: + result['licSchet'] = re.search(re_sipid, response1.text).group(1).replace(' ', '').strip() + except Exception: + logging.info(f'Not found {licSchet}') + + store.save_session(storename, session) + return result + + +if __name__ == '__main__': + print('This is module sipnet') diff --git a/plugin/stock.py b/plugin/stock.py new file mode 100644 index 0000000..b0cb04a --- /dev/null +++ b/plugin/stock.py @@ -0,0 +1,88 @@ +# -*- coding: utf8 -*- +''' Сумма по всем стокам + Стоки прописаны в personalsetting.py + словарь stock {имя набора':{'stocks': список_стоков, 'remain': остатки_на_счетах} } + имя набора берется из login + пример + stocks = {'BROKER_RU': {'STOCKS':(('AAPL',1,'Y'),('TATNP',16,'M'),('FXIT',1,'M')), 'REMAIN': {'USD':5, 'RUB':536}, 'CURRENC': 'USD'}} + Каждый сток - код стока, количество акций, источник данных (Y yahoo, M moex) + REMAIN - остатки на долларовом и рублевом счетах + CURRENC - в какой валюте считать итог + Проверить что код стока корректный можно подставив в ссылку: + https://finance.yahoo.com/quote/AAPL + https://query1.finance.yahoo.com/v8/finance/chart/AAPL + https://iss.moex.com/iss/engines/stock/markets/shares/securities/TATNP + https://iss.moex.com/iss/securities/TATNP.xml +''' +import sys;sys.dont_write_bytecode = True +import os, sys, re, time, logging, threading, queue +import xml.etree.ElementTree as etree +import requests +import store, settings, personalsetting + +def get_usd_moex(): + session = requests.Session() + response = session.get('https://iss.moex.com/iss/statistics/engines/futures/markets/indicativerates/securities') + res = re.findall(r'secid="USD/RUB" rate="(.*?)"',response.text)[0] + return float(res) + +def get_yahoo(security, cnt, qu=None): + session = requests.Session() + url = time.strftime(f'https://query1.finance.yahoo.com/v8/finance/chart/{security}') + response = session.get(url) + meta = response.json()['chart']['result'][0]['meta'] + meta['regularMarketPrice'] + res = meta['regularMarketPrice']*cnt, security, 'USD' + if qu: + qu.put(res) + return res + +def get_moex(security, cnt, qu=None): + session = requests.Session() + url = time.strftime(f'https://iss.moex.com/iss/engines/stock/markets/shares/securities/{security}') + response = session.get(url) + root=etree.fromstring(response.text) + rows = root.findall('*[@id="marketdata"]/rows')[0] + res = float([c.get('LAST') for c in list(rows) if c.get('LAST')!=''][0])*cnt, security, 'RUB' + if qu: + qu.put(res) + return res + +def count_all_scocks_multithread(stocks, remain, currenc): + usd = get_usd_moex() + k = {'USD': 1, 'RUB': 1} # Коэффициенты для приведения к одной валюте + if currenc == 'USD': + k['RUB'] = 1/usd + else: + k['USD'] = usd + qu = queue.Queue() # Очередь для данных из thread [val, sec_code, currency] + # Каждое получение данных в отдельном трэде + for sec,cnt,market in stocks: + target = get_yahoo if market=='Y' else get_moex + threading.Thread(target=target, name='stock', args=(sec,cnt,qu)).start() + # Ждем завершения всех трэдов с получением данных + while [1 for i in threading.enumerate() if i.name=='stock']: + time.sleep(0.01) + data = [] + # Забираем данные от трэдов + while qu.qsize()>0: + data.append(qu.get_nowait()) + data.sort(key=lambda i:(i[2],i[1])) # Сортируем сначала по валюте. затем по коду бумаги + res_full = '\n'.join([f'{sec:5} : {round(val*k[curr],2):7.2f} {curr}' for val,sec,curr in data])+'\n' + res_balance = round(sum([val*k[curr] for val,sec,curr in data]) + remain['USD']*k['USD'] + remain['RUB']*k['RUB'],2) + return res_balance, res_full + +def get_balance(login, password, storename=None): + result = {} + stocks = personalsetting.stocks[login]['STOCKS'] + remain = personalsetting.stocks[login]['REMAIN'] + currenc = personalsetting.stocks[login]['CURRENC'] + res_balance, res_full = count_all_scocks_multithread(stocks, remain, currenc) + result['Stock'] = res_full # Полная информация по стокам + result['Balance'] = res_balance # Сумма в заданной валюте + result['Currenc'] = currenc # Валюта + return result + + +if __name__ == '__main__': + print('This is module finance.yahoo.com') diff --git a/plugin/usd.py b/plugin/usd.py index 72f22ab..362c614 100644 --- a/plugin/usd.py +++ b/plugin/usd.py @@ -8,8 +8,8 @@ def get_balance(login, password, storename=None): result = {} session = requests.Session() url = time.strftime("http://cbrates.rbc.ru/tsv/840/%Y/%m/%d.tsv") - response2 = session.get(url) - result['Balance'] = response2.text.split()[-1] + response = session.get(url) + result['Balance'] = response.text.split()[-1] result['userName'] = 'Курс доллара от РБК' return result diff --git a/readme.md b/readme.md index c04e44c..33d7133 100644 --- a/readme.md +++ b/readme.md @@ -37,6 +37,12 @@ sodexo - Получение баланса карты Sodexo (подарочны strelka - Баланс карты стрелка tele2 - ТЕЛЕ2 zadarma - Zadarma.com (IP телефония) +usd - Курс доллара с RBC +eur - Курс евро с RBC +financeyahoo - Курс ценных бумаг с finance.yahoo.com +moex - Курс ценных бумаг с moex.com +stock - Рассчет цены портфеля ценных бумаг +sipnet - Sipnet (IP телефония) ## Как проверить вручную запустите из C:\mbplugin\plugin: