外_匯_邦 WaiHuiBang.com
1.MetaTrader 4客戶端中 "交易運作" 的概念來自MetaEditor參考文檔的一段話:
來自智能交易和腳本的交易,只能夠提供一個並在交易作業中開啟 (來自智能交易和腳本的自動交易作業)。www.emoneybtc.com這就是為什麼如果智能交易業務作業忙,其他的智能交易或腳本在此刻不能調用函數生成錯誤146 (ERR_TRADE_CONTEXT_BUSY)。換句話說,只有一個智能交易(腳本)可以准時交易。所以其他智能交易嘗試開始交易將被錯誤 146停止。文章將會找到問題的解決方案。
2. 函數 IsTradeAllowed()這是最簡單的方法是使用名稱為IsTradeAllowed()的函數找出交易作業忙。
來自 MetaEditor參考文檔的一段話:
"bool IsTradeAllowed()如果智能交易允許交易,返回TRUE 。否則,返回FALSE。這就意味著如果函數 IsTradeAllowed()返回TRUE只有一個可以嘗試交易。
在交易業務之前必須檢測完成。
函數錯誤使用范例:
- int start()
- {
- // 檢測交易作業
- if(!IsTradeAllowed())
- {
- // 如果函數IsTradeAllowed() 返回FALSE, 通知用戶
- Print("交易作業忙。智能交易不能開倉!");
- // 並且中止交易業務。當下一個替克進入將重新開始
- // 進入
- return(-1);
- }
- else
- {
- // 如果函數IsTradeAllowed()返回TRUE,通知用戶
- // 並繼續運行
- Print("交易作業空閒!開始運作...");
- }
- // 現在檢測市場
- ...
- // 計算止損和贏利水平和標准手
- ...
- // 開倉
- if(OrderSend(...) < 0)
- Alert("開倉錯誤 # ", GetLastError());
- return(0);
- }
復制代碼在這個范例中,在start() 函數開始時檢測交易運作狀態。這是個錯誤想法: 在我們的智能交易計算的時間內交易作業會被其他智能交易占據(需要進入市場,止損和贏利,標准手等等)。這些情況,接受開倉將失敗。
函數適當應用范例:
- int start()
- {
- // 現在檢測市場
- ...
- // 計算止損和贏利水平,標准手數
- ...
- // 現在檢測交易作業
- if(!IsTradeAllowed())
- {
- Print("交易作業忙! 智能交易不能開倉!");
- return(-1);
- }
- else
- Print("交易作業正常! 嘗試開倉...");
- //如果檢測正常,開倉
- if(OrderSend(...) < 0)
- Alert("錯誤開倉 # ", GetLastError());
- return(0);
- }
復制代碼在開倉之前立即檢測交易作業狀態,並且可能在兩種動作行為之間插入其他的智能交易 .
這種方法存在兩點不足:
智能交易在接收到明確結果檢測狀態的同時,將嘗試開始交易.
如果檢測失敗,智能交易將嘗試使用下一個替克交易; 將會延誤.
解決第二種不足很簡單:等待交易作業空閒即可.隨後,在其他智能交易結束後,智能交易將立即開始交易.
范例如下:
- int start()
- {
- // 現在檢測是否進入市場
- ...
- // 計算贏利/止損水平和標准手數
- ...
- // 檢測交易作業是否空閒
- if(!IsTradeAllowed())
- {
- Print("交易作業忙!等待空閒...");
- // 無限循環
- while(true)
- {
- // 如果智能交易被用戶停止,停止業務
- if(IsStopped())
- {
- Print("智能交易被用停止!");
- return(-1);
- }
- // 如果交易作業空閒,開始交易
- if(IsTradeAllowed())
- {
- Print("交易作業空閒!");
- break;
- }
- // 如果沒有條件設置循環, "等待" 0.1秒
- // 並且檢測重新開始
- Sleep(100);
- }
- }
- else
- Print("交易作業空閒!嘗試開倉...");
- // 嘗試開倉
- if(OrderSend(...) < 0)
- Alert("錯誤開倉 # ", GetLastError());
- return(0);
- }
復制代碼這種情況出現,我們可以指出以下錯誤:
函數 IsTradeAllowed()不僅僅能夠顯現交易作業的狀態,同樣可以在無限循環中以“隱藏”開啟/關閉;如果從圖表中手動移除,將停止運作。
如果智能交易等待交易作業空閒,在這個時間裡,價格會改變並且可能用這個價格交易 - 數據需要刷新開倉重新計算。
糾正的錯誤代碼將會是以下:
- // 智能交易等待交易的時間time (in seconds) whithin which the expert will wait until the trade
- // 交易作業空閒(如果忙)
- int MaxWaiting_sec = 30;
- int start()
- {
- // 現在檢驗是否進入市場
- ...
- // 計算止損,贏利和標准手數
- ...
- // 檢測交易作業是否空閒
- if(!IsTradeAllowed())
- {
- int StartWaitingTime = GetTickCount();
- Print("交易作業忙!等待空閒...");
- // 無限循環
- while(true)
- {
- // 如過用戶中止智能交易,停止業務
- if(IsStopped())
- {
- Print("智能交易被用戶中止!");
- return(-1);
- }
- // 如果等待時間超過命名變量
- // MaxWaiting_sec, 停止業務
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("標准限定(" + MaxWaiting_sec + " sec)超過!");
- return(-2);
- }
- // 如果交易作業空閒,
- if(IsTradeAllowed())
- {
- Print("交易作業空閒!");
- // 刷新市場信息
- RefreshRates();
- // 重新計算止損和贏利水平
- ...
- // 離開循環狀態並開始交易
- break;
- }
- // 如過沒有條件離開,請 "等待" 0.1秒
- // 並且重新開始檢測
- Sleep(100);
- }
- }
- else
- Print("交易作業空閒!嘗試開倉...");
-
- // 嘗試開倉
- if(OrderSend(...) < 0)
- Alert("錯誤開倉 # ", GetLastError());
-
- return(0);
- }
-
復制代碼對於上面的范例,我們還可以添加:
刷新市場信息(RefreshRates())並且重新計算止損和贏利水平
在超過最大時間限定等待後 MaxWaiting_sec,智能交易將停止業務
以上的這些代碼你已經可以使用到你的智能交易中。
現在讓我們來談談在單獨函數中的檢測。這將簡化在智能交易中的簡化和用法。
- /////////////////////////////////////////////////////////////////////////////////
- // int _IsTradeAllowed( int MaxWaiting_sec = 30 )
- //
- // 函數檢測交易作業狀態. R返回代碼:
- // 1 - 交易作業空閒, 允許交易
- // 0 - 交易作業忙,但是將空閒。刷新市場信息後允許交易。
- // -1 - 交易作業忙,用戶中止等待(智能交易從圖表中刪除,終端刪除,圖表周期/貨幣對改變等等)
- // -2 - 交易作業忙,達到最大等待限度 (MaxWaiting_sec).
- // 智能交易禁止交易(檢測 "Allow live trading" ).
- //
- // MaxWaiting_sec - 函數將等待的時間
- // 直到交易作業控點(如果交易作業忙).默認值,30.
- /////////////////////////////////////////////////////////////////////////////////
- int _IsTradeAllowed(int MaxWaiting_sec = 30)
- {
- // 檢測交易作業是否空閒
- if(!IsTradeAllowed())
- {
- int StartWaitingTime = GetTickCount();
- Print("交易作業忙!等待空閒...");
- // 無限循環
- while(true)
- {
- // 如果智能交易被用戶中止,停止業務
- if(IsStopped())
- {
- Print("智能交易被用戶中止!");
- return(-1);
- }
- // 如果等待時間超出指定
- // MaxWaiting_sec 變量 ,停止業務
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("等待限度超過 (" + MaxWaiting_sec + " сек.)!");
- return(-2);
- }
- // 如果交易作業空閒
- if(IsTradeAllowed())
- {
- Print("交易作業空閒!");
- return(0);
- }
- // 如果沒有條件離開循環狀態,請"等待" 0.1秒
- // 並且重新開始檢測 Sleep(100);
- }
- }
- else
- {
- Print("交易作業空閒!");
- return(1);
- }
- }
復制代碼對於智能交易使用函數的一個模板:
- int start()
- {
- // 現在檢測是否進入市場
- ...
- // 計算止損,贏利水平和標准手數
- ...
- // 檢測交易作業是否空閒
- int TradeAllow = _IsTradeAllowed();
- if(TradeAllow < 0)
- {
- return(-1);
- }
- if(TradeAllow == 0)
- {
- RefreshRates();
- // 重新計算贏利水平和止損水平
- ...
- }
- // 開倉
- if(OrderSend(...) < 0)
- Alert("錯誤開倉 # ", GetLastError());
- return(0);
- }
復制代碼由此我們得出以下結論:
函數 IsTradeAllowed()很方便使用,並且對於兩到三個智能交易同時運行同樣適用。雖然存在一些不足,當很多智能交易同時運行時會出現錯誤 146。如果"Allow live trading" 禁止,同樣可能出現智能交易"hanging" 。這就是為什麼我們考慮解決方案-整體變量作為一個 "信號旗"的原因。
3.客戶終端的整體變量首先是概念:
客戶終端的整體變量是所有智能交易,腳本和指標的變量通道。這就意味著整體變量可以由一個智能交易創建,其他的智能交易同樣可以使用 。
在 MQL4中提供了以下函數的整體變量:
GlobalVariableCheck() - 檢測已經存在的整體變量
GlobalVariableDel() - 刪除整體變量
GlobalVariableGet() - 獲取整體變量值
GlobalVariableSet() - 創建或修改整體變量
GlobalVariableSetOnCondition() - 用戶改變整體變量的指定值。不同於 GlobalVariableSet(),新值將被設定。這個函數是一個創建semaphore的關鍵。
GlobalVariablesDeleteAll() - 刪除所有整體變量 (我們不敢想象它的實用性:))
為什麼使用 GlobalVariableSetOnCondition(),而不是聯合函數 GlobalVariableGet()和 GlobalVariableSet()呢? 同樣的原因:兩個函數之前可能重合。這樣其他的智能交易則不能插入。這就不使用的原因。
4. 信號旗的基本理念智能交易准備交易應該檢測信號旗的狀態。如果信號旗顯示 "紅色" (整體變量 = 1),意味著其他智能交易在運行中,這樣需要等待。如果顯示“綠色” (整體變量 = 0),交易可以立即開始 (但不要忘記對其他智能交易設定"紅色")。
由此,我們創建了2個函數:一個設定"紅色",另一個設定“綠色”。事實上,他們類似。我們嘗試地制定了函數的次序(函數TradeIsBusy() 和函數TradeIsNotBusy()) 並且賦予實踐。
5. 函數TradeIsBusy()像我們前面所講的,這個函數的主要功能是使智能交易等待直至“綠色”顯現,並且將其切換成“紅色”。另外,我們需要檢驗是否存在整體變量,並且進行創建。如果不存在。這個檢測會從智能交易的函數init() 中進行邏輯性地執行。 但是隨後可能被用戶刪除並且不會有智能交易進行運行。這就是我們將它放置到創建函數中的原因。
所有的這些整體變量的運行都需要伴隨信息的展示和錯誤的生成。 應該記住"hanging":函數的業務時間需要限定。
這就是我們最終得到的:
- /////////////////////////////////////////////////////////////////////////////////
- // int TradeIsBusy( int MaxWaiting_sec = 30 )
- //
- // 函數還原TradeIsBusy 值0 - 1.
- // 在開啟時如果TradeIsBusy = 1 ,函數等待直至 TradeIsBusy 為 0,
- // 隨後還原
- // 如果TradeIsBusy沒有任何整體變量,函數將會自己創建。
- // 返回代碼:
- // 1 - 成功編譯。TradeIsBusy整體變量值指定為 1
- // -1 - TradeIsBusy = 1 函數在此刻開啟,等待用戶中止
- // (智能交易從圖表中移除,終端被停止,圖表周期/貨幣對被改變等等)
- // -2 - TradeIsBusy = 1 函數在此刻開啟,等待限定超時
- // (MaxWaiting_sec)
- /////////////////////////////////////////////////////////////////////////////////
- int TradeIsBusy( int MaxWaiting_sec = 30 )
- {
- // 測試時,沒有理由劃分交易作業 - 只是終止
- // 此函數
- if(IsTesting())
- return(1);
- int _GetLastError = 0, StartWaitingTime = GetTickCount();
- //+------------------------------------------------------------------+
- //| 檢測整體變量是否存在,如果沒有,創建整體變量 |
- //+------------------------------------------------------------------+
- while(true)
- {
- // 如果智能交易被用戶中止,停止業務
- if(IsStopped())
- {
- Print("智能交易被用戶中止!");
- return(-1);
- }
- // 如果等待時間超過指定限定時間
- // MaxWaiting_sec, 停止業務
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("等待時間(" + MaxWaiting_sec + " sec)超出!");
- return(-2);
- }
- // 檢測整體變量是否存在
- // 如果不存在離開循環模式,進行改變
- // TradeIsBusy值
- if(GlobalVariableCheck( "TradeIsBusy" ))
- break;
- else
- // 如果GlobalVariableCheck 返回FALSE, 意味著整體變量不存在或者
- // 檢測中生成錯誤
- {
- _GetLastError = GetLastError();
- // 如果仍然有錯誤信息顯示,等待0.1 秒,
- //重新開始檢測
- if(_GetLastError != 0)
- {
- Print("TradeIsBusy()-GlobalVariableCheck("TradeIsBusy")-Error #",
- _GetLastError );
- Sleep(100);
- continue;
- }
- }
- // 如果沒有錯誤,意味著沒有整體變量,嘗試創建
- // 整體變量
- //如果 the GlobalVariableSet > 0, 說明整體變量成功創建。
- // 離開函數
- if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 0 )
- return(1);
- else
- // 如果GlobalVariableSet返回值<= 0, 說明有錯誤
- // 在變量創建時生成
- {
- _GetLastError = GetLastError();
- //顯示信息,等待0.1秒,再次嘗試
- if(_GetLastError != 0)
- {
- Print("TradeIsBusy()-GlobalVariableSet("TradeIsBusy",0.0 )-Error #",
- _GetLastError );
- Sleep(100);
- continue;
- }
- }
- }
- //+----------------------------------------------------------------------------------+
- //| 如果函數達到執行點,說明整體變量 |
- //| 變量退出. |
- //| 等待TradeIsBusy 值成為0 並且改變 TradeIsBusy 值為 1 |
- //+----------------------------------------------------------------------------------+
- while(true)
- {
- // 如果智能交易被用戶中止,停止業務
- if(IsStopped())
- {
- Print("智能交易被用戶中止!");
- return(-1);
- }
- // 如果等待超過限定時間
- // MaxWaiting_sec, 停止業務
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("等待時間 (" + MaxWaiting_sec + " sec) 超出!");
- return(-2);
- }
- // 嘗試改變 TradeIsBusy的值從 0 - 1
- // 如果成功,離開函數返回1 ("成功編譯")
- if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 ))
- return(1);
- else
- // 如果失敗,可能導致失敗的2個原因: TradeIsBusy = 1 (隨後等待),
-
- // 錯誤生成 (需要我們檢測)
- {
- _GetLastError = GetLastError();
- // 如果仍然存在錯誤,顯示信息並且重新嘗試
- if(_GetLastError != 0)
- {
- Print("TradeIsBusy()-GlobalVariableSetOnCondition("TradeIsBusy",1.0,0.0 )-Error #",
- _GetLastError );
- continue;
- }
- }
- //如果沒有錯誤,說明TradeIsBusy = 1 (其他智能交易在運行),
- // 隨後顯示信息並且等待...
- Comment("等待其他智能交易交易完成...");
- Sleep(1000);
- Comment("");
- }
- }
-
復制代碼在這裡可以清楚地看到:
檢測整體變量是否存在,如果沒有,進行創建
試圖改變整體變量的值從 0到 1;如果其值等於0,將開啟。
函數可以運行 MaxWaiting_sec,並且不從圖表中刪除任何商品。
錯誤信息生成你可以在日志中找到。
6. 函數TradeIsNotBusy()函數TradeIsNotBusy 解決返回的問題:開啟"綠色"。
這項功能沒有限定並且不能由用戶中止。方式非常簡單:如果 "綠色" 關閉,智能交易將不會進行交易。
不會返回任何代碼:結果只能被成功編譯。
參見下面示例:
- /////////////////////////////////////////////////////////////////////////////////
- // void TradeIsNotBusy()
- //
- // 函數設置整體變量 TradeIsBusy 值等於0.
- // 如果TradeIsBusy不存在,函數創建。
- /////////////////////////////////////////////////////////////////////////////////
- void TradeIsNotBusy()
- {
- int _GetLastError;
- // 測試時,交易作業不被劃分 - 只是終止
- // 此函數
- if(IsTesting())
- {
- return(0);
- }
- while(true)
- {
- // 如果智能交易被用戶中止,停止業務
- if(IsStopped())
- {
- Print("智能交易被用戶中止!");
- return(-1);
- }
- // 嘗試設置整變量值= 0 (創建整體變量)
- // 如果 GlobalVariableSet 返回值 > 0, 說明成功
- // 離開函數
- if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0)
- return(1);
- else
- // 如果GlobalVariableSet 返回值 <= 0, 說明錯誤生成
- // 顯示信息,等待並且嘗試重新開始
- {
- _GetLastError = GetLastError();
- if(_GetLastError != 0 )
- Print("TradeIsNotBusy()-GlobalVariableSet("TradeIsBusy",0.0)-Error #",
- _GetLastError );
- }
- Sleep(100);
- }
- }
復制代碼7. 在智能交易中的結合使用現在我們有 3 個函數可以通向交易作業。使他們簡單地結合到智能交易中,我們可以創建一個 TradeContext.mq4 文件並且使用 #include (獲取文件)。
這是一個使用函數 TradeIsBusy()和函數TradeIsNotBusy()的模板:
- #include <TradeContext.mq4>
-
- int start()
- {
- // 現在檢測是否進入市場
- ...
- // 計算止損水平,贏利水平和標准手數
- ...
- // 等待交易作業空閒並且進入(如果生成錯誤,
- // 離開)
- if(TradeIsBusy() < 0)
- return(-1);
- // 刷新市場信息
- RefreshRates();
- // 重新計算止損和贏利水平
- ...
- // 開倉
- if(OrderSend(...) < 0)
- {
- Alert("錯誤開倉位置 # ", GetLastError());
- }
-
- //設置交易作業空閒
- TradeIsNotBusy();
-
- return(0);
- }
-
復制代碼在使用函數 TradeIsBusy()和函數 TradeIsNotBusy()時,只有一個問題能夠產生: 如果在交易作業變成忙後,智能交易從圖表中移除,變量 TradeIsBusy將會等於 1。其他的智能交易將不可能運行。
這個問題可以很輕松地解決: 在智能交易在圖表中交易時,不從圖表中移除;)
在終端停歇時, TradeIsBusy值也有可能不等於0。這種情況,函數 TradeIsNotBusy()從智能交易的函數 init() 被使用。
當然,在任何時間內可以手動改變變量值: 終端內的F3鍵 。不建議進行使用。
外_匯_邦 WaiHuiBang.com