1 | /* |
2 | * Legal Notice |
3 | * |
4 | * This document and associated source code (the "Work") is a part of a |
5 | * benchmark specification maintained by the TPC. |
6 | * |
7 | * The TPC reserves all right, title, and interest to the Work as provided |
8 | * under U.S. and international laws, including without limitation all patent |
9 | * and trademark rights therein. |
10 | * |
11 | * No Warranty |
12 | * |
13 | * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION |
14 | * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE |
15 | * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER |
16 | * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, |
17 | * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, |
18 | * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR |
19 | * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF |
20 | * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE. |
21 | * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, |
22 | * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT |
23 | * WITH REGARD TO THE WORK. |
24 | * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO |
25 | * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE |
26 | * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS |
27 | * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, |
28 | * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY, |
29 | * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT |
30 | * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD |
31 | * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. |
32 | * |
33 | * Contributors |
34 | * - Sergey Vasilevskiy |
35 | * - Doug Johnson |
36 | */ |
37 | |
38 | /* |
39 | * Class representing the DAILY_MARKET table. |
40 | */ |
41 | #ifndef DAILY_MARKET_TABLE_H |
42 | #define DAILY_MARKET_TABLE_H |
43 | |
44 | #include "EGenTables_common.h" |
45 | #include "SecurityPriceRange.h" |
46 | |
47 | #include "input/DataFileManager.h" |
48 | |
49 | namespace TPCE { |
50 | |
51 | const int iTradeDaysInYear = 261; // the number of trading days in a year (for DAILY_MARKET) |
52 | const int iDailyMarketYears = 5; // number of years of history in DAILY_MARKET |
53 | const int iDailyMarketTotalRows = iDailyMarketYears * iTradeDaysInYear; |
54 | |
55 | const double fDailyMarketCloseMin = fMinSecPrice; |
56 | const double fDailyMarketCloseMax = fMaxSecPrice; |
57 | |
58 | const double fDailyMarketHighRelativeToClose = 1.05; |
59 | const double fDailyMarketLowRelativeToClose = 0.92; |
60 | |
61 | const INT64 iDailyMarketVolumeMax = 10000; |
62 | const INT64 iDailyMarketVolumeMin = 1000; |
63 | |
64 | const int iRNGSkipOneRowDailyMarket = 2; // number of RNG calls for one row |
65 | |
66 | typedef struct DAILY_MARKET_GEN_ROW { |
67 | // big array of all the history for one security |
68 | DAILY_MARKET_ROW m_daily_market[iDailyMarketTotalRows]; |
69 | } * PDAILY_MARKET_GEN_ROW; |
70 | |
71 | class CDailyMarketTable : public TableTemplate<DAILY_MARKET_GEN_ROW> { |
72 | TIdent m_iStartFromSecurity; |
73 | TIdent m_iSecurityCount; |
74 | const CSecurityFile &m_SecurityFile; |
75 | CDateTime m_StartFromDate; |
76 | int m_iDailyMarketTotalRows; |
77 | // Number of times GenerateNextRecord() was called for the current security |
78 | // data. Needed to decide when to generate next security's data. |
79 | int m_iRowsGeneratedPerSecurity; |
80 | // Stores whether there is another security(s) for which to |
81 | // generate daily market data. |
82 | bool m_bMoreSecurities; |
83 | TIdent m_iSecurityCountForOneLoadUnit; |
84 | |
85 | /* |
86 | * DAILY_MARKET table rows generation |
87 | */ |
88 | void GenerateDailyMarketRows() { |
89 | int i; |
90 | int iDayNo = 0; // start from the oldest date (start date) |
91 | char szSymbol[cSYMBOL_len + 1]; |
92 | |
93 | // Create symbol only once. |
94 | // |
95 | m_SecurityFile.CreateSymbol(m_iLastRowNumber, szSymbol, static_cast<int>(sizeof(szSymbol))); |
96 | |
97 | for (i = 0; i < m_iDailyMarketTotalRows; ++i) { |
98 | // copy the symbol |
99 | strncpy(m_row.m_daily_market[i].DM_S_SYMB, szSymbol, sizeof(m_row.m_daily_market[i].DM_S_SYMB)); |
100 | |
101 | // generate trade date |
102 | m_row.m_daily_market[i].DM_DATE = m_StartFromDate; |
103 | m_row.m_daily_market[i].DM_DATE.Add(iDayNo, 0); |
104 | |
105 | // generate prices |
106 | m_row.m_daily_market[i].DM_CLOSE = |
107 | m_rnd.RndDoubleIncrRange(fDailyMarketCloseMin, fDailyMarketCloseMax, 0.01); |
108 | m_row.m_daily_market[i].DM_HIGH = m_row.m_daily_market[i].DM_CLOSE * fDailyMarketHighRelativeToClose; |
109 | m_row.m_daily_market[i].DM_LOW = m_row.m_daily_market[i].DM_CLOSE * fDailyMarketLowRelativeToClose; |
110 | |
111 | // generate volume |
112 | m_row.m_daily_market[i].DM_VOL = m_rnd.RndInt64Range(iDailyMarketVolumeMin, iDailyMarketVolumeMax); |
113 | |
114 | ++iDayNo; // go one day forward for the next row |
115 | |
116 | if ((iDayNo % DaysPerWeek) == DaysPerWorkWeek) |
117 | iDayNo += 2; // skip weekend |
118 | } |
119 | } |
120 | |
121 | /* |
122 | * Reset the state for the next load unit. |
123 | * |
124 | * PARAMETERS: |
125 | * none. |
126 | * |
127 | * RETURNS: |
128 | * none. |
129 | */ |
130 | void InitNextLoadUnit() { |
131 | m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault, (RNGSEED)m_iLastRowNumber * iRNGSkipOneRowDailyMarket)); |
132 | |
133 | ClearRecord(); // this is needed for EGenTest to work |
134 | } |
135 | |
136 | public: |
137 | /* |
138 | * Constructor. |
139 | */ |
140 | CDailyMarketTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer) |
141 | : TableTemplate<DAILY_MARKET_GEN_ROW>(), m_SecurityFile(dfm.SecurityFile()), |
142 | m_iDailyMarketTotalRows(sizeof(m_row.m_daily_market) / sizeof(m_row.m_daily_market[0])), |
143 | m_iRowsGeneratedPerSecurity(sizeof(m_row.m_daily_market) / sizeof(m_row.m_daily_market[0])), |
144 | m_bMoreSecurities(true) // initialize once |
145 | { |
146 | // Set DAILY_MARKET start date to Jan 03, 2000. |
147 | // |
148 | m_StartFromDate.Set(iDailyMarketBaseYear, iDailyMarketBaseMonth, iDailyMarketBaseDay, iDailyMarketBaseHour, |
149 | iDailyMarketBaseMinute, iDailyMarketBaseSecond, iDailyMarketBaseMsec); |
150 | |
151 | m_bMoreRecords = true; // initialize once |
152 | |
153 | m_iSecurityCount = m_SecurityFile.CalculateSecurityCount(iCustomerCount); |
154 | m_iStartFromSecurity = m_SecurityFile.CalculateStartFromSecurity(iStartFromCustomer); |
155 | |
156 | m_iSecurityCountForOneLoadUnit = m_SecurityFile.CalculateSecurityCount(iDefaultLoadUnitSize); |
157 | |
158 | m_iLastRowNumber = m_iStartFromSecurity; |
159 | }; |
160 | |
161 | bool GenerateNextRecord() { |
162 | ++m_iRowsGeneratedPerSecurity; |
163 | |
164 | if (m_iRowsGeneratedPerSecurity >= m_iDailyMarketTotalRows) { |
165 | if (m_bMoreSecurities) { |
166 | // Reset RNG at Load Unit boundary, so that all data is |
167 | // repeatable. |
168 | // |
169 | if (m_iLastRowNumber % m_iSecurityCountForOneLoadUnit == 0) { |
170 | InitNextLoadUnit(); |
171 | } |
172 | |
173 | GenerateDailyMarketRows(); // generate all rows for the current |
174 | // security |
175 | |
176 | ++m_iLastRowNumber; |
177 | |
178 | // Update state info |
179 | m_bMoreSecurities = m_iLastRowNumber < (m_iStartFromSecurity + m_iSecurityCount); |
180 | |
181 | m_iRowsGeneratedPerSecurity = 0; |
182 | } |
183 | } |
184 | |
185 | // Return false when generated the last row of the last security |
186 | if (!m_bMoreSecurities && (m_iRowsGeneratedPerSecurity == m_iDailyMarketTotalRows - 1)) { |
187 | m_bMoreRecords = false; |
188 | } |
189 | |
190 | return (MoreRecords()); |
191 | } |
192 | |
193 | const DAILY_MARKET_ROW &GetRow() { |
194 | return m_row.m_daily_market[m_iRowsGeneratedPerSecurity]; |
195 | } |
196 | }; |
197 | |
198 | } // namespace TPCE |
199 | |
200 | #endif // DAILY_MARKET_TABLE_H |
201 | |