7

我是一名初学者/中级 Python 程序员,但我没有编写应用程序,只是编写脚本。我目前没有使用很多面向对象的设计,所以我希望这个项目能够帮助我培养 OOD 技能。问题是,我不知道从设计角度从哪里开始(我知道如何创建对象和所有这些东西)。对于它的价值,我也是自学的,没有正规的 CS 教育。

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

我对什么是好的对象候选(投资组合、股票、期权等)和方法(购买、销售、UpdateData 等)有一个粗略的想法。

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

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 个价格卖出全部头寸。

一种可能的解决方案是为每一股股票创建一个对象,这样每一股就会有不同的日期和价格。这会不会有太多开销?投资组合可能有成千上万个小 Share 对象。如果你想找出一个头寸的总市值,你需要这样的东西:

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

如果你有一个位置对象,计算会很简单:

position.last * position.qty

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

反思后的附加信息 目的 该程序将跟踪所有头寸,包括未平仓头寸;能够查看详细的损益。

当我考虑详细的损益时,我想查看... - 所有开盘日期(和收盘日期) - 持有时间 - 开盘价(收盘日期) - 自开盘以来的盈亏 - 每天的盈亏

@Senderle

我认为也许您将“对象”比喻过于字面化,因此正试图将在某些方面看起来非常像对象的共享变成该词的编程意义上的对象。如果是这样,那是一个错误,这就是我认为并列的观点。

这是我的错误。考虑“对象”一个share对象似乎很自然。直到可能有数百万人,这个想法才显得疯狂。这个周末我会有一些空闲的编码时间,并会尝试创建一个有数量的对象。

4

5 回答 5

2

在设计这样的系统时,您应该牢记两个基本原则:

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

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

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

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

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

首先用命令行界面编写 API。当这令您满意时,如果您愿意,您可以继续创建 GUI 前端。

祝好运并玩得开心点!

于 2011-03-25T07:22:20.917 回答
1

我想我会把它分成

  • 持股(您当前拥有或欠每个符号的资产)
  • 订单(一次购买或出售单个交易品种的简单要求)
  • 交易(订单集合)

这使得获取当前值、排队订单和构建更复杂的订单变得非常容易,并且可以轻松地映射到数据对象中,并在它们后面有一个数据库。

于 2011-03-23T03:01:27.773 回答
1

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

一种可能的解决方案是为每一股股票创建一个对象,这样每一股就会有不同的日期和价格。这会不会有太多开销?投资组合可能有成千上万个小 Share 对象。如果你想找出一个头寸的总市值,你需要这样的东西:

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

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

于 2011-03-23T02:36:37.693 回答
1

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

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

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

稍微有点哲学性:我认为您可能过于从字面上理解“对象”隐喻,因此正试图将在某些方面看起来非常像对象的共享变成编程意义上的对象单词。如果是这样,那是一个错误,这就是我认为并列的观点。

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

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

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

于 2011-03-24T00:16:26.807 回答
0

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

目前,我保存了两个文件

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

一个“订单日志”,它是一个单一的 DataFrame - 这个文件符合您关注的目的。

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

改进

  1. List of Classes 而不是 DataFrame:我认为将每个 Order 保存为 an 的实例Order_Class(而不是 DataFrame 的一行)会更加pythonic,它具有SuborderandBroker_Suborder属性,它们也是Suborder_Classand的实例Broker_Suborder_Class。我目前的问题是保存一个类列表作为我所有打开和关闭订单的记录是pythonic还是愚蠢。

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

  3. 都是废话吗?:每个Broker Suborder(对经纪人的买入/卖出请求)是否应该附加到一个Order(这只是来自策略脚本的特定策略请求),或者应该全部Broker Suborders按时间顺序记录,并且只是参考策略顺序(Order)催生了Broker Suborder?Idk...但我会喜欢每个人的意见。

于 2020-12-20T14:22:29.357 回答