腳本配置介面
當使用者點擊腳本圖例上的 ⚙ 按鈕時,圖表會推送一個 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>:
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 非空,顯示下拉選單而非自由輸入框。遵循 min、max、step 約束。
Float { value, min, max, step, options } —— 帶小數步長(預設 0.1)的數字輸入框。options、min、max 行為與 Int 相同。
Bool { value } —— 開關切換。
Color { value } —— 色塊 + 顏色選擇器彈窗。顏色為 RGBA 格式的打包 u32:(R << 24) | (G << 16) | (B << 8) | A。顯示為填充矩形;點擊時開啟包含十六進制輸入和透明度滑桿的顏色選擇器。
Str { value, options } —— 文字輸入框。如果 options 非空,顯示下拉選單。
Source { value } —— 固定選項的下拉選單:open、high、low、close、hl2、hlc3、ohlc4、hlcc4。值為 SourceType 列舉。寫入 input_values 時,轉換為整數判別值:open=0、high=1、low=2、close=3、hl2=4、hlc3=5、ohlc4=6、hlcc4=7。
Enum { value, options } —— 下拉選單。options 為 Vec<(i64, String)> ——(判別值,顯示標籤)配對。在 input_values 中儲存判別值。
Symbol { value } —— 股票代碼的文字輸入框(如 "AAPL")。
TimeFrame { value, options } —— 下拉選單或文字輸入。值為 TimeFrame。如果 options 非空,顯示下拉選單。
Session { value, options } —— 交易時段字串的文字輸入框或下拉選單(如 "0930-1600")。
Time { value } —— 日期/時間選擇器。值為自紀元以來的毫秒數(i64)。使用腳本的交易所時區(可透過 cv.timezone() 取得)進行日期時間轉換。
TextArea { value } —— 多行文字區域。
套用輸入變更:
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 中。
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 | 佣金計算方式:percent、cash_per_contract 或 cash_per_order | percent |
commission_value | 佣金金額。percent 模式下為百分比數值(1 = 1%);cash_per_contract 或 cash_per_order 模式下為每合約或每筆訂單的絕對金額。 | 0 |
margin_long | 多頭保證金比率(%) | 100 |
margin_short | 空頭保證金比率(%) | 100 |
slippage | 每筆成交滑點,單位:tick | 0 |
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 | 優先平倉規則:FIFO 或 ANY | FIFO |
strategy_config_override 的變更會觸發完整的 session 重啟(與輸入值變更相同),因為回測結果取決於這些參數。
視覺分頁
視覺分頁顯示每個序列圖的視覺覆寫。取得資料:
let graph_configs: HashMap<SeriesGraphId, SeriesGraphConfig> = cv.graph_configs(id).unwrap();
let overrides: HashMap<SeriesGraphId, SeriesGraphOverride> = cv.script_overrides(id).unwrap();SeriesGraphConfig 變體
SeriesGraphConfig 描述原始(覆寫前)視覺狀態。每個變體對應一種繪圖類型:
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
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 排序。每個分區顯示:
- 一個標題行,包含圖表標題(來自
SeriesGraphConfig::title)或產生的名稱如「Plot #1」。 - 色塊 —— 每個不同的顏色插槽一個。
- 屬性控件 —— 特定於類型(樣式、寬度、圖形等)。
- 可見性切換 —— 核取方塊或開關,控制
SeriesGraphOverride::visible。
Plot(折線/面積/直方圖)
最複雜的類型 —— 每個顏色插槽有自己的線條樣式和寬度:
| 控件 | 欄位 | 值 |
|---|---|---|
| 色塊(每個插槽) | color_overrides[i] | 顏色選擇器。顯示為使用有效顏色填充的矩形。None 插槽顯示交叉陰影或「自動」指示器。 |
| 線寬(每個插槽) | line_width_overrides[i] | 按鈕組:1、2、3、4 像素。未設定時回退到全域 line_width。 |
| 線條樣式(每個插槽) | line_style_overrides[i] | 按鈕組或下拉選單:Solid、Dashed、Dotted。未設定時回退到全域 line_style。 |
| 繪圖樣式(全域) | style | 下拉選單,包含所有 PlotStyle 值 —— 見下表。 |
| 可見性 | visible | 核取方塊 / 開關切換。 |
PlotStyle 列舉值:
| 值 | 描述 |
|---|---|
Line | 連接各 K 線值的連續線 |
LineBr | 在 na 值處斷開的線(不內插) |
StepLine | 階梯線 |
StepLineBr | 在 na 處斷開的階梯線 |
Area | 線下方的填充面積 |
AreaBr | 在 na 處斷開的面積 |
Histogram | 從零線到值的垂直柱 |
Columns | 從零線到值的填充柱 |
Circles | 每根 K 線處的圓形標記 |
Cross | 每根 K 線處的十字標記 |
Diamond | 每根 K 線處的菱形標記 |
PlotLineStyle 列舉值:
| 值 | 虛線模式 |
|---|---|
Solid | 無虛線 |
Dashed | [6, 3] |
Dotted | [2, 2] |
每個插槽的覆寫佈局:line_width_overrides 和 line_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 ▾] ☑ VisiblePlotChar(字元標記)
| 控件 | 欄位 | 值 |
|---|---|---|
| 色塊(每個插槽) | 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):
| 值 | 描述 |
|---|---|
AboveBar | K 線上方 |
BelowBar | K 線下方 |
Top | 窗格頂部 |
Bottom | 窗格底部 |
Absolute | Y 位置來自序列浮點值 |
Size(用於 PlotChar / PlotShape):
| 值 | 描述 |
|---|---|
Auto | 自動大小 |
Tiny | 最小 |
Small | 小 |
Normal | 預設 |
Large | 大 |
Huge | 最大 |
Shape(用於 PlotShape):
| 值 | 描述 |
|---|---|
XCross | X 形 |
Cross | + 形 |
Circle | 實心圓 |
Diamond | 菱形 |
Square | 實心方形 |
TriangleUp | 向上三角形 |
TriangleDown | 向下三角形 |
ArrowUp | 向上箭頭 |
ArrowDown | 向下箭頭 |
Flag | 旗幟 |
LabelUp | 向上標籤 |
LabelDown | 向下標籤 |
顏色選擇器
每個色塊點擊後應開啟顏色選擇器,包含:
- 預設調色盤 —— 常用顏色網格(如 6x6)。
- 十六進制輸入 —— 接受
#RRGGBB格式的文字欄位。 - 透明度滑桿 —— 0-255 範圍,控制 alpha 通道。
顏色編碼:顏色是 RGBA 格式的打包 u32 值:(R << 24) | (G << 16) | (B << 8) | A。
// 從 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]。 - PlotArrow:
color_overrides = [..up_colors | ..down_colors](串接)。前up_colors.len()個項目為上升箭頭覆寫,其餘為下降箭頭。 - PlotCandle:
color_overrides = [..colors | ..wick_colors | ..border_colors](串接)。
None 項目表示「保留原始顏色」。Some(color) 項目取代原始值。
套用視覺變更
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 中顯示屬性的目前值時,按三級回退解析:
- 覆寫值(來自
SeriesGraphOverride)—— 如已設定,使用它。 - 設定預設值(來自
SeriesGraphConfig)—— 腳本的原始值。 - 主題預設值 —— 來自圖表主題色彩調色盤的回退顏色。
重設為預設值
要將所有覆寫和輸入重設為原始值:
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_overrides、strategy_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 模式的完整實作。