fork download
  1. #include <iostream>
  2. #include <array>
  3. #include <string>
  4. #include <vector>
  5. #include <map>
  6. #include <set>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <cstring>
  10. #include <ctime>
  11.  
  12. using namespace std;
  13. enum class instr_type { CALL, PUT, SPOT };
  14.  
  15. typedef std::int8_t BS;
  16.  
  17. const BS Buy = 'B';
  18. const BS Sell = 'S';
  19. const BS SellShort = 'H';
  20. const BS BuyCover = 'C';
  21.  
  22. template <typename T = BS>
  23. class BuySellT {
  24. public:
  25. BuySellT() : _bs(0) {}
  26. BuySellT(const T bs) noexcept : _bs(bs){}
  27. BuySellT& operator =(const T& p) {
  28. _bs = p;
  29. return *this;
  30. }
  31. BuySellT& operator =(const BuySellT& bs) {
  32. if (this != &bs) {
  33. _bs = bs.native();
  34. }
  35. return *this;
  36. }
  37. bool operator ==(const BuySellT& bs) const {
  38. return (regular() == bs.regular());
  39. }
  40. bool operator ==(const T& bs) const {
  41. return (regular() == bs);
  42. }
  43. operator T() const {
  44. return regular();
  45. }
  46. T regular() const {
  47. if (SellShort == _bs) {
  48. return Sell;
  49. }
  50. if (BuyCover == _bs) {
  51. return Buy;
  52. }
  53. return _bs;
  54. }
  55. T native() const {
  56. return _bs;
  57. }
  58. bool empty() const {
  59. return (0 == _bs);
  60. }
  61. private:
  62. T _bs;
  63. };
  64. typedef BuySellT<BS> TBuySell;
  65.  
  66. class DateCode {
  67. public:
  68. static const char* YYYYMMDD(std::time_t datetime, char* to, size_t maxchar){
  69. if (nullptr == to) {
  70. return to;
  71. }
  72. if(datetime < 0) {
  73. sprintf(to, "not datetime");
  74. return to;
  75. }
  76. struct tm *TM = gmtime(&datetime);
  77. if(nullptr == TM) {
  78. sprintf(to, "null");
  79. return to;
  80. }
  81. sprintf(to, "%04d%02d%02d",
  82. TM->tm_year + 1900, TM->tm_mon + 1, TM->tm_mday);
  83. return to;
  84. }
  85. static std::string YYYYMMDD(std::time_t datetime) {
  86. if (datetime < 0) {
  87. return "not datetime";
  88. }
  89. struct tm *TM = gmtime(&datetime);
  90. if (nullptr == TM) {
  91. return "null";
  92. }
  93. char buf[356];
  94. sprintf(buf, "'%04d%02d%02d'",
  95. TM->tm_year + 1900, TM->tm_mon + 1, TM->tm_mday);
  96. return std::string(buf);
  97. }
  98. static const char* YYYYMMDD(std::time_t datetime, char* to, size_t maxchar, unsigned char delimiter){
  99. if (nullptr == to) {
  100. return to;
  101. }
  102. if (datetime < 0) {
  103. sprintf(to, "not datetime");
  104. return to;
  105. }
  106. struct tm *TM = gmtime(&datetime);
  107. if (nullptr == TM) {
  108. sprintf(to, "null");
  109. return to;
  110. }
  111. sprintf(to, "%04d%c%02d%c%02d", TM->tm_year + 1900, delimiter, TM->tm_mon + 1, delimiter, TM->tm_mday);
  112. return to;
  113. }
  114. const char* date(std::time_t time) noexcept {
  115. DateCode::YYYYMMDD(time, date_, sizeof(date_), '/');
  116. return date_;
  117. }
  118. const char* time(std::time_t time, const char delimeter = ':') noexcept {
  119. auto seconds = time % 86400;
  120. date_[0] = 0;
  121. if (delimeter != 0) {
  122. sprintf(date_, "%02zd%c%02zd%c%02zd", seconds / 3600, delimeter, (seconds / 60) % 60, delimeter, seconds % 60);
  123. } else {
  124. sprintf(date_, "%02zd%02zd%02zd", seconds / 3600, (seconds / 60) % 60, seconds % 60);
  125. }
  126. return date_;
  127. }
  128. private:
  129. char date_[256]{0};
  130. };
  131.  
  132.  
  133. static const char* sInstrType(instr_type type) noexcept{
  134. constexpr std::array<const char*, 3> ar{ "CALL", "PUT", "SPOT"};
  135. auto idx = static_cast<std::size_t>(type);
  136. if (idx >= ar.size() || type < instr_type::CALL){
  137. return "Invalid instrument type";
  138. }
  139. return ar[idx];
  140. }
  141.  
  142. template<typename T>
  143. static const char* sLevel(T level) noexcept {
  144. constexpr std::array<const char*, 6> ar{ "", "Covered Calls", "Long options", "Option strategies and Short-stock Covered Puts", "Naked Puts", "Naked Calls" };
  145. if (level >= ar.size() || level < 0) {
  146. return "Invalid Option Level";
  147. }
  148. return ar[level];
  149. }
  150.  
  151.  
  152.  
  153. template <int len = 25, typename T = char>
  154. class FixedString {
  155. public:
  156. std::array<T, len> str_ = { 0 };
  157. public:
  158. FixedString() {}
  159. FixedString(const char* str) {
  160. if (nullptr == str) {
  161. return;
  162. }
  163. copy(str);
  164. }
  165. FixedString(const FixedString& str) {
  166. str_ = str.str_;
  167. }
  168. FixedString& operator = (const FixedString& str) {
  169. if (this != &str && str.str_.size() == str_.size()) {
  170. str_ = str.str_;
  171. }
  172. return *this;
  173. }
  174. FixedString& operator = (const char* str) {
  175. if (nullptr == str) {
  176. return *this;
  177. }
  178. copy(str);
  179. return *this;
  180. }
  181. FixedString& operator = (const std::string& str) {
  182. copy(str.c_str());
  183. return *this;
  184. }
  185. const char* c_str() const {
  186. return str_.data();
  187. }
  188. bool empty() const {
  189. return (str_[0] == 0);
  190. }
  191. bool operator == (const FixedString& str) const {
  192. return (0 == strcmp(str.str_.data(), str_.data()));
  193. }
  194. bool operator == (const char* str) const {
  195. return (0 == strcmp(str, str_.data()));
  196. }
  197. bool operator != (const char* str) const {
  198. return (0 != strcmp(str, str_.data()));
  199. }
  200. bool operator < (const FixedString& str) const {
  201. return strcmp(str_.data(), str.str_.data()) < 0;
  202. }
  203. protected:
  204. void copy(const char* from) {
  205. for (auto& x : str_) {
  206. if (0 == *from) {
  207. x = 0;
  208. break;
  209. }
  210. x = *from;
  211. from++;
  212. }
  213. str_.back() = 0;
  214. }
  215. };
  216.  
  217. class option_level_calc
  218. {
  219. public:
  220. template<typename T = int64_t, size_t len = 25 + 1>
  221. struct position
  222. {
  223. position() : B(0), S(0), N(0), contract_size(1), type(instr_type::SPOT), expiration(0)
  224. {
  225. }
  226. position(const char* Seccode, const char* Underlying, T OrderBuy, T OrderSell, T Saldo, T ContractSize, instr_type InstrType, std::time_t Expiration) :
  227. seccode(Seccode)
  228. , underlying_asset(Underlying)
  229. , B(OrderBuy)
  230. , S(OrderSell)
  231. , N(Saldo)
  232. , contract_size(ContractSize)
  233. , type(InstrType)
  234. , expiration(Expiration)
  235. {
  236. }
  237. std::string print() const noexcept {
  238. std::string s{ "POS: seccode=" };
  239. s += seccode.c_str();
  240. s += " root="; s += underlying_asset.c_str();
  241. s += " N="; s += std::to_string(N);
  242. s += " B="; s += std::to_string(B);
  243. s += " S="; s += std::to_string(S);
  244. s += " cs="; s += std::to_string(contract_size);
  245. s += " type="; s += sInstrType(type);
  246. return s;
  247. }
  248. FixedString<len> seccode;
  249. FixedString<len> underlying_asset;
  250. T B;
  251. T S;
  252. T N;
  253. T contract_size;
  254. instr_type type;
  255. std::time_t expiration;
  256. };
  257. template<typename T = int64_t, size_t len = 25 + 1>
  258. struct order
  259. {
  260. order() = default;
  261. order(const char* Seccode, const char* Underlying, std::int64_t Vol, TBuySell Bs, T ContractSize, instr_type InstrType, std::time_t Expiration) :
  262. seccode(Seccode)
  263. , underlying_asset(Underlying)
  264. , Qty(Vol)
  265. , bs(Bs)
  266. , contract_size(ContractSize)
  267. , type(InstrType)
  268. , expiration(Expiration)
  269. {
  270. }
  271. static void update(order<>& ord, instr_type type, TBuySell bs, T contract_size, T Qty) noexcept {
  272. if (instr_type::SPOT == type) {
  273. if (bs == Buy) {
  274. ord.Bspot += Qty;
  275. } else {
  276. ord.Sspot += Qty;
  277. }
  278. } else if (instr_type::CALL == type) {
  279. if (bs == Buy) {
  280. ord.Bcall += (Qty * contract_size);
  281. } else {
  282. ord.Scall += (Qty * contract_size);
  283. }
  284. } else if (instr_type::PUT == type) {
  285. if (bs == Buy) {
  286. ord.Bput += (Qty * contract_size);
  287. } else {
  288. ord.Sput += (Qty * contract_size);
  289. }
  290. }
  291. }
  292.  
  293. void calc_buy_sell_params() noexcept {
  294. if (legs.empty()) {
  295. order<>::update(*this, type, bs, contract_size, Qty);
  296. } else {
  297. for (const auto& leg : legs) {
  298. order<>::update(*this, leg.type, leg.bs, leg.contract_size, leg.Qty);
  299. }
  300. }
  301. }
  302. void clear() noexcept {
  303. Bspot = 0;
  304. Sspot = 0;
  305. Bcall = 0;
  306. Scall = 0;
  307. Bput = 0;
  308. Sput = 0;
  309. // остальные поля чистить не надо.
  310. }
  311. std::string print() const noexcept {
  312. std::string s{"ORD"};
  313. if (!legs.empty()) {
  314. s += " MULTILEG";
  315. }
  316. s += " seccode="; s += seccode.c_str();
  317. s += " root="; s += underlying_asset.c_str();
  318. s += " Qty="; s += std::to_string(Qty);
  319. s += " bs="; s += bs.native();
  320. s += " cs="; s += std::to_string(contract_size);
  321. s += " type="; s += sInstrType(type);
  322. s += " Bspot="; s += std::to_string(Bspot);
  323. s += " Sspot="; s += std::to_string(Sspot);
  324. s += " Bcall="; s += std::to_string(Bcall);
  325. s += " Scall="; s += std::to_string(Scall);
  326. s += " Bput="; s += std::to_string(Bput);
  327. s += " Sput="; s += std::to_string(Sput);
  328. for (const auto& x : legs) {
  329. s += "\n\t LEG";
  330. auto sLeg = x.print();
  331. s += sLeg;
  332. }
  333. return s;
  334. }
  335. FixedString<len> seccode;
  336. FixedString<len> underlying_asset;
  337. T Bspot{ 0 }; // заявлено купить спота
  338. T Sspot{ 0 }; // заявлено продать спота
  339. T Bcall{ 0 }; // заявлено купить коллов
  340. T Scall{ 0 }; // заявлено продать коллов
  341. T Bput{ 0 }; // заявлено купить путов
  342. T Sput{ 0 }; // заявлено продать путов
  343. T Qty{ 0 }; // исходные. заявлено количество
  344. TBuySell bs{ 0 }; // исходные. направление
  345. T contract_size{ 1 };
  346. instr_type type{ instr_type::SPOT };
  347. std::time_t expiration{ 0 };
  348. std::vector<order> legs;
  349. };
  350. template<typename Container_positions, typename Container_orders, typename Container_trace>
  351. static std::int64_t calc(Container_positions& positions, Container_orders& orders, Container_trace& output, std::int32_t log_severity)
  352. {
  353. return option_level_calc::the_calc(positions, orders, output, log_severity);
  354. }
  355. protected:
  356. using DATES = std::set<std::time_t>;
  357.  
  358. struct BA {
  359. void clear() noexcept {
  360. NspotLong = 0;
  361. NspotShort = 0;
  362. NcallLong = 0;
  363. NcallShort = 0;
  364. NputLong = 0;
  365. NputShort = 0;
  366. orders.clear();
  367. positions.clear();
  368. // exp_dates чистить не надо
  369. }
  370. void fill(instr_type type, std::int64_t N, std::int64_t ContractSize) {
  371. if (instr_type::SPOT == type) {
  372. if (N > 0) {
  373. NspotLong += N;
  374. } else if (N < 0) {
  375. NspotShort += abs(N);
  376. }
  377. } else if (instr_type::CALL == type) {
  378. if (N > 0) {
  379. NcallLong += N * ContractSize;
  380. } else if (N < 0) {
  381. NcallShort += abs(N * ContractSize);
  382. }
  383. } else {
  384. if (N > 0) {
  385. NputLong += N * ContractSize;
  386. } else if (N < 0) {
  387. NputShort += abs(N * ContractSize);
  388. }
  389. }
  390. }
  391. std::string print() const noexcept {
  392. std::string s{};
  393. s += "NspotLong="; s += std::to_string(NspotLong);
  394. s += " NspotShort="; s += std::to_string(NspotShort);
  395. s += " NcallLong="; s += std::to_string(NcallLong);
  396. s += " NcallShort="; s += std::to_string(NcallShort);
  397. s += " NputLong="; s += std::to_string(NputLong);
  398. s += " NputShort="; s += std::to_string(NputShort);
  399. for (const auto& ord : orders) {
  400. s += "\n";
  401. auto sOrd = ord.print();
  402. s += sOrd;
  403. }
  404. for (const auto& x : positions) {
  405. s += "\n";
  406. auto sPos = x.print();
  407. s += sPos;
  408. }
  409. return s;
  410. }
  411. std::int64_t NspotLong{ 0 }; // текущий лонг в споте
  412. std::int64_t NspotShort{ 0 }; // текущий шорт в споте(фактически не используется)
  413. std::int64_t NcallLong{ 0 }; // совокупный лонг в коллах
  414. std::int64_t NcallShort{ 0 }; // совокупный шорт в коллах
  415. std::int64_t NputLong{ 0 }; // совокупный лонг в путах
  416. std::int64_t NputShort{ 0 }; // совокупный шорт в путах
  417. std::vector<order<>> orders;
  418. std::vector<position<>> positions;
  419. DATES exp_dates; // date + рассчетный опционный уровень
  420. std::int64_t MaxBaLevel{ 0 }; // максимальный уровень в этом базовом активе
  421. };
  422. static std::int64_t omega(std::int64_t V, std::int64_t N) noexcept {
  423. auto x{ V };
  424. auto y{ V };
  425.  
  426. if ((x < -N ? V : -N) < 0) { x = 0; }
  427. if ((y > -N ? V : -N) > 0) { y = 0; }
  428. return x - y;
  429. }
  430.  
  431. template<typename Container_positions, typename Container_orders, typename Container_trace>
  432. static std::int64_t ba_calc(const BA& ba, Container_positions& positions, Container_orders& orders, Container_trace& output) {
  433. auto three_level = [&](const auto& ba, const auto& orders) -> std::int64_t {
  434. // На уровнях 3 и 4 не должно быть внеспредовых шортов в коллах, не перекрытых спотом
  435. std::int64_t W{ ba.NspotLong + ba.NcallLong - ba.NcallShort };
  436. if (W < 0) {
  437. return 5;
  438. }
  439. for (const auto& o : orders) {
  440. std::int64_t dW{ o.Sspot - o.Bspot };
  441. if (!ba.NspotLong && dW > 0) {
  442. dW = 0;
  443. }
  444. dW += o.Scall - o.Bcall;
  445. if (dW > 0) {
  446. W -= dW;
  447. if (W < 0) {
  448. return 5;
  449. }
  450. }
  451. }
  452. // На уровне 3 не должно быть внеспредовых шортов в путах
  453. W = ba.NputLong - ba.NputShort;
  454. if (W < 0) {
  455. return 4;
  456. }
  457. for (const auto& o : orders) {
  458. std::int64_t dW{ o.Sput - o.Bput };
  459. if (dW > 0) {
  460. W -= dW;
  461. if (W < 0) {
  462. return 4;
  463. }
  464. }
  465. }
  466. return 3;
  467. };
  468. auto two_level = [&](const auto& ba, const auto& positions, const auto& orders) -> std::int64_t {
  469. // На уровне 2 не должно быть шортов в путах
  470. for (const auto& i : positions) {
  471. if (instr_type::PUT == i.type && i.N - i.S < 0) {
  472. return three_level(ba, orders);
  473. }
  474. }
  475. return 2;
  476. };
  477. auto one_level = [&](const auto& ba, const auto& positions, const auto& orders) -> std::int64_t {
  478. // На уровнях 1 и 2 не должно быть непокрытых шортов в коллах
  479. // Определяем isPositive ("положительность" базового актива)
  480. bool isPositive{ false };
  481. if (ba.NspotLong) {
  482. isPositive = true;
  483. }
  484. else if (0 == ba.NspotShort) {
  485. for (const auto& i : positions) {
  486. if (instr_type::SPOT == i.type && i.B) {
  487. isPositive = true;
  488. break;
  489. }
  490. }
  491. }
  492. if (isPositive) {
  493. std::int64_t W{ ba.NspotLong - ba.NcallShort };
  494. if (W < 0) {
  495. return three_level(ba, orders);
  496. }
  497. for (const auto& o : orders) {
  498. std::int64_t dW{ o.Sspot - o.Bspot + o.Scall };
  499. for (const auto& m : o.legs) {
  500. if (instr_type::CALL == m.type) {
  501. std::int64_t N{ 0 };
  502. for (const auto& i : positions) {
  503. if (instr_type::CALL == i.type &&
  504. i.seccode == m.seccode.c_str()) {
  505. N = i.N;
  506. break;
  507. }
  508. }
  509. // legVol = полный заявленный объём инструмента этой ноги, со знаком
  510. // legVol = leg.QtyRatio * Quantity * Contractsize * sign(leg.buysell)
  511. std::int64_t legVol{ m.Qty * o.Qty * m.contract_size * (m.bs == Buy ? 1 : -1) };
  512. dW -= omega(legVol, N);
  513. }
  514. }
  515. if (dW > 0) {
  516. W -= dW;
  517. if (W < 0) {
  518. return three_level(ba, orders);
  519. }
  520. }
  521. }
  522. } else {
  523. for (const auto& i : positions) {
  524. if (instr_type::CALL == i.type && i.N - i.S < 0) {
  525. return three_level(ba, orders);
  526. }
  527. }
  528. }
  529.  
  530. // На уровне 1 не должно быть путов
  531. if (ba.NputLong || ba.NputShort) {
  532. return two_level(ba, positions, orders);
  533. }
  534. for (const auto& o : orders) {
  535. if (o.Bput || o.Sput) {
  536. return two_level(ba, positions, orders);
  537. }
  538. }
  539. // На уровне 1 не должно быть лонгов в коллах
  540. for (const auto& i : positions) {
  541. if (instr_type::CALL == i.type && i.N + i.B > 0) {
  542. return two_level(ba, positions, orders);
  543. }
  544. }
  545. return 1;
  546. };
  547. auto calc_level = [&](const auto& ba, const auto& positions, const auto& orders) -> std::int64_t {
  548. // На уровне 0 не должно быть никаких опционов
  549. if (ba.NcallLong || ba.NcallShort || ba.NputLong || ba.NputShort) {
  550. return one_level(ba, positions, orders);
  551. }
  552. for (const auto& ord : orders) {
  553. if (ord.Bcall || ord.Scall || ord.Bput || ord.Sput) {
  554. return one_level(ba, positions, orders);;
  555. }
  556. }
  557. return 0ll;
  558. };
  559. return calc_level(ba, positions, orders);
  560. }
  561. template<typename Container_positions, typename Container_orders, typename Container_trace>
  562. static std::int64_t the_calc(Container_positions& positions, Container_orders& orders, Container_trace& output, std::int32_t log_severity)
  563. {
  564. auto now = ::time(nullptr);
  565. now /= 86400;
  566.  
  567. std::map<FixedString<25 + 1>, BA> base_actives;
  568. for (const auto& i : positions) {
  569. if (!i.underlying_asset.empty()) {
  570. if (log_severity > 1) {
  571. output.push_back(i.print().c_str());
  572. }
  573. auto& ba = base_actives[i.underlying_asset];
  574. // формируем пустой список, рассчитываем список дат экспираций
  575. // где первый самый маленький элемент - текущая дата
  576. ba.exp_dates.insert(DATES::value_type(now));
  577. if (i.expiration && i.expiration > now) {
  578. ba.exp_dates.insert(DATES::value_type(i.expiration));
  579. }
  580. }
  581. }
  582. // Все опционы базового актива группируются по дате экспирации.
  583. // Если количество уникальных дат экспирации больше одной, то дополнительно производится
  584. // определение прогнозного опционного уровня в базовом активе на последовательные моменты после каждой очередной экспирации,
  585. // кроме самой дальней.
  586. for (auto& x : base_actives) {
  587. if (x.second.exp_dates.size() > 1) {
  588. x.second.exp_dates.erase(std::prev(x.second.exp_dates.end())); // удаляем самую дальнюю дату экспирации
  589. }
  590. }
  591. for (auto& ord : orders) {
  592. ord.clear();
  593. ord.calc_buy_sell_params();
  594. }
  595.  
  596. if (log_severity > 1) {
  597. for (const auto& ord : orders) {
  598. output.push_back(ord.print().c_str());
  599. }
  600. output.push_back("===============================");
  601. }
  602.  
  603. std::int64_t max_level{ 0 };
  604. for (auto& j : base_actives) {
  605.  
  606. std::string log("OptLevels: ba=");
  607.  
  608. const auto& underlying = j.first;
  609. log += underlying.c_str();
  610. auto& ba = j.second;
  611. for (auto date : ba.exp_dates) {
  612. if (log_severity > 0) {
  613. char buf[256];
  614. log += " {date="; log += DateCode::YYYYMMDD(date * 86400, buf, sizeof(buf), '-');
  615. }
  616.  
  617. for (const position<>& i : positions) {
  618. if (!i.underlying_asset.empty() && underlying == i.underlying_asset) {
  619. if (0 == i.expiration || i.expiration > date) {
  620. ba.fill(i.type, i.N, i.contract_size);
  621. ba.positions.push_back(i);
  622. }
  623. }
  624. }
  625. for (const order<>& o : orders) {
  626. // ноги мультилега могут вырождаться
  627. if (!o.underlying_asset.empty() && underlying == o.underlying_asset) {
  628. if (0 == o.expiration || o.expiration > date) {
  629. if (o.legs.empty()) {
  630. ba.orders.push_back(o);
  631. } else {
  632. // multileg
  633. order<> ord(o.seccode.c_str(), o.underlying_asset.c_str(), o.Qty, o.bs, o.contract_size, o.type, o.expiration);
  634. for (const auto& leg : o.legs) {
  635. if (0 == leg.expiration || leg.expiration > date) {
  636. ord.legs.push_back(leg);
  637. }
  638. }
  639. auto size = ord.legs.size();
  640. //вырождение мультилега, или неверные параметры
  641. if (size < 5) {
  642. ord.calc_buy_sell_params();
  643. ba.orders.push_back(ord);
  644. }
  645. }
  646. }
  647. }
  648. }
  649. auto LevelByDate = ba_calc<>(ba, ba.positions, ba.orders, output);
  650. if (log_severity > 1) {
  651. char buf[256]{ 0 };
  652.  
  653. DateCode::YYYYMMDD(date * 86400, buf, sizeof(buf), '-');
  654. std::string s{ "BA=" + std::string(underlying.c_str()) + " "};
  655. s += buf;
  656. s += (" ----------------------------------------");
  657. output.push_back(s.c_str());
  658. s = ba.print();
  659. output.push_back(s.c_str());
  660. }
  661. if (log_severity > 0) {
  662. log += " level="; log += std::to_string(LevelByDate); log += "}";
  663. }
  664. if (LevelByDate > ba.MaxBaLevel) {
  665. ba.MaxBaLevel = LevelByDate;
  666. }
  667. if (ba.MaxBaLevel > max_level) {
  668. max_level = ba.MaxBaLevel;
  669. }
  670. ba.clear(); // очищаем результаты выборок
  671. }
  672. if (log_severity > 0) {
  673. output.push_back(log.c_str());
  674. }
  675. }
  676. return max_level;
  677. }
  678. };
  679.  
  680. int main() {
  681. std::vector<option_level_calc::position<>> positions;
  682. std::vector<option_level_calc::order<>> orders;
  683. orders.emplace_back("AAPL 200619C00250000", "AAPL", 1, 'B', 100, instr_type::CALL, 29587);
  684. positions.emplace_back("AAPL 200619C00250000", "AAPL", 60, 6, 4, 100, instr_type::CALL, 29587);
  685. positions.emplace_back("AAPL 200619230250000", "AAPL", 1, 70, 0, 100, instr_type::PUT, 29587);
  686. positions.emplace_back("MSFT 200619230250020", "MSFT", 1, 77, 0, 100, instr_type::CALL, 29587);
  687. positions.emplace_back("MSFT 20061923wq50020", "MSFT", 1, 22, 0, 100, instr_type::CALL, 29587);
  688. positions.emplace_back("MSFT 20061923ws50020", "MSFT", 1, 22, 900, 100, instr_type::CALL, 29587);
  689. positions.emplace_back("CISCO 2006192350020", "CSCO", 1, 22, 900, 100, instr_type::CALL, 29587);
  690. positions.emplace_back("CISCO 2006192350020", "CSCO", 700, 22, 90, 100, instr_type::PUT, 29587);
  691. positions.emplace_back("IBS 2006192350020", "IBS", 700, 22, 90, 100, instr_type::PUT, 29587);
  692. positions.emplace_back("MSFT", "MSFT", 1, 0, 4, 1, instr_type::SPOT, 0);
  693. positions.emplace_back("MSFTA", "", 12, 0, 4, 1, instr_type::SPOT, 0);
  694. std::vector<FixedString<128>> output;
  695. auto level = option_level_calc::calc(positions, orders, output, 3);
  696. std::cout << "Option level calc : port_level=" << level << " " << std::endl;
  697. for (auto& item : output)
  698. {
  699. std::cout << "\t" << item.c_str() << std::endl;
  700. }
  701. return 0;
  702. }
Success #stdin #stdout 0s 5304KB
stdin
Standard input is empty
stdout
Option level calc : port_level=3 
	POS: seccode=AAPL  200619C00250000 root=AAPL N=4 B=60 S=6 cs=100 type=CALL
	POS: seccode=AAPL  200619230250000 root=AAPL N=0 B=1 S=70 cs=100 type=PUT
	POS: seccode=MSFT  200619230250020 root=MSFT N=0 B=1 S=77 cs=100 type=CALL
	POS: seccode=MSFT  20061923wq50020 root=MSFT N=0 B=1 S=22 cs=100 type=CALL
	POS: seccode=MSFT  20061923ws50020 root=MSFT N=900 B=1 S=22 cs=100 type=CALL
	POS: seccode=CISCO 2006192350020 root=CSCO N=900 B=1 S=22 cs=100 type=CALL
	POS: seccode=CISCO 2006192350020 root=CSCO N=90 B=700 S=22 cs=100 type=PUT
	POS: seccode=IBS 2006192350020 root=IBS N=90 B=700 S=22 cs=100 type=PUT
	POS: seccode=MSFT root=MSFT N=4 B=1 S=0 cs=1 type=SPOT
	ORD seccode=AAPL  200619C00250000 root=AAPL Qty=1 bs=B cs=100 type=CALL Bspot=0 Sspot=0 Bcall=100 Scall=0 Bput=0 Sput=0
	===============================
	BA=AAPL 2023-12-01 ----------------------------------------
	NspotLong=0 NspotShort=0 NcallLong=400 NcallShort=0 NputLong=0 NputShort=0
ORD seccode=AAPL  200619C00250000 root=AAPL Qty=1 bs
	OptLevels: ba=AAPL {date=2023-12-01 level=3}
	BA=CSCO 2023-12-01 ----------------------------------------
	NspotLong=0 NspotShort=0 NcallLong=90000 NcallShort=0 NputLong=9000 NputShort=0
POS: seccode=CISCO 2006192350020 root=CSCO N=90
	OptLevels: ba=CSCO {date=2023-12-01 level=2}
	BA=IBS 2023-12-01 ----------------------------------------
	NspotLong=0 NspotShort=0 NcallLong=0 NcallShort=0 NputLong=9000 NputShort=0
POS: seccode=IBS 2006192350020 root=IBS N=90 B=700 
	OptLevels: ba=IBS {date=2023-12-01 level=2}
	BA=MSFT 2023-12-01 ----------------------------------------
	NspotLong=4 NspotShort=0 NcallLong=90000 NcallShort=0 NputLong=0 NputShort=0
POS: seccode=MSFT  200619230250020 root=MSFT N=0 B
	OptLevels: ba=MSFT {date=2023-12-01 level=2}