2011-03-23 7 views
7

Soy un programador principiante/intermedio de Python pero no he escrito una aplicación, solo scripts. Actualmente no uso mucho diseño orientado a objetos, por lo que me gustaría que este proyecto me ayudara a desarrollar mis habilidades OOD. El problema es que no sé por dónde empezar desde la perspectiva del diseño (sé cómo crear los objetos y todo eso). Por lo que vale, también soy autodidacta, no tengo educación formal de CS.Diseño orientado a objetos para un portafolio de inversiones/stock y opciones en Python

Me gustaría intentar escribir un programa para hacer un seguimiento de las posiciones de stock/opciones de una cartera.

Tengo una idea aproximada de lo que serían buenos candidatos para objetos (Cartera, Stock, Opción, etc.) y métodos (Comprar, Vender, Actualizar datos, etc.).

Una posición larga sería buy-to-open, y sell-to-close mientras que una posición corta tiene sell-to-open y buy-to-close.

portfolio.PlaceOrder(type="BUY", symbol="ABC", date="01/02/2009", price=50.00, qty=100) 
portfolio.PlaceOrder(type="SELL", symbol="ABC", date="12/31/2009", price=100.00, qty=25) 
portfolio.PlaceOrder(type="SELLSHORT", symbol="XYZ", date="1/2/2009", price=30.00, qty=50) 
portfolio.PlaceOrder(type="BUY", symbol="XYZ", date="2/1/2009", price=10.00, qty=50) 

Luego, una vez que se llama este método, ¿cómo almaceno la información? Al principio pensé que tendría un objeto Position con atributos como Symbol, OpenDate, OpenPrice, etc. pero pensar en actualizar la posición para dar cuenta de las ventas se vuelve complicado porque las compras y las ventas ocurren en diferentes momentos y cantidades.

  • Comprar 100 acciones para abrir, 1 vez, 1 precio. Vende 4 veces diferentes, 4 precios diferentes.
  • Comprar 100 acciones. Venda 1 acción por día, durante 100 días.
  • Compre 4 veces diferentes, 4 precios diferentes. Vende toda la posición al 1 vez, 1 precio.

Una posible solución sería crear un objeto para cada acción, de esta forma cada acción tendría diferentes fechas y precios. ¿Esto sería demasiado por encima? La cartera podría tener miles o millones de pequeños objetos Share. Si usted quiere saber el valor total de mercado de una posición que había necesidad de algo así como:

sum([trade.last_price for trade in portfolio.positions if trade.symbol == "ABC"]) 

Si tuviera una posición objetar el cálculo sería simple:

position.last * position.qty 

Gracias de antemano por la ayuda. En cuanto a otras publicaciones, es evidente que SO es para "ayudar" a no "escribir su programa para usted". Siento que solo necesito una dirección, señalando el camino correcto.

INFORMACIÓN ADICIONAL después de una reflexión El propósito El programa sería realizar un seguimiento de todas las posiciones, abierta y cerrada; con la capacidad de ver una ganancia y una pérdida detalladas.

Cuando pienso en detalles P & L Quiero ver ... - todas las fechas de apertura (y fechas cerradas) - tiempo mantuvo - precio de apertura (fecha de cierre) - P & L desde la apertura - P & L por día

@Senderle

I piense que tal vez está tomando la metáfora del "objeto" demasiado literalmente, y por eso está tratando de hacer un intercambio, que en cierto sentido parece muy similar a un objeto, en un objeto en el sentido de programación de la palabra. Si es así, es un error, que es lo que considero un punto de yuxtaposición.

Este es mi error. Al pensar en "objetos", un objeto share parece candidato natural. Solo hasta que haya millones, la idea parece una locura. Voy a tener un poco de tiempo de codificación libre este fin de semana y trataré de crear un objeto con una cantidad.

+1

Desea una capa de base de datos para este tipo de aplicaciones. – Santa

+0

por curiosidad, al no estar muy familiarizado con esta jerga, ¿tengo razón en que una posición "abierta" es simplemente una tenencia distinta de cero (positiva, o negativa para una posición corta) en una acción en particular? – senderle

+0

Sí, una posición abierta sería distinta de cero. Básicamente hay dos tipos de posiciones: larga y corta. Largo es lo que piensa la mayoría de la gente cuando invierte. Compre bajo, venda alto. Una posición corta es lo opuesto a ir largo. Usted toma prestado acciones de su corredor y las vende en el mercado, creando una obligación de que deba devolver las acciones a su proveedor roto (o cuando él las devuelva). El proceso es (pedir prestado) vender alto, comprar bajo (devolverlo a su corredor). –

Respuesta

1

Evita los objetos. El diseño orientado a objetos es defectuoso. Piense en su programa como una colección de comportamientos que operan en datos (listas y diccionarios). Luego, agrupe sus comportamientos relacionados como funciones en un módulo. Cada función debe tener entradas y salidas claras. Almacene sus datos globalmente en cada módulo. ¿Por qué hacerlo sin objetos? Porque se mapea más cerca del espacio problemático. La programación orientada a objetos crea demasiada indirección para resolver un problema. La indirección innecesaria causa la hinchazón y los errores del software.

Una posible solución sería crear un objeto para cada acción, de esta forma cada acción tendría fechas y precios diferentes. ¿Esto sería demasiado por encima? La cartera podría tener miles o millones de pequeños objetos Share. Si quisiera conocer el valor total de mercado de una posición, necesitaría algo como:

Sí, sería demasiado sobrecargado. La solución aquí es que almacenaría los datos en una base de datos. Encontrar el valor de mercado total de una posición se haría en SQL a menos que use un esquema NOSQL.

No intente diseñar para todos los posibles resultados futuros. Simplemente haga que su programa funcione de esa manera, debe funcionar ahora.

+4

Estoy de acuerdo con 'almacenar sus datos en una base de datos' y 'no sobre-diseñar para todo'; Estoy completamente en desacuerdo con 'el diseño orientado a objetos es defectuoso'. Es posible hacerlo mal, pero eso es cierto para cualquier cosa. –

+0

Quizás no sé cómo hacerlo bien. Pero me gusta hacer cosas. No pienses en hacerlos. –

+0

@juxtapose: ¿De verdad? ¿Cuántos programas más de 500 líneas ha hecho sin pensar? –

1

creo que será separarlo en

  • explotaciones (lo que actualmente posee o debo de cada símbolo)
  • órdenes simples (demandas para comprar o vender un solo símbolo en una sola vez)
  • oficios (colecciones de órdenes)

Esto hace que sea muy fácil conseguir un valor actual, órdenes de cola, y construir órdenes más complejas y mapas fácilmente en objetos de datos con una base de datos detrás de ellos.

+0

Estoy tratando de imaginar cómo funcionaría esto. Es obvio que los historiales de precios deben almacenarse en una base de datos. Pero, ¿y las acciones? ¿Todavía quisiera usar la idea de compartir un objeto? (Solo en este caso sería un registro de base de datos en lugar de un objeto) –

1

Para responder a su pregunta: Parece que ya tiene una idea bastante clara de su modelo de datos. Pero me parece que necesita pensar más sobre lo que quiere que haga este programa. ¿Hará un seguimiento de los cambios en los precios de las acciones? ¿Realiza pedidos o sugiere que se realicen pedidos? ¿O simplemente hará un seguimiento de los pedidos que ha realizado? Cada uno de estos usos puede requerir diferentes estrategias.

Dicho esto, no veo por qué alguna vez necesitaría tener un objeto para cada acción; No entiendo el razonamiento detrás de esa estrategia.Incluso si desea poder seguir su historial de pedidos en gran detalle, puede almacenar datos agregados, como en "x acciones al y dólares por acción, en la fecha z".

Tendría más sentido tener un position objeto (o holding objeto, en la terminología de Hugh) - uno por acción, tal vez con un atributo .order_history, si realmente necesita una historia detallada de sus participaciones en esa población. Y sí, una base de datos definitivamente sería útil para este tipo de cosas.

Para cera filosófica por un momento: Creo que tal vez usted está tomando la metáfora del "objeto" demasiado literalmente, y así está tratando de hacer una acción, lo que parece muy objeto similar en algunos aspectos, en un objeto en el sentido de programación de la palabra. Si es así, es un error, que es lo que considero un punto de yuxtaposición.

No estoy de acuerdo con él en que el diseño orientado a objetos es defectuoso. ¡Es una declaración bastante audaz! - pero su respuesta es correcta en la medida en que un "objeto" (a.k.a. una instancia de clase) es casi idéntico a un módulo **. Es una colección de funciones relacionadas ligadas a un estado compartido. En una instancia de clase, el estado se comparte a través de self o this, mientras que en un módulo, se comparte a través del espacio de nombres global.

Para la mayoría de los fines, la única diferencia importante entre una instancia de clase y un módulo es que puede haber muchas instancias de clase, cada una con su propio estado independiente, mientras que solo puede haber una instancia de módulo. (Hay otras diferencias, por supuesto, pero la mayoría de las veces involucran asuntos técnicos que no son muy importantes para aprender OOD.) Eso significa que puede pensar en los objetos de una manera similar a la forma en que piensa sobre los módulos, y ese es un enfoque útil aquí.

** En muchos idiomas compilados, el archivo que resulta al compilar un módulo se denomina archivo "objeto". Creo que es de donde proviene la metáfora del "objeto". (¡No tengo ninguna evidencia real de eso! Así que cualquiera que conozca mejor, no dude en corregirme.) Los ejemplos de juguetes omnipresentes de OOD que uno ve - car.drive(mph=50); car.stop(); car.refuel(unleaded, regular) - Creo que son formaciones secundarias que pueden confundir el concepto un poco.

+0

Gracias, su comentario fue útil. Estoy de acuerdo con pensar sobre el problema demasiado literalmente. –

2

Hay dos preceptos básicos que debe tener en cuenta a la hora de diseñar un sistema de este tipo:

  1. eliminar la redundancia de los datos. Sin redundancia asegura integridad.
  2. Guarde todos los datos que necesita para responder cualquier consulta, con el nivel de detalle más bajo.

De acuerdo con estos preceptos, mi sugerencia es mantener un archivo de registro de transacciones. Cada transacción representa un cambio de estado de algún tipo, y todos los hechos pertinentes al respecto: cuándo, qué, comprar/vender, cuántos, cuánto, etc. Cada transacción estaría representada por un registro (una enumeración específica es útil aquí) en un archivo plano. Un año (o incluso 5 o 10 años) de transacciones deberían caber fácilmente en una lista de residentes de memoria. A continuación, puede crear funciones para seleccionar, ordenar y resumir la información que necesita de esta lista, y al ser residente en la memoria, será increíblemente rápido, mucho más rápido que una base de datos SQL.

Cuando y si el Registro de transacciones se vuelve demasiado grande o lento, puede calcular el estado de todas sus posiciones a partir de una fecha determinada (como fin de año), use eso para el estado inicial para el siguiente período y archive su antiguo archivo de registro en el disco.

Es posible que desee información adicional sobre sus propiedades, como el valor/precio en una fecha determinada, para que pueda trazar el valor frente atiempo para una o todas las tenencias (hay fuentes en línea para este tipo de información, yahoo finance para una). Una base de datos maestra que contenga información estática sobre cada una de sus tenencias también sería útil.

Sé que esto no suena muy "orientado a objetos", pero el diseño OO podría ser útil para ocultar el funcionamiento detallado del sistema en un objeto TransLog con métodos para guardar/restaurar los datos en/desde el disco (guardar/métodos abiertos), ingrese/cambie/elimine una transacción; y métodos adicionales para procesar los datos en pantallas de información significativas.

Primero escriba la API con una interfaz de línea de comando. Cuando esto funcione para su satisfacción, puede continuar creando una interfaz gráfica de usuario si lo desea.

¡Buena suerte y diviértete!

Cuestiones relacionadas