0

我正在尝试创建一个存储过程来匹配虚假股票市场程序的买家和卖家。我最终想用它来填充交易表以完成人们的订单。这也将在 SQL Server 代理作业中。这是我的表:

Id    UserId    Type    QtyRemaining    Price   CreatedOn
1      3        BUY     50              1.00    2012-09-09 05:25:48.4470000
2      6        BUY     50              1.00    2012-09-09 19:25:34.4300000
3      5        SELL    30              1.00    2012-09-09 19:22:59.5900000
4      3        SELL    50              0.90    2012-09-09 06:39:34.9100000
5      2        SELLALL 50              1.00    2012-09-09 04:10:01.8400000

进行这些匹配需要满足几个条件:

  1. 如果是“卖出”订单,买方必须寻找具有 >= 买方想要的股份数量的卖方。如果是“SELLALL”订单,则买方购买股票的数量必须相等。例如,卖方必须卖出 50 股,而买方必须以相同或更低的价格买入 50 股。
  2. 买家想要股票的最低价格。
  3. 如果有多个卖家符合上述条件,买家先在最低价格后购买最旧的销售库存。

所以交易者对将是#1 和#4、#2 和#5。因此#3 仍将处于未决状态。

这是我正在使用的代码,但我无法让它与最低价格和最旧的优先匹配:

select o.*, oa.*, r.* from [Order] o
join OrderActivity oa on o.Id = oa.OrderId
join (
    select o2.Id, o2.VideoId, o2.UserId, oa2.Price, oa2.QtyRemaining, o2.[Type] from [Order] o2
    join OrderActivity oa2 on o2.Id = oa2.OrderId
    where o2.Type = 'buy' and oa2.Status = 'open'
) as r on (o.VideoId = r.VideoId and oa.Price <= r.Price and r.QtyRemaining = oa.QtyRemaining and o.UserId != r.UserId)
where (o.Type = 'sell' or o.Type = 'sellall') and oa.Status = 'open'
4

2 回答 2

2

试试这个

简要地 ,

1.根据createddate对买家进行排名(以下查询中称为stocks)
2.根据价格对卖家进行排名,createddate(称为lowNoldstock)
3.获取匹配排名

select stocks.*,lowNoldStock.* 
from    (select *,row_number() over(order by createdon) as buyerrank
         from stocktable(nolock)  where c='buy' ) stocks 
inner join 
       (select  *,row_number() over(order by price,createdon) as sellerrank
        from stocktable(nolock) where [type]='sell' or [type]='sellall' ) lowNoldstock
on      (stocks.qty<=lowNoldStock.qty and lowNoldStock.type='sell') 
       or (lowNoldStock.type='sellall' and stocks.qty=lowNoldStock.qty and stocks.price>=lowNoldStock.price)
where  lowNoldStock.sellerrank=stocks.buyerrank

sql fiddle 中的测试脚本,由于某种原因,它在 sql fiddle 中显示部分结果这适用于我的本地数据库

于 2012-09-10T10:37:06.667 回答
0

欢迎你玩这个:

declare @Transactions as Table
  ( Id Int, UserId Int, Type VarChar(8), QtyRemaining Int, Price Money, CreatedOn DateTime )
insert into @Transactions ( Id, UserId, Type, QtyRemaining, Price, CreatedOn ) values
  ( 1, 3, 'BUY',     50, 1.00, '2012-09-09 05:25:48.447' ),
  ( 2, 6, 'BUY',     50, 1.00, '2012-09-09 19:25:34.430' ),
  ( 3, 5, 'SELL',    30, 1.00, '2012-09-09 19:22:59.590' ),
  ( 4, 3, 'SELL',    50, 0.90, '2012-09-09 06:39:34.910' ),
  ( 5, 2, 'SELLALL', 50, 1.00, '2012-09-09 04:10:01.840' )

-- Split the transactions into temporary working tables.
declare @Buyers as Table
  ( Id Int, UserId Int, Type VarChar(8), QtyRemaining Int, Price Money, CreatedOn DateTime )
declare @Sellers as Table
  ( Id Int, UserId Int, Type VarChar(8), QtyRemaining Int, Price Money, CreatedOn DateTime )
insert into @Buyers
  select Id, UserId, Type, QtyRemaining, Price, CreatedOn
    from @Transactions
    where Type = 'BUY'
insert into @Sellers
  select Id, UserId, Type, QtyRemaining, Price, CreatedOn
    from @Transactions
    where Type like 'SELL%'

-- Process the buy orders in the order in which they were created.
declare @BuyerId as Int = ( select top 1 Id from @Buyers order by CreatedOn )
declare @SellerId as Int
declare @Balance as Int

while @BuyerId is not NULL
  begin
  -- Pair a seller, if possible, with the current buyer.
  ; with Willard as (
  select Row_Number() over ( order by S.Price, S.CreatedOn ) as Priority,
    S.Id as S_Id, S.QtyRemaining as S_QtyRemaining,
    B.QtyRemaining as B_QtyRemaining
    from @Sellers as S inner join
      @Buyers as B on B.Id = @BuyerId and
        case 
          when S.Type = 'SELL' and B.QtyRemaining <= S.QtyRemaining then 1
          when S.Type = 'SELLALL' and B.QtyRemaining = S.QtyRemaining then 1
          else 0
          end = 1
    ) 
  select @SellerId = S_Id, @Balance = S_QtyRemaining - B_QtyRemaining
    from Willard
    where Priority = 1
  -- Display the result.
  select @BuyerId as BuyerId, @SellerId as SellerId, @Balance as RemainingShares
  -- Update the working tables.
  if @Balance = 0
    delete from @Sellers
      where Id = @SellerId
  else
    update @Sellers
      set QtyRemaining = @Balance
      where Id = @SellerId
  delete from @Buyers
    where Id = @BuyerId
  -- Find the next buy order.
  set @BuyerId = ( select top 1 Id from @Buyers order by CreatedOn )
  end

-- Display any unfilled orders.
select 'Unmatched Buy', *
  from @Buyers
select 'Unmatched Sell', *
  from @Sellers
于 2012-09-10T00:56:05.627 回答