Récemment, il y a eu une forte volatilité sur les marchés boursiers lorsque, par exemple, un papier stable d'une société bien connue peut perdre plusieurs pour cent à la fois en raison de sanctions contre sa direction ou vice versa s'envoler dans le ciel sur un rapport positif et les attentes des investisseurs concernant les dividendes extra-profit.
Comment déterminer si la propriété d'un titre donné a généré des revenus ou seulement des pertes et des déceptions?
(Source)Dans cet article, je vais vous expliquer comment identifier et visualiser le résultat financier ajusté des titres.
En utilisant l'exemple du reporting client Opening Broker, nous considérerons l'analyse et la consolidation des rapports de courtage pour le marché boursier, en construisant l'architecture d'un systÚme de reporting cloud avec une analyse simple et pratique ultérieure dans AWS Quicksight.
Description de la tĂąche
De nombreuses formations et leçons de formation nous parlent de la nĂ©cessitĂ© d'un journal du commerçant, oĂč tous les paramĂštres de transaction sont enregistrĂ©s pour une analyse plus approfondie et rĂ©sumer les rĂ©sultats de la stratĂ©gie de trading. Je suis d'accord que cette approche du travail sur la Bourse vous permet de discipliner un commerçant, d'augmenter sa conscience, mais cela peut aussi vous fatiguer d'un processus fastidieux.
J'avoue qu'au début, j'ai essayé soigneusement de suivre les conseils de la journalisation, écrit méticuleusement chaque transaction avec ses paramÚtres dans un tableau Excel, construit des rapports, des graphiques récapitulatifs, planifié les transactions futures, mais ... J'en ai vite été fatigué.
Pourquoi tenir un journal d'un commerçant manuellement n'est pas pratique?- le remplissage manuel du journal (mĂȘme en utilisant une automatisation partielle, sous forme de dĂ©chargement des transactions quotidiennes du terminal de trading) se fatigue rapidement;
- il y a un risque élevé d'erreur ou de faute de frappe avec la saisie manuelle;
- il peut arriver qu'un trader actif devienne un investisseur passif et il revient de moins en moins dans ce magazine, puis l'oublie complĂštement (mon cas); enfin et enfin
- nous pouvons programmer, pourquoi ne pas en profiter et automatiser l'ensemble du processus? Alors allons-y!
Souvent, les sociĂ©tĂ©s de courtage sont des organisations de haute technologie qui fournissent Ă leurs clients des analyses d'assez bonne qualitĂ© sur presque toutes les questions d'intĂ©rĂȘt. Il est juste de dire que ces rapports s'amĂ©liorent de plus en plus avec chaque mise Ă jour, mais mĂȘme les plus avancĂ©s d'entre eux peuvent ne pas avoir la personnalisation et la consolidation que les clients exigeants et curieux veulent voir.
Par exemple, Opening Broker vous permet de recevoir des rapports de courtage au format XML dans votre compte personnel, mais si vous avez un IIA et un compte de courtage régulier à la Bourse de Moscou (MOEX), ce seront deux rapports différents, et si vous avez un autre compte sur St. Petersburg Stock Exchange (SPB), puis les deux premiers en ajouteront un de plus.
Au total, pour obtenir un journal consolidé de l'investisseur, il faudra traiter trois fichiers au format XML.
Les rapports susmentionnĂ©s sur le MOEX et le SPB diffĂšrent lĂ©gĂšrement dans leurs formats, qui devront ĂȘtre pris en compte dans le processus de mise en Ćuvre de la cartographie des donnĂ©es.
Architecture du systÚme en cours de développement
Le schéma ci-dessous montre le modÚle d'architecture du systÚme en cours de développement:
Implémentation de l'analyseur
Nous recevrons des rapports sur les trois comptes dans le compte personnel pour la pĂ©riode maximale possible (peut ĂȘtre divisĂ© en plusieurs rapports pour chaque annĂ©e), les enregistrer au format XML et les mettre dans un dossier. Comme donnĂ©es de test pour l'Ă©tude, nous utiliserons un portefeuille de clients fictifs, mais avec des paramĂštres aussi proches que possible des rĂ©alitĂ©s du marchĂ©.
Supposons que l'investisseur M. X considéré ait un petit portefeuille de cinq titres:
- Le rapport sur l'échange SPB comprendra deux articles: Apple et Microsoft;
- Le rapport sur la bourse MOEX (courtage) contient un document: FGC UES;
- Le rapport sur le MOEX Exchange (IIS) contient deux titres: MMK et OFZ 24019;
Selon nos cinq titres, il peut y avoir des transactions sur l'achat / la vente, le paiement de dividendes et d'un coupon, le prix peut changer, etc. Nous voulons voir la situation actuelle, à savoir: le résultat financier, en tenant compte de tous les paiements, transactions et valeur marchande actuelle.
Et ici Python entre en jeu, nous lisons les informations de tous les rapports dans un tableau:
my_files_list = [join('Data/', f) for f in listdir('Data/') if isfile(join('Data/', f))] my_xml_data = []
Pour l'analyse, les rapports nécessitent plusieurs entités, à savoir:
- Positions de titres dans un portefeuille;
- Accords conclus;
- Opérations non commerciales et autres mouvements de compte;
- Prix ââmoyens des positions ouvertes
Afin de préparer l'échantillon, nous utiliserons quatre dictionnaires pour décrire les ensembles ci-dessus.
dict_stocks = {'stock_name': [], 'account': [], 'currency': [], 'current_cost': [], 'current_cost_rub': [], 'saldo' : []} dict_deals = {'stock_name': [], 'account': [], 'date_oper': [], 'type_oper': [], 'quantity': [], 'price': [], 'currency': [], 'brokerage': [], 'result': []} dict_flows = {'stock_name': [], 'account': [], 'date_oper': [], 'type_oper': [], 'result': [], 'currency': []} dict_avg_price = {'stock_name': [], 'account': [], 'avg_open_price' : []}
Quelques mots sur la signification de ces dictionnaires.
Dictionnaire Dict_stocksLe dictionnaire dict_stocks est nécessaire pour stocker des informations générales sur le portefeuille:
- Nom du papier (nom_stock);
- Nom du compte (SPB, MOEX BROK, MOEX IIS) (compte);
- Devise utilisée pour les rÚglements sur ce papier (devise);
- Valeur actuelle (au moment de la génération du rapport dans le courtier d'ouverture de compte personnel) (current_cost). Ici, je tiens à noter que pour les clients trop exigeants, il est possible d'apporter des améliorations supplémentaires à l'avenir et d'utiliser la réception dynamique d'un devis de sécurité à partir d'un terminal de trading ou du site Web de la bourse correspondante;
- La valeur actuelle de la position de sĂ©curitĂ© au moment oĂč le rapport a Ă©tĂ© gĂ©nĂ©rĂ© (current_cost_rub)
De maniÚre similaire à l'article ci-dessus, vous pouvez également obtenir ici le taux de la Banque centrale au moment actuel ou le taux de change, comme vous le souhaitez. - Solde courant des titres (saldo)
Dictionnaire dict_dealsLe dictionnaire dict_deals est nécessaire pour stocker les informations suivantes sur les transactions terminées:
- Nom du papier (nom_stock);
- Nom du compte (SPB, MOEX BROK, MOEX IIS) (compte);
- Date de transaction, c.-Ă -d. T0 (date_oper);
- Type d'opération (type_oper);
- Le volume de titres participant à la transaction (quantité);
- Le prix auquel la transaction a été exécutée (prix);
- Devise dans laquelle la transaction a été effectuée (devise);
- Commission de courtage pour une transaction (courtage);
- Le résultat financier de la transaction (résultat)
Dictionnaire Dict_flowsLe dictionnaire dict_flows reflÚte le mouvement des fonds sur le compte client et est utilisé pour stocker les informations suivantes:
- Nom du papier (nom_stock);
- Nom du compte (SPB, MOEX BROK, MOEX IIS) (compte);
- Date de transaction, c.-Ă -d. T0 (date_oper);
- Type d'opération (type_oper). Il peut prendre plusieurs valeurs: div, NKD, tax;
- Devise dans laquelle la transaction a été effectuée (devise);
- Le résultat financier de l'opération (résultat)
Dictionnaire dict_avg_priceLe dictionnaire dict_avg_price est nécessaire pour les informations comptables au prix d'achat moyen pour chaque papier:
- Nom du papier (nom_stock);
- Nom du compte (SPB, MOEX BROK, MOEX IIS) (compte);
- Prix ââmoyen d'une position ouverte (avg_open_price)
Nous traitons un tableau de documents XML et remplissons ces dictionnaires avec les données appropriées:
Tout le traitement passe par la boucle sur toutes les donnĂ©es XML des rapports. Les informations sur la plateforme de trading, le code client sont les mĂȘmes dans tous les rapports, vous pouvez donc les extraire en toute sĂ©curitĂ© des mĂȘmes balises sans utiliser de mappage.
Mais nous devons ensuite utiliser une conception spéciale qui fournira l'alias nécessaire pour la balise basée sur le rapport (SPB ou MOEX), car les données de nature identique dans ces rapports sont appelées différemment.
Ăcarts de balise- La commission de courtier de transactions dans le rapport SBP se trouve dans la balise de courtage et dans le rapport MOEX - broker_commission ;
- La date de transaction du compte non commercial dans le rapport SPB est operationdate et dans MOEX, c'est operation_date , etc.
Exemple de mappage de balises tags_mapping = { 'SPB': { 'current_position': 'briefcase_position', 'deals': 'closed_deal', 'flows': 'nontrade_money_operation', ... 'stock_name_deal': 'issuername', 'paymentcurrency': 'paymentcurrency', 'currency_flows': 'currencycode' }, 'MOEX': { 'current_position': 'spot_assets', 'deals': 'spot_main_deals_conclusion', 'flows': 'spot_non_trade_money_operations', ... 'stock_name_deal': 'security_name', 'paymentcurrency': 'price_currency_code', 'currency_flows': 'currency_code' } }
La fonction get_allias renvoie le nom de la balise nécessaire pour le traitement, en prenant le nom de la plateforme de trading en entrée:
Fonction Get_allias def get_allias(exchange_name): return( tags_mapping[exchange_name]['current_position'], tags_mapping[exchange_name]['deals'], tags_mapping[exchange_name]['flows'], ... tags_mapping[exchange_name]['stock_name_deal'], tags_mapping[exchange_name]['paymentcurrency'], tags_mapping[exchange_name]['currency_flows'] )
La fonction get_briefcase est responsable du traitement des informations sur l'état du portefeuille client:
Fonction Get_briefcase def get_briefcase(XMLdata):
Ensuite, la fonction get_deals récupÚre des informations sur les transactions:
Fonction Get_deals def get_deals(XMLdata): stock_name_proc = '' closed_deal = XMLdata.find(deals) if not closed_deal: return
En plus de traiter un tableau avec des informations sur les paramÚtres de la transaction, le prix moyen d'une position ouverte et réalisé par PNL en utilisant la méthode FIFO est également calculé ici. La classe PnlSnapshot est responsable de ce calcul, dont la création avec les petites modifications le code présenté ici a été prise comme base:
calcul P&LEt enfin, le plus difficile Ă mettre en Ćuvre est la fonction d'obtention d'informations sur les opĂ©rations non commerciales -
get_nontrade_operation . Sa complexité réside dans le fait que dans le bloc de rapport utilisé pour les opérations non commerciales, il n'y a pas d'informations claires sur le type de transaction et la sécurité à laquelle cette opération est liée.
Exemple de destinations de paiement pour les opĂ©rations non commercialesLe paiement de dividendes ou de revenus de coupons accumulĂ©s peut ĂȘtre indiquĂ© comme suit:
- Paiement des revenus du client <777777> dividendes < APPLE INC-ao> -> paiement des dividendes du rapport SPB;
- Paiement des revenus du client <777777> dividendes < MICROSOFT COM->
- Paiement des revenus des clients 777777i (NKD 2 OFZ 24019 ) retenue Ă la source 0,00 roubles -> paiement du coupon du rapport MOEX;
- Paiement des revenus au client 777777 dividendes de FGC UES -ao précompte mobilier XX.XX roubles -> paiement des dividendes du rapport MOEX. etc.
En consĂ©quence, il sera difficile de se passer d'expressions rĂ©guliĂšres, nous les utiliserons donc au maximum. L'autre cĂŽtĂ© du problĂšme est que le nom de l'entreprise ne coĂŻncide pas toujours avec le nom dans le portefeuille ou dans les transactions aux fins du paiement. Par consĂ©quent, le nom reçu de l'Ă©metteur du but du paiement doit ĂȘtre corrĂ©lĂ© en plus avec le dictionnaire. En tant que dictionnaire, nous utiliserons un Ă©ventail d'offres, car il y a la liste la plus complĂšte des entreprises.
La fonction
get_company_from_str récupÚre le nom de l'émetteur dans le commentaire:
Fonction Get_company_from_str def get_company_from_str(comment): company_name = ''
La fonction
get_company_from_briefcase mÚne le nom de la société au dictionnaire si elle trouve une correspondance parmi les sociétés qui ont participé aux transactions:
Fonction Get_company_from_briefcase def get_company_from_briefcase(company_name): company_name_full = None value_from_dic = df_deals[df_deals['stock_name'].str.contains(company_name)] company_arr = value_from_dic['stock_name'].unique() if len(company_arr) == 1: company_name_full = company_arr[0] return company_name_full
Et enfin, la fonction finale de la collecte de données sur les opérations non commerciales est
get_nontrade_operation :
Fonction Get_nontrade_operation def get_nontrade_operation(XMLdata): nontrade_money_operation = XMLdata.find(flows) if not nontrade_money_operation: return try: for child in nontrade_money_operation: comment = child.get('comment') type_oper_match = re.search('||^.+.+.+$', comment) if type_oper_match: company_name = get_company_from_str(comment) type_oper = get_type_oper(comment) dict_flows['stock_name'].append(company_name) dict_flows['account'].append(account_name) dict_flows['date_oper'].append(to_dt(child.get(operationdate)).strftime('%Y-%m-%d')) dict_flows['type_oper'].append(type_oper) dict_flows['result'].append(float(child.get('amount'))) dict_flows['currency'].append(child.get(currency_flows)) except Exception as e: print('get_nontrade_operation --> Oops! It seems we have a BUG!', e)
Le résultat de la collecte de données à partir des rapports sera trois DataFrames, qui sont approximativement les suivants:
- DataFrame avec des informations sur les prix moyens des positions ouvertes:
- Deal DataFrame:
- DataFrame avec des informations sur les opérations non commerciales:
Il ne nous reste donc plus qu'Ă effectuer une union externe de la table des transactions avec la table d'informations du portefeuille:
df_result = pd.merge(df_deals, df_stocks_avg, how='outer', on=['stock_name', 'account', 'currency']).fillna(0) df_result.sample(10)
Enfin, la derniÚre étape du traitement du tableau de données est la fusion du tableau de données obtenu à l'étape précédente avec le DataFrame pour les transactions non commerciales.
Le résultat du travail effectué est une grande table plate avec toutes les informations nécessaires à l'analyse:
df_result_full = df_result.append(df_flows, ignore_index=True).fillna(0) df_result_full.sample(10).head()
L'ensemble de donnĂ©es rĂ©sultant (rapport final) du DataFrame est facilement tĂ©lĂ©chargĂ© sur le CSV et peut ensuite ĂȘtre utilisĂ© pour une analyse dĂ©taillĂ©e dans n'importe quel systĂšme de BI.
if not exists('OUTPUT'): makedirs('OUTPUT') report_name = 'OUTPUT\my_trader_diary.csv' df_result_full.to_csv(report_name, index = False, encoding='utf-8-sig')
Charger et traiter des données dans AWS
Les progrÚs ne sont pas en reste et les services cloud et les modÚles informatiques sans serveur gagnent désormais en popularité dans le traitement et le stockage des données. Cela est en grande partie dû à la simplicité et au coût peu élevé de cette approche, lorsque vous n'avez pas besoin d'acheter un équipement coûteux pour construire une architecture systÚme pour le calcul complexe ou le traitement de données volumineuses, mais que vous louez simplement l'énergie dans le cloud pour le temps dont vous avez besoin et déployez les ressources nécessaires assez rapidement pour un coût relativement faible. .
Amazon est l'un des fournisseurs de cloud les plus importants et les plus connus du marché. Regardons l'exemple de l'environnement Amazon Web Services (AWS) pour construire un systÚme analytique de traitement des données sur notre portefeuille d'investissement.
AWS dispose d'une vaste sélection d'outils, mais nous utiliserons les éléments suivants:
- Amazon S3 - stockage d'objets, qui vous permet de stocker des quantités presque illimitées d'informations;
- AWS Glue - le service ETL cloud le plus puissant qui peut lui-mĂȘme dĂ©terminer la structure et gĂ©nĂ©rer le code ETL Ă partir des donnĂ©es source donnĂ©es;
- Amazon Athena , un service de requĂȘte SQL en ligne sans serveur, vous permet d'analyser rapidement les donnĂ©es de S3 sans trop de prĂ©paration. Il a Ă©galement accĂšs aux mĂ©tadonnĂ©es qu'AWS Glue prĂ©pare, ce qui vous permet d'accĂ©der aux donnĂ©es immĂ©diatement aprĂšs avoir passĂ© l'ETL;
- Amazon QuickSight - BI-service sans serveur, vous pouvez créer n'importe quelle visualisation, des rapports analytiques "à la volée", etc.
La documentation d'Amazon est correcte, en particulier, il existe un bon article
Meilleures pratiques lors de l'utilisation d'Athena avec AWS Glue , qui décrit comment créer et utiliser des tables et des données à l'aide d'AWS Glue. Profitons des idées principales de cet article et appliquons-les pour créer notre propre architecture d'un systÚme de rapports analytiques.
Les fichiers CSV préparés par notre analyseur de rapports seront ajoutés au compartiment S3. Il est prévu que le dossier correspondant sur S3 soit réapprovisionné tous les samedis - à la fin de la semaine de négociation, de sorte que vous ne pouvez pas vous passer du partitionnement des données à la date de formation et de traitement du rapport.
En plus d'optimiser le fonctionnement des requĂȘtes SQL sur de telles donnĂ©es, cette approche nous permettra de mener des analyses complĂ©mentaires, par exemple, pour obtenir la dynamique des changements dans le rĂ©sultat financier de chaque article, etc.
Travailler avec Amazon S3- Créez un compartiment sur S3, appelez-le «report-parser»;
- Dans ce bucket "report-parser" créez un dossier appelé "my_trader_diary";
- Dans le répertoire "my_trader_diary", créez un répertoire avec la date du rapport actuel, par exemple, "date_report = 2018-10-01" et placez-y le fichier CSV;
- Dans le seul but d'expĂ©rimenter et de mieux comprendre le partitionnement, nous allons crĂ©er deux rĂ©pertoires supplĂ©mentaires: "date_report = 2018-09-27" et "date_report = 2018-10-08". Nous y mettons le mĂȘme fichier CSV;
- Le dernier "analyseur de rapports" du compartiment S3 devrait ressembler à celui illustré dans les images ci-dessous:
Travailler avec AWS GlueEn gros, vous ne pouvez faire qu'Amazon Athena pour créer une table externe à partir des données se trouvant sur S3, mais AWS Glue est un outil plus flexible et pratique pour cela.
- Nous allons dans AWS Glue et créons un nouveau robot, qui collectera une table à partir de fichiers CSV distincts par date de rapport:
- Définissez le nom du nouveau robot;
- Nous indiquons le rĂ©fĂ©rentiel d'oĂč obtenir les donnĂ©es (s3: // report-parser / my_trader_diary /)
- Nous sélectionnons ou créons un nouveau rÎle IAM qui aura accÚs au lancement du robot et à la ressource spécifiée sur S3;
- Ensuite, vous devez définir la fréquence de démarrage. Nous l'avons mis sur demande pour l'instant, mais à l'avenir, je pense que cela va changer et le lancement deviendra hebdomadaire;
- Enregistrez et attendez la création du robot.
- Lorsque le robot entre en Ă©tat PrĂȘt, dĂ©marrez-le!
- Une fois que cela fonctionne, une nouvelle table my_trader_diary apparaßtra dans l'onglet AWS Glue: Base de données -> Tables:
Considérez le tableau généré plus en détail.
Si vous cliquez sur le nom de la table créée, nous irons à la page avec la description des métadonnées. En bas, il y a une disposition de table et la plus récente est une colonne qui n'était pas dans le fichier CSV source - date_report. Cette colonne qu'AWS Glue crée automatiquement en fonction de la définition des sections des données source (dans Bucket S3, nous avons spécialement nommé les dossiers date_report = YYYY-MM-DD, ce qui nous a permis de les utiliser comme sections séparées par date).
Partitionnement de tableSur la mĂȘme page dans le coin supĂ©rieur droit, il y a un bouton Afficher les partitions, en cliquant sur lequel nous pouvons voir quelles sections notre tableau gĂ©nĂ©rĂ© comprend:
Analyse des données
Ayant Ă notre disposition des donnĂ©es traitĂ©es tĂ©lĂ©chargĂ©es, nous pouvons facilement commencer Ă les analyser. Pour commencer, considĂ©rez les capacitĂ©s d'Amazon Athena comme le moyen le plus simple et le plus rapide d'effectuer des requĂȘtes analytiques. Pour ce faire, accĂ©dez au service Amazon Athena, sĂ©lectionnez la base de donnĂ©es dont nous avons besoin (financiĂšre) et Ă©crivez le code SQL suivant:
select d.date_report, d.account, d.stock_name, d.currency, sum(d.quantity) as quantity, round(sum(d.result), 2) as result from my_trader_diary d group by d.date_report, d.account, d.stock_name, d.currency order by d.account, d.stock_name, d.date_report;
Cette demande nous affichera un rĂ©sultat financier net pour chaque titre pour toutes les dates de dĂ©claration. Parce que nous avons tĂ©lĂ©chargĂ© le mĂȘme rapport trois fois pour des dates diffĂ©rentes, le rĂ©sultat ne changera pas, ce qui, bien sĂ»r, sur un marchĂ© rĂ©el sera diffĂ©rent:
Mais que se passe-t-il si nous voulons visualiser les donnĂ©es reçues sous forme de tableaux ou de diagrammes flexibles? Ici, Amazon QuickSight vient Ă la rescousse, avec l'aide de laquelle vous pouvez configurer des analyses flexibles presque aussi rapidement que l'Ă©criture d'une requĂȘte SQL. Nous allons accĂ©der au service Amazon QuickSight (si vous n'y ĂȘtes pas encore inscrit, l'inscription est obligatoire).
Cliquez sur le bouton Nouvelles analyses -> Nouvel ensemble de donnĂ©es et dans la fenĂȘtre qui apparaĂźt sĂ©lectionnez les sources pour l'ensemble de donnĂ©es, cliquez sur AthĂ©na:
Nous allons trouver un nom pour notre source de données, par exemple, "PNL_analysis" et cliquer sur le bouton "Créer une source de données".
Ensuite, la fenĂȘtre Choisissez votre table s'ouvre, oĂč vous devez sĂ©lectionner la base de donnĂ©es et la table de source de donnĂ©es. Nous sĂ©lectionnons la base de donnĂ©es - financiĂšre, et la table qu'elle contient: my_traider_diary. Par dĂ©faut, la table entiĂšre est utilisĂ©e, mais si vous sĂ©lectionnez «Utiliser SQL personnalisé», vous pouvez personnaliser et affiner l'Ă©chantillon de donnĂ©es dont vous avez besoin. Par exemple, nous utilisons l'ensemble du tableau et cliquez sur le bouton Modifier / Aperçu des donnĂ©es.
Une nouvelle page s'ouvrira oĂč vous pourrez effectuer des rĂ©glages supplĂ©mentaires et traiter les donnĂ©es existantes.
Nous devons maintenant ajouter des champs calculés supplémentaires à notre jeu de données: trimestre et année de fonctionnement. Un lecteur attentif peut remarquer que de telles manipulations étaient plus faciles à faire du cÎté de l'analyseur avant d'enregistrer le rapport final au format CSV. Sans aucun doute, mon objectif est maintenant de démontrer les capacités et la flexibilité des paramÚtres du systÚme BI à la volée. Nous continuons à créer des champs calculés en cliquant sur le bouton «Nouveau champ».
Pour mettre en évidence l'année de l'opération et le trimestre, des formules simples sont utilisées:
Remplir des formules pour un nouveau champ Lorsque les champs calculés ont été créés avec succÚs et ajoutés à la sélection, donnez un nom à notre jeu de données, par exemple, "my_pnl_analyze" et cliquez sur le bouton "Enregistrer et visualiser".
AprĂšs cela, nous transfĂ©rons vers la carte principale d'Amazon QuickSight et la premiĂšre chose que nous devons faire est de configurer un filtre pour la date du rapport (en tenant compte du fait que les mĂȘmes donnĂ©es ont Ă©tĂ© collectĂ©es dans trois sections). SĂ©lectionnez la date du rapport 2018-10-01 et cliquez sur le bouton Appliquer et accĂ©dez Ă l'onglet Visualiser.
, , , (.. ) . BI â . , ( MS Excel)
, , , .. 1 509.91 . (1 763.36 . â 174 . â ). .
â :
, , , . : sum_investment count_days.
sum_investmentsum_investment ( ) :
ifelse({stock_name} = ' 24019',{avg_open_price} * quantity * 10,{avg_open_price} * quantity)
, â ( â 1000).
count_dayscount_day ( ) :
dateDiff(parseDate({date_oper}),parseDate({date_report}))
:
« » Amazon. , .. , , , .
, ( ) . , , , â .
, . , PNL (, ), .⊠Quicksight , , Python .
- , : XML-! , , API . Amazon: ETL-job AWS Glue Amazon QuickSight .
GitHub