Python 中投资/股票和期权投资组合的面向对象设计

发布于 2024-10-25 17:28:04 字数 1711 浏览 3 评论 0原文

我是一名初级/中级 Python 程序员,但我还没有编写过应用程序,只是编写了脚本。我目前没有大量使用面向对象的设计,因此我希望这个项目能够帮助培养我的 OOD 技能。问题是,我不知道从设计角度从哪里开始(我知道如何创建对象和所有这些东西)。无论如何,我也是自学的,没有接受过正规的计算机科学教育。

我想尝试编写一个程序来跟踪投资组合股票/期权头寸。

我对什么是好的候选对象(投资组合、股票、期权等)和方法(买入、卖出、更新数据等)有一个粗略的了解。

多头头寸是买入开仓和卖出平仓,而空头头寸则是卖出开仓和买入平仓。

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)

那么,一旦调用这个方法,我如何存储信息呢?起初,我以为我会拥有一个具有 Symbol、OpenDate、OpenPrice 等属性的 Position 对象,但考虑更新仓位以计算销售额变得很棘手,因为买入和卖出发生在不同的时间和金额。

  • 买100股开仓,1次,1价。出售 4 次不同的时间,4 种不同的价格。
  • 购买 100 股。每天出售 1 股,持续 100 天。
  • 购买 4 次不同的时间,4 种不同的价格。以 1 次、1 个价格出售整个头寸。

一种可能的解决方案是为每一股股票创建一个对象,这样每一股都有不同的日期和价格。这会不会造成太大的开销?该投资组合可能有数千或数百万个小共享对象。如果您想找出某个头寸的总市场价值,您需要类似以下内容:

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

如果您有一个头寸对象,则计算会很简单:

position.last * position.qty

提前感谢您的帮助。看看其他帖子,很明显 SO 是“帮助”而不是“为你编写程序”。我觉得我只需要一些方向,指明正确的道路。

反思后的其他信息 目的 该程序将跟踪所有持仓,包括持仓和平仓;能够查看详细的损益。

当我考虑详细的损益表时想看看...... - 所有开放日期(和关闭日期) - 举行时间 - 开盘价(截止日期) - 自开业以来的损益 - 每日损益

@Senderle

我认为您可能过于字面地理解“对象”隐喻,因此尝试将共享(在某些方面看起来非常像对象)变成编程意义上的对象。如果是这样,那就是一个错误,这就是我认为并置的观点。

这是我的错误。考虑“对象”,共享对象似乎是自然的候选者。只有当人数达到数百万人时,这个想法才显得疯狂。这个周末我将有一些空闲的编码时间,并尝试创建一个具有数量的对象。

I'm a beginner/intermediate Python programmer but I haven't written an application, just scripts. I don't currently use a lot of object oriented design, so I would like this project to help build my OOD skills. The problem is, I don't know where to start from a design perspective (I know how to create the objects and all that stuff). For what it's worth, I'm also self taught, no formal CS education.

I'd like to try writing a program to keep track of a portfolio stock/options positions.

I have a rough idea about what would make good object candidates (Portfolio, Stock, Option, etc.) and methods (Buy, Sell, UpdateData, etc.).

A long position would buy-to-open, and sell-to-close while a short position has a sell-to-open and 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)

Then, once this method is called how do I store the information? At first I thought I would have a Position object with attributes like Symbol, OpenDate, OpenPrice, etc. but thinking about updating the position to account for sales becomes tricky because buys and sells happen at different times and amounts.

  • Buy 100 shares to open, 1 time, 1 price. Sell 4 different times, 4 different prices.
  • Buy 100 shares. Sell 1 share per day, for 100 days.
  • Buy 4 different times, 4 different prices. Sell entire position at 1 time, 1 price.

A possible solution would be to create an object for each share of stock, this way each share would have a different dates and prices. Would this be too much overhead? The portfolio could have thousands or millions of little Share objects. If you wanted to find out the total market value of a position you'd need something like:

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

If you had a position object the calculation would be simple:

position.last * position.qty

Thanks in advance for the help. Looking at other posts it's apparent SO is for "help" not to "write your program for you". I feel that I just need some direction, pointing down the right path.

ADDITIONAL INFO UPON REFLECTION
The Purpose
The program would keep track of all positions, both open and closed; with the ability to see a detailed profit and loss.

When I think about detailed P&L I want to see...
- all the open dates (and closed dates)
- time held
- open price (closed date)
- P&L since open
- P&L per day

@Senderle

I think perhaps you're taking the "object" metaphor too literally, and so are trying to make a share, which seems very object-like in some ways, into an object in the programming sense of the word. If so, that's a mistake, which is what I take to be juxtapose's point.

This is my mistake. Thinking about "objects" a share object seems natural candidate. It's only until there may be millions that the idea seems crazy. I'll have some free coding time this weekend and will try creating an object with a quantity.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

伤痕我心 2024-11-01 17:28:04

设计此类系统时应牢记两个基本原则:

  1. 消除数据中的冗余。没有冗余确保完整性。
  2. 以最低的详细程度保留回答任何查询所需的所有数据。

基于这些规则,我的建议是维护一个事务日志文件。每笔交易都代表某种状态的变化,以及与之相关的所有事实:何时、什么、买/卖、多少、多少等。每笔交易都由一条记录表示(命名元组在这里很有用)在平面文件中。一年(甚至 5 或 10 年)的交易应该很容易放入内存驻留列表中。然后,您可以创建函数来从该列表中选择、排序和汇总您需要的任何信息,并且由于它是驻留在内存中的,因此速度会快得惊人,比 SQL 数据库快得多。

当交易日志变得太大或太慢时,您可以计算截至特定日期(例如年底)的所有头寸的状态,将其用作下一个时期的初始状态,并将旧日志存档文件到光盘。

您可能需要一些有关您所持资产的辅助信息,例如任何特定日期的价值/价格,以便您可以绘制任何或所有持股的价值与时间的关系图(此类信息有在线资源,雅虎财经就是其中之一。 )包含有关您的每笔资产的静态信息的主数据库也很有用。

我知道这听起来不太“面向对象”,但是 OO 设计可以将系统的详细工作隐藏在 TransLog 对象中,并提供将数据保存到光盘或从光盘恢复数据的方法。 (保存/打开方法),输入/更改/删除交易;以及将数据处理成有意义的信息显示的其他方法。

首先用命令行界面编写API。当这一切令您满意时,您可以根据需要继续创建 GUI 前端。

祝你好运,玩得开心!

There are two basic precepts you should keep in mind when designing such a system:

  1. Eliminate redundancy from your data. No redundancy insures integrity.
  2. Keep all the data you need to answer any inquiry, at the lowest level of detail.

Based on these precepts, my suggestion is to maintain a Transaction Log file. Each transaction represents a change of state of some kind, and all the pertinent facts about it: when, what, buy/sell, how many, how much, etc. Each transaction would be represented by a record (a namedtuple is useful here) in a flat file. A years worth (or even 5 or 10 years) of transactions should easily fit in a memory resident list. You can then create functions to select, sort and summarize whatever information you need from this list, and being memory resident, it will be amazingly fast, much faster than a SQL database.

When and if the Transaction Log becomes too large or too slow, you can compute the state of all your positions as of a particular date (like year-end), use that for the initial state for the following period, and archive your old log file to disc.

You may want some auxiliary information about your holdings such as value/price on any particular date, so you can plot value vs. time for any or all holdings (There are on-line sources for this type of information, yahoo finance for one.) A master database containing static information about each of your holdings would also be useful.

I know this doesn't sound very "object oriented", but OO design could be useful to hide the detailed workings of the system in a TransLog object with methods to save/restore the data to/from disc (save/open methods), enter/change/delete a transaction; and additional methods to process the data into meaningful information displays.

First write the API with a command line interface. When this is working to your satisfaction, then you can go on to creating a GUI front end if you wish.

Good luck and have fun!

固执像三岁 2024-11-01 17:28:04

我想我会将其分为

  • 持有量(您当前拥有或欠每个符号的内容)
  • 订单(一次购买或出售单个符号的简单要求)
  • 交易(订单集合)

这使得很容易获得当前值、排队订单以及构建更复杂的订单,并轻松映射到背后有数据库的数据对象。

I think I'd separate it into

  • holdings (what you currently own or owe of each symbol)
  • orders (simple demands to buy or sell a single symbol at a single time)
  • trades (collections of orders)

This makes it really easy to get a current value, queue orders, and build more complex orders, and maps easily into data objects with a database behind them.

薄荷港 2024-11-01 17:28:04

回答您的问题:您似乎已经对自己的数据模型有了相当清晰的了解。但在我看来,你需要更多地考虑你想要这个程序做什么。它会跟踪股票价格的变化吗?下订单,或建议下订单?或者它只是简单地跟踪您所下的订单?这些用途中的每一种都可能需要不同的策略。

也就是说,我不明白为什么你需要为每个共享都有一个对象;我不明白该策略背后的原因。即使您希望能够详细跟踪您的订单历史记录,您也可以只存储汇总数据,例如“日期x 股,每股 y 美元” z”。

拥有一个 position 对象(或者用 Hugh 的术语来说是 holding 对象)会更有意义——每只股票一个,也许还有一个 .order_history 属性,如果您确实需要持有该股票的详细历史记录。是的,数据库对于这种事情肯定很有用。

稍微讲一下哲学:我想也许你太字面地理解了“对象”的比喻,所以试图将在某些方面看起来非常像对象的共享变成一个编程意义上的对象。如果是这样,那就是一个错误,这就是我认为并置的观点。

我不同意他关于面向对象设计有缺陷的观点——这是一个非常大胆的声明! ——但他的答案是正确的,因为“对象”(又名类实例)几乎与模块**相同。它是链接到某些共享状态的相关函数的集合。在类实例中,状态通过 self 或 this 共享,而在模块中,状态通过全局命名空间共享。

对于大多数用途,类实例和模块之间的唯一主要区别在于,可以有许多类实例,每个类实例都有自己的独立状态,而只能有一个模块实例。 (当然还有其他差异,但大多数时候它们涉及对于学习 OOD 来说并不是很重要的技术问题。)这意味着您可以以类似于考虑模块的方式来考虑对象,并且这是一个有用的方法。

**在许多编译语言中,编译模块时生成的文件称为“对象”文件。我认为这就是“对象”隐喻的实际来源。 (我没有任何真正的证据证明这一点!所以任何更了解的人都可以随时纠正我。)人们看到的无处不在的 OOD 玩具示例 -- car.drive(mph=50);汽车.stop(); car.refuel(unleaded, Regular)——我相信反向形成可能会有点混淆这个概念。

To answer your question: You appear to have a fairly clear idea of your data model already. But it looks to me like you need to think more about what you want this program to do. Will it keep track of changes in stock prices? Place orders, or suggest orders to be placed? Or will it simply keep track of the orders you've placed? Each of these uses may call for different strategies.

That said, I don't see why you would ever need to have an object for every share; I don't understand the reasoning behind that strategy. Even if you want to be able to track your order history in great detail, you could just store aggregate data, as in "x shares at y dollars per share, on date z".

It would make more sense to have a position object (or holding object, in Hugh's terminology) -- one per stock, perhaps with an .order_history attribute, if you really need a detailed history of your holdings in that stock. And yes, a database would definitely be useful for this kind of thing.

To wax philosophical for a moment: I think perhaps you're taking the "object" metaphor too literally, and so are trying to make a share, which seems very object-like in some ways, into an object in the programming sense of the word. If so, that's a mistake, which is what I take to be juxtapose's point.

I disagree with him that object oriented design is flawed -- that's a pretty bold pronouncement! -- but his answer is right insofar as an "object" (a.k.a. a class instance) is almost identical to a module**. It's a collection of related functions linked to some shared state. In a class instance, the state is shared via self or this, while in a module, it's shared through the global namespace.

For most purposes, the only major difference between a class instance and a module is that there can be many class instances, each one with its own independent state, while there can be only one module instance. (There are other differences, of course, but most of the time they involve technical matters that aren't very important for learning OOD.) That means that you can think about objects in a way similar to the way you think about modules, and that's a useful approach here.

**In many compiled languages, the file that results when you compile a module is called an "object" file. I think that's where the "object" metaphor actually comes from. (I don't have any real evidence of that! So anyone who knows better, feel free to correct me.) The ubiquitous toy examples of OOD that one sees -- car.drive(mph=50); car.stop(); car.refuel(unleaded, regular) -- I believe are back-formations that can confuse the concept a bit.

东走西顾 2024-11-01 17:28:04

避免物体。面向对象的设计是有缺陷的。将您的程序视为对数据(列表和字典)进行操作的行为的集合。然后将相关行为分组为模块中的函数。
每个功能都应该有明确的输入和输出。将您的数据全局存储在每个模块中。
为什么要在没有物体的情况下进行呢?因为它映射得更接近问题空间。面向对象编程为解决问题创造了太多的间接性。不必要的间接会导致软件膨胀和错误。

一个可能的解决方案是为每一股股票创建一个对象,这样每一股都会有不同的日期和价格。这会不会造成太大的开销?该投资组合可能有数千或数百万个小共享对象。如果您想找出某个头寸的总市场价值,您需要类似以下内容:

是的,这会产生太多的管理费用。这里的解决方案是将数据存储在数据库中。除非您使用 NOSQL 方案,否则查找头寸的总市场价值将在 SQL 中完成。

不要尝试为未来所有可能的结果进行设计。只需让您的程序按照现在需要的方式运行即可。

Avoid objects. Object oriented design is flawed. Think about your program as a collection of behaviors that operate on data (lists and dictionaries). Then group your related behaviors as functions in a module.
Each function should have clear input and outputs. Store your data globally in each module.
Why do it without objects? Because it maps closer to the problem space. Object oriented programming creates too much indirection to solve a problem. Unnecessary indirection causes software bloat and bugs.

A possible solution would be to create an object for each share of stock, this way each share would have a different dates and prices. Would this be too much overhead? The portfolio could have thousands or millions of little Share objects. If you wanted to find out the total market value of a position you'd need something like:

Yes it would be too much overhead. The solution here is you would store the data in a database. Finding the total market value of a position would be done in SQL unless you use a NOSQL scheme.

Don't try to design for all possible future outcomes. Just make your program work that way it needs to work now.

冷情 2024-11-01 17:28:04

我很想听听你的想法。我花了大约 4 个月(兼职)时间创建了一个订单处理程序,虽然它已经基本完成,但我仍然有和你一样的问题,因为我希望它能够正确制作。

目前,我保存两个文件

策略命中日志”,其中保存来自任何策略脚本的每个买入/​​卖出信号。例如:当 buy_at_yesterdays_close_price.py 策略被触发时,它将购买请求保存在此文件中,并将该请求传递给订单处理程序

订单日志”,它是单个 DataFrame - 该文件适合你所关注的目的。

  • 来自策略的每个请求都与单个基础证券(例如 AAPL 股票)相关,并创建一个订单,该订单在 DataFrame 中保存为一行,其中包含股票代码列、生成的策略名称此 Order 以及 SuborderBroker Suborder 列(如下所述)。
  • 每个订单都有一个存储在“子订单”列中的子订单(字典)列表。例如:如果您看好 AAPL,子订单可以是:
[
{'security': 'equity', 'quantity':10},
{'security': 'option call', 'quantity':10}
]
  • 每个订单还有一个存储在“经纪商子订单”列中的经纪商子订单(字典)列表。每个经纪商子订单都是对经纪商购买或出售证券的请求,并使用经纪商为该请求提供的“订单 ID”进行索引。对 Broker 的每个新请求都是一个新的 Broker Suborder,取消该 Broker Suborder 会记录在该字典中。要记录对经纪商子订单的修改,您需要取消旧的经纪商子订单并发送并记录新订单(与使用 IBKR 的佣金相同)。

改进

  1. 类列表而不是 DataFrame:我认为将每个订单保存为 Order_Class 的实例(而不是一行DataFrame),它具有 SuborderBroker_Suborder 属性,这两个属性也是 Suborder_ClassBroker_Suborder_Class 的实例。
    我当前的问题是保存类列表作为我所有未结订单和已结订单的记录是否是Python式的或愚蠢的。

  2. 可视化注意事项:订单似乎应该以表格形式保存以便于查看,但也许最好将它们保存在“类实例列表”形式中并使用函数来表格化他们在观看时?任何人的任何意见将不胜感激。我想摆脱这个并开始使用机器学习,但我不想让订单处理程序未完成。

  3. 这都是废话吗?:是否应该将每个经纪商子订单(对经纪商的买入/卖出请求)附加到一个订单(其中只是来自策略脚本的特定策略请求)或者应该按时间顺序记录所有经纪商子订单,并且仅引用所生成的策略订单 (Order) 经纪商子订单?我不知道...但我希望每个人都能提供意见。

I would love to hear with what you came up with. I am ~ 4 months (part time) into creating an Order Handler and although its mostly complete, I still have the same questions as you as I'd like it to be made properly.

Currently, I save two files

A "Strategy Hit Log" where each buy/sell signal that comes from any strategy script is saved. For example: when the buy_at_yesterdays_close_price.py strategy is triggered, it saved that buy request in this file, and passes the request to the Order Handler

An "Order Log" which is a single DataFrame - this file fits the purpose you were focusing on.

  • Each request from a strategy pertains to a single underlying security (for example, AAPL stock) and creates an Order which is saved as a row in the DataFrame, containing columns for the Ticker, the Strategy name that spawned this Order as well as Suborder and Broker Suborder columns (explained below).
  • Each Order has a list of Suborders (dicts) stored in the Suborder column. For example: if you are bullish on AAPL, the suborders could be:
[
{'security': 'equity', 'quantity':10},
{'security': 'option call', 'quantity':10}
]
  • Each Order also has a list of Broker Suborders (dicts) stored in the Broker Suborder column. Each Broker Suborder is a request to the Broker to buy or sell a security, and is indexed with the "order ID" that the Broker provides for that request. Every new request to the Broker is a new Broker Suborder, and canceling that Broker Suborder is recorded in that dict. To record modifications to Broker Suborders, you cancel the old Broker Suborder and send and record a new one (its the same commission using IBKR).

Improvements

  1. List of Classes instead of DataFrame: I think it'd be much more pythonic to save each Order as an instance of an Order_Class (instead of a row of a DataFrame), which has Suborder and Broker_Suborder attributes, both of which are also instances of Suborder_Class and Broker_Suborder_Class.
    My current question is whether saving a list of classes as my record of all open and closed Orders is pythonic or silly.

  2. Visualization Considerations: It seems like Orders should be saved in table form for easier viewing, but maybe it is better to save them in this "list of class instances" form and use a function to tabularize them at the time of viewing? Any input by anyone would be greatly appreciated. I'd like to move away from this and start playing with ML, but I don't want to leave the Order Handler unfinished.

  3. Is it all crap?: should each Broker Suborder (buy/sell request to a Broker) be attached to an Order (which is just a specific strategy request from a strategy script) or should all Broker Suborders be recorded in chronological order and simply have a reference to the strategy-order (Order) that spawned the Broker Suborder? Idk... but I would love everyone's input.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文