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 | */ |
36 | |
37 | /* |
38 | * Class representing the securities table. |
39 | */ |
40 | #ifndef SECURITY_TABLE_H |
41 | #define SECURITY_TABLE_H |
42 | |
43 | #include <stdio.h> // for snprintf which is not part of the C++ headers |
44 | #include "EGenTables_common.h" |
45 | #include "SecurityPriceRange.h" |
46 | |
47 | #include "input/DataFileManager.h" |
48 | |
49 | namespace TPCE { |
50 | |
51 | const INT64 iS_NUM_OUTMin = INT64_CONST(4000000); |
52 | const INT64 iS_NUM_OUTMax = INT64_CONST(9500000000); |
53 | |
54 | const double fS_PEMin = 1.0; |
55 | const double fS_PEMax = 120.0; |
56 | |
57 | const double fS_DIVIDNonZeroMin = 0.01; |
58 | const double fS_DIVIDMax = 10.0; |
59 | |
60 | const double fS_YIELDNonZeroMin = 0.01; |
61 | const double fS_YIELDMax = 120.0; |
62 | |
63 | const int iWeeksPerYear = 52; |
64 | const int iDaysPerWeek = 7; |
65 | |
66 | const int iPercentCompaniesWithNonZeroDividend = 60; |
67 | |
68 | const int iRNGSkipOneRowSecurity = 11; // number of RNG calls for one row |
69 | |
70 | class CSecurityTable : public TableTemplate<SECURITY_ROW> { |
71 | TIdent m_iSecurityCount; |
72 | TIdent m_iStartFromSecurity; |
73 | const CCompanyFile &m_CompanyFile; |
74 | const CSecurityFile &m_SecurityFile; |
75 | CDateTime m_date; |
76 | int m_iCurrentDayNo; |
77 | int m_iJan1_1900DayNo; |
78 | int m_iJan2_2000DayNo; |
79 | TIdent m_iSecurityCountForOneLoadUnit; |
80 | |
81 | /* |
82 | * SECURITY table row generation |
83 | */ |
84 | void GenerateSecurityRow() { |
85 | int iStartDayNo, iExchangeDayNo, i52HighDayNo, i52LowDayNo; |
86 | |
87 | strncpy(m_row.S_ST_ID, m_SecurityFile.GetRecord(m_iLastRowNumber).S_ST_ID_CSTR(), sizeof(m_row.S_ST_ID)); |
88 | strncpy(m_row.S_ISSUE, m_SecurityFile.GetRecord(m_iLastRowNumber).S_ISSUE_CSTR(), sizeof(m_row.S_ISSUE)); |
89 | |
90 | CreateName(m_iLastRowNumber, m_row.S_NAME, static_cast<int>(sizeof(m_row.S_NAME))); |
91 | |
92 | m_SecurityFile.CreateSymbol(m_iLastRowNumber, m_row.S_SYMB, static_cast<int>(sizeof(m_row.S_SYMB))); |
93 | strncpy(m_row.S_EX_ID, m_SecurityFile.GetRecord(m_iLastRowNumber).S_EX_ID_CSTR(), sizeof(m_row.S_EX_ID)); |
94 | m_row.S_CO_ID = m_SecurityFile.GetCompanyId(m_iLastRowNumber); |
95 | m_row.S_NUM_OUT = m_rnd.RndInt64Range(iS_NUM_OUTMin, iS_NUM_OUTMax); |
96 | |
97 | iStartDayNo = m_rnd.RndIntRange(m_iJan1_1900DayNo, m_iJan2_2000DayNo); // generate random date |
98 | m_row.S_START_DATE.Set(iStartDayNo); |
99 | iExchangeDayNo = m_rnd.RndIntRange(iStartDayNo, m_iJan2_2000DayNo); |
100 | m_row.S_EXCH_DATE.Set(iExchangeDayNo); |
101 | m_row.S_PE = m_rnd.RndDoubleIncrRange(fS_PEMin, fS_PEMax, 0.01); |
102 | // iExchangeDayNo contains S_EXCH_DATE date in days. |
103 | |
104 | // 52 week high - selected from upper half of security price range |
105 | m_row.S_52WK_HIGH = |
106 | (float)m_rnd.RndDoubleIncrRange(fMinSecPrice + ((fMaxSecPrice - fMinSecPrice) / 2), fMaxSecPrice, 0.01); |
107 | i52HighDayNo = m_rnd.RndIntRange(m_iCurrentDayNo - iDaysPerWeek * iWeeksPerYear, m_iCurrentDayNo); |
108 | m_row.S_52WK_HIGH_DATE.Set(i52HighDayNo); |
109 | |
110 | // 52 week low - selected from the minimum security price up to the 52wk |
111 | // high |
112 | m_row.S_52WK_LOW = (float)m_rnd.RndDoubleIncrRange(fMinSecPrice, m_row.S_52WK_HIGH, 0.01); |
113 | i52LowDayNo = m_rnd.RndIntRange(m_iCurrentDayNo - iDaysPerWeek * iWeeksPerYear, m_iCurrentDayNo); |
114 | m_row.S_52WK_LOW_DATE.Set(i52LowDayNo); |
115 | |
116 | if (m_rnd.RndPercent(iPercentCompaniesWithNonZeroDividend)) { |
117 | m_row.S_YIELD = m_rnd.RndDoubleIncrRange(fS_YIELDNonZeroMin, fS_YIELDMax, 0.01); |
118 | m_row.S_DIVIDEND = m_rnd.RndDoubleIncrRange((m_row.S_YIELD * 0.20), (m_row.S_YIELD * 0.30), 0.01); |
119 | } else { |
120 | m_row.S_DIVIDEND = 0.0; |
121 | m_row.S_YIELD = 0.0; |
122 | } |
123 | } |
124 | |
125 | /* |
126 | * Reset the state for the next load unit. |
127 | * |
128 | * PARAMETERS: |
129 | * none. |
130 | * |
131 | * RETURNS: |
132 | * none. |
133 | */ |
134 | void InitNextLoadUnit() { |
135 | m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault, (RNGSEED)m_iLastRowNumber * iRNGSkipOneRowSecurity)); |
136 | |
137 | ClearRecord(); // this is needed for EGenTest to work |
138 | } |
139 | |
140 | public: |
141 | CSecurityTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer) |
142 | : TableTemplate<SECURITY_ROW>(), m_CompanyFile(dfm.CompanyFile()), m_SecurityFile(dfm.SecurityFile()) { |
143 | m_iCurrentDayNo = CDateTime::YMDtoDayno(InitialTradePopulationBaseYear, InitialTradePopulationBaseMonth, |
144 | InitialTradePopulationBaseDay); // last initial trading date |
145 | m_iJan1_1900DayNo = CDateTime::YMDtoDayno(1900, 1, 1); // find out number of days for Jan-1-1900 |
146 | m_iJan2_2000DayNo = CDateTime::YMDtoDayno(2000, 1, 2); // find out number of days for Jan-2-2000 |
147 | |
148 | m_iSecurityCount = m_SecurityFile.CalculateSecurityCount(iCustomerCount); |
149 | m_iStartFromSecurity = m_SecurityFile.CalculateStartFromSecurity(iStartFromCustomer); |
150 | |
151 | m_iSecurityCountForOneLoadUnit = m_SecurityFile.CalculateSecurityCount(iDefaultLoadUnitSize); |
152 | |
153 | m_iLastRowNumber = m_iStartFromSecurity; |
154 | }; |
155 | |
156 | bool GenerateNextRecord() { |
157 | // Reset RNG at Load Unit boundary, so that all data is repeatable. |
158 | // |
159 | if (m_iLastRowNumber % m_iSecurityCountForOneLoadUnit == 0) { |
160 | InitNextLoadUnit(); |
161 | } |
162 | |
163 | GenerateSecurityRow(); |
164 | |
165 | ++m_iLastRowNumber; |
166 | |
167 | // Update state info |
168 | m_bMoreRecords = m_iLastRowNumber < (m_iStartFromSecurity + m_iSecurityCount); |
169 | |
170 | return (MoreRecords()); |
171 | } |
172 | |
173 | void CreateName(TIdent iIndex, // row number |
174 | char *szOutput, // output buffer |
175 | size_t iOutputLen) // size of the output buffer (including null) |
176 | { |
177 | char CompanyName[cCO_NAME_len + 1]; |
178 | |
179 | m_CompanyFile.CreateName(m_SecurityFile.GetCompanyIndex(iIndex), CompanyName, |
180 | static_cast<int>(sizeof(CompanyName))); |
181 | snprintf(szOutput, iOutputLen, "%s of %s" , m_SecurityFile.GetRecord(iIndex).S_ISSUE_CSTR(), CompanyName); |
182 | } |
183 | }; |
184 | |
185 | } // namespace TPCE |
186 | |
187 | #endif // SECURITY_TABLE_H |
188 | |