安全與執行限制
將 OpenPine 嵌入宿主應用程式時,使用者提供的 Pine 腳本會在 VM 內執行。VM 提供可配置的限制,以保護宿主進程不受失控腳本的影響。
為何需要限制
Pine 腳本可以包含迴圈(for、while、for..in),其迭代次數可能根據使用者輸入或資料任意增加。若無限制,惡意或有缺陷的腳本可能導致宿主進程無限期掛起。OpenPine 的執行限制按 Bar 檢查,因此開銷可預測。
配置限制
在呼叫 build() 前,將 ExecutionLimits 傳入 InstanceBuilder::with_execution_limits:
rust
use openpine_vm::{ExecutionLimits, Instance, TimeFrame};
let limits = ExecutionLimits::default()
.with_max_loop_iterations_per_bar(1_000_000);
let mut instance = Instance::builder(source, TimeFrame::days(1), "NASDAQ:AAPL")
.with_execution_limits(limits)
.build().await?;超出限制時,VM 會拋出執行時錯誤(Error::Exception),處理方式與其他執行時異常相同。
可用限制
max_loop_iterations_per_bar
| 屬性 | 值 |
|---|---|
| 預設值 | 500,000 |
| 作用域 | 所有 for、while、for..in 迴圈在每個 Bar 內共享同一預算 |
| 重置時機 | 每根 K 線執行開始時計數器重置 |
| 停用方式 | 設定為 u64::MAX 可關閉限制 |
同一 Bar 內所有迴圈類型共享同一預算。例如,腳本中兩個巢狀 for 迴圈各迭代 1,000 次,則共消耗 1,000,000 次迭代——超過預設預算 500,000。
rust
// 為計算密集型腳本提高限制
let limits = ExecutionLimits::default()
.with_max_loop_iterations_per_bar(2_000_000);
// 完全停用限制(不建議用於不受信任的腳本)
let limits = ExecutionLimits::default()
.with_max_loop_iterations_per_bar(u64::MAX);max_security_depth
| 屬性 | 值 |
|---|---|
| 預設值 | 3 |
| 作用域 | request.security() 呼叫的最大巢狀深度 |
| 停用方式 | 設定為 0 可完全禁止 request.security() |
控制 request.security() 的最大巢狀層數。深度為 1 表示 security 表達式內部不得再呼叫 request.security()。預設值 3 與 TradingView 行為一致。
rust
// 僅允許一層 request.security()(不允許巢狀)
let limits = ExecutionLimits::default()
.with_max_security_depth(1);
// 完全禁止 request.security()
let limits = ExecutionLimits::default()
.with_max_security_depth(0);max_security_calls
| 屬性 | 值 |
|---|---|
| 預設值 | 40 |
| 作用域 | 所有 request.security() 呼叫點中,唯一 (symbol, timeframe) 組合的最大數量 |
| 停用方式 | 設定為 0 可完全禁止 request.security() |
每個不同的 (symbol, timeframe) 組合會建立一個獨立的資料流。共享同一組合的多個呼叫點只計一次。預設值 40 與 TradingView 行為一致。
rust
// 在資源受限的環境中收緊限制
let limits = ExecutionLimits::default()
.with_max_security_calls(10);處理超限錯誤
超限錯誤以 Error::Exception 的形式拋出,與 runtime.error() 及其他執行時錯誤類型相同:
rust
match instance.run_to_end("NASDAQ:AAPL", TimeFrame::days(1)).await {
Err(openpine_vm::Error::Exception(e)) => {
eprintln!("腳本錯誤:{}", e.display());
}
_ => {}
}有關處理執行時錯誤的完整說明,請參閱錯誤處理。
建議
- 不受信任的腳本:保持預設限制或將其調低。如無需使用
request.security(),可將max_security_depth設為1或0。 - 已知腳本:僅在確認腳本確實需要更多資源時才提高限制。
- 服務端執行:建議在獨立執行緒中執行每個
Instance,並配合作業系統層級的逾時作為二次保障。迴圈限制僅防止過多迭代,不能防範其他耗時計算來源。