根据条件查询匹配的股票交易买家/卖家

时间:2012-09-09 20:37:02

标签: sql sql-server sql-server-2008

我正在尝试创建一个存储过程,以匹配买家和卖家的虚假股票市场计划。我最终想用这个来填充一个事务表来完成人们的订单。这也将在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. 买方必须寻找具有>买方想要的股票数量的卖方(如果是“卖出”订单)。如果是“卖方”订单,那么买方购买股票的数量必须相等。例如。卖方必须出售50股,买方必须以相同或更低的价格购买50股。
  2. 买家想要股票的最低价格。
  3. 如果有多个卖家符合上述条件,买家会在最低价格之后先购买最早的卖单。
  4. 所以交易者对将是#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'
    

2 个答案:

答案 0 :(得分:2)

试试这个

简而言之,

1.基于createddate(在下面的查询中命名为stock)的佣金买家.2。基于价格的卖家卖家,创建日期(命名为lowNoldstock)
。获取匹配等级

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

test script in sql fiddle,由于某种原因,它在sql小提琴中显示部分结果 这适用于我的本地数据库

答案 1 :(得分: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