Skip to content

腳本配置介面

當使用者點擊腳本圖例上的 ⚙ 按鈕時,圖表會推送一個 ConfigureScript(ScriptId) 事件。本頁介紹如何使用 ScriptManagement trait 方法建構配置對話框。

ChartView

使用 cv.script_inputs_effective(id) 取得已合併預設值的目前輸入。 使用 cv.set_script_config_with_complete(id, config, callback)cv.set_script_config(id, config) 套用變更。

建構設定 UI

本節描述如何為腳本設定建構設定對話框。

設定對話框佈局設定對話框佈局

對話框結構

對話框有兩個分頁:

分頁內容顯示條件
輸入腳本的 input.*() 參數inputs.len() > 0
視覺序列圖視覺覆寫(顏色、樣式)graph_configs 非空

對話框預設應顯示輸入分頁(如有輸入),否則顯示視覺分頁。

頁腳按鈕:

  • 重設為預設值 — 清除所有覆寫並將輸入重設為原始值。
  • 確定 — 關閉對話框(變更會立即套用,無需確認)。

輸入分頁

ConfigureScript 事件提供一個 Vec<InputInfo>

rust
pub struct InputInfo {
    pub idx: usize,                       // 從零開始的輸入索引(input_values 的鍵)
    pub title: Option<String>,            // 人類可讀的標籤
    pub tooltip: Option<String>,          // 懸停提示文字
    pub group: Option<String>,            // 分組標題(可選)
    pub kind: InputKind,                  // 類型特定的值和約束
    pub default_value: serde_json::Value, // 腳本原始預設值(用於「重設為預設值」)
}

根據 InputKind 變體渲染每個輸入:

Int { value, min, max, step, options } —— 數字輸入框。如果 options 非空,顯示下拉選單而非自由輸入框。遵循 minmaxstep 約束。

Float { value, min, max, step, options } —— 帶小數步長(預設 0.1)的數字輸入框。optionsminmax 行為與 Int 相同。

Bool { value } —— 開關切換。

Color { value } —— 色塊 + 顏色選擇器彈窗。顏色為 RGBA 格式的打包 u32(R << 24) | (G << 16) | (B << 8) | A。顯示為填充矩形;點擊時開啟包含十六進制輸入和透明度滑桿的顏色選擇器。

Str { value, options } —— 文字輸入框。如果 options 非空,顯示下拉選單。

Source { value } —— 固定選項的下拉選單:openhighlowclosehl2hlc3ohlc4hlcc4。值為 SourceType 列舉。寫入 input_values 時,轉換為整數判別值:open=0、high=1、low=2、close=3、hl2=4、hlc3=5、ohlc4=6、hlcc4=7。

Enum { value, options } —— 下拉選單。optionsVec<(i64, String)> ——(判別值,顯示標籤)配對。在 input_values 中儲存判別值。

Symbol { value } —— 股票代碼的文字輸入框(如 "AAPL")。

TimeFrame { value, options } —— 下拉選單或文字輸入。值為 TimeFrame。如果 options 非空,顯示下拉選單。

Session { value, options } —— 交易時段字串的文字輸入框或下拉選單(如 "0930-1600")。

Time { value } —— 日期/時間選擇器。值為自紀元以來的毫秒數(i64)。使用腳本的交易所時區(可透過 cv.timezone() 取得)進行日期時間轉換。

TextArea { value } —— 多行文字區域。

套用輸入變更:

rust
let mut config = cv.script_config(id).unwrap_or_default();
// 對於索引 0 處值為 20 的 Int 輸入:
config.input_values.insert(0, serde_json::json!(20));
// 對於 Source 輸入,儲存整數判別值:
config.input_values.insert(1, serde_json::json!(3)); // close
cv.set_script_config(id, config);

變更應立即套用(即時預覽)—— 圖表重新執行腳本並自動重繪。

策略配置分頁

對於策略腳本,可提供專用分頁(或分區),讓使用者覆蓋 strategy() 的執行參數,而無需修改原始碼。這些覆蓋儲存於 ScriptConfig::strategy_config_override 中。

rust
use navi_vm::StrategyConfigOverride;

let mut config = cv.script_config(id).unwrap_or_default();
config.strategy_config_override = Some(StrategyConfigOverride {
    initial_capital: Some(50_000.0),
    commission_value: Some(0.1),
    ..Default::default()
});
cv.set_script_config(id, config);

StrategyConfigOverride 欄位(均為 Option<T>None = 使用腳本預設值):

欄位說明預設值
initial_capital初始帳戶資金1_000_000
commission_type佣金計算方式:percentcash_per_contractcash_per_orderpercent
commission_value佣金金額。percent 模式下為百分比數值(1 = 1%);cash_per_contractcash_per_order 模式下為每合約或每筆訂單的絕對金額。0
margin_long多頭保證金比率(%)100
margin_short空頭保證金比率(%)100
slippage每筆成交滑點,單位:tick0
pyramiding同方向最大開倉次數0
risk_free_rate年化無風險利率(%),用於計算 Sharpe/Sortino 比率2
process_orders_on_close在 bar 收盤價成交,而非下一根 bar 開盤價false
calc_on_order_fills訂單成交後重新執行腳本false
backtest_fill_limits_assumption限價單成交所需超出限價的額外 tick 數0
close_entries_rule優先平倉規則:FIFOANYFIFO

strategy_config_override 的變更會觸發完整的 session 重啟(與輸入值變更相同),因為回測結果取決於這些參數。

視覺分頁

視覺分頁顯示每個序列圖的視覺覆寫。取得資料:

rust
let graph_configs: HashMap<SeriesGraphId, SeriesGraphConfig> = cv.graph_configs(id).unwrap();
let overrides: HashMap<SeriesGraphId, SeriesGraphOverride> = cv.script_overrides(id).unwrap();

SeriesGraphConfig 變體

SeriesGraphConfig 描述原始(覆寫前)視覺狀態。每個變體對應一種繪圖類型:

rust
pub enum SeriesGraphConfig {
    Plot {
        title: Option<String>,
        colors: Vec<Option<Color>>,          // 不同的顏色插槽
        line_width: i32,
        style: PlotStyle,
        line_style: PlotLineStyle,
    },
    PlotChar {
        title: Option<String>,
        colors: Vec<Option<Color>>,
        char_value: char,
        location: Location,
        size: Size,
    },
    PlotShape {
        title: Option<String>,
        colors: Vec<Option<Color>>,
        style: Shape,
        location: Location,
        size: Size,
    },
    PlotArrow {
        title: Option<String>,
        up_colors: Vec<Option<Color>>,       // 上升箭頭顏色插槽
        down_colors: Vec<Option<Color>>,     // 下降箭頭顏色插槽
    },
    PlotCandle {
        title: Option<String>,
        colors: Vec<Option<Color>>,          // 實體顏色插槽
        wick_colors: Vec<Option<Color>>,
        border_colors: Vec<Option<Color>>,
    },
    PlotBar {
        title: Option<String>,
        colors: Vec<Option<Color>>,
    },
    BackgroundColor {
        title: Option<String>,
        colors: Vec<Option<Color>>,
    },
    Fill {
        title: Option<String>,
        colors: Vec<Option<Color>>,
    },
}

顏色插槽colors 向量包含腳本使用的不重複顏色(按首次出現順序)。None 表示 na / 主題預設值。每個插槽在 SeriesGraphOverride::color_overrides 中有對應位置。

SeriesGraphOverride

rust
pub struct SeriesGraphOverride {
    pub color_overrides: Vec<Option<Color>>,
    pub line_width: Option<i32>,
    pub style: Option<PlotStyle>,
    pub line_style: Option<PlotLineStyle>,
    pub char_value: Option<char>,
    pub shape: Option<Shape>,
    pub location: Option<Location>,
    pub size: Option<Size>,
    pub line_width_overrides: Vec<Option<i32>>,
    pub line_style_overrides: Vec<Option<PlotLineStyle>>,
    pub visible: bool,  // 預設為 true
}

UI 佈局

視覺分頁渲染一個垂直的分區列表 —— 每個序列圖一個分區,按 SeriesGraphId 排序。每個分區顯示:

  1. 一個標題行,包含圖表標題(來自 SeriesGraphConfig::title)或產生的名稱如「Plot #1」。
  2. 色塊 —— 每個不同的顏色插槽一個。
  3. 屬性控件 —— 特定於類型(樣式、寬度、圖形等)。
  4. 可見性切換 —— 核取方塊或開關,控制 SeriesGraphOverride::visible

Plot(折線/面積/直方圖)

最複雜的類型 —— 每個顏色插槽有自己的線條樣式和寬度:

控件欄位
色塊(每個插槽)color_overrides[i]顏色選擇器。顯示為使用有效顏色填充的矩形。None 插槽顯示交叉陰影或「自動」指示器。
線寬(每個插槽)line_width_overrides[i]按鈕組:1、2、3、4 像素。未設定時回退到全域 line_width
線條樣式(每個插槽)line_style_overrides[i]按鈕組或下拉選單:SolidDashedDotted。未設定時回退到全域 line_style
繪圖樣式(全域)style下拉選單,包含所有 PlotStyle 值 —— 見下表。
可見性visible核取方塊 / 開關切換。

PlotStyle 列舉值:

描述
Line連接各 K 線值的連續線
LineBrna 值處斷開的線(不內插)
StepLine階梯線
StepLineBrna 處斷開的階梯線
Area線下方的填充面積
AreaBrna 處斷開的面積
Histogram從零線到值的垂直柱
Columns從零線到值的填充柱
Circles每根 K 線處的圓形標記
Cross每根 K 線處的十字標記
Diamond每根 K 線處的菱形標記

PlotLineStyle 列舉值:

虛線模式
Solid無虛線
Dashed[6, 3]
Dotted[2, 2]

每個插槽的覆寫佈局line_width_overridesline_style_overrides 是與 color_overrides 相同索引的平行陣列。如果陣列長度小於顏色插槽數量,缺失的條目使用全域 line_width / line_style 覆寫值(或設定預設值)。

範例:一個有 3 種不同顏色的 plot 渲染 3 行,每行包含一個色塊 + 線寬按鈕 + 線條樣式按鈕:

[■ #2962FF] [1] [2] [3] [4]  [━━] [╌╌] [∙∙]
[■ #FF6D00] [1] [2] [3] [4]  [━━] [╌╌] [∙∙]
[■ #00BCD4] [1] [2] [3] [4]  [━━] [╌╌] [∙∙]
Style: [Line ▾]                    ☑ Visible

PlotChar(字元標記)

控件欄位
色塊(每個插槽)color_overrides[i]顏色選擇器
字元char_value單字元文字輸入。在每根 K 線上繪製的字元。
位置location下拉選單 —— 見下方 Location 表
大小size下拉選單 —— 見下方 Size 表
可見性visible核取方塊

PlotShape(圖形標記)

控件欄位
色塊(每個插槽)color_overrides[i]顏色選擇器
圖形shape下拉選單 —— 見下方 Shape 表
位置location下拉選單 —— 見下方 Location 表
大小size下拉選單 —— 見下方 Size 表
可見性visible核取方塊

PlotArrow(方向箭頭)

PlotArrow 有兩個獨立的顏色組 —— 上升箭頭和下降箭頭:

控件欄位說明
上升色塊color_overrides[0..up_len]標籤:「上升顏色」。每個不同的上升箭頭顏色一個色塊。
下降色塊color_overrides[up_len..]標籤:「下降顏色」。偏移量為設定中的 up_colors.len()
可見性visible核取方塊

PlotCandle(OHLC K 線)

PlotCandle 有三個顏色組,使用扁平的 color_overrides 佈局:

控件覆寫偏移量標籤
實體色塊0..body_len「實體」
影線色塊body_len..body_len+wick_len「影線」
邊框色塊body_len+wick_len..「邊框」
可見性visible核取方塊

其中 body_len = colors.len()wick_len = wick_colors.len() 來自設定。

PlotBar

控件欄位
色塊(每個插槽)color_overrides[i]
可見性visible

BackgroundColor(bgcolor)

控件欄位
色塊(每個插槽)color_overrides[i]
可見性visible

Fill

控件欄位
色塊(每個插槽)color_overrides[i]
可見性visible

共享列舉值

Location(用於 PlotChar / PlotShape):

描述
AboveBarK 線上方
BelowBarK 線下方
Top窗格頂部
Bottom窗格底部
AbsoluteY 位置來自序列浮點值

Size(用於 PlotChar / PlotShape):

描述
Auto自動大小
Tiny最小
Small
Normal預設
Large
Huge最大

Shape(用於 PlotShape):

描述
XCrossX 形
Cross+ 形
Circle實心圓
Diamond菱形
Square實心方形
TriangleUp向上三角形
TriangleDown向下三角形
ArrowUp向上箭頭
ArrowDown向下箭頭
Flag旗幟
LabelUp向上標籤
LabelDown向下標籤

顏色選擇器

每個色塊點擊後應開啟顏色選擇器,包含:

  1. 預設調色盤 —— 常用顏色網格(如 6x6)。
  2. 十六進制輸入 —— 接受 #RRGGBB 格式的文字欄位。
  3. 透明度滑桿 —— 0-255 範圍,控制 alpha 通道。

顏色編碼:顏色是 RGBA 格式的打包 u32 值:(R << 24) | (G << 16) | (B << 8) | A

rust
// 從 Color 提取分量
let r = color.r(c);     // 0–255
let g = color.g(c);   // 0–255
let b = color.b(c);    // 0–255
let a = color.alpha();   // 0–255

// 從分量建立
let color = Color::from_rgba(255, 0, 0, 255); // 不透明紅色

在 CSS 中顯示:rgba({r}, {g}, {b}, {a / 255})

顏色覆寫編碼

color_overrides 陣列與 SeriesGraphConfig 中的顏色插槽對齊:

  • 單段類型(Plot、PlotChar、PlotShape、PlotBar、BackgroundColor、Fill):color_overrides[i] 對應 colors[i]
  • PlotArrowcolor_overrides = [..up_colors | ..down_colors](串接)。前 up_colors.len() 個項目為上升箭頭覆寫,其餘為下降箭頭。
  • PlotCandlecolor_overrides = [..colors | ..wick_colors | ..border_colors](串接)。

None 項目表示「保留原始顏色」。Some(color) 項目取代原始值。

套用視覺變更

rust
let mut config = cv.script_config(id).unwrap_or_default();
let ovr = config.series_overrides.entry(graph_id).or_default();

// 將第一個顏色插槽覆寫為紅色
ovr.color_overrides = vec![Some(Color::from_rgba(255, 0, 0, 255))];

// 將繪圖樣式改為直方圖
ovr.style = Some(PlotStyle::Histogram);

// 隱藏此序列圖
ovr.visible = false;

cv.set_script_config(id, config);

僅視覺變更會立即重新渲染,無需重新執行腳本。

有效值解析

在 UI 中顯示屬性的目前值時,按三級回退解析:

  1. 覆寫值(來自 SeriesGraphOverride)—— 如已設定,使用它。
  2. 設定預設值(來自 SeriesGraphConfig)—— 腳本的原始值。
  3. 主題預設值 —— 來自圖表主題色彩調色盤的回退顏色。

重設為預設值

要將所有覆寫和輸入重設為原始值:

rust
let mut config = ScriptConfig::default();
// 使用 InputInfo 中的原始預設值重新填入 input_values
for input in &inputs {
    config.input_values.insert(input.idx, input.default_value.clone());
}
// strategy_config_override 預設為 None,無需明確清除
cv.set_script_config(id, config);

這會清除所有 series_overridesstrategy_config_override 並重設輸入,觸發完整的重新執行。

事件流程摘要

使用者點擊圖例工具列上的 ⚙

cv.on_mouse_up(x, y)  →  點擊手勢被偵測到  →  ChartEvent::ConfigureScript(id) 推入佇列

cv.poll_event()  →  宿主收到 ConfigureScript(id)

cv.tag_for(id)                   → 腳本標籤(用於顯示)
cv.script_inputs_effective(id)   → 攜帶目前值的 Vec<InputInfo>
cv.graph_configs(id)             → 每個圖表的 SeriesGraphConfig
cv.script_overrides(id)          → 目前視覺覆寫

你的應用程式開啟設定對話框

使用者編輯輸入或視覺屬性

建構 ScriptConfig { series_overrides, input_values, strategy_config_override }
cv.set_script_config(id, config)

圖表自動重新渲染(僅視覺)或重新執行(輸入或策略配置變更)

如果輸入變更,重新取得 graph_configs(繪圖結構可能改變)

使用者點擊確定 → 關閉對話框
儲存快照以便持久化

參考實作: 參閱 Web playground 中的 ScriptConfigDialog.vue,其中包含此 UI 模式的完整實作。

基於 MIT 許可證發佈。