【问题标题】:Min & Max Value from Projected boost MultiIndex iterator来自 Projected boost MultiIndex 迭代器的最小值和最大值
【发布时间】:2017-06-30 12:08:43
【问题描述】:

我正面临一个基于 MultiIndex 容器中迭代器的投影值的排序问题。下面是完整的代码。我在这里删除的是SellOrderRecord 的调用,因为调用的函数是相同的GenerateData,但预期结果不同,即;在BuyOrderRecord 中的前 10 名最小记录应该导致前 10 名最大记录。

假设我将在错误的范围内获得 Max/Min 值,我将强制迭代到 500。我需要获取的是前 10 个唯一价格,如果价格重复,则将其数量相加。

例如。价格 10 数量 5;价格 9 数量 4;价格 8 数量 7 .... n

当我尝试使用 Qty 获取前 10 分钟价格时也是如此。

使用 printf 生成的result(在生成数据中注释)显示即使我已使用std::less 对其进行排序,一条记录在 Buy 记录的末尾有 Max,而另一个持有者在最后有 Min 结果。我认为两者都应该是最小到最大或最大到最小。完整的实际代码已共享。

namespace bip = boost::interprocess;
namespace bmi = boost::multi_index;

struct MIOrder_Message /// For Data
{
    // STREAM_HEADER Global_Header;
    // char Message_Type;

    MIOrder_Message(Order_Message _Ord)
        : Timestamp(_Ord.Timestamp), Order_Id(_Ord.Order_Id), Token(_Ord.Token),
        Order_Type(_Ord.Order_Type), Price(_Ord.Price),
        Quantity(_Ord.Quantity) {
            //  std::cout << " Insert data for Token "<< _Ord.Token<<std::endl;
        }

    long Timestamp;
    double Order_Id;
    int Token;
    char Order_Type;
    int Price;
    int Quantity;
};
/// Order_Message and MIOrder_Message are almost identical
typedef bip::allocator<MIOrder_Message,
                       bip::managed_shared_memory::segment_manager>
    shared_struct_allocator;

enum {
    ORDERVIEW,
    TOKENVIEW,
    PRICEVIEW,
    TYPEVIEW,
};

typedef bmi::multi_index_container<
    MIOrder_Message,
    bmi::indexed_by<
        bmi::ordered_unique<bmi::tag<struct Order_Id>, BOOST_MULTI_INDEX_MEMBER( MIOrder_Message, double, MIOrder_Message::Order_Id)>,
        bmi::ordered_non_unique<bmi::tag<struct Token>, BOOST_MULTI_INDEX_MEMBER( MIOrder_Message, int, MIOrder_Message::Token)>,
        bmi::ordered_non_unique<bmi::tag<struct Price>, BOOST_MULTI_INDEX_MEMBER( MIOrder_Message, int, MIOrder_Message::Price), std::less<int>>,
        bmi::ordered_non_unique<bmi::tag<struct Order_Type>, BOOST_MULTI_INDEX_MEMBER(MIOrder_Message, char, Order_Type)> >,
        shared_struct_allocator
    > Order_Set;

typedef bmi::nth_index<Order_Set, ORDERVIEW>::type Order_view;
typedef bmi::nth_index<Order_Set, TOKENVIEW>::type Token_View;
typedef bmi::nth_index<Order_Set, PRICEVIEW>::type Price_View;

typedef std::map<int, int> _PricePoint;

_PricePoint GenerateData(int _TKN, std::pair<Order_Set *, std::size_t> OrderRecord, bool IsReverse = false) {

  _PricePoint CurrentPrice;

  if (OrderRecord.second > 0) {

    Token_View::const_iterator t1 =
        OrderRecord.first->get<TOKENVIEW>().find(_TKN);

    Price_View::const_iterator it2 = OrderRecord.first->project<PRICEVIEW>(t1);

    int icount = 0;

    int Price = 0;

    while (icount < 500)
    /// I am forcefully iterating to 500 assuming that i will
    /// get Max value within that range. What i need to fetch is
    /// Top 10 unique Price and sum its Qty if Price is repeated.
    /// Ex. Price 10 Qty 5 ; Price 9 Qty 4; Price 8 Qty 7 .... n
    /// Same is the case when I am trying to fetch top 10 Min Price with Qty.
    {
      auto val = std::next(it2, icount);

      if (val->Token == _TKN) {
        // printf("  Bid Data Found for token %d , Price %d , Qty %d , Time %li
        // , OrderNumber %16f , icount %d  \n
        // ",val->Token,val->Price,val->Quantity,val->Timestamp,val->Order_Id,icount);

        CurrentPrice[val->Price] += val->Quantity;

        Price = val->Price;
      }
      icount++;
    }
    std::cout << " Bid Price " << Price << std::endl;
  }

  return CurrentPrice;
}

int main() {

  bip::managed_shared_memory segment(bip::open_or_create, "mySharedMemory", 20ull<<20);

  Order_Set::allocator_type alloc(segment.get_segment_manager());
  Order_Set * BuyOrderRecord = segment.find_or_construct<Order_Set>("MCASTPORT0BUY")(alloc);

  if (BuyOrderRecord->empty()) {
  }

  while (true) {
    int _TKN = 49732;

    _PricePoint CurrentPrice = GenerateData(_TKN, std::make_pair(BuyOrderRecord, 1), true);

    std::cout << "=========================================================" << std::endl;
    sleep(2);
  }

  return 0;
}

【问题讨论】:

标签: boost boost-multi-index const-iterator


【解决方案1】:

你永远不会检查std::next(it2, icount)的结果是否有效。

很有可能,事实并非如此。毕竟it2 只是_TKN 找到的元素,投影在有序价格指数上。如果 _TKN 恰好在 Order_Set 中具有最高价格,那么 it2 已经是

处的最后一个元素
Price_View::const_iterator it2 = OrderRecord.first->project<PRICEVIEW>(t1);

这意味着仅增加 1 的事件将返回价格指数的 end()

在我看来,您错误地认为“投影”迭代器会投影到 过滤子集,但事实并非如此。它只是投影到另一个索引上。全套。

如果您确实希望能够以最高价格迭代与令牌匹配的所有记录,您会更喜欢使用复合键:

typedef bmi::multi_index_container<
    MIOrder_Message,
    bmi::indexed_by<
        bmi::ordered_unique<bmi::tag<struct Order_Id>, BOOST_MULTI_INDEX_MEMBER( MIOrder_Message, double, MIOrder_Message::Order_Id)>,
        bmi::ordered_non_unique<bmi::tag<struct Token>, BOOST_MULTI_INDEX_MEMBER( MIOrder_Message, int, MIOrder_Message::Token)>,
        bmi::ordered_non_unique<bmi::tag<struct Price>, BOOST_MULTI_INDEX_MEMBER( MIOrder_Message, int, MIOrder_Message::Price), std::less<int>>,
        bmi::ordered_non_unique<bmi::tag<struct Order_Type>, BOOST_MULTI_INDEX_MEMBER(MIOrder_Message, char, Order_Type)>
        , bmi::ordered_non_unique<bmi::tag<struct Composite>, 
            bmi::composite_key<MIOrder_Message, 
                bmi::member<MIOrder_Message, int, &MIOrder_Message::Token>,
                bmi::member<MIOrder_Message, int, &MIOrder_Message::Price> 
            >
        >
        >,
        shared_struct_allocator
    > Order_Set;

有序复合键接受部分键,所以你可以这样做:

auto range = OrderRecord.first->get<Composite>().equal_range(boost::make_tuple(_TKN));

【讨论】:

  • 感谢@sehe 成功了。抱歉,样本不完整。
猜你喜欢
  • 2022-09-27
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2014-10-22
  • 1970-01-01
相关资源
最近更新 更多