[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [system-traders] MetaStockReader?
Le Wed, Nov 12, 2003 at 12:11:59AM +0100, Pirani Enrico écrivait:
> Hi,
Hi,
> I would like to ask you if the metatstock.pm module works only in windows,
> or there is a way to comunicate with a Metastock db even under Linux ?.
Yes there is. The metastock.pm uses the program attached. It was
authored by Fabien Fulhaber.
Cheers,
--
Raphaël Hertzog -+- http://www.ouaza.com
Formation Linux et logiciel libre : http://www.logidee.com
Earn money with free software: http://www.geniustrader.org
/******************************************************************************/
/* */
/* MetaStock & Computrac Reader */
/* */
/* Copyright (c) 2001 Fabien Fulhaber. All Rights Reserved. */
/* */
/* MetaStock is a registered trademark of EQUIS International Inc. */
/* Computrac is a registered trademark of Dow Jones Telerate. */
/* */
/* Last-Modified : Mar Sep 04 18:25:22 CET 2001 */
/* */
/******************************************************************************/
/******************************************************************************/
/* MetaStockReader : INCLUDES */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdlib.h>
/******************************************************************************/
/* MetaStockReader : TYPEDEFS */
/******************************************************************************/
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
/******************************************************************************/
/* MetaStockReader : STRUCTS */
/******************************************************************************/
struct Master_file_header {
u_short num_files; // Number of files master contains
u_short file_num; // Highest F# to use
char zeroes[49]; // Nothing or copyright info
};
struct Master_file_record {
u_char file_num; // File number : F#
char file_type[2]; // CT file type = 0'e' (5 or 7 flds)
u_char rec_len; // Record length in bytes (4 x num_fields)
u_char num_fields; // Number of 4-byte fields in each record in the data file
char reserved1[2];
char issue_name[16]; // Issue name
char reserved2;
char CT_v2_8_flag; // If CT ver. 2.8, 'Y'; o.w., anything else
float first_date; // First date in yymmdd format
float last_date; // Last date in yymmdd format
char time_frame; // Time frame : I = Intraday D = Daily / W = Weekly / M = Monthly / Q = Quarterly / Y = Yearly
u_short ida_time; // Time interval, the time between trades in minute intervals, minimum 1 minute
char symbol[14]; // Symbol
char reserved3; // Reserved (must be a space)
char flag; // ' ' or '*' for autorun
char reserved4;
};
struct Master_file {
Master_file_header header;
Master_file_record record;
};
struct Data_file_header {
u_short max_recs;
u_short last_rec;
char zeroes[28];
};
struct Data_file_record {
float date;
float time;
float open;
float high;
float low;
float close;
float volume;
float op_int;
};
/******************************************************************************/
/* MetaStockReader : DECLARATIONS */
/******************************************************************************/
class MetaStockDataBase
{
public:
MetaStockDataBase();
~MetaStockDataBase();
bool initialize(char *directory, bool recursive = false);
void get_quotes(char *symbol);
private:
Master_file_header get_master_file_header(FILE *fp);
Master_file_record get_master_file_record(FILE *fp, int go_to_record_number);
char ** get_all_master_files(char *directory, bool recursive = false);
};
/******************************************************************************/
/* MetaStockReader : GLOBAL VARIABLES */
/******************************************************************************/
bool init_recursive = false;
char *init_directory = NULL;
char **resultats = NULL;
int taille_resultats = 0;
int master_file_id = 0;
/******************************************************************************/
/* fmsbin2ieee : Microsoft Basic floating point format to IEEE floating */
/* point format */
/******************************************************************************/
int fmsbin2ieee(float *src, float *dst) {
union {
float a;
u_long b;
} c;
u_short man;
u_short exp;
c.a = *src;
if (c.b) { // not zero
man = c.b >> 16;
exp = (man & 0xff00) - 0x0200;
if ((exp & 0x8000) != (man & 0x8000))
return 1; // exponent overflow
man = (man & 0x7f) | ((man << 8) & 0x8000); // move sign
man |= exp >> 1;
c.b = (c.b & 0xffff) | ((long)man << 16);
}
*dst = c.a;
return 0;
}
/******************************************************************************/
/* fieee2msbin : IEEE floating point format to Microsoft Basic floating */
/* point format */
/******************************************************************************/
int fieee2msbin(float *src, float *dst) {
union {
float a;
u_long b;
} c;
u_short man;
u_short exp;
c.a = *src;
if (c.b) { /* not zero */
man = c.b >> 16;
exp = ((man << 1) & 0xff00) + 0x0200;
if ((exp & 0x8000) != ((man << 1) & 0x8000))
return 1; /* exponent overflow */
man = (man & 0x7f) | ((man >> 8) & 0x80); /* move sign */
man |= exp;
c.b = (c.b & 0xffff) | ((long)man << 16);
}
*dst = c.a;
return 0;
}
/******************************************************************************/
/* read_dat_file : Read and print all records for a specific DAT file */
/******************************************************************************/
bool read_dat_file(FILE *df, Master_file_record master_file_record) {
if (df != (FILE *)NULL) {
Data_file_header data_file_header;
Data_file_record data_file_record;
float last_record;
float first_date;
float last_date;
float record_date;
float record_time;
float record_open;
float record_high;
float record_low;
float record_close;
float record_volume;
float record_op_int;
/* The following code is currently not necessary but might be usefull one day...
if ( fmsbin2ieee((float *) &master_file_record.first_date, &first_date) == 0) {
printf("First date : %f\n", first_date);
}
if ( fmsbin2ieee((float *) &master_file_record.last_date, &last_date) == 0) {
printf("Last date : %f\n", last_date);
}
printf("Time frame : %c\n", master_file_record.time_frame);
if (master_file_record.time_frame == 'I') {
printf("Time interval : %u minute(s)\n", master_file_record.ida_time);
}
printf("\n");
*/
fread(&data_file_header.max_recs, sizeof(data_file_header.max_recs), 1, df);
fread(&data_file_header.last_rec, sizeof(data_file_header.last_rec), 1, df);
if (master_file_record.num_fields == 5) {
fread(&data_file_header.zeroes, sizeof(char), 16, df);
}
if (master_file_record.num_fields == 6) {
fread(&data_file_header.zeroes, sizeof(char), 20, df);
}
if (master_file_record.num_fields == 7) {
fread(&data_file_header.zeroes, sizeof(char), 24, df);
}
if (master_file_record.num_fields == 8) {
fread(&data_file_header.zeroes, sizeof(char), 28, df);
}
/* The following code is currently not necessary but might be usefull one day...
printf("Total Record Number : %u\n", data_file_header.max_recs);
printf("Highest Record Used : %u\n", data_file_header.last_rec);
printf("Zeroes : %s\n", data_file_header.zeroes);
printf("\n");
*/
last_record = data_file_header.last_rec;
// Build and print record's header according to the fields we have
printf("Date\t");
if (master_file_record.time_frame == 'I') {
printf("Time\t");
}
if (((master_file_record.time_frame == 'D') && ((master_file_record.num_fields == 6) || (master_file_record.num_fields == 7) || (master_file_record.num_fields == 8))) || ((master_file_record.time_frame == 'I') && ((master_file_record.num_fields == 7) || (master_file_record.num_fields == 8)))) {
printf("Open\t");
}
printf("High\tLow\tClose\tVolume\n");
// Get and print all record available, in the same order than the header
for (int i=0; i < last_record - 1; i++) {
// Record's Date
fread(&data_file_record.date, sizeof(data_file_record.date), 1, df);
if ( fmsbin2ieee((float *) &data_file_record.date, &record_date) == 0) {
int date = int(record_date);
char date_str[6], new_date[8];
sprintf(date_str, "%i", date);
// Swap fields order from yymmdd to ddmmyyyy
new_date[0] = date_str[4];
new_date[1] = date_str[5];
new_date[2] = date_str[2];
new_date[3] = date_str[3];
new_date[4] = '1';
new_date[5] = '9';
new_date[6] = date_str[0];
new_date[7] = date_str[1];
printf("%c%c%c%c%c%c%c%c\t", new_date[0], new_date[1], new_date[2],
new_date[3], new_date[4], new_date[5], new_date[6], new_date[7]);
}
// Record's Time
if (master_file_record.time_frame == 'I') {
fread(&data_file_record.time, sizeof(data_file_record.time), 1, df);
if ( fmsbin2ieee((float *) &data_file_record.time, &record_time) == 0) {
printf("%f\n", record_time);
}
}
// Record's Open
if (((master_file_record.time_frame == 'D') && ((master_file_record.num_fields == 6) || (master_file_record.num_fields == 7) || (master_file_record.num_fields == 8))) || ((master_file_record.time_frame == 'I') && ((master_file_record.num_fields == 7) || (master_file_record.num_fields == 8)))) {
fread(&data_file_record.open, sizeof(data_file_record.open), 1, df);
if (fmsbin2ieee((float *) &data_file_record.open, &record_open) == 0 ) {
printf("%f\t", record_open);
}
}
// Record's High
fread(&data_file_record.high, sizeof(data_file_record.high), 1, df);
if ( fmsbin2ieee((float *) &data_file_record.high, &record_high) == 0) {
printf("%f\t", record_high);
}
// Record's Low
fread(&data_file_record.low, sizeof(data_file_record.low), 1, df);
if ( fmsbin2ieee((float *) &data_file_record.low, &record_low) == 0) {
printf("%f\t", record_low);
}
// Record's Close
fread(&data_file_record.close, sizeof(data_file_record.close), 1, df);
if ( fmsbin2ieee((float *) &data_file_record.close, &record_close) == 0) {
printf("%f\t", record_close);
}
// Record's Volume
fread(&data_file_record.volume, sizeof(data_file_record.volume), 1, df);
if ( fmsbin2ieee((float *) &data_file_record.volume, &record_volume) == 0) {
int volume = int(record_volume);
printf("%i", volume);
}
// Record's Open Interest
if (((master_file_record.time_frame == 'D') && (master_file_record.num_fields == 7)) || ((master_file_record.time_frame == 'I') && (master_file_record.num_fields == 8))) {
fread(&data_file_record.op_int, sizeof(data_file_record.op_int), 1, df);
/* The following code is currently not necessary but might be usefull one day...
if (fmsbin2ieee((float *) &data_file_record.op_int, &record_op_int) == 0) {
printf("%f\t", record_op_int);
}
*/
}
printf("\n");
}
return true;
} else {
return false;
}
}
/******************************************************************************/
/* MetaStockDataBase - Constructor */
/******************************************************************************/
MetaStockDataBase::MetaStockDataBase() {
}
/******************************************************************************/
/* MetaStockDataBase - Destructor */
/******************************************************************************/
MetaStockDataBase::~MetaStockDataBase() {
}
/******************************************************************************/
/* MetaStockDataBase - get_all_master_files : */
/* return a list of all MetaStock master files found in a directory, */
/* with or without recursive scan. */
/******************************************************************************/
char ** MetaStockDataBase::get_all_master_files(char *directory, bool recursive = false)
{
DIR *dir;
struct dirent *entry;
struct stat buf;
char search[MAXPATHLEN], next_directory[MAXPATHLEN];
/* Little things to do to have the same sort of path */
if (!strcmp(&directory[strlen(directory)-1], "/"))
strcpy(search, directory);
else
strcat(strcpy(search, directory), "/");
/* Initialize directory with the directory we have */
if ((dir = opendir(search)) == NULL) {
printf("Error opening directory (%s).\n", search);
return(NULL);
}
/* Scan all entries in the main directory or in its sub-directories to find all MetaStock Master file. */
while((entry = readdir(dir)) != NULL)
{
if (!((!strcmp(entry->d_name, ".")) || (!strcmp(entry->d_name, "..")))) {
strcat(strcat(next_directory, search), entry->d_name);
if ((!stat(next_directory, &buf)) && (buf.st_mode & S_IFDIR) && (recursive)) {
get_all_master_files(next_directory, recursive);
} else {
if (!strcasecmp(entry->d_name, "Master")) {
/* Master file found in next_directory */
if (! resultats)
{
resultats = (char **) malloc(sizeof(void*) * 25);
taille_resultats = 25;
} else
{
if (master_file_id == taille_resultats)
{
taille_resultats += 25;
resultats = (char **) realloc(resultats, sizeof(void*) * taille_resultats);
}
}
resultats[master_file_id] = (char *) malloc((strlen(next_directory)+1)*sizeof(char));
strcpy(resultats[master_file_id], next_directory);
master_file_id++;
}
}
next_directory[0] = '\0';
}
}
if (closedir(dir) != 0) {
printf("Error closing directory (%s).\n", search);
}
return(resultats);
}
/******************************************************************************/
/* MetaStockDataBase - initialize : */
/* Set up the directory where all research should be located and initialize */
/* our research with or without recursive scan */
/******************************************************************************/
bool MetaStockDataBase::initialize(char *directory, bool recursive = false)
{
init_directory = directory;
init_recursive = recursive;
DIR *dir;
if ((dir = opendir(init_directory)) == NULL) {
printf("Error opening directory (%s).\n", init_directory);
return false;
} else {
return true;
}
}
/******************************************************************************/
/* MetaStockDataBase - get_quotes : */
/* Get all master files for the directory where our search is located and */
/* look into to check if the symbol we need is there. Then, get all quotes */
/* available from the .dat or .DAT file corresponding to the symbol. */
/******************************************************************************/
void MetaStockDataBase::get_quotes(char *symbol)
{
char **list_of_master_files = get_all_master_files(init_directory, init_recursive);
int max = 0;
if (list_of_master_files != NULL) {
for (int i = 0; i < master_file_id; i++) {
Master_file master_file;
master_file.header = get_master_file_header(fopen(list_of_master_files[i],"r"));
if (master_file.header.num_files <= 255) {
max = master_file.header.num_files;
} else {
max = 255;
}
printf("Master file : %s\nNum files : %i\n", list_of_master_files[i], max);
for (int j = 0; j < max; j++) {
printf("J : %i\n", j);
master_file.record = get_master_file_record(fopen(list_of_master_files[i],"r"),j);
printf("Symbol : %s\n", master_file.record.symbol);
/* char *symbol_record = (char *) (master_file.record.symbol);
char *ptr = strchr(symbol_record, ' ');
*ptr = '\0';
printf("%s\n", symbol_record);
if (!strcmp(symbol, symbol_record)) {
char path[MAXPATHLEN], new_path[MAXPATHLEN];
char file_number[3];
sprintf(file_number, "%u", master_file.record.file_num);
strncat(path, list_of_master_files[i], (strlen(list_of_master_files[i]) - 6));
strcat(strcat(path, "F"), file_number);
// Try to read the .dat file, otherwise try to read the .DAT file
if (read_dat_file(fopen(strcat(path, ".dat"),"r"), master_file.record) == false) {
read_dat_file(fopen(strcat(strncpy(new_path, path, (strlen(path) - 4)), ".DAT"),"r"), master_file.record);
}
}
*/
}
free(list_of_master_files[i]);
}
free(list_of_master_files);
} else {
printf("Master file not found.\n");
}
}
/******************************************************************************/
/* MetaStockDataBase : PRIVATE FUNCTIONS */
/******************************************************************************/
/******************************************************************************/
/* get_master_file_header will read and return the master file header */
/******************************************************************************/
Master_file_header MetaStockDataBase::get_master_file_header(FILE *fp)
{
Master_file_header record;
if (fp != (FILE *)NULL)
{
fread(&record.num_files, sizeof(record.num_files), 1, fp);
fread(&record.file_num, sizeof(record.file_num), 1, fp);
fread(&record.zeroes, sizeof(char), 49, fp);
}
return(record);
}
/******************************************************************************/
/* get_master_file_record will read and return any master file record */
/******************************************************************************/
Master_file_record MetaStockDataBase::get_master_file_record(FILE *fp, int record_number)
{
Master_file_header header_record;
Master_file_record record;
if (fp != (FILE *)NULL)
{
fseek(fp, (sizeof(header_record.num_files)+sizeof(header_record.file_num)+sizeof(header_record.zeroes)) + 53 * record_number, SEEK_SET);
fread(&record.file_num, sizeof(record.file_num), 1, fp);
fread(&record.file_type, sizeof(char), 2, fp);
fread(&record.rec_len, sizeof(record.rec_len), 1, fp);
fread(&record.num_fields, sizeof(record.num_fields), 1, fp);
fread(&record.reserved1, sizeof(char), 2, fp);
fread(&record.issue_name, sizeof(char), 16, fp);
fread(&record.reserved2, sizeof(record.reserved2), 1, fp);
fread(&record.CT_v2_8_flag, sizeof(record.CT_v2_8_flag), 1, fp);
fread(&record.first_date, sizeof(record.first_date), 1, fp);
fread(&record.last_date, sizeof(record.last_date), 1, fp);
fread(&record.time_frame, sizeof(record.time_frame), 1, fp);
fread(&record.ida_time, sizeof(record.ida_time), 1, fp);
fread(&record.symbol, sizeof(char), 14, fp);
fread(&record.reserved3, sizeof(record.reserved3), 1, fp);
fread(&record.flag, sizeof(record.flag), 1, fp);
fread(&record.reserved4, sizeof(record.reserved4), 1, fp);
}
return(record);
}
void usage(void) {
printf("MetaStockReader (C) Fabien Fulhaber\n");
printf("usage: MetaStockReader [r] directory symbol\n");
}
int main(int argc, char *argv[]) {
// Set up a MetaStockDataBase object and initialize recursive to false
MetaStockDataBase msdb;
bool recursive = false;
// Process all options specified by ARGV
while ((argc > 1) && (argv[1][0] == '-')) {
switch(argv[1][1]) {
case 'r':
recursive = true;
break;
default:
usage();
}
++argv;
--argc;
}
if (argc > 2) {
// Initialize the MetaStockDataBase object according to the options
// and parameters previously selected
if (msdb.initialize(argv[1], recursive)) {
// Get quotes for the specified symbol
msdb.get_quotes(argv[2]);
}
} else {
usage();
}
return 0;
}