Skip to content

Commit

Permalink
v3.0.0: Massive change, use new APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas Béguier committed Feb 12, 2023
1 parent d4d6b0b commit a7c02c8
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 1,107 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ settings.py
cache/
report.html
venv/
*.txt
20 changes: 0 additions & 20 deletions .travis.yml

This file was deleted.

4 changes: 2 additions & 2 deletions autocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
# Third party library imports

# Own library
import lib.common as common
from lib import common

# Debug
# from pdb import set_trace as st

VERSION = '1.4.0'
VERSION = '3.0.0'

def print_autocomplete(input_str):
"""
Expand Down
16 changes: 8 additions & 8 deletions dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from tabulate import tabulate

# Own library
import lib.reporting as reporting
from lib import reporting
try:
import settings
except ImportError:
Expand All @@ -25,26 +25,26 @@
# Debug
# from pdb import set_trace as st

VERSION = '1.2.0'
VERSION = '3.0.0'

def main():
"""
Main function
"""
listing = list()
listing = []
for isin in settings.ISIN_DASHBOARD:
market = 'XPAR'
if ',' in isin:
market = isin.split(',')[1]
isin = isin.split(',')[0]
isin = isin.split(',', maxsplit=1)[0]
isin_data = reporting.get_cours(isin, market, disable_cache=True)
if not isin_data:
listing.append(list())
listing.append([])
continue
listing.append([
isin_data['cotation']['name'],
isin_data['cotation']['valorisation'],
isin_data['cotation']['variation'],
isin_data['DISPLAY_NAME']['v'],
isin_data['LVAL_NORM']['v'], # TODO: test in real time
isin_data['NC2_PR_NORM']['v'],
])
print(tabulate(listing, [
'Nom',
Expand Down
40 changes: 6 additions & 34 deletions isin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,26 @@
import sys

# Own library
import lib.common as common
import lib.display as display
import lib.reporting as reporting
from lib import common, display, reporting

# Debug
# from pdb import set_trace as st

VERSION = '2.8.1'
VERSION = '3.0.0'

def main(parameters):
"""
Main function
"""
report = reporting.get_report(parameters)
report = reporting.simplify_report(report, parameters)
if parameters['history']['healthy']:
display.print_health(report, parameters['verbose'])
else:
display.print_report(
report,
mic=parameters['mic'],
header=parameters['header'],
footer=parameters['footer'],
verbose=parameters['verbose'])
display.print_report(
report,
header=parameters['header'])

if __name__ == '__main__':
PARSER = ArgumentParser()

PARSER.add_argument('--version', action='version', version=VERSION)
PARSER.add_argument('--verbose', action='store_true',\
help="Affiche plus d'informations (=False)", default=False)

PARSER.add_argument('-i', '--isin', action='store',\
help="Code ISIN")
Expand All @@ -52,30 +41,13 @@ def main(parameters):
help="Code d'identification de marché (=XPAR)", default='XPAR')
PARSER.add_argument('--no-header', action='store_true',\
help="Cache les informations de bases (=False)", default=False)
PARSER.add_argument('--no-footer', action='store_true',\
help="Cache les URLs de fin (=False)", default=False)
PARSER.add_argument('--dividendes-history', action='store_true',\
help="Affiche plus d'informations sur les dividendes (=False)", default=False)
PARSER.add_argument('--per-history', action='store_true',\
help="Affiche la valeur théorique du PER (=False)", default=False)
PARSER.add_argument('--peg-history', action='store_true',\
help="Affiche la valeur théorique du PEG (=False)", default=False)
PARSER.add_argument('--is-healthy', action='store_true',\
help="Affiche l'état de santé de l'action (=False)", default=False)

ARGS = PARSER.parse_args()

PARAMS = dict()
PARAMS = {}
PARAMS['isin'] = ARGS.isin
PARAMS['mic'] = ARGS.market_id_code
PARAMS['verbose'] = ARGS.verbose
PARAMS['header'] = not ARGS.no_header
PARAMS['footer'] = not ARGS.no_footer
PARAMS['history'] = dict()
PARAMS['history']['dividendes'] = ARGS.dividendes_history
PARAMS['history']['per'] = ARGS.per_history
PARAMS['history']['peg'] = ARGS.peg_history
PARAMS['history']['healthy'] = ARGS.is_healthy
if not ARGS.isin and not ARGS.nom:
PARSER.print_help()
sys.exit(1)
Expand Down
120 changes: 16 additions & 104 deletions lib/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,124 +14,36 @@ def per_text(per_value):
"""
Retuns the analysis of the PER value
"""
if per_value is None:
if per_value == '-':
return 'inconnu'
result = 'bulle spéculative'
result = 'croissance annoncée extraordinaire'
if float(per_value) <= 0:
result = 'action sans bénéfices'
result = 'aucune croissance annoncée'
elif float(per_value) <= 10:
result = 'action sous-évaluée'
result = 'croissance annoncée raisonable'
elif float(per_value) <= 17:
result = 'ration bon'
result = 'croissance annoncée forte'
elif float(per_value) <= 25:
result = 'action surévaluée'
result = 'croissance annoncée énorme'
return result

def peg_text(peg_value):
"""
Retuns the analysis of the PEG value
"""
if peg_value is None:
if peg_value == '-':
return 'inconnu'
result = 'croissance annoncée trop faible'
if peg_value == 'infini':
return 'bulle spéculative'
result = 'bulle spéculative'
if float(peg_value) <= 0:
result = 'aucune croissance'
result = 'action sans bénéfices'
elif float(peg_value) <= 0.5:
result = 'croissance annoncée extrème'
elif float(peg_value) <= 1.5:
result = 'croissance annoncée forte'
result = 'action sous-évaluée'
elif float(peg_value) <= 1:
result = 'ration bon'
elif float(peg_value) <= 2.5:
result = 'croissance annoncée ok'
result = 'action surévaluée'
elif float(peg_value) <= 3.5:
result = 'croissance annoncée faible'
result = 'bulle spéculative'
return result

def per_by_value(current_per, current_val):
"""
Returns for each PER stage the share value
"""
result = {}
result[current_per] = {}
result[10] = {}
result[17] = {}
result[25] = {}
result[current_per]['value'] = current_val
result[current_per]['current'] = True
result[10]['value'] = current_val * 10 / current_per
result[10]['current'] = False
result[17]['value'] = current_val * 17 / current_per
result[17]['current'] = False
result[25]['value'] = current_val * 25 / current_per
result[25]['current'] = False
return result

def peg_by_value(current_peg, current_val):
"""
Returns for each PEG stage the share value
"""
result = {}
result[current_peg] = {}
result[0.5] = {}
result[1] = {}
result[2] = {}
result[3] = {}
result[3.6] = {}
result[current_peg]['value'] = current_val
result[current_peg]['current'] = True
result[0.5]['value'] = 0.5 * current_val / current_peg
result[0.5]['current'] = False
result[1]['value'] = 1 * current_val / current_peg
result[1]['current'] = False
result[2]['value'] = 2 * current_val / current_peg
result[2]['current'] = False
result[3]['value'] = 3 * current_val / current_peg
result[3]['current'] = False
result[3.6]['value'] = 3.6 * current_val / current_peg
result[3.6]['current'] = False
return result

def trend(simple_report):
"""
Returns the trend score on 5pts
- 3pts : average of trend
- 2pts : average of potential
"""
report = {}
report['short term'] = 0
report['mid term'] = 0
mapping = {
'Hausse': 1,
'Neutre': 0.5,
'Baisse': 0,
}
# Count trend and the sum of trend points (see mapping)
count_st_trend = 0
count_mt_trend = 0
for market in simple_report['trend']:
if simple_report['trend'][market]['short term'] in mapping:
count_st_trend += 1
report['short term'] += mapping[simple_report['trend'][market]['short term']]
if simple_report['trend'][market]['mid term'] in mapping:
count_mt_trend += 1
report['mid term'] += mapping[simple_report['trend'][market]['mid term']]
if count_st_trend == 0 or count_mt_trend == 0:
return {'short term': '-', 'mid term': '-'}
report['short term'] = 3 * report['short term'] / count_st_trend
report['mid term'] = 3 * report['mid term'] /count_mt_trend
# Sum potential points
potential_value = 0
potential_count = 0
for market in simple_report['potential']:
if simple_report['potential'][market]['value'] is not None:
potential_count += 1
if simple_report['potential'][market]['percentage'] > 1:
potential_value += 1
elif simple_report['potential'][market]['percentage'] > -1:
potential_value += 0.5
if potential_count == 0:
report['short term'] = report['short term'] * 5/3
report['mid term'] = report['mid term'] * 5/3
else:
report['short term'] += 2 * potential_value / potential_count
report['mid term'] += 2 * potential_value / potential_count
return report
67 changes: 60 additions & 7 deletions lib/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@
"""

# Standard library imports
from base64 import b64decode
from codecs import getencoder
from datetime import datetime
from hashlib import sha512
import json
import os
from pathlib import Path
from random import randint
import re
import time

# Third party library imports
Expand All @@ -32,15 +38,60 @@
# TTL = 60 # 1 minute
TTL = 21600 # 6 hours

def gen_headers():
def decode_rot(encoded_str):
"""
Returns the ROT-13 of the input string
"""
enc = getencoder('rot-13')
return enc(encoded_str)[0]

def gen_user_agent():
"""
Returns random User-Agent
"""
return {'User-Agent': \
'Mozilla/5.{a} (Macintosh; Intel Mac OS X 10_15_{a}) '.format(a=randint(1, 100)) +
'AppleWebKit/537.{} '.format(randint(1, 100)) +
'(KHTML, like Gecko) Chrome/80.{a}.3987.{a} '.format(a=randint(1, 100)) +
'Safari/537.{}'.format(randint(1, 100))}
return f'Mozilla/5.{randint(1, 100)} (Macintosh; Intel Mac OS X 10_15_{randint(1, 100)}) ' + \
f'AppleWebKit/537.{randint(1, 100)} ' + \
f'(KHTML, like Gecko) Chrome/80.{randint(1, 100)}.3987.{randint(1, 100)} ' + \
f'Safari/537.{randint(1, 100)}'

def get_token():
"""
Returns new token
"""
token_path = Path('/tmp/financial_token.jwt')
if token_path.exists():
token = token_path.open('r', encoding='utf-8').read()
if len(token.split('.')) <= 1:
print('Error retrieving token... (jwt invalid). Removing token.')
token_path.unlink()
return ''
try:
if datetime.timestamp(datetime.now()) < json.loads(b64decode(token.split('.')[1]+'=='))['exp']:
return token
except:
print('Error retrieving token... (exp not found). Removing token.')
token_path.unlink()
return ''
content = SESSION.get(
decode_rot('uggcf://vairfgve.yrfrpubf.se/pbhef/npgvbaf/xrevat-xre-se0000121485-kcne'),
headers={'User-Agent': gen_user_agent()})
if content.status_code != 200:
print('Error retrieving token... (page not found)')
return ''
result = re.findall('_TOKEN__="[a-zA-Z0-9\.=\-\_]+"', content.text)[0].split('"')
if len(result) <= 1 or not result[1].startswith('ey'):
print('Error retrieving token... (token not found)')
return ''
token = result[1]
token_path.open('w', encoding='utf-8').write(token)
return token

def gen_headers():
"""
Returns headers
"""
return {'Authorization': f'Bearer {get_token()}',
'User-Agent': gen_user_agent()}

HEADERS = gen_headers()

Expand Down Expand Up @@ -105,10 +156,12 @@ def load(url):
content = get(url, verify=False, disable_cache=True)
return content

def get(url, verify=True, disable_cache=False):
def get(url, verify=True, disable_cache=False, token=''):
"""
Requests the url is not in cache
"""
if token:
HEADERS['Authorization'] = f'Bearer {token}'
try:
enable_cache = settings.ENABLE_CACHE and not disable_cache
except AttributeError:
Expand Down
Loading

0 comments on commit a7c02c8

Please sign in to comment.