Table of Contents
Dans le cadre de l’analyse de portefeuille, j’ai récemment utilisé la bibliothèque yfinance de Python. Au lieu d’utiliser un notebook Jupyter pour exécuter le code Python et visualiser les résultats, j’ai décidé de créer une application de bureau .NET avec WinUI 3.0, XAML et C#. Cette application permet de définir un portefeuille et de gérer la présentation graphique des résultats, tandis que l’analyse sous-jacente est effectuée en Python. J’utilise Python.NET pour appeler le code Python depuis C#. Cet article décrit comment utiliser Python.NET pour appeler des fonctions Python à partir d’une application C#.
Versions Utilisées
Nous avons utilisé les versions suivantes :
- Python 3.12
- yfinance 0.2.54
- Python.NET 3.0.5
L’API Python
J’ai commencé par écrire un script simple d’analyse de portefeuille. Ce script est basé sur une application de gestion de portefeuille écrite en Python, mais j’ai réorganisé la fonctionnalité principale pour séparer les calculs et l’analyse de la couche de présentation graphique. Cela m’a permis d’appeler les fonctions Python depuis C# pour obtenir les données et ensuite traiter ces données dans l’application C#.
L’API est composée de quatre fonctions :
portfolio_returns(ticker_values, start_date, end_date)
: Cette fonction calcule les poids des tickers et obtient les prix de clôture ajustés pour chaque ticker à l’aide de la bibliothèque yfinance.perform_portfolio_analysis(data, ticker_weights, risk_free_rate)
: Elle utilise les données de retour du portefeuille et calcule les rendements des titres individuels, les rendements cumulés, la volatilité et les ratios de Sharpe.benchmark_returns(benchmark, start_date, end_date)
: Cette fonction obtient les données de référence depuis yfinance à l’aide des paramètres fournis.portfolio_vs_benchmark(port_returns, benchmark_returns, risk_free_rate)
: Elle calcule les rendements cumulés, la volatilité annualisée et les ratios de Sharpe pour comparer le portefeuille et la référence.
L’application .NET
Pré-requis
Pour l’application .NET, il faut d’abord télécharger et construire Python.NET. Le code est disponible sur GitHub. Une fois téléchargé, ouvrez le fichier de solution et sélectionnez Python.Runtime comme projet de démarrage. Après avoir compilé la version de débogage, Python.Runtime.dll
sera situé dans le répertoire pythonnet.
Application PortfolioManager
Après avoir construit Python.Runtime.dll
, il faut l’ajouter à l’application Portfolio Manager. Cette dernière est une application WinUI 3.0 qui utilise le Windows Community Toolkit pour l’injection de dépendances et l’architecture MVVM, ainsi qu’une base de données Sqlite pour gérer les portefeuilles.
La solution se compose de deux projets principaux : PortfolioManager et PortfolioManager.Core. Le projet PortfolioManager gère la logique de l’application, les paramètres utilisateur et les vues. Nous ajoutons Python.Runtime.dll
aux Dépendances sous le nœud Assemblies.
Le Service Python
Dans la bibliothèque de base, nous définissons une interface simple IPythonService
qui encapsule l’initialisation et les appels à l’API Python.
Dans le projet PortfolioManager, nous ajoutons IPythonService
à la liste des services à activer et passons une instance de celui-ci au PortfolioDetailViewModel
.
Analyse de Portefeuille
La fonction principale RunPortfolioAnalysis
est appelée avec l’élément de portefeuille sélectionné. Elle charge le script d’analyse de portefeuille et le passe à Python.NET, qui crée un objet module
pour accéder aux fonctions et variables du script.
Une fois l’analyse terminée, les résultats sont copiés dans les membres de données de l’élément de portefeuille. Le modèle de données du portefeuille est ensuite utilisé pour mettre à jour les graphiques affichés dans l’application.
Couche d’interopérabilité
Cette couche fournit des facilités pour convertir entre les types C# et Python. Les types de base (chaînes, entiers, doubles, etc.) sont convertis de manière transparente. Nous utilisons la méthode d’extension .ToPython()
pour convertir un objet C# en objet Python.
Performance et Investigations
Il est à noter que les performances sont relativement lentes. L’initialisation du moteur Python prend du temps, et il pourrait être intéressant de l’effectuer une seule fois au démarrage. De plus, le PortfolioDetailViewModel
crée plusieurs graphiques séquentiellement, ce qui pourrait être amélioré en utilisant un traitement asynchrone en C#.