背景
本人實現自動化交易通道搭建過程中,已知:某股票交易客戶端系統本身支持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
結語
該通道目前實盤中。搭建你自己的交易系統,實現自動化交易下單,通道是關鍵。