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
49namespace TPCE {
50
51const INT64 iS_NUM_OUTMin = INT64_CONST(4000000);
52const INT64 iS_NUM_OUTMax = INT64_CONST(9500000000);
53
54const double fS_PEMin = 1.0;
55const double fS_PEMax = 120.0;
56
57const double fS_DIVIDNonZeroMin = 0.01;
58const double fS_DIVIDMax = 10.0;
59
60const double fS_YIELDNonZeroMin = 0.01;
61const double fS_YIELDMax = 120.0;
62
63const int iWeeksPerYear = 52;
64const int iDaysPerWeek = 7;
65
66const int iPercentCompaniesWithNonZeroDividend = 60;
67
68const int iRNGSkipOneRowSecurity = 11; // number of RNG calls for one row
69
70class 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
140public:
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