背景
本人实现自动化交易通道搭建过程中,已知:某股票交易客户端系统本身支持python写交易策略,调用下单接口,实现自动下单。现需要:把外面的交易系统的下单信号通过该股票交易客户端系统实现下单。采用的大概方案如下:
结构非常简单,交易系统有信号的时候以追加写的方式写这个中间文件。另一边,股票交易系统中,构建一个python策略,定时(10ms或更短时间)读这个文件,再调用自身的下单接口下单,为了防止重复信号,读完删除这个文件。
实现
写文件实现
void writeOrder(const string &orderStr)
{
try {
string filename = "order.csv";
string fullpath = filepath + "/" + filename;
std::ofstream ofs;
while(true){
ofs.open(fullpath, std::ios_base::app);
if(!ofs.is_open()) {
//有一定概率打开文件失败,是因为股票系统策略那边正在操作。这里需要sleep一下。再打开,防止漏单。
Sleep(1);
continue;
}
ofs << orderStr;
ofs.close();
break;
}
} catch (const exception &e) {
//出错日志
}
}
股票交易系统中,python策略读文件实现
#定时函数
def insertOrder():
#order_file中间文件
if os.path.exists(order_file):
print('start',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
for line in open(order_file,'r'): #读取文件单
#处理对应信号,调用下单接口下单。或保存信号。后面删除文件后再下单。
pass
print('end read file',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
os.remove(order_file) #删去文件
else:
return
问题
上面的读写中间文件看着是没有问题的,但是python策略直接读原文件order_file,读完后,再删除原文件。 这种方式,因为读取过程中需要时间较多如100ms,当外面的交易系统那边频繁报单写文件的时候,因为order_file不是独占的。python这边读取的过程中,外面的交易系统那边也写入了很多单,那么python策略这里随后删除文件时,删除了还没有读取的新写入的单子。导致漏单!!
解决
中间的读写文件最好是读的时候不能写,写的时候不能读,读写互斥。如果是同一个系统的话是很好实现的,加一个文件锁就可以了。或者别的锁。 读写文件的时候都需要获得锁。 但是现在是双系统,这个加锁的方式不现实。
有没有一种方式,能控制我读文件的时候,别的一切程序都不能写?
没找到!!
换一种思路?
问题:因为读的过程耗时较多,期间写入了额外的信号,导致删除文件的 时候,把额外的信号也删除了,导致漏单。
分析:删除文件是需要的,否则引发重复单更麻烦。读耗时是关键。
那么:怎么办呢?
答案
修改一下Python策略定时函数,读文件之前,先重命名,重命名耗时短,一旦另一边正在写,那么重命名就失败。失败就能下一个定时点就行。这样只要重命名成功,那么就做到了读写分开啦!妙!!!
代码处理如下:
#定时函数
def insertOrder():
#order_file中间文件
#order_file_new 中间文件重命名后文件名
if os.path.exists(order_file):
#lsl:用rename的方式,当自动化下单那么正在写文件时,这里会失败,那么股票交易系统会捕捉异常,等待下一个时间点再触发,冲突概率小,且是可控的,最多延迟几个定时时间点下单。
os.rename(order_file, order_file_new)
print('start',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
for line in open(order_file_new,'r'): #读取文件单
#处理对应信号
pass
print('end read file',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
os.remove(order_file_new) #删去文件
else:
return
结语
该通道目前实盘中。搭建你自己的交易系统,实现自动化交易下单,通道是关键。