Bug fixes for alias&join. Add test in presentation.

This commit is contained in:
2022-09-20 02:21:49 +08:00
parent 2614d010da
commit ff63be720c
24 changed files with 1135 additions and 146 deletions
+41
View File
@@ -0,0 +1,41 @@
-- please run datagen.get_stock_data() to generate data/stock.csv first
-- create table ticks(ID varchar(10), timestamp int, tradeDate date, price int);
-- LOAD DATA INFILE "data/stock.csv"
-- INTO TABLE ticks
-- FIELDS TERMINATED BY ","
-- SELECT max(price-mins(price))
-- FROM ticks ASSUMING ASC timestamp
-- WHERE ID="S"
-- AND tradeDate='2003-01-10'
-- create table base(ID varchar(10), name varchar(10));
-- LOAD DATA INFILE "data/base.csv"
-- INTO TABLE base
-- FIELDS TERMINATED BY ","
-- SELECT last(price)
-- FROM ticks t, base b
-- ASSUMING ASC name, ASC timestamp
-- WHERE t.ID=b.ID
-- AND name="x"
create table TradedStocks(ID varchar(15), SeqNo int, TradeDate date, TimeStamp time, Type varchar(5));
create table HistoricQuotes(ID varchar(15), TradeDate date, HighPrice real, LowPrice real, ClosePrice real, OpenPrice real, volume bigint);
LOAD DATA INFILE "data/tick-price-file.csv"
INTO TABLE TradedStocks
FIELDS TERMINATED BY "|"
LOAD DATA INFILE "data/hist-price-file.csv"
INTO TABLE HistoricQuotes
FIELDS TERMINATED BY "|"
SELECT ts.ID, avgs(10, hq.ClosePrice)
FROM TradedStocks AS ts NATURAL JOIN
HistoricQuotes AS hq
ASSUMING ASC hq.TradeDate
GROUP BY ts.ID
+26
View File
@@ -0,0 +1,26 @@
There are 2 programs included in this package:
1. histgen - generation program for historical data
2. tickgen - generation program for tick data
histgen takes 2 parameters
a) Scale-factor: Number of securities for which data is to be generated
b) Depth of history: The number of days for which data is to be generated
and genertes 2 files
a) hist-base-file: contains all the static data
b) hist-price-file: contains the pricing info
c) hist-split-file: contains the split info
tickgen also takes 2 parameters
a) Scale-factor: Number of securities for which data is to be generated
b) Ticks per day: A measure of the activity on a per security basis. e.g 100 would mean
that each security ticks about 100 time in a trading day
and generates 2 files
a) tick-base-file
b) tick-price-file
run the programs without args to see the parameters required.
------------------
Make of programs:
run the make program. It requires the C++ compiler (CC) to be in your path.
+61
View File
@@ -0,0 +1,61 @@
// cmvc_id = %Z% %W% %I% %E% %U%
#ifndef RandGenHEADER
#define RandGenHEADER
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997 Morgan Stanley & Co. Incorporated, All Rights Reserved
//
// Unpublished copyright. All rights reserved. This material contains
// proprietary information that shall be used or copied only within Morgan
// Stanley, except with written permission of Morgan Stanley.
//
// Module Name : RandGen.H
// Version : %Z% %W% %I% %E% %U%
// Project : DataGen
// Description : Random Number generator
//
///////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <iostream>
#include <sys/time.h>
using namespace std;
class RandNumGen
{
public:
RandNumGen(void)
{
struct timeval tv;
gettimeofday(&tv,0 );
srand(tv.tv_sec + tv.tv_usec);
}
RandNumGen(unsigned long seed_)
{
srand(seed_);
}
~RandNumGen(){}
inline unsigned long operator() (void);
inline int operator() (int min_, int max_);
};
// Implementation of inline functions
inline unsigned long RandNumGen::operator() (void)
{
return rand();
}
inline int RandNumGen::operator() (int min_, int max_)
{
unsigned long t = (*this)();
int r = max_ - min_;
return (min_ + t % r);
}
#endif
+71
View File
@@ -0,0 +1,71 @@
// cmvc_id = %Z% %W% %I% %E% %U%
#ifndef TimeIMPLEMENTATION
#define TimeIMPLEMENTATION
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997 Morgan Stanley & Co. Incorporated, All Rights Reserved
//
// Unpublished copyright. All rights reserved. This material contains
// proprietary information that shall be used or copied only within Morgan
// Stanley, except with written permission of Morgan Stanley.
//
// Module Name : Time.C
// Version : %Z% %W% %I% %E% %U%
// Project :
// Description :
//
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "Time.H"
Time::Time(char *startTime_)
{
sscanf(startTime_,"%d:%d:%d", &_hrs, &_mins, &_secs);
cout << "Hrs: " << _hrs << ",Mins: " << _mins << ",Secs: " << _secs << endl;
}
Time::~Time()
{}
Time &Time::operator++ (int)
{
_secs++;
adjust();
return *this;
}
void Time::adjust(void)
{
if (_secs >= 60)
{
_mins += _secs/60;
_secs = _secs%60;
}
if (_mins >= 60)
{
_hrs += _mins/60;
_mins = _mins%60;
}
if (_hrs >= 24) _hrs = _hrs = _hrs%24;
}
ostream &operator<< (ostream &os_, Time &that_)
{
if (that_.hrs() < 10) os_ << "0";
os_ << that_.hrs();
os_ << ":" ;
if (that_.mins() < 10) os_ << "0";
os_ << that_.mins();
os_ << ":" ;
if (that_.secs() < 10) os_ << "0";
os_ << that_.secs();
return os_;
}
#endif
+43
View File
@@ -0,0 +1,43 @@
// cmvc_id = %Z% %W% %I% %E% %U%
#ifndef TimeHEADER
#define TimeHEADER
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997 Morgan Stanley & Co. Incorporated, All Rights Reserved
//
// Unpublished copyright. All rights reserved. This material contains
// proprietary information that shall be used or copied only within Morgan
// Stanley, except with written permission of Morgan Stanley.
//
// Module Name : Time.H
// Version : %Z% %W% %I% %E% %U%
// Project :
// Description :
//
///////////////////////////////////////////////////////////////////////////////
#include <iostream>
using namespace std;
class Time
{
public:
Time(char *startTime_);
~Time();
Time &operator++(int);
void adjust(void);
int hrs(void) { return _hrs; }
int mins(void) { return _mins; }
int secs(void) { return _secs; }
friend ostream &operator<< (ostream &os_, Time &that_);
private:
int _hrs, _mins, _secs;
};
#endif
+79
View File
@@ -0,0 +1,79 @@
#include <sys/types.h>
#include <time.h>
#include <iostream>
#include "cal.H"
using namespace std;
Calendar::Calendar(void)
{
time_t clk = time(0);
struct tm *now = localtime(&clk);
_currdate = asJulianNumber(now->tm_mon+1, now->tm_mday, now->tm_year+1900);
}
Calendar::~Calendar()
{}
// year_ in yyyy format
unsigned int Calendar::asJulianNumber(int month_,int day_,int year_)
{
unsigned long c,ya;
if (month_>2) month_-=3;
else { month_+=9; year_--; }
c=year_/100;
ya=year_-100*c;
return ((146097*c)>>2)+((1461*ya)>>2)+(153*month_+2)/5+day_+1721119;
}
void Calendar::split(int& month_,int& day_,int& year_)
{
unsigned long d;
unsigned long j=_currdate-1721119;
year_=(int) (((j<<2)-1)/146097);
j=(j<<2)-1-146097*year_;
d=(j>>2);
j=((d<<2)+3)/1461;
d=(d<<2)+3-1461*j;
d=(d+4)>>2;
month_=(int)(5*d-3)/153;
d=5*d-3-153*month_;
day_=(int)((d+5)/5);
year_=(int)(100*year_+j);
if (month_<10) month_+=3;
else { month_-=9; year_++; }
}
int Calendar::dayInWeek(void)
{
return ((((_currdate+1)%7)+6)%7)+1;
}
Calendar &Calendar::nextWeekday(void)
{
(*this) += 1;
while (!isWeekday()) (*this)+= 1;
return *this;
}
int Calendar::isWeekday(void)
{
return (dayInWeek()<6)?1:0;
}
Calendar &Calendar::operator+= (int incr_)
{
_currdate += incr_;
return *this;
}
ostream &operator<< (ostream &os_, Calendar &that_)
{
int mo, day, year;
that_.split(mo,day,year);
os_ << year << "-" << mo << "-" << day;
// the below is a pain for monetdb
//os_ << mo << "/" << day << "/" << year;
return os_;
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef _CAL_H_
#define _CAL_H_
#include <iostream>
using namespace std;
class Calendar
{
public:
Calendar(void);
~Calendar();
unsigned int asJulianNumber(int month_, int day_, int year_);
int isWeekday(void);
Calendar &operator+= (int incr_);
friend ostream &operator<< (ostream &os_,Calendar &that_);
int dayInWeek(void);
Calendar &nextWeekday(void);
void split(int &mo_, int &day_, int &year_);
private:
unsigned int _currdate;
};
#endif
+76
View File
@@ -0,0 +1,76 @@
#include <sys/types.h>
#include <time.h>
#include <iostream>
#include "cal.H"
Calendar::Calendar(void)
{
time_t clk = time(0);
struct tm *now = localtime(&clk);
_currdate = asJulianNumber(now->tm_mon+1, now->tm_mday, now->tm_year+1900);
}
Calendar::~Calendar()
{}
// year_ in yyyy format
unsigned int Calendar::asJulianNumber(int month_,int day_,int year_)
{
unsigned long c,ya;
if (month_>2) month_-=3;
else { month_+=9; year_--; }
c=year_/100;
ya=year_-100*c;
return ((146097*c)>>2)+((1461*ya)>>2)+(153*month_+2)/5+day_+1721119;
}
void Calendar::split(int& month_,int& day_,int& year_)
{
unsigned long d;
unsigned long j=_currdate-1721119;
year_=(int) (((j<<2)-1)/146097);
j=(j<<2)-1-146097*year_;
d=(j>>2);
j=((d<<2)+3)/1461;
d=(d<<2)+3-1461*j;
d=(d+4)>>2;
month_=(int)(5*d-3)/153;
d=5*d-3-153*month_;
day_=(int)((d+5)/5);
year_=(int)(100*year_+j);
if (month_<10) month_+=3;
else { month_-=9; year_++; }
}
int Calendar::dayInWeek(void)
{
return ((((_currdate+1)%7)+6)%7)+1;
}
Calendar &Calendar::nextWeekday(void)
{
(*this) += 1;
while (!isWeekday()) (*this)+= 1;
return *this;
}
int Calendar::isWeekday(void)
{
return (dayInWeek()<6)?1:0;
}
Calendar &Calendar::operator+= (int incr_)
{
_currdate += incr_;
return *this;
}
ostream &operator<< (ostream &os_, Calendar &that_)
{
int mo, day, year;
that_.split(mo,day,year);
os_ << mo << "/" << day << "/" << year;
return os_;
}
+58
View File
@@ -0,0 +1,58 @@
// cmvc_id = %Z% %W% %I% %E% %U%
#ifndef genIMPLEMENTATION
#define genIMPLEMENTATION
#include <iostream.h>
#include "RandGen.H"
int num[6];
int nelems=0;
int member(int a_)
{
for (int i=0; i<nelems; i++)
{
if (num[i] == a_) return 1;
}
return 0;
}
int gen(int flag_)
{
RandNumGen rg;
if (flag_ == 0)
{
for (int i=0;i<6;i++) num[i] = 0;
nelems=0;
return 0;
}
int rn;
while (1)
{
rn = rg(1,52);
if (member(rn) == 0) break;
}
num[nelems++] = rn;
return rn;
}
int main(int ac, char *av[])
{
if (ac < 2)
{
cerr << "Usage: " << av[0] << " <number>" << endl;
return 1;
}
int k = atoi(av[1]);
for(int i=0; i<k; i++)
{
gen(0);
for (int j=0;j<6;j++) cout << gen(1) << " ";
cout << endl;
}
}
#endif
+198
View File
@@ -0,0 +1,198 @@
// cmvc_id = %Z% %W% %I% %E% %U%
#ifndef histgenIMPLEMENTATION
#define histgenIMPLEMENTATION
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sys/time.h>
#include "RandGen.H"
#include "cal.H"
using namespace std;
inline int max(int a, int b)
{
return (a>b)?a:b;
}
inline int min(int a, int b)
{
return (a<b)?a:b;
}
int main(int ac, char *av[])
{
RandNumGen rg;
int i, j, d, k;
ofstream basefile("../../data/hist-base-file.csv");
ofstream pricefile("../../data/hist-price-file.csv");
ofstream splitfile("../../data/hist-split-file.csv");
ofstream dividendfile("../../data/hist-dividend-file.csv");
if (!basefile)
{
cerr << "Cannot open base-file" << endl;
return 1;
}
if (!pricefile)
{
cerr << "Cannot open price-file" << endl;
return 1;
}
if (!splitfile)
{
cerr << "Cannot open split-file" << endl;
return 1;
}
if (!dividendfile)
{
cerr << "Cannot open dividend-file" << endl;
return 1;
}
if (ac < 2)
{
cerr << "Usage: " << av[0] << " <scale - no of elements> [depth - in days. Default = 4000days]" << endl;
return 1;
}
int scale=0, ndays = 4000;
if (ac >= 2) scale = atoi(av[1]);
if (ac >= 3) ndays = atoi(av[2]);
// Generation of base info
int nex = 5;
char *ex[] = { "NY", "O", "AM", "LN", "TK"};
int nsic = 10;
char *sic[] = { "COMPUTERS", "CHEMICALS", "FINANCIAL", "INDUSTRIAL", "PHARMACEUTICALS",
"MEDICAL", "BANKING", "SOFTWARE", "ENTERTAINMENT", "CONSTRUCTION" };
char *cu[] = { "USD", "DEM", "JPY", "FFR", "GBP"};
int ncu = 5;
char *spr[] = { "AAA", "AA", "A", "BBB", "BB", "B", "CCC", "CC", "C"};
int nspr = 9;
unsigned int rnum;
char id[100];
char descr[256];
// the below is a pain with monetdb, changing to better date format
//char *crdate = "3/11/1999";
char *crdate = "1999-11-03";
basefile << "Id|Ex|Descr|SIC|SPR|Cu|CreateDate" << endl;
for (i=0; i<scale; i++)
{
sprintf(id,"Security_%d", i);
sprintf(descr, "'Financial security number: %d'", i);
basefile << id;
basefile << "|" << ex[rg(0,nex)];
basefile << "|" << descr;
basefile << "|" << sic[rg(0,nsic)];
basefile << "|" << spr[rg(0,nspr)];
basefile << "|" << cu[rg(0, ncu)];
basefile << "|" << crdate;
basefile << endl;
}
basefile.close();
// generation of price info
double *minop = new double[scale];
for (i=0; i<scale; i++) minop[i] = 0.0;
double *op = new double[scale];
for (i=0; i<scale; i++) op[i] = 0.0;
unsigned long *vs = new unsigned long[scale];
for (i=0; i<scale; i++) vs[i] = 0;
double cp, hp, lp;
Calendar cal;
pricefile << "Id|TradeDate|HighPrice|LowPrice|ClosePrice|OpenPrice|Volume" << endl;
splitfile << "Id|SplitDate|EntryDate|SplitFactor" << endl;
dividendfile << "Id|XdivDate|DivAmt|AnnounceDate" << endl;
for (d=0;d<ndays; d++)
{
cal.nextWeekday();
for (k=0;k<scale;k++)
{
sprintf(id,"Security_%d", k);
if (op[k]==0.0) op[k] = rg(0,100);
if (minop[k]==0.0) minop[k] = op[k];
if (vs[k]==0) vs[k] = rg();
else vs[k] = vs[k]*(100.0+rg(-10,+10))/100.0;
int skew = rg(0,+2);
double f = (100.0 + rg(-2,3+skew))/100.0;
cp = op[k] * f;
hp = max(op[k], cp) * (100.0+rg(0,+10))/100.0;
lp = min(op[k], cp) * (100.0-rg(0,+10))/100.0;
pricefile << id;
pricefile << "|" << cal;
pricefile << "|" << hp;
pricefile << "|" << lp;
pricefile << "|" << cp;
pricefile << "|" << op[k];
pricefile << "|" << vs[k];
pricefile << endl;
op[k] = cp;
// check splits
if (op[k] > 2.0*minop[k])
{
int splitfactor = rg(1,4);
op[k] /= (double)splitfactor;
vs[k] *= splitfactor;
splitfile << id;
splitfile << "|" << cal;
splitfile << "|" << cal;
splitfile << "|" << splitfactor;
splitfile << endl;
}
// check dividends
if (op[k] > minop[k])
{
// dividend as a fraction of current closing price
double dividend = (rg(1, 100) / 100.0) * cp;
dividendfile << id;
dividendfile << "|" << cal;
dividendfile << "|" << dividend;
// assumes announced and disbursed same day,
// queries can be trivially modified to do away with this assumption
dividendfile << "|" << cal;
dividendfile << endl;
}
}
}
splitfile.close();
pricefile.close();
dividendfile.close();
}
#endif
+20
View File
@@ -0,0 +1,20 @@
.PHONY: clean
all: histgen tickgen
clean:
rm -rf *.o histgen tickgen
%.o: %.C
g++-12 -Ofast -march=native -g -c $<
tickgen: cal.o Time.o tickgen.o
g++-12 -lstdc++ -Ofast -march=native -flto -o tickgen cal.o Time.o tickgen.o
histgen: cal.o histgen.o
g++-12 -lstdc++ -Ofast -flto -march=native -o histgen cal.o histgen.o
timetest: Time.o timetest.o
g++-12 -lstdc++ -g -o timetest Time.o timetest.o
+197
View File
@@ -0,0 +1,197 @@
// cmvc_id = %Z% %W% %I% %E% %U%
#ifndef histgenIMPLEMENTATION
#define histgenIMPLEMENTATION
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sys/time.h>
#include "RandGen.H"
#include "cal.H"
#include "Time.H"
using namespace std;
inline int max(int a, int b)
{
return (a>b)?a:b;
}
inline int min(int a, int b)
{
return (a<b)?a:b;
}
int main(int ac, char *av[])
{
RandNumGen rg;
int i, j, d, k;
ofstream basefile("../../data/tick-base-file.csv");
ofstream pricefile("../../data/tick-price-file.csv");
if (!basefile)
{
cerr << "Cannot open base-file" << endl;
return 1;
}
if (!pricefile)
{
cerr << "Cannot open price-file" << endl;
return 1;
}
if (ac < 2)
{
cerr << "Usage: " << av[0] << " <n -scale> [t -ticks per day.Default=100] [d - no of days.Default=90]" << endl;
return 1;
}
int n=0,t=100,days=90;
if (ac >= 2) n = atoi(av[1]);
if (ac >= 3) t = atoi(av[2]);
if (ac >= 4) days = atoi(av[3]);
int tps = (n*t)/28800; // ticks per second
tps++;
cout << "Ticks per second: " << tps << endl;
// Generation of base info
int nex = 5;
char *ex[] = { "NY", "O", "AM", "LN", "TK"};
int nsic = 10;
char *sic[] = { "COMPUTERS", "CHEMICALS", "FINANCIAL", "INDUSTRIAL", "PHARMACEUTICALS",
"MEDICAL", "BANKING", "SOFTWARE", "ENTERTAINMENT", "CONSTRUCTION" };
char *cu[] = { "USD", "DEM", "JPY", "FFR", "GBP"};
int ncu = 5;
char *spr[] = { "AAA", "AA", "A", "BBB", "BB", "B", "CCC", "CC", "C"};
int nspr = 9;
unsigned int rnum;
char id[100];
char descr[256];
char *crdate = "3/11/1999";
basefile << "Id | Ex | Descr | SIC | Cu" << endl;
for (i=0; i<n; i++)
{
sprintf(id,"Security_%d", i);
sprintf(descr, "'Financial security number: %d'", i);
basefile << id;
basefile << " | " << ex[rg(0,nex)];
basefile << " | " << descr;
basefile << " | " << sic[rg(0,nsic)];
basefile << " | " << cu[rg(0, ncu)];
basefile << endl;
}
basefile.close();
// generation of price info
double tick=1.0/32.0;
// 1. gen the starting price of each security
double *bp = new double[n];
int *seq = new int[n];
for (i=0;i<n;i++)
{
bp[i] = rg(0,100);
seq[i] = 0;
}
Calendar cal;
Time tm("9:00:00");
cal.nextWeekday();
pricefile << "Id | SeqNo | TradeDate | TimeStamp | Type" << endl;
for (k=0;k<days; k++)
{
// for each second of the business day - 8*60*60
for(i=0;i<28800;i++)
{
// generate the required ticks
for(j=0;j<tps;j++)
{
//1. select a security
int sec = rg(0,n);
sprintf(id, "Security_%d", sec);
//2. select if it is a trade, ask, bid
int tqb = rg(0,4);
switch (tqb)
{
case 0: // trade
{
double tp = bp[sec];
int ts = rg(1,100) * 100;
pricefile << id;
pricefile << "|" << ++seq[sec];
pricefile << "|" << cal;
pricefile << "|" << tm;
pricefile << "|T" << endl;
break;
}
case 1: // ask
{
double ap = rg(0,4)*tick+bp[sec];
int as = rg(1,100) * 100;
pricefile << id;
pricefile << "|" << ++seq[sec];
pricefile << "|" << cal;
pricefile << "|" << tm;
pricefile << "|Q" << endl;
break;
}
case 2: // bid
{
int dir = (rg(3,10) > 5)? +1:-1;
bp[sec] = (dir*rg(0,3)*tick)+bp[sec];
int bs = rg(1,100) * 100;
pricefile << id;
pricefile << "|" << ++seq[sec];
pricefile << "|" << cal;
pricefile << "|" << tm;
pricefile << "|Q" << endl;
break;
}
case 3: // cancel/correct as a trade
{
if (rg(0,100) < 5) break;
double tp = bp[sec];
int ts = rg(1,100) * 100;
pricefile << id;
pricefile << "|" << ++seq[sec];
pricefile << "|" << cal;
pricefile << "|" << tm;
pricefile << "|CT" << endl;
break;
}
default:
break;
}
}
// Go to the next second
tm++;
}
cal.nextWeekday();
}
pricefile.close();
}
#endif
+1
View File
@@ -30,3 +30,4 @@ SELECT price, timestamp FROM stocks where price - timestamp > 1 and not (price*t
SELECT max(price-mins(price))
FROM stocks
ASSUMING DESC timestamp