【问题标题】:construct orderbook from orders example [closed]从订单示例构建订单簿 [关闭]
【发布时间】:2012-03-29 17:38:10
【问题描述】:

我正在寻找从订单构造订单簿的代码

例如,如果订单是

side | price | quantity
buy   100      1
buy   101      10
buy   100      1000
buy   100      10000

那么聚合的订单应该是:

side | price | quantity
buy    100     11001
buy    101     10 

在程序生命周期内添加、修改或删除订单。在每次订单更新时,我都需要快速更新 OrderBook。

我确定这是非常常见的任务,所以互联网上应该已经有很多实现了。

感谢您的任何参考,我正在寻找 c# 实现,但如果需要,我可以用另一种语言重写它。

upd 其实我应该重新表述我的问题。最初订单簿是空的。然后我收到事件:添加订单、更改订单数量或取消订单。我应该从此消息中重新计算 orderBook。但现在我很清楚它应该多么简单。添加订单时,我只需在此价格水平添加数量。当订单数量改变时,我只需要添加“更改”,当订单被取消时,我只需要从相应的价格水平中删除相应的数量。唯一的问题是我应该在哪里存储“最后订单数量”总共有很多订单(数千万),但没有很多活动订单(不超过 100 000),对于每个活动订单我需要通过 orderId 获取“最后数量”...当然我可以使用字典,但这可能太慢了。我想要更快的东西。但我不能使用 50 000 000 个项目数组。

【问题讨论】:

  • “互联网上应该已经有很多实现了”。我对此表示怀疑。不过,这些东西可能存在商业实现。
  • 我认为 ociweb Liquibook 是最流行的 orderbook 开源实现

标签: algorithm algorithmic-trading


【解决方案1】:

这是LINQPad中测试的代码


var orders = new [] {
    new {Side = "Buy", Price = 100, Quantity = 1 },
    new {Side = "Buy", Price = 101, Quantity = 10 },
    new {Side = "Buy", Price = 100, Quantity = 1000 },
    new {Side = "Buy", Price = 100, Quantity = 10000 },
    new {Side = "Sell", Price = 100, Quantity = 10000 }
};

var orderboook 
    = from o in (           
                    from order in orders
                    group order by order.Side into sideGroup
                    select new {
                        Side = sideGroup.Key,
                        SideGroup = 
                            from s in sideGroup
                            group s by s.Price into g
                            select new {
                                Side = sideGroup.Key,
                                Price = g.Key, 
                                Quantity = g.Sum( s => s.Quantity) 
                            }
                    }
                )
     from g in o.SideGroup
     select g;

orderboook.Dump(); // .Dump() is LINQPad helper method...

LINQPad 中的结果是

【讨论】:

  • +1 将我指向 LINQPad :)
【解决方案2】:

您需要按priceside 分组,然后为每个组选择quantity 的总和。由于您没有指定任何媒介(数据库、内存中的对象等),我们无法真正为您提供具体的实现。

编辑:显然这些是内存中的对象,在这种情况下 LINQ 是你的朋友:

var results = orders.OrderBy(order => new{order.side, order.price})
.Select(group => new{ group.Key.side, group.Key.price, group.Sum(order => order.quantity));

【讨论】:

  • 我需要c#实现,当然内存中有订单:)
【解决方案3】:

我当然可以使用字典,但那可能太慢了

任何解决方案都将涉及树或哈希表。因此,您最好使用您的语言的标准字典实现。

现在,不要对性能进行任何猜测,尤其是在实施可行的方法之前。然后进行分析,如果您使用的特定字典实现被证明会影响性能,请使用实际代码提出具体问题,我们将很乐意尝试和改进。

【讨论】:

  • 我猜你是对的。知道 95% 的活动订单“彼此非常接近”,即他们的 id 在 100 000 间隔内,我可能可以尝试对这部分使用数组,并为其余 5% 的订单使用字典,我需要动态地将订单从数组移动到字典。但这听起来很复杂,我最好先使用Dictionary 作为第一枪,并在需要时对其进行分析
  • @javapowered:俗话说“做最简单的事情,可能会起作用”(根据经验,这是任何形式的[算法]交易的黄金法则)。
  • @javapowered:同样,这里的性能是相对的。我想您关心的更多是连接延迟,而不是像在字典中存储东西这样的廉价东西。金钱可以为 HFT 买到的最好的改进就是托管。
  • 我已经搭配好了。这在 HFT 中是必备的 :) 不幸的是,由于 quickfast,我已经损失了 150 µs,我不想因为我自己的代码而损失更多。
【解决方案4】:

使用查询可以做到

UPDATE OrderBook 
SET quantity = (
    SELECT SUM(quantity) FROM orders
    WHERE price = :your_price
      AND side = :your_side) p
WHERE price = :your_price
  AND side = :your_side

其中 :your_price 和 :your_side 是修改后订单的值。
如果您可以清除所有表格并从头开始填写,那就更好了:

TRUNCATE TABLE OrderBook;
INSERT INTO OrderBook
SELECT side, price, SUM(quantity)
FROM orders
GROUP BY side, price

在我的第一个示例中,我假设您的订单中只有数量可以更改;但如果其他值可以更改,则无法正常工作。
第二个示例很昂贵,因此请仅在您的订单不经常更改时使用它。
最后:如果您的订单经常变化并且每个值都可以更改,您可以:

  1. 更新 OrderBook 从订单中删除应该修改的值(所以在更新之前)
  2. 更新 OrderBook,添加已更改订单的值。

【讨论】:

  • 将其作为基于 group by 查询的视图更有意义。让数据库处理缓存和维护缓存。
  • 抱歉,我更新了描述。我不需要将当前订单“转移”到订单簿。我需要在每个“订单更新事件”的应用程序生命周期内这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
相关资源
最近更新 更多