C++读入通达信日线及1分钟数据
通达信日线、1分钟数据调用后,便于使用数据进行回测。
struct dayData //通达信日线数据结构,32个字节
{
int date;//4字节
int open;//4字节
int high;//4字节
int low;//4字节
int close;//4字节
float amount;//4字节
int vol;//4字节
int x;//4字节,备用数据
};
void 读入日线数据(CString &sj)//参数sj把数据传回调用程序
{
//二进制文件读入
FILE* fp;
int nLen;
dayData* data = new dayData[50000];//在堆中开数组,大小不受限制,理论上可以无限大
char filename[30] = "sh600968.day";//读入日线文件名称
if ((fp = fopen(filename, "rb+")) == NULL)//打开文件进行二进制读入
{
printf("文件打开失败!Fail to open file!");
exit(0);
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp) / 32;//获取文件大小
fseek(fp, 0, SEEK_SET);//重新回到文件起始位置
nLen = fread(data, size, 32, fp);//使用fread读入数据
for (int i = 0; i < 10; i++)//根据需要,把数据连成一个字符串,此处测试10个数据用于调试
{ //把数据连接成一个字符串,进行数据传递
CString str = L"";//把数据转换为CString类型
str.Format(L"%d", data[i].date);
sj.Append(str + L"|");
str.Format(L"%.2f", double(data[i].open)/100);
sj.Append(str + L"|");
str.Format(L"%.2f", double(data[i].high) / 100);
sj.Append(str + L"|");
str.Format(L"%.2f", double(data[i].low) / 100);
sj.Append(str + L"|");
str.Format(L"%.2f", double(data[i].close) / 100);
sj.Append(str + L"|");
str.Format(L"%.0f", data[i].amount);
sj.Append(str + L"|");
str.Format(L"%d", data[i].vol/100);
sj.Append(str + L";");
}
// TracePrint(L"%s", sj);//自定义的输出函数,观察结果
fclose(fp);
delete[] data;//释放所开的内存空间
data = nullptr;//指向空指针
}
struct lc1Data //通达信1分钟数据结构,32个字节
{
short date;//2字节
short time;//2字节
float open;//4字节
float high;//4字节
float low;//4字节
float close;//4字节
float amount;//4字节
int vol;//4字节
int x;//4字节
};
void 读入1分钟数据(CString &sj)//参数sj把数据传回调用程序
{
//二进制文件读入
FILE* fp;
int nLen;
lc1Data* data = new lc1Data[50000];//在堆中开数组,大小不受限制,理论上可以无限大
// char filename[30] = "sh600968.day";//读入日线文件名称
char filename[30] = "sz000001.lc1";//读入1分钟线的文件名称
lc1Data sj1[100];
if ((fp = fopen(filename, "rb+")) == NULL)//打开文件进行二进制读入
{
printf("文件打开失败!Fail to open file!");
exit(0);
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp) / 32;//获取文件大小
fseek(fp, 0, SEEK_SET);//重新回到文件起始位置
nLen = fread(data, size, 32, fp);//使用fread读入数据
for (int i = 0; i < 10; i++)//根据需要,把数据连成一个字符串,此处测试10个数据用于调试
{ //把数据连接成一个字符串,进行数据传递
CString str=L"";//把数据转换为CString类型
str.Format(L"%d", data[i].date);
sj.Append(str+L"|");
str.Format(L"%d", data[i].time);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].open);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].high);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].low);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].close);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].amount);
sj.Append(str + L"|");
str.Format(L"%d", data[i].vol);
sj.Append(str + L";");
}
// TracePrint(L"%s", sj);//自定义的输出函数,观察结果
fclose(fp);
delete[] data;//释放所开的内存空间
data = nullptr;//指向空指针
}
void C超短回测Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString dataM1=L"";
CStringArray data0;
读入1分钟数据(dataM1);
TracePrint(L"%s", dataM1);//自定义的输出函数,观察结果
Split(dataM1, L";", data0);//利用自定义函数拆分字符串为成为字符串数组
}
void C超短回测Dlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CString dataDay=L"";
CStringArray data0;
读入日线数据(dataDay);
TracePrint(L"%s", dataDay);//自定义的输出函数,观察结果
Split(dataDay, L";", data0);//利用自定义函数拆分字符串为成为字符串数组
}
又研究了一下,有一个更好的解决方案,实现回传数据,输入指定的股票代码与日期,立即得到相应日期的数据;
void 读入1分钟数据(CString gpdm,CString sellDate, CString &sj)//参数sj把数据传回调用程序
{
lc1Data* data = new lc1Data[50000];//在堆中开数组,大小不受限制,理论上可以无限大
CString str;
CFile file;
CString FilePath = L"";
CString filename = L"";
int rq = (_ttoi(sellDate.Left(4)) - 2036) * 2048 + _ttoi(sellDate.Right(4));//字符串日期转换后的数字
CString fn = L"";
if (gpdm.Left(1) == "6") filename.Append(数据下载路径 + "\\sh\\minline\\sh" + gpdm + ".lc1");
if (gpdm.Left(1) == "3" || gpdm.Left(1) == "0") filename.Append(数据下载路径 + "\\sz\\minline\\sz" + gpdm + ".lc1");
BOOL isOpenOK = file.Open(FilePath + filename, CFile::modeRead);
CString strState;
if (FALSE == isOpenOK)
{
strState.Format(L"文件:【" + FilePath + filename + L"】打开失败!");
MessageBox(NULL,strState,0,0);
return;
}
int size = (DWORD)file.GetLength(); //确定文件大小
int nRet = file.Read(data, size);//读入数据
file.Close();//数据读入结束后,关闭文件
int iPos = -1;
for (int i = 0; i < size; i++) //找到指定日期的位置
if (data[i].date == rq)
{
iPos = i;
break;
}
for (int i = iPos - 241; i < iPos + 240; i++)//根据需要,把数据连成一个字符串,此处测试10个数据用于调试
{
//指定日期当天与前一交易日,数据连接成一个字符串,进行数据传递
CString str = L"";//把数据转换为CString类型
str.Format(L"%.f", floor(double(data[i].date) / 2048) + 2036);
sj.Append(str);
str.Format(L"%.f", (double(data[i].date) - floor(double(data[i].date) / 2048) * 2048));
sj.Append(str + L"|");
str.Format(L"%02.0f", floor(double(data[i].time) / 60));
sj.Append(str);
str.Format(L"%02d", int(double(data[i].time - floor(double(data[i].time) / 60) * 60)));
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].open);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].high);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].low);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].close);
sj.Append(str + L"|");
str.Format(L"%.2f", data[i].amount);
sj.Append(str + L"|");
str.Format(L"%d", data[i].vol);
sj.Append(str + L";");
}
// TracePrint(L"%s", sj);//自定义的输出函数,观察结果
delete[] data;//释放所开的内存空间
data = nullptr;//指向空指针
}
void C超短回测Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
// CString gpdm = L"600873";
CString gpdm = L"000001";
CString sellDate = L"20221018";
CString dataM1=L"";
CStringArray data0;
读入1分钟数据(gpdm,sellDate,dataM1);
TracePrint(L"%s", dataM1);//自定义的输出函数,观察结果
Split(dataM1, L";", data0);//利用自定义函数拆分字符串为成为字符串数组
}