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, Cecil Reames, Matt Emmerton, Doug Johnson
35 */
36
37/*
38 * Class representing the Financial table.
39 */
40#ifndef FINANCIAL_TABLE_H
41#define FINANCIAL_TABLE_H
42
43#include "EGenTables_common.h"
44#include "CompanyTable.h"
45#include "utilities/Money.h"
46
47#include "input/DataFileManager.h"
48
49namespace TPCE {
50
51const int iYearsForFins = 5;
52const int iQuartersInYear = 4;
53const int iFinsPerCompany = iYearsForFins * iQuartersInYear; // 5 years of 4 quaters each year
54
55// multiplier to get the diluted number of shares from outstanding
56const double fDilutedSharesMultiplier = 1.1;
57
58// Multipliers for previous quarter to get the current quarter data
59const double fFinDataDownMult = 0.9;
60const double fFinDataUpMult = 1.15;
61const double fFinDataIncr = 0.00000000000001;
62
63const double fFinancialRevenueMin = 100000.00;
64const double fFinancialRevenueMax = 16000000000.00;
65
66const double fFinancialEarningsMin = -300000000.00;
67const double fFinancialEarningsMax = 3000000000.00;
68
69const INT64 iFinancialOutBasicMin = 400000;
70const INT64 iFinancialOutBasicMax = INT64_CONST(9500000000);
71
72const double fFinancialInventMin = 0.00;
73const double fFinancialInventMax = 2000000000.00;
74
75const double fFinancialAssetsMin = 100000.00;
76const double fFinancialAssetsMax = 65000000000.00;
77
78const double fFinancialLiabMin = 100000.00;
79const double fFinancialLiabMax = 35000000000.00;
80
81// Number of RNG calls to skip for one row in order
82// to not use any of the random values from the previous row.
83//
84const int iRNGSkipOneRowFinancial = 6 + iFinsPerCompany * 6;
85
86typedef struct FINANCIAL_GEN_ROW {
87 FINANCIAL_ROW m_financials[iFinsPerCompany];
88} * PFINANCIAL_GEN_ROW;
89
90class CFinancialTable : public TableTemplate<FINANCIAL_GEN_ROW> {
91 CCompanyTable m_CompanyTable;
92 int m_iFinYear; // first year to generate financials
93 int m_iFinQuarter; // first quarter to generate financials (0-based)
94 // Number of times GenerateNextRecord() was called for the current company
95 // data. Needed to decide when to generate next company's data.
96 int m_iRowsGeneratedPerCompany;
97 // Stores whether there is another company(s) for which to
98 // generate financial data.
99 bool m_bMoreCompanies;
100 TIdent m_iFinancialCountForOneLoadUnit;
101
102 //
103 // Generate the financial data for the next company.
104 //
105 // Return whether there are more companies to generate data for.
106 //
107 bool GenerateFinancialRows() {
108 TIdent FI_CO_ID;
109 int iFinYear, iFinQuarter;
110 int i;
111 CMoney fRev, fEarn, fInvent, fAssets, fLiab, fBasicEPS, fDilutEPS, fMargin;
112 INT64 iOutBasic, iOutDilut;
113
114 // Set starting values for financial values
115 FI_CO_ID = m_CompanyTable.GetCurrentCO_ID();
116 iFinYear = m_iFinYear;
117 iFinQuarter = m_iFinQuarter;
118
119 fRev = m_rnd.RndDoubleIncrRange(fFinancialRevenueMin, fFinancialRevenueMax, 0.01);
120 fEarn = m_rnd.RndDoubleIncrRange(
121 fFinancialEarningsMin, fRev < fFinancialEarningsMax ? fRev.DollarAmount() : fFinancialEarningsMax, 0.01);
122 iOutBasic = m_rnd.RndInt64Range(iFinancialOutBasicMin, iFinancialOutBasicMax);
123 iOutDilut = 0;
124 fInvent = m_rnd.RndDoubleIncrRange(fFinancialInventMin, fFinancialInventMax, 0.01);
125 fAssets = m_rnd.RndDoubleIncrRange(fFinancialAssetsMin, fFinancialAssetsMax, 0.01);
126 fLiab = m_rnd.RndDoubleIncrRange(fFinancialLiabMin, fFinancialLiabMax, 0.01);
127 fBasicEPS = 0.00;
128 fDilutEPS = 0.00;
129 fMargin = 0.00;
130
131 for (i = 0; i < iFinsPerCompany; ++i) {
132 // Compute values for this quarter
133 fRev = fRev * m_rnd.RndDoubleIncrRange(fFinDataDownMult, fFinDataUpMult, fFinDataIncr);
134 fEarn = fEarn * m_rnd.RndDoubleIncrRange(fFinDataDownMult, fFinDataUpMult, fFinDataIncr);
135 if (fEarn >= fRev) { // earnings cannot be greater than the revenue
136 fEarn = fEarn * fFinDataDownMult;
137 }
138 iOutBasic =
139 (INT64)((double)iOutBasic * m_rnd.RndDoubleIncrRange(fFinDataDownMult, fFinDataUpMult, fFinDataIncr));
140 iOutDilut = (INT64)((double)iOutBasic * fDilutedSharesMultiplier);
141 fInvent = fInvent * m_rnd.RndDoubleIncrRange(fFinDataDownMult, fFinDataUpMult, fFinDataIncr);
142 fAssets = fAssets * m_rnd.RndDoubleIncrRange(fFinDataDownMult, fFinDataUpMult, fFinDataIncr);
143 fLiab = fLiab * m_rnd.RndDoubleIncrRange(fFinDataDownMult, fFinDataUpMult, fFinDataIncr);
144 fBasicEPS = fEarn / (double)iOutBasic;
145 fDilutEPS = fEarn / (double)iOutDilut;
146 fMargin = fEarn / fRev.DollarAmount();
147
148 // Assign values for this quarter
149 m_row.m_financials[i].FI_CO_ID = FI_CO_ID;
150 m_row.m_financials[i].FI_YEAR = iFinYear;
151 m_row.m_financials[i].FI_QTR = iFinQuarter + 1;
152 m_row.m_financials[i].FI_QTR_START_DATE.Set(iFinYear, iFinQuarter * 3 + 1, 1);
153 m_row.m_financials[i].FI_REVENUE = fRev.DollarAmount();
154 m_row.m_financials[i].FI_NET_EARN = fEarn.DollarAmount();
155 m_row.m_financials[i].FI_OUT_BASIC = iOutBasic;
156 m_row.m_financials[i].FI_OUT_DILUT = iOutDilut;
157 m_row.m_financials[i].FI_INVENTORY = fInvent.DollarAmount();
158 m_row.m_financials[i].FI_ASSETS = fAssets.DollarAmount();
159 m_row.m_financials[i].FI_LIABILITY = fLiab.DollarAmount();
160 m_row.m_financials[i].FI_BASIC_EPS = fBasicEPS.DollarAmount();
161 m_row.m_financials[i].FI_DILUT_EPS = fDilutEPS.DollarAmount();
162 m_row.m_financials[i].FI_MARGIN = fMargin.DollarAmount();
163
164 // Increment quarter
165 iFinQuarter++;
166 if (iFinQuarter == iQuartersInYear) { // reached the last quarter in the year
167 iFinQuarter = 0; // start from the first quarter
168 ++iFinYear; // increment year
169 }
170 }
171
172 return m_CompanyTable.GenerateNextCO_ID();
173 }
174
175 /*
176 * Reset the state for the next load unit.
177 *
178 * PARAMETERS:
179 * none.
180 *
181 * RETURNS:
182 * none.
183 */
184 void InitNextLoadUnit() {
185 m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault, (RNGSEED)m_iLastRowNumber * iRNGSkipOneRowFinancial));
186
187 ClearRecord(); // this is needed for EGenTest to work
188 }
189
190public:
191 CFinancialTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer)
192 : TableTemplate<FINANCIAL_GEN_ROW>(), m_CompanyTable(dfm, iCustomerCount, iStartFromCustomer),
193 m_iRowsGeneratedPerCompany(iFinsPerCompany), m_bMoreCompanies(true) {
194 // Start year to generate financials.
195 // Count by quaters
196 m_iFinYear = iDailyMarketBaseYear; // first financial year
197 m_iFinQuarter = iDailyMarketBaseMonth / 3; // first financial quarter in the year (0-based)
198
199 m_bMoreRecords = true; // initialize once
200
201 m_iFinancialCountForOneLoadUnit =
202 dfm.CompanyFile().CalculateCompanyCount(iDefaultLoadUnitSize) * iFinsPerCompany;
203
204 m_iLastRowNumber = dfm.CompanyFile().CalculateStartFromCompany(iStartFromCustomer) * iFinsPerCompany;
205 };
206
207 bool GenerateNextRecord() {
208 // Reset RNG at Load Unit boundary, so that all data is repeatable.
209 //
210 if (m_iLastRowNumber % m_iFinancialCountForOneLoadUnit == 0) {
211 InitNextLoadUnit();
212 }
213
214 ++m_iLastRowNumber;
215
216 ++m_iRowsGeneratedPerCompany;
217
218 if (m_iRowsGeneratedPerCompany >= iFinsPerCompany) {
219 if (m_bMoreCompanies) {
220 // All rows for the current company have been returned
221 // therefore move on to the next company
222 m_bMoreCompanies = GenerateFinancialRows();
223
224 m_iRowsGeneratedPerCompany = 0;
225 }
226 }
227
228 // Return false when generated the last row of the last company
229 if (!m_bMoreCompanies && (m_iRowsGeneratedPerCompany == iFinsPerCompany - 1)) {
230 m_bMoreRecords = false;
231 }
232
233 return MoreRecords();
234 }
235
236 const FINANCIAL_ROW &GetRow() {
237 return m_row.m_financials[m_iRowsGeneratedPerCompany];
238 }
239};
240
241} // namespace TPCE
242
243#endif // FINANCIAL_TABLE_H
244