7
votes

Conception orientée objet pour un portefeuille d'investissements / actions et options à Python

Je suis un programmeur python débutant / intermédiaire, mais je n'ai pas écrit de demande, juste des scripts. Je n'utilise actuellement pas beaucoup de conception orientée objet, je voudrais donc que ce projet aidait à construire mes compétences de l'OOD. Le problème est que je ne sais pas où commencer à partir d'une perspective de conception (je sais comment créer les objets et tout ce genre de choses). Pour ce que ça vaut la peine, je suis aussi auto-enseigné, pas d'éducation formelle CS.

J'aimerais essayer de rédiger un programme pour suivre les postes de stocks / options de portefeuille. P>

J'ai une idée approximative de ce qui ferait de bons candidats à un objet (portefeuille, stock, option, etc.) et des méthodes (acheter, vendre, mettre à jour, etc.). p>

Une position longue achèterait-à-ouvrir et de vendre-à-fermer lors d'une position courte a une position de vente à la vente et d'acheter à proximité. P> xxx

Ensuite, une fois cette méthode appelée comment puis-je stocker les informations? Au début, je pensais avoir un objet de position avec des attributs comme le symbole, l'opportunité, l'openprice, etc. Mais réfléchissez à la mise à jour de la position des ventes devient délicate car l'achats et la vente se produisent à des moments différents et des montants. p>

  • Achetez 100 actions pour ouvrir, 1 heure, 1 prix. Vendez 4 fois différents, 4 prix différents. Li>
  • Achetez 100 actions. Vendre 1 action par jour, pour 100 jours. Li>
  • Achetez 4 fois différents, 4 prix différents. Vendre une position entière à 1 heure, 1 prix. Li> ul>

    Une solution éventuelle serait de créer un objet pour chaque part de stock, de cette manière que chaque action aurait une dates et des prix différentes. Cela serait-il trop au-dessus de la tête? Le portefeuille pourrait avoir des milliers ou des millions de petits objets de part. Si vous vouliez trouver la valeur marchande totale d'une position que vous auriez besoin de quelque chose comme: p> xxx pré>

    Si vous aviez un objet de position, le calcul serait simple: P >

    position.last * position.qty
    


4 commentaires

Vous voulez un calque de base de données pour ce type d'application.


En dehors de la curiosité, ne pas être très familier avec ce lingo, suis-je raison qu'une position "ouverte" est simplement un non-zéro (positif ou négatif pour une position courte) tenant dans un stock particulier?


Oui, une position ouverte serait non nulle. Fondamentalement, il y a deux types de positions: long et court. Long est ce que la plupart des gens pensent en investissant. Achetez bas, vendre haut. Une position courte est l'opposé d'aller longtemps. Vous empruntez des actions de votre courtier et vendez-les sur le marché, créant un passif que vous devez renvoyer les actions à votre casson (ou quand il les pose de retour). Le processus est (emprunter des actions) Vendez haut, Achetez-les bas (retournez-les à votre courtier).


Je sais que ce post est très vieux, mais je serais très intéressé d'apprendre à savoir si vous avez fait des progrès ici, car je pense au même problème et que vous avez 2 ans sur la route de moi.


5 Réponses :


1
votes

Évitez les objets. La conception orientée objet est défectueuse. Pensez à votre programme en tant que collection de comportements qui fonctionnent sur les données (listes et dictionnaires). Ensuite, regroupez vos comportements associés comme des fonctions dans un module. Chaque fonction doit avoir une entrée et des sorties claires. Stockez vos données globalement dans chaque module. Pourquoi le faire sans objets? Parce qu'il correspond à plus près de l'espace problématique. La programmation orientée objet crée une trop grande indirection pour résoudre un problème. L'indirection inutile provoque des bœufs logiciels et des bugs.

Une solution éventuelle serait de créer un objet pour chaque action de stock, de cette manière que chaque action aurait une dates et des prix différentes. Cela serait-il trop au-dessus de la tête? Le portefeuille pourrait avoir des milliers ou des millions de petits objets de part. Si vous vouliez trouver la valeur marchande totale d'une position que vous auriez besoin de quelque chose comme:

Oui, ce serait trop au-dessus de la tête. La solution ici est que vous stockiez les données dans une base de données. Trouver la valeur marchande totale d'une position serait effectuée dans SQL à moins que vous n'utilisiez un schéma NOSQL.

N'essayez pas de concevoir pour tous les résultats futurs possibles. Il suffit de faire fonctionner votre programme de cette façon dont il a besoin de travailler maintenant.


6 commentaires

Je suis d'accord avec "stocker tes données dans une base de données" et "ne pas trop sur conception de tout"; Je suis assez complètement en désaccord avec «la conception orientée objet est imparfait». Il est possible de le faire mal, mais c'est vrai de quoi que ce soit.


Peut-être que je ne sais pas comment faire correctement. Mais j'aime faire des choses. Ne pense pas à les faire.


@JUXTAPOSE: vraiment? Combien de programmes sur 500 lignes avez-vous fait sans réfléchir?


@Hugh heh. Ce n'est pas ce que je voulais dire. Mon expérience avec OO est que je dois passer à travers un tas de cerceaux pour résoudre un problème. De plus, les programmes ont tendance à être plus complexes car je ajoute des abstractions inutiles. Les modules qui ont un ensemble de fonctions font toujours le travail. Je n'ai peut-être pas travaillé sur un logiciel vraiment grand et complexe ... mais je ne suis pas sûr de vouloir aussi.


Je suis à peu près d'accord avec le commentaire de Hugh. @JUXTAPOSE: J'aime l'idée de laisser le "espace de problème" déterminer la solution et un ensemble de fonctions peut être une alternative à la solution de l'OOD.


Je ne peux pas croire que je suis le premier évoquant ce post. Je suis complètement d'accord avec @eat_a_lemon. J'irais plus loin et disons #unixphilosophy est la réponse.



1
votes

Je pense que je le séparerais en

  • Holdings (ce que vous possédez actuellement ou doit de chaque symbole)
  • commandes (demandes simples d'acheter ou de vendre un seul symbole à un moment donné)
  • métiers (collections de commandes)

    Cela facilite la nécessité d'obtenir une valeur actuelle, des commandes de la file d'attente et de créer des commandes plus complexes et de créer facilement des objets de données avec une base de données derrière eux.


1 commentaires

J'essaie d'imaginer comment cela fonctionnerait. Il est évident que les historiques de prix doivent être stockés dans une base de données. Mais qu'en est-il des actions? Est-ce que je voudrais toujours utiliser l'idée d'un objet comme une part? (Ce n'est que dans ce cas, ce serait un enregistrement de base de données plutôt qu'un objet)



1
votes

Pour répondre à votre question : vous semblez avoir une idée assez claire de votre modèle de données déjà. Mais cela me semble que vous devez penser davantage à ce que vous voulez ce programme. Sera-t-il suivre les changements de la bourse? Passer des commandes ou suggérer des ordres à placer? Ou cela gardera-t-il simplement une trace des commandes que vous avez placées? Chacune de ces utilisations peut appeler à différentes stratégies.

Cela dit, je ne vois pas pourquoi vous auriez jamais besoin d'avoir un objet pour chaque action ; Je ne comprends pas le raisonnement derrière cette stratégie. Même si vous souhaitez pouvoir suivre vos antécédents de commande en détail, vous pouvez simplement stocker des données agrégées, comme dans " x sur y dollars par action, à jour z ".

Il serait plus logique d'avoir une position objet objet (ou Holding objet, dans la terminologie de Hugh) - une par stock, peut-être avec un .Order_history attribut, si vous avez vraiment besoin d'une histoire détaillée de vos avoirs dans ce stock. Et oui, une base de données serait certainement utile pour ce genre de chose.

à cire philosophique pendant un moment : Je pense que vous prenez aussi la métaphore "objet" trop littéralement, et essayez de faire une part, ce qui semble très objet à certains égards , dans un objet dans le sens de la programmation du mot. Si oui, c'est une erreur, ce que je prends pour être le point de Juxtaposique.

Je ne suis pas d'accord avec lui que la conception orientée objet est défectueuse - c'est une belle déclaration audacieuse! - Mais sa réponse est juste dans la mesure où un "objet" (a.k.a. une instance de classe) est presque identique à un module **. C'est une collection de fonctions connexes liées à un État partagé. Dans une instance de classe, l'état est partagé via auto ou ceci , tandis que dans un module, il est partagé via l'espace de noms global.

À la plupart des fins, la seule différence majeure entre une instance de classe et un module est qu'il peut y avoir de nombreuses instances de classe, chacune avec son propre état indépendant, tandis qu'il ne peut y avoir qu'une seule instance de module. (Il existe d'autres différences, bien sûr, mais la plupart du temps impliquent des questions techniques qui ne sont pas très importantes pour l'apprentissage de l'OOD.) Cela signifie que vous pouvez penser à des objets d'une manière similaire à la façon dont vous pensez des modules, et C'est une approche utile ici.

** Dans de nombreuses langues compilées, le fichier qui permet de compiler un module est appelé fichier "objet". Je pense que c'est où la métaphore "objet" provient réellement. (Je n'ai aucune preuve réelle de cela! Alors quiconque connaît mieux, n'hésitez pas à me corriger.) Les exemples de jouets omniprésents d'ood que l'on voit - voiture.Drive (mph = 50); car.stop (); car.refuel (non plongé, régulier) - Je crois que sont des formations de retour qui peuvent confondre un peu le concept.


1 commentaires

Merci, votre commentaire a été utile. Je suis d'accord avec penser au problème trop littéralement.



2
votes

Il y a deux préceptes de base que vous devez garder à l'esprit lors de la conception d'un tel système:

  1. Éliminer la redondance de vos données. Aucun redondance assure l'intégrité.
  2. Gardez toutes les données dont vous avez besoin pour répondre à toute demande, au plus bas niveau de détail.

    Sur la base de ces préceptes, ma suggestion est de maintenir un fichier journal de transaction. Chaque transaction représente un changement d'état d'une sorte, et tous les faits pertinents à ce sujet: quand, quoi, acheter / vendre, combien, combien, etc. Chaque transaction serait représentée par un enregistrement (NamedTuple est utile ici) dans un fichier plat. Une des années d'une années (ou même 5 ou 10 ans) de transactions devraient facilement s'inscrire dans une liste de résident de la mémoire. Vous pouvez ensuite créer des fonctions pour sélectionner, trier et résumer les informations dont vous avez besoin dans cette liste et être résident de la mémoire, ce sera incroyablement rapide, beaucoup plus rapide qu'une base de données SQL.

    Quand et si le journal de transaction devient trop volumineux ou trop lent, vous pouvez calculer l'état de toutes vos positions à une date donnée (comme la fin de l'année), utilisez-la pour l'état initial pour la période suivante et des archives. votre ancien fichier journal au disque.

    Vous voudrez peut-être des informations auxiliaires sur vos avoirs tels que la valeur / prix à une date donnée, de sorte que vous pouvez tracer la valeur par rapport à tout ou partie de toutes les exploitations (des sources en ligne pour ce type d'information, Yahoo Finance Pour un.) Une base de données principale contenant des informations statiques sur chacune de vos exploitations serait également utile.

    Je sais que cela ne semble pas très "orienté objet", mais OO Design pourrait être utile pour masquer les fonctionnements détaillés du système dans un objet Translog avec des méthodes pour enregistrer / restaurer les données à / de disque (Save / Ouvrir des méthodes), entrez / modifiez / supprimez une transaction; et des méthodes supplémentaires pour traiter les données dans des affichages d'informations significatifs.

    Commencez par écrire l'API avec une interface de ligne de commande. Lorsque cela fonctionne à votre satisfaction, vous pouvez continuer à créer une extrémité frontale de l'interface graphique si vous le souhaitez.

    bonne chance et amusez-vous!


0 commentaires

0
votes

J'aimerais entendre avec ce que vous avez proposé. Je suis à 4 mois (temps partiel) dans la création d'un gestionnaire de commandes et, bien que sa plupart complète, j'ai toujours les mêmes questions que vous que j'aimerais que cela soit faite correctement.

Actuellement, je sauvey deux fichiers

A " Stratégie Hit Log " Lorsque chaque signal d'achat / vente provenant de tout script de stratégie est enregistré. Par exemple: lorsque la stratégie Buy_AT_YESTERDAYS_CLOSE_PRICE.PY est déclenchée, elle a sauvegardé la demande d'achat dans ce fichier et transmet la demande au gestionnaire de commande

un " journal de commande " qui est Un seul fichier de données - ce fichier correspond au but que vous vous concentrez.

  • Chaque demande d'une stratégie concerne une seule sécurité sous-jacente (par exemple, un stock AAPL) et crée une commande enregistrée comme une rangée dans le fichier de données, contenant des colonnes pour le ticker, la stratégie Nom qui a engendré ce Commandez ainsi que Suborder et Subrard de courtier Colonnes (expliquées ci-dessous).
  • Chaque commande a une liste de suborders (dict) stockés dans la colonne Subrôteur. Par exemple: Si vous êtes haussier sur AAPL, les suborders pourraient être: xxx
    • Chaque commande a également une liste des suborders de courtier (dict> (dict) stockés dans la colonne Subrôteur de courtier. Chaque sous-commande de courtier est une demande au courtier d'acheter ou de vendre une sécurité et est indexée avec "l'ID de commande" que le courtier prévoit cette demande. Chaque nouvelle demande de courtier est un nouveau sous-commande de courtier et annule que le sous-poste de courtier est enregistré dans cette dict. Pour enregistrer des modifications aux subordonneurs de courtier, vous annulez l'ancien sous-commandant de courtier et envoyez-en une nouvelle (sa même commission utilisant IBKR).

      améliorations
      1. Liste des classes au lieu de Dataframe : Je pense que ce serait beaucoup plus pythonique d'enregistrer chaque commande comme une instance d'un order_class (au lieu d'un Rangée d'un fichier de données), qui a Suborder et Attributs de courtier_suborder , qui sont également des instances de Subord_class et courtier_suborder_class . Ma question actuelle est de savoir si une sauvegarde d'une liste de classes comme mon enregistrement de toutes les commandes ouvertes et fermées est pythonique ou idiote.

      2. Considérations de visualisation : Il semble que les commandes soient enregistrées sous forme de tableau pour une visualisation plus facile, mais il est peut-être préférable de les enregistrer dans cette "liste des instances de classe" et d'utiliser un fonctionner pour les tabulariser au moment de la visualisation? Toute entrée de quiconque serait grandement appréciée. J'aimerais m'éloigner de cela et commencer à jouer avec ml, mais je ne veux pas quitter le gestionnaire de commande inachevé.

      3. Est-ce tout la merde? : Si chaque Subrard (Acheter / vente demande à un courtier) soit connecté à un Commander (qui est juste une demande de stratégie spécifique d'un script stratégique) ou si tous les suborders de courtier doivent être enregistrés dans l'ordre chronologique et ont simplement une référence à la stratégie-ordonnance ( commander ) Cela a engendré le sous-commandant ? Idk ... Mais j'aimerais l'entrée de chacun.


0 commentaires