根据日期范围和股票数量匹配买家和卖家

时间:2014-01-22 02:56:53

标签: c# sql algorithm

我正在建立一个交易应用程序,以匹配拥有订阅的买家/卖家。订阅在特定持续时间内具有一定数量的金额。有8种订单类型:

  • 购买/出售订阅(可以在数量或时间方面部分填写)
  • 购买/出售所有数量订阅(只能部分填写时间)
  • 买卖所有时间订阅(只能部分填写数量)
  • 购买/出售所有数量和时间订阅(不能部分填写,全部或全部)

填写

的每个用户

示例1

假设此示例中的所有订单可以在数量和时间方面得到部分填充,我们可以说用户A在2014年1月1日至2014年1月3日期间发出要求100股的买单(dd / mm / yyyy) 。

目前订单簿中有4个卖单

  • 用户B在1/1/2014 - 2014年5月1日之间出售25股
  • 用户C在1/1/2014 - 2014年2月15日之间出售50股
  • 用户D在10/2/2014 - 2014年1月7日之间出售70股
  • 用户E在15/2/2014 - 2014年2月25日之间出售5股

看起来像

User A                 |--------------100-----------|
User B    |----------------------------25-----------------------|
User C    |-------------------50---|
User D                       |--------------70------------------|
User E                             |--5--|

匹配完成后,订单簿中的每个用户订单都会显示为

User A                 |-25--|           |----5-----|
User B    |------25----|                            |----25-----|
User C    |------50----|
User D                                              |----70-----|
User E has no open orders

毕竟说完了,订单看起来像是:

  • 用户A在1/2/2014 - 2014年2月2日之间购买25股
  • 用户A在15/2/2014 - 2014年1月3日之间购买5股
  • 用户B在1/1/2014 - 1/2/2014
  • 之间出售25股
  • 用户B在1/3/2014 - 2014年5月1日之间出售25股
  • 用户C在1/1/2014 - 1/2/2014
  • 之间出售50股
  • 用户D在1/3/2014 - 2014年1月7日之间卖出70股
  • 用户E不销售任何东西

示例2

此示例完全相同,除非用户B销售所有数量和时间订阅类型。换句话说,用户B想要出售他/她的整个职位。

匹配完成后,订单簿中的每个用户订单都会显示为

User A                 |-50--|     |--25-|----30----|
User B    |----------------------------25-----------------------|
User C    |------50----|
User D                       |-20--|                |----70-----|
User E has no open orders

毕竟说完了,订单看起来像是:

  • 用户A在1/2/2014 - 2014年2月2日之间购买50股
  • 用户A在15/2/2014 - 2014年3月25日之间购买25股
  • 用户A在25/2/2014 - 2014年1月3日之间购买30股
  • 用户B在2014年1月1日至2014年5月1日之间出售25股(由于此订单不允许部分填写,因此无法匹配)
  • 用户C在1/1/2014 - 1/2/2014
  • 之间出售50股
  • 用户D在15/2/2014 - 2014年2月25日之间出售70股
  • 用户D在1/3/2014 - 2014年1月7日之间卖出70股
  • 用户E不销售任何东西

过程

另一个要求是我需要能够跟踪数据库中订单的填写方式。当用户A的购买订单进入时,它将首先与用户B匹配,这将导致:

User A                 |--------------75------------|
User B    |------25----|                            |----25-----|

这两个状态都需要保存到数据库中。完成后,用户C的订单会匹配,如下所示:

User A                 |-----25----|------75--------|
User B    |------25----|                            |----25-----|
User C    |------50----|

继续前进:

User A                 |--25-|     |-------5--------|
User B    |------25----|                            |----25-----|
User C    |------50----|
User D                                              |----70-----|

当前流程

  1. 获取与买单重叠的所有卖单(响应者)' (请求者)日期范围(如果是传入的卖单,这将是相反的。请求者被称为触发传入订单的人。响应者是潜在的匹配)
  2. 先按价格按时间按销售订单排序
  3. 遍历每个卖单
    • 计算约定价格
    • 计算交易数量
    • 获取与当前卖单日期范围相关的买方日期范围
    • 根据买方和卖方之间的日期范围关系确定是否为部分填充
    • 如果卖家不允许部分填充,则继续下一个订单
    • 处理卖单
      • 卖单是否出现但与买家订单重叠?如果是这样,则拆分卖单并处理右边重叠并减去买方要求的数量。
      • 卖单是否属于买家订单?如果是这样,不要拆分任何东西只需完全处理该订单并减去买方要求的数量。
      • 卖单是否在买方订单之后?如果是这样,则拆分卖单并处理左侧重叠并减去买方要求的数量。
      • 卖单是否是买方订单的较大日期范围?如果在开始和结束时分开,则通过减去买方要求的数量来处理中间件。
  4. 如果我在订单簿中有多个订单时没有正常工作,那就已经成功了。问题可能在于,对于每个卖单而言,我总是将其与原始买单进行比较,而实际上买单随着卖单的重复而被填满。也许我需要另一个嵌套循环?我不确定。


    问题

    有没有现成的算法可以做我要问的事情?

    编辑:经过一些搜索后,它似乎就像我在一个间隔树或一个分段树之后,在那里我可以总结一下给定时间内树中的内容范围。但是,我需要能够使用start和dates将修改存储在数据库中。 LINQ或SQL是否有任何实现?

    编辑2:在我的第一次编辑中,我认为它是间隔树,但现在看起来更像bin packing algorithm

    编辑3 好的,所以我似乎没有在这里正确地传达我的问题。我没有真正的编码问题,但更多的是如何正确实现这一目标的思考问题。我需要一个流程图或执行步骤,以便能够通过根据顶部概述的条件拆分订阅来处理买方和卖方。

    我发布了同样的问题@ https://softwareengineering.stackexchange.com/,以防这是发布此问题的错误网站。

3 个答案:

答案 0 :(得分:2)

显然,每个买/卖订单都需要自行处理,基础应该相对简单。填写你可以做的,提交部分(如果部分允许),然后继续直到订单完成。

显然,这个查询是一个样本,因为没有真正的结构,也没有实际引用的SQL数据库,但原则应该是相同的。

SELECT
      buy.OrderID BuyOrderID,
      buy.qty BuyQty,
      buy.price BuyPrice,
      sell.OrderID SellOrderID,
      sell.qty SellQty,
      sell.price SellPrice
   from
      pendingOrders buy
         JOIN pendingOrders sell
            ON buy.stock = sell.stock
            AND sell.orderType = 'sell'
            AND (  sell.beginDate between buy.beginDate and buy.endDate
                OR sell.endDate between buy.beginDate and buy.endDate )
            AND (( buy.qty = sell.qty )
                OR ( buy.qty > sell.qty AND buy.AllowPartial )
                OR ( buy.qty < sell.qty AND sell.AllowPartial ))
   where
      buy.OrderID = SampleParmBuyOrderIDTryingToBeFilled
   order by
      ABS( buy.price - sell.price ) DESC

因此,对于此示例中的单个购买订单,您只需要传递您要填写的订单。您甚至可能希望对其进行限制,因此它不会尝试返回您实际上永远无法获得的100多个条目。

现在让我们看看这个查询的逻辑,它几乎可以满足您的所有需求。首先,该示例以特定ID的已知“购买”顺序开始。所以我们从你的桌子的“PendingOrders”开始,并给它别名“买”。然后我们用别名“Sell”将它加入到同一个表中。

加入条件显然是针对相同的股票,并且“卖出”版本必须是“卖出”类型才能填写您想要的“买入”订单。此外,您只关心卖家提供的那些股票在买家寻求履行的时间范围内某个地点的开始或结束日期。这预先评定了主要目标。

现在,基于部分买入或卖出的唯一稍微更难的。如果买方和卖方都考虑到相同的数量,那么任何一方是否有部分时间/数量或全部或全部订单都无关紧要。它们具有相同的数量,并且在时间范围内,无论如何都是双方的。

下一个OR正在检查买方是否想要卖方提供的更多且买方允许部分填写订单。卖家,谁在乎,他们想要摆脱他们的股份,你会把它们全部拿走,所以卖方要点的全部或部分是没有考虑的。

最后一个OR是买方希望的价格低于卖方提供的,但如果买方允许部分填写订单,那么买方是全部还是部分,卖方的数量无关紧要将填写他们的订单...只有确认是卖方允许部分出售他们的股票。

现在,您将获得所有可能合格交易的清单,但现在是价格。作为贸易经纪人,您基本上保持买方和卖方商定价格之间的差异。所以你想要两者之间最大的差距。如果有人想以每股100美元的价格购买,而有人提出以90美元的价格出售,另有人以95美元的价格出售,那么您可能希望首先卖出90美元的股票,以获得10美元的保证金分割与5美元的保证金分割。

也就是说,ORDER BY子句将获得DESCENDING订单中买入/卖出价格之间的绝对值差异,因此最大的保证金位于工作列表的顶部。

现在,您可以获得结果,并由您自己尝试从一个交易中进行交易,从另一个交易以完成交易。如果在获得提交之前使用了结果集中的第一条记录,则显然需要滚动到下一个可用事务,直到完成为止。然后,继续前进,直到完成订单的所有数量都被提交。

如果您正在测试SELL交易并寻找给定股票的买家,则会应用REVERSE查询,但这应该满足您的需求。这只是一个交易承诺的问题,取决于实际上有多少进程实际上自动填充订单并与处理相同订单的多次尝试相冲突。

答案 1 :(得分:0)

您不能每天处理订单吗?也就是说,如果出现多日订单,请分别处理每一天?这会简化事情。此外,对于多日订单的每一天,您将存储当天仍有多少订单。

哪个订单获得满意的确切规则取决于您/您的老板决定(最老的匹配价格?最便宜?无论如何?)。

不确定性能要求是什么,但每天处理很可能符合要求。如果没有,这是一个很好的第一步。

答案 2 :(得分:0)

瑞安,

对我来说听起来像背包问题,其目标是尽量减少成本而不是重量。认为购买订单是您每天必须填写的麻烦。有一个动态编程解决方案,它优雅,需要更少的内存。但是我怀疑你能得到它是如何填充的历史数据。

我从互联网获得的随机资源: http://www.programminglogic.com/knapsack-problem-dynamic-programming-algorithm/

如果您想进一步学习,我建议您阅读[Steven Skienna的算法设计手册]中的解释(http://www.amazon.com/Algorithm-Design-Manual-Steven-Skiena/dp/1848000693

希望这有帮助。