输入/搜索内容
内置函数
Global
Version
Sleep
IsVirtual
Mail
Mail_Go
SetErrorFilter
GetPid
GetLastError
GetCommand
GetMeta
Dial
HttpQuery
HttpQuery_Go
Encode
UnixNano
Unix
GetOS
MD5
DBExec
UUID
EventLoop
__Serve
_G
_D
_N
_C
_Cross
JSON.parse
JSON.stringify
SetChannelData
GetChannelData
Log
Market
Trade
Account
Futures
Threads
threading
Thread
getThread
mainThread
currentThread
Lock
Condition
Event
Dict
pending
Thread
ThreadLock
ThreadEvent
ThreadCondition
ThreadDict
TA
Talib
talib.CDL2CROWS
talib.CDL3BLACKCROWS
talib.CDL3INSIDE
talib.CDL3LINESTRIKE
talib.CDL3OUTSIDE
talib.CDL3STARSINSOUTH
talib.CDL3WHITESOLDIERS
talib.CDLABANDONEDBABY
talib.CDLADVANCEBLOCK
talib.CDLBELTHOLD
talib.CDLBREAKAWAY
talib.CDLCLOSINGMARUBOZU
talib.CDLCONCEALBABYSWALL
talib.CDLCOUNTERATTACK
talib.CDLDARKCLOUDCOVER
talib.CDLDOJI
talib.CDLDOJISTAR
talib.CDLDRAGONFLYDOJI
talib.CDLENGULFING
talib.CDLEVENINGDOJISTAR
talib.CDLEVENINGSTAR
talib.CDLGAPSIDESIDEWHITE
talib.CDLGRAVESTONEDOJI
talib.CDLHAMMER
talib.CDLHANGINGMAN
talib.CDLHARAMI
talib.CDLHARAMICROSS
talib.CDLHIGHWAVE
talib.CDLHIKKAKE
talib.CDLHIKKAKEMOD
talib.CDLHOMINGPIGEON
talib.CDLIDENTICAL3CROWS
talib.CDLINNECK
talib.CDLINVERTEDHAMMER
talib.CDLKICKING
talib.CDLKICKINGBYLENGTH
talib.CDLLADDERBOTTOM
talib.CDLLONGLEGGEDDOJI
talib.CDLLONGLINE
talib.CDLMARUBOZU
talib.CDLMATCHINGLOW
talib.CDLMATHOLD
talib.CDLMORNINGDOJISTAR
talib.CDLMORNINGSTAR
talib.CDLONNECK
talib.CDLPIERCING
talib.CDLRICKSHAWMAN
talib.CDLRISEFALL3METHODS
talib.CDLSEPARATINGLINES
talib.CDLSHOOTINGSTAR
talib.CDLSHORTLINE
talib.CDLSPINNINGTOP
talib.CDLSTALLEDPATTERN
talib.CDLSTICKSANDWICH
talib.CDLTAKURI
talib.CDLTASUKIGAP
talib.CDLTHRUSTING
talib.CDLTRISTAR
talib.CDLUNIQUE3RIVER
talib.CDLUPSIDEGAP2CROWS
talib.CDLXSIDEGAP3METHODS
talib.AD
talib.ADOSC
talib.OBV
talib.ACOS
talib.ASIN
talib.ATAN
talib.CEIL
talib.COS
talib.COSH
talib.EXP
talib.FLOOR
talib.LN
talib.LOG10
talib.SIN
talib.SINH
talib.SQRT
talib.TAN
talib.TANH
talib.MAX
talib.MAXINDEX
talib.MIN
talib.MININDEX
talib.MINMAX
talib.MINMAXINDEX
talib.SUM
talib.HT_DCPERIOD
talib.HT_DCPHASE
talib.HT_PHASOR
talib.HT_SINE
talib.HT_TRENDMODE
talib.ATR
talib.NATR
talib.TRANGE
talib.BBANDS
talib.DEMA
talib.EMA
talib.HT_TRENDLINE
talib.KAMA
talib.MA
talib.MAMA
talib.MIDPOINT
talib.MIDPRICE
talib.SAR
talib.SAREXT
talib.SMA
talib.T3
talib.TEMA
talib.TRIMA
talib.WMA
talib.LINEARREG
talib.LINEARREG_ANGLE
talib.LINEARREG_INTERCEPT
talib.LINEARREG_SLOPE
talib.STDDEV
talib.TSF
talib.VAR
talib.ADX
talib.ADXR
talib.APO
talib.AROON
talib.AROONOSC
talib.BOP
talib.CCI
talib.CMO
talib.DX
talib.MACD
talib.MACDEXT
talib.MACDFIX
talib.MFI
talib.MINUS_DI
talib.MINUS_DM
talib.MOM
talib.PLUS_DI
talib.PLUS_DM
talib.PPO
talib.ROC
talib.ROCP
talib.ROCR
talib.ROCR100
talib.RSI
talib.STOCH
talib.STOCHF
talib.STOCHRSI
talib.TRIX
talib.ULTOSC
talib.WILLR
talib.AVGPRICE
talib.MEDPRICE
talib.TYPPRICE
talib.WCLPRICE
OS
结构体
内置变量

在回测系统或实盘页面的状态栏中输出信息。

LogStatus(...msgs)

示例

  • 支持设置输出内容的颜色:

    javascript
    function main() { LogStatus('这是一个普通的状态提示') LogStatus('这是一个红色字体的状态提示#ff0000') LogStatus('这是一个多行的状态信息\n我是第二行') }
    python
    def main(): LogStatus('这是一个普通的状态提示') LogStatus('这是一个红色字体的状态提示#ff0000') LogStatus('这是一个多行的状态信息\n我是第二行')
    rust
    fn main() { LogStatus!("这是一个普通的状态提示"); LogStatus!("这是一个红色字体的状态提示#ff0000"); LogStatus!("这是一个多行的状态信息\n我是第二行"); }
    c++
    void main() { LogStatus("这是一个普通的状态提示"); LogStatus("这是一个红色字体的状态提示#ff0000"); LogStatus("这是一个多行的状态信息\n我是第二行"); }
  • 以下是在状态栏中输出数据的示例:

    javascript
    function main() { var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]} // 将 JSON 序列化后,在字符串两端加上 ` 字符,即可将其识别为一种复杂消息格式(当前支持表格) LogStatus('`' + JSON.stringify(table) + '`') // 表格信息也可以出现在多行文本中 LogStatus('第一行消息\n`' + JSON.stringify(table) + '`\n第三行消息') // 支持同时显示多个表格,它们将以 TAB 形式归为一组显示 LogStatus('`' + JSON.stringify([table, table]) + '`') // 也可以在表格中构造按钮,策略通过 GetCommand 接收 cmd 属性的内容 var table = { type: 'table', title: '持仓操作', cols: ['列1', '列2', 'Action'], rows: [ ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': '平仓'}] ] } LogStatus('`' + JSON.stringify(table) + '`') // 或者构造一个独立的按钮 LogStatus('`' + JSON.stringify({'type':'button', 'cmd': 'coverAll', 'name': '平仓'}) + '`') // 可以自定义按钮样式(Bootstrap 的按钮属性) LogStatus('`' + JSON.stringify({'type':'button', 'class': 'btn btn-xs btn-danger', 'cmd': 'coverAll', 'name': '平仓'}) + '`') }
    python
    import json def main(): table = {"type": "table", "title": "持仓信息", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]} LogStatus('`' + json.dumps(table) + '`') LogStatus('第一行消息\n`' + json.dumps(table) + '`\n第三行消息') LogStatus('`' + json.dumps([table, table]) + '`') table = { "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] } LogStatus('`' + json.dumps(table) + '`') LogStatus('`' + json.dumps({"type": "button", "cmd": "coverAll", "name": "平仓"}) + '`') LogStatus('`' + json.dumps({"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "平仓"}) + '`')
    rust
    fn main() { let table = r#"{"type": "table", "title": "持仓信息", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}"#; // 在 JSON 字符串两端加上 ` 字符,即可将其识别为一种复杂消息格式(当前支持表格) LogStatus!(format!("`{}`", table)); // 表格信息也可以出现在多行文本中 LogStatus!(format!("第一行消息\n`{}`\n第三行消息", table)); // 支持同时显示多个表格,它们将以 TAB 形式归为一组显示 LogStatus!(format!("`[{},{}]`", table, table)); // 也可以在表格中构造按钮,策略通过 GetCommand 接收 cmd 属性的内容 let table = r#"{"type": "table", "title": "持仓操作", "cols": ["列1", "列2", "Action"], "rows": [["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}]]}"#; LogStatus!(format!("`{}`", table)); // 或者构造一个独立的按钮 LogStatus!(r#"`{"type": "button", "cmd": "coverAll", "name": "平仓"}`"#); // 可以自定义按钮样式(Bootstrap 的按钮属性) LogStatus!(r#"`{"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "平仓"}`"#); }
    c++
    void main() { json table = R"({"type": "table", "title": "持仓信息", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]})"_json; LogStatus("`" + table.dump() + "`"); LogStatus("第一行消息\n`" + table.dump() + "`\n第三行消息"); json arr = R"([])"_json; arr.push_back(table); arr.push_back(table); LogStatus("`" + arr.dump() + "`"); table = R"({ "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] })"_json; LogStatus("`" + table.dump() + "`"); LogStatus("`" + R"({"type": "button", "cmd": "coverAll", "name": "平仓"})"_json.dump() + "`"); LogStatus("`" + R"({"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "平仓"})"_json.dump() + "`"); }
  • 支持在状态栏中设计按钮控件(旧版按钮结构):

    javascript
    function main() { var table = { type: "table", title: "状态栏按钮样式", cols: ["默认", "原始", "成功", "信息", "警告", "危险"], rows: [ [ {"type":"button", "class": "btn btn-xs btn-default", "name": "默认"}, {"type":"button", "class": "btn btn-xs btn-primary", "name": "原始"}, {"type":"button", "class": "btn btn-xs btn-success", "name": "成功"}, {"type":"button", "class": "btn btn-xs btn-info", "name": "信息"}, {"type":"button", "class": "btn btn-xs btn-warning", "name": "告警"}, {"type":"button", "class": "btn btn-xs btn-danger", "name": "危险"} ] ] } LogStatus("`" + JSON.stringify(table) + "`") }
    python
    import json def main(): table = { "type": "table", "title": "状态栏按钮样式", "cols": ["默认", "原始", "成功", "信息", "警告", "危险"], "rows": [ [ {"type":"button", "class": "btn btn-xs btn-default", "name": "默认"}, {"type":"button", "class": "btn btn-xs btn-primary", "name": "原始"}, {"type":"button", "class": "btn btn-xs btn-success", "name": "成功"}, {"type":"button", "class": "btn btn-xs btn-info", "name": "信息"}, {"type":"button", "class": "btn btn-xs btn-warning", "name": "告警"}, {"type":"button", "class": "btn btn-xs btn-danger", "name": "危险"} ] ] } LogStatus("`" + json.dumps(table) + "`")
    rust
    fn main() { let table = String::from(r#"{"type": "table", "title": "状态栏按钮样式", "cols": ["默认", "原始", "成功", "信息", "警告", "危险"], "rows": [["#) + r#"{"type": "button", "class": "btn btn-xs btn-default", "name": "默认"},"# + r#"{"type": "button", "class": "btn btn-xs btn-primary", "name": "原始"},"# + r#"{"type": "button", "class": "btn btn-xs btn-success", "name": "成功"},"# + r#"{"type": "button", "class": "btn btn-xs btn-info", "name": "信息"},"# + r#"{"type": "button", "class": "btn btn-xs btn-warning", "name": "告警"},"# + r#"{"type": "button", "class": "btn btn-xs btn-danger", "name": "危险"}"# + r#"]]}"#; LogStatus!(format!("`{}`", table)); }
    c++
    void main() { json table = R"({ "type": "table", "title": "状态栏按钮样式", "cols": ["默认", "原始", "成功", "信息", "警告", "危险"], "rows": [ [ {"type":"button", "class": "btn btn-xs btn-default", "name": "默认"}, {"type":"button", "class": "btn btn-xs btn-primary", "name": "原始"}, {"type":"button", "class": "btn btn-xs btn-success", "name": "成功"}, {"type":"button", "class": "btn btn-xs btn-info", "name": "信息"}, {"type":"button", "class": "btn btn-xs btn-warning", "name": "告警"}, {"type":"button", "class": "btn btn-xs btn-danger", "name": "危险"} ] ] })"_json; LogStatus("`" + table.dump() + "`"); }
  • 设置状态栏按钮的禁用及描述功能(旧版按钮结构):

    javascript
    function main() { var table = { type: "table", title: "状态栏按钮的禁用、描述功能测试", cols: ["列1", "列2", "列3"], rows: [] } var button1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} var button2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": true} var button3 = {"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": false} table.rows.push([button1, button2, button3]) LogStatus("`" + JSON.stringify(table) + "`") }
    python
    import json def main(): table = { "type": "table", "title": "状态栏按钮的禁用、描述功能测试", "cols": ["列1", "列2", "列3"], "rows": [] } button1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} button2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": True} button3 = {"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": False} table["rows"].append([button1, button2, button3]) LogStatus("`" + json.dumps(table) + "`")
    rust
    fn main() { let button1 = r#"{"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"}"#; let button2 = r#"{"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": true}"#; let button3 = r#"{"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": false}"#; let table = format!( r#"{{"type": "table", "title": "状态栏按钮的禁用、描述功能测试", "cols": ["列1", "列2", "列3"], "rows": [[{}, {}, {}]]}}"#, button1, button2, button3 ); LogStatus!(format!("`{}`", table)); }
    c++
    void main() { json table = R"({ "type": "table", "title": "状态栏按钮的禁用、描述功能测试", "cols": ["列1", "列2", "列3"], "rows": [] })"_json; json button1 = R"({"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"})"_json; json button2 = R"({"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": true})"_json; json button3 = R"({"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": false})"_json; json arr = R"([])"_json; arr.push_back(button1); arr.push_back(button2); arr.push_back(button3); table["rows"].push_back(arr); LogStatus("`" + table.dump() + "`"); }
  • 结合 GetCommand() 函数,构造状态栏按钮的交互功能(旧版按钮结构):

    javascript
    function test1() { Log("调用自定义函数") } function main() { while (true) { var table = { type: 'table', title: '操作', cols: ['列1', '列2', 'Action'], rows: [ ['a', '1', { 'type': 'button', 'cmd': "CoverAll", 'name': '平仓' }], ['b', '1', { 'type': 'button', 'cmd': 10, 'name': '发送数值' }], ['c', '1', { 'type': 'button', 'cmd': _D(), 'name': '调用函数' }], ['d', '1', { 'type': 'button', 'cmd': 'test1', 'name': '调用自定义函数' }] ] } LogStatus(_D(), "\n", '`' + JSON.stringify(table) + '`') var str_cmd = GetCommand() if (str_cmd) { Log("接收到的交互数据 str_cmd:", "类型:", typeof(str_cmd), "值:", str_cmd) if(str_cmd == "test1") { test1() } } Sleep(500) } }
    python
    import json def test1(): Log("调用自定义函数") def main(): while True: table = { "type": "table", "title": "操作", "cols": ["列1", "列2", "Action"], "rows": [ ["a", "1", { "type": "button", "cmd": "CoverAll", "name": "平仓" }], ["b", "1", { "type": "button", "cmd": 10, "name": "发送数值" }], ["c", "1", { "type": "button", "cmd": _D(), "name": "调用函数" }], ["d", "1", { "type": "button", "cmd": "test1", "name": "调用自定义函数" }] ] } LogStatus(_D(), "\n", "`" + json.dumps(table) + "`") str_cmd = GetCommand() if str_cmd: Log("接收到的交互数据 str_cmd", "类型:", type(str_cmd), "值:", str_cmd) if str_cmd == "test1": test1() Sleep(500)
    rust
    fn test1() { Log!("调用自定义函数"); } fn main() { loop { let table = String::from(r#"{"type": "table", "title": "操作", "cols": ["列1", "列2", "Action"], "rows": ["#) + r#"["a", "1", {"type": "button", "cmd": "CoverAll", "name": "平仓"}],"# + r#"["b", "1", {"type": "button", "cmd": 10, "name": "发送数值"}],"# + &format!(r#"["c", "1", {{"type": "button", "cmd": "{}", "name": "调用函数"}}],"#, _D(None)) + r#"["d", "1", {"type": "button", "cmd": "test1", "name": "调用自定义函数"}]"# + r#"]}"#; LogStatus!(_D(None), "\n", format!("`{}`", table)); if let Some(str_cmd) = GetCommand(0) { Log!("接收到的交互数据 str_cmd:", "类型:", "String", "值:", &str_cmd); if str_cmd == "test1" { test1(); } } Sleep(500); } }
    c++
    void test1() { Log("调用自定义函数"); } void main() { while(true) { json table = R"({ "type": "table", "title": "操作", "cols": ["列1", "列2", "Action"], "rows": [ ["a", "1", { "type": "button", "cmd": "CoverAll", "name": "平仓" }], ["b", "1", { "type": "button", "cmd": 10, "name": "发送数值" }], ["c", "1", { "type": "button", "cmd": "", "name": "调用函数" }], ["d", "1", { "type": "button", "cmd": "test1", "name": "调用自定义函数" }] ] })"_json; table["rows"][2][2]["cmd"] = _D(); LogStatus(_D(), "\n", "`" + table.dump() + "`"); auto str_cmd = GetCommand(); if(str_cmd != "") { Log("接收到的交互数据 str_cmd", "类型:", typeid(str_cmd).name(), "值:", str_cmd); if(str_cmd == "test1") { test1(); } } Sleep(500); } }
  • 在构造状态栏按钮进行交互时,同样支持输入数据,交互指令最终由GetCommand()函数捕获。

    在状态栏按钮控件的数据结构中增加input项(旧版按钮结构)。例如,为{"type": "button", "cmd": "open", "name": "开仓"}增加:"input": {"name": "开仓数量", "type": "number", "defValue": 1},即可使该按钮在被点击时弹出一个带输入框控件的弹窗(输入框中的默认值为1,即defValue所设置的数据),从而在输入一个数据后与按钮命令一起发送。例如运行以下测试代码,点击「开仓」按钮后会弹出一个带输入框的弹窗,在输入框中输入111并点击「确定」,GetCommand()函数便会捕获到消息:open:111

    javascript
    function main() { var tbl = { type: "table", title: "操作", cols: ["列1", "列2"], rows: [ ["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}], ["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}] ] } LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`") while (true) { var cmd = GetCommand() if (cmd) { Log("cmd:", cmd) } Sleep(1000) } }
    python
    import json def main(): tbl = { "type": "table", "title": "操作", "cols": ["列1", "列2"], "rows": [ ["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}], ["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}] ] } LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`") while True: cmd = GetCommand() if cmd: Log("cmd:", cmd) Sleep(1000)
    rust
    fn main() { let tbl = String::from(r#"{"type": "table", "title": "操作", "cols": ["列1", "列2"], "rows": ["#) + r#"["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}],"# + r#"["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}]"# + r#"]}"#; LogStatus!(_D(None), "\n", format!("`{}`", tbl)); loop { if let Some(cmd) = GetCommand(0) { Log!("cmd:", cmd); } Sleep(1000); } }
    c++
    void main() { json tbl = R"({ "type": "table", "title": "操作", "cols": ["列1", "列2"], "rows": [ ["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}], ["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}] ] })"_json; LogStatus(_D(), "\n", "`" + tbl.dump() + "`"); while(true) { auto cmd = GetCommand(); if(cmd != "") { Log("cmd:", cmd); } Sleep(1000); } }
  • 支持分组按钮控件(旧版按钮结构),其功能与支持输入数据的状态栏按钮(使用"input"字段设置)一致。交互指令最终由GetCommand()函数捕获。区别在于:分组按钮控件通过"group"字段进行设置,当点击按钮触发交互时,页面弹出的对话框中会显示预先设置好的一组输入控件,可以一次性输入一组数据。

    关于状态栏按钮控件与分组按钮控件结构中的"group"字段,需要注意以下几点:

    • group中type属性仅支持以下4种类型,defValue属性用于设置默认值。
      "selected":下拉框控件,设置下拉框的各个选项时使用|符号分隔。
      "number":数值输入框控件。
      "string":字符串输入框控件。
      "boolean":勾选框控件,勾选表示(布尔值)真,不勾选表示(布尔值)假。
    • 交互输入时的控件支持依赖设置:
      例如以下例子中的"name": "tradePrice@orderType==1"设置,使交易价格tradePrice)输入控件仅在下单方式(orderType)下拉框控件选择为挂单时可用。
    • 交互输入时的控件名称支持双语设置:
      例如以下例子中的"description": "下单方式|order type"设置,使用|符号分隔中英文描述内容。
    • group中的namedescription与按钮结构中的namedescription虽然字段名一致,但定义并不相同:
      group中的name与input中的name定义也不相同。
    • 分组按钮控件触发后,发送的交互内容格式为:按钮的cmd字段值,加上group字段的相关数据。例如以下例子测试时Log("cmd:", cmd)语句输出的内容:
      cmd: open:{"orderType":1,"tradePrice":99,"orderAmount":"99","boolean":true},即发生交互操作时GetCommand()函数返回的内容:open:{"orderType":1,"tradePrice":99,"orderAmount":"99","boolean":true}
    • 按钮控件的type属性仅支持"button"
      支持输入数据的按钮控件,即设置了input属性的控件,其input字段的配置信息中的type属性支持多种控件类型。
      参考以下例子:
    javascript
    function main() { var tbl = { type: "table", title: "演示分组按钮控件", cols: ["操作"], rows: [] } // 创建分组按钮控件结构 var groupBtn = { type: "button", cmd: "open", name: "开仓", group: [ {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"}, {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100}, {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100}, {"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": true} ] } // 测试按钮1 var testBtn1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} var testBtn2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}} // 在tbl中添加groupBtn tbl.rows.push([groupBtn]) // 支持状态栏表格的一个单元格内设置多个按钮,即一个单元格内的数据为一个按钮结构数组:[testBtn1, testBtn2] tbl.rows.push([[testBtn1, testBtn2]]) while (true) { LogStatus("`" + JSON.stringify(tbl) + "`", "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", "`" + JSON.stringify(groupBtn) + "`") var cmd = GetCommand() if (cmd) { Log("cmd:", cmd) } Sleep(5000) } }
    python
    import json def main(): tbl = { "type": "table", "title": "演示分组按钮控件", "cols": ["操作"], "rows": [] } groupBtn = { "type": "button", "cmd": "open", "name": "开仓", "group": [ {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"}, {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100}, {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100}, {"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": True} ] } testBtn1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} testBtn2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}} tbl["rows"].append([groupBtn]) tbl["rows"].append([[testBtn1, testBtn2]]) while True: LogStatus("`" + json.dumps(tbl) + "`", "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", "`" + json.dumps(groupBtn) + "`") cmd = GetCommand() if cmd: Log("cmd:", cmd) Sleep(5000)
    rust
    fn main() { // 创建分组按钮控件结构 let group_btn = String::from(r#"{"type": "button", "cmd": "open", "name": "开仓", "group": ["#) + r#"{"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"},"# + r#"{"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100},"# + r#"{"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100},"# + r#"{"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": true}"# + r#"]}"#; // 测试按钮1、测试按钮2 let test_btn1 = r#"{"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"}"#; let test_btn2 = r#"{"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}"#; // 在tbl中添加groupBtn;支持状态栏表格的一个单元格内设置多个按钮,即一个单元格内的数据为一个按钮结构数组:[testBtn1, testBtn2] let tbl = format!( r#"{{"type": "table", "title": "演示分组按钮控件", "cols": ["操作"], "rows": [[{}], [[{}, {}]]]}}"#, group_btn, test_btn1, test_btn2 ); loop { LogStatus!(format!("`{}`", tbl), "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", format!("`{}`", group_btn)); if let Some(cmd) = GetCommand(0) { Log!("cmd:", cmd); } Sleep(5000); } }
    c++
    void main() { json tbl = R"({ "type": "table", "title": "演示分组按钮控件", "cols": ["操作"], "rows": [] })"_json; json groupBtn = R"({ "type": "button", "name": "开仓", "cmd": "open", "group": [ {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"}, {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100}, {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100}, {"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": true} ]})"_json; json testBtn1 = R"({"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"})"_json; json testBtn2 = R"({"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}})"_json; tbl["rows"].push_back({groupBtn}); tbl["rows"].push_back({{testBtn1, testBtn2}}); while(true) { LogStatus("`" + tbl.dump() + "`", "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", "`" + groupBtn.dump() + "`"); auto cmd = GetCommand(); if(cmd != "") { Log("cmd:", cmd); } Sleep(5000); } }
  • 当状态栏分组按钮控件(通过设置group字段实现)与状态栏按钮控件(通过设置input字段实现)被点击触发交互时(旧版按钮结构),页面弹出对话框中的下拉框控件同样支持多选。以下示例演示如何设计包含多选选项的下拉框控件:

    javascript
    function main() { // 状态栏按钮控件(通过设置input字段实现)中,testBtn1按钮触发页面的下拉框控件通过options字段设置选项,并通过defValue字段设置默认选项。此方式区别于本章其它示例中直接使用defValue设置选项的做法。 var testBtn1 = { type: "button", name: "testBtn1", cmd: "cmdTestBtn1", input: {name: "testBtn1ComboBox", type: "selected", options: ["A", "B"], defValue: 1} } /* 状态栏按钮控件(通过设置input字段实现)中,testBtn2按钮触发页面的下拉框控件通过options字段设置选项。options字段中的选项不仅支持字符串, 也支持使用```{text: "描述", value: "值"}```结构。defValue字段用于设置默认选项,默认选项可以为多选(通过数组结构实现多选)。多选时需额外将multiple字段设置为真值(true)。 */ var testBtn2 = { type: "button", name: "testBtn2", cmd: "cmdTestBtn2", input: { name: "testBtn2MultiComboBox", type: "selected", description: "实现下拉框多选", options: [{text: "选项A", value: "A"}, {text: "选项B", value: "B"}, {text: "选项C", value: "C"}], defValue: ["A", "C"], multiple: true } } // 状态栏分组按钮控件(通过设置group字段实现)中,testBtn3按钮触发页面的下拉框控件通过options字段设置选项,也支持直接使用defValue设置选项。 var testBtn3 = { type: "button", name: "testBtn3", cmd: "cmdTestBtn3", group: [ {name: "comboBox1", label: "labelComboBox1", description: "下拉框1", type: "selected", defValue: 1, options: ["A", "B"]}, {name: "comboBox2", label: "labelComboBox2", description: "下拉框2", type: "selected", defValue: "A|B"}, {name: "comboBox3", label: "labelComboBox3", description: "下拉框3", type: "selected", defValue: [0, 2], multiple: true, options: ["A", "B", "C"]}, { name: "comboBox4", label: "labelComboBox4", description: "下拉框4", type: "selected", defValue: ["A", "C"], multiple: true, options: [{text: "选项A", value: "A"}, {text: "选项B", value: "B"}, {text: "选项C", value: "C"}, {text: "选项D", value: "D"}] } ] } while (true) { LogStatus("`" + JSON.stringify(testBtn1) + "`\n", "`" + JSON.stringify(testBtn2) + "`\n", "`" + JSON.stringify(testBtn3) + "`\n") var cmd = GetCommand() if (cmd) { Log(cmd) } Sleep(5000) } }
    python
    import json def main(): testBtn1 = { "type": "button", "name": "testBtn1", "cmd": "cmdTestBtn1", "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1} } testBtn2 = { "type": "button", "name": "testBtn2", "cmd": "cmdTestBtn2", "input": { "name": "testBtn2MultiComboBox", "type": "selected", "description": "实现下拉框多选", "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}], "defValue": ["A", "C"], "multiple": True } } testBtn3 = { "type": "button", "name": "testBtn3", "cmd": "cmdTestBtn3", "group": [ {"name": "comboBox1", "label": "labelComboBox1", "description": "下拉框1", "type": "selected", "defValue": 1, "options": ["A", "B"]}, {"name": "comboBox2", "label": "labelComboBox2", "description": "下拉框2", "type": "selected", "defValue": "A|B"}, {"name": "comboBox3", "label": "labelComboBox3", "description": "下拉框3", "type": "selected", "defValue": [0, 2], "multiple": True, "options": ["A", "B", "C"]}, { "name": "comboBox4", "label": "labelComboBox4", "description": "下拉框4", "type": "selected", "defValue": ["A", "C"], "multiple": True, "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}, {"text": "选项D", "value": "D"}] } ] } while True: LogStatus("`" + json.dumps(testBtn1) + "`\n", "`" + json.dumps(testBtn2) + "`\n", "`" + json.dumps(testBtn3) + "`\n") cmd = GetCommand() if cmd: Log(cmd) Sleep(5000)
    rust
    fn main() { // 状态栏按钮控件(通过设置input字段实现)中,testBtn1按钮触发页面的下拉框控件通过options字段设置选项,并通过defValue字段设置默认选项。此方式区别于本章其它示例中直接使用defValue设置选项的做法。 let test_btn1 = r#"{"type": "button", "name": "testBtn1", "cmd": "cmdTestBtn1", "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1}}"#; /* 状态栏按钮控件(通过设置input字段实现)中,testBtn2按钮触发页面的下拉框控件通过options字段设置选项。options字段中的选项不仅支持字符串, 也支持使用{"text": "描述", "value": "值"}结构。defValue字段用于设置默认选项,默认选项可以为多选(通过数组结构实现多选)。多选时需额外将multiple字段设置为真值(true)。 */ let test_btn2 = String::from(r#"{"type": "button", "name": "testBtn2", "cmd": "cmdTestBtn2", "input": {"#) + r#""name": "testBtn2MultiComboBox", "type": "selected", "description": "实现下拉框多选","# + r#""options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}],"# + r#""defValue": ["A", "C"], "multiple": true}}"#; // 状态栏分组按钮控件(通过设置group字段实现)中,testBtn3按钮触发页面的下拉框控件通过options字段设置选项,也支持直接使用defValue设置选项。 let test_btn3 = String::from(r#"{"type": "button", "name": "testBtn3", "cmd": "cmdTestBtn3", "group": ["#) + r#"{"name": "comboBox1", "label": "labelComboBox1", "description": "下拉框1", "type": "selected", "defValue": 1, "options": ["A", "B"]},"# + r#"{"name": "comboBox2", "label": "labelComboBox2", "description": "下拉框2", "type": "selected", "defValue": "A|B"},"# + r#"{"name": "comboBox3", "label": "labelComboBox3", "description": "下拉框3", "type": "selected", "defValue": [0, 2], "multiple": true, "options": ["A", "B", "C"]},"# + r#"{"name": "comboBox4", "label": "labelComboBox4", "description": "下拉框4", "type": "selected", "defValue": ["A", "C"], "multiple": true, "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}, {"text": "选项D", "value": "D"}]}"# + r#"]}"#; loop { LogStatus!(format!("`{}`\n", test_btn1), format!("`{}`\n", test_btn2), format!("`{}`\n", test_btn3)); if let Some(cmd) = GetCommand(0) { Log!(cmd); } Sleep(5000); } }
    c++
    void main() { json testBtn1 = R"({ "type": "button", "name": "testBtn1", "cmd": "cmdTestBtn1", "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1} })"_json; json testBtn2 = R"({ "type": "button", "name": "testBtn2", "cmd": "cmdTestBtn2", "input": { "name": "testBtn2MultiComboBox", "type": "selected", "description": "实现下拉框多选", "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}], "defValue": ["A", "C"], "multiple": true } })"_json; json testBtn3 = R"({ "type": "button", "name": "testBtn3", "cmd": "cmdTestBtn3", "group": [ {"name": "comboBox1", "label": "labelComboBox1", "description": "下拉框1", "type": "selected", "defValue": 1, "options": ["A", "B"]}, {"name": "comboBox2", "label": "labelComboBox2", "description": "下拉框2", "type": "selected", "defValue": "A|B"}, {"name": "comboBox3", "label": "labelComboBox3", "description": "下拉框3", "type": "selected", "defValue": [0, 2], "multiple": true, "options": ["A", "B", "C"]}, { "name": "comboBox4", "label": "labelComboBox4", "description": "下拉框4", "type": "selected", "defValue": ["A", "C"], "multiple": true, "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}, {"text": "选项D", "value": "D"}] } ] })"_json; while (true) { LogStatus("`" + testBtn1.dump() + "`\n", "`" + testBtn2.dump() + "`\n", "`" + testBtn3.dump() + "`\n"); auto cmd = GetCommand(); if (cmd != "") { Log(cmd); } Sleep(5000); } }
  • 使用当前最新的按钮结构,在状态栏表格中构造按钮;点击按钮触发交互时,会弹出一个包含多个控件的弹窗。

    详细内容请参阅:用户指南-状态栏中的交互控件

    javascript
    var symbols = ["rb2410", "MA501", "hc2501", "i2501", "TA888"] function createBtn(tmp, group) { var btn = JSON.parse(JSON.stringify(tmp)) _.each(group, function(eleByGroup) { btn["group"].unshift(eleByGroup) }) return btn } function main() { var arrManager = [] _.each(symbols, function(symbol) { arrManager.push({ "symbol": symbol, }) }) // Btn var tmpBtnOpen = { "type": "button", "cmd": "open", "name": "开仓下单", "group": [{ "type": "selected", "name": "tradeType", "label": "下单类型", "description": "市价单、限价单", "default": 0, "group": "交易设置", "settings": { "options": ["市价单", "限价单"], "required": true, } }, { "type": "selected", "name": "direction", "label": "交易方向", "description": "买入、卖出", "default": "buy", "group": "交易设置", "settings": { "render": "segment", "required": true, "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}], } }, { "type": "number", "name": "price", "label": "价格", "description": "订单的价格", "group": "交易设置", "filter": "tradeType==1", "settings": { "required": true, } }, { "type": "number", "name": "amount", "label": "下单量", "description": "订单的下单量", "group": "交易设置", "settings": { "required": true, } }], } while (true) { var tbl = {"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": []} _.each(arrManager, function(m) { var btnOpen = createBtn(tmpBtnOpen, [{"type": "string", "name": "symbol", "label": "交易品种", "default": m["symbol"], "settings": {"required": true}}]) tbl["rows"].push([m["symbol"], btnOpen]) }) var cmd = GetCommand() if (cmd) { Log("收到交互:", cmd) // 解析交互消息: open:{"symbol":"TA888","tradeType":0,"direction":"buy","amount":111} // 根据第一个冒号:之前的指令判断是哪种按钮模板触发的消息 var arrCmd = cmd.split(":", 2) if (arrCmd[0] == "open") { var msg = JSON.parse(cmd.slice(5)) Log("交易品种:", msg["symbol"], ",交易方向:", msg["direction"], ",订单类型:", msg["tradeType"] == 0 ? "市价单" : "限价单", msg["tradeType"] == 0 ? ",订单价格:当前市价" : ",订单价格:" + msg["price"], ",订单数量:", msg["amount"]) } } LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`") Sleep(1000) } }
    python
    import json symbols = ["rb2410", "MA501", "hc2501", "i2501", "TA888"] def createBtn(tmp, group): btn = json.loads(json.dumps(tmp)) for eleByGroup in group: btn["group"].insert(0, eleByGroup) return btn def main(): arrManager = [] for symbol in symbols: arrManager.append({"symbol": symbol}) # Btn tmpBtnOpen = { "type": "button", "cmd": "open", "name": "开仓下单", "group": [{ "type": "selected", "name": "tradeType", "label": "下单类型", "description": "市价单、限价单", "default": 0, "group": "交易设置", "settings": { "options": ["市价单", "限价单"], "required": True, } }, { "type": "selected", "name": "direction", "label": "交易方向", "description": "买入、卖出", "default": "buy", "group": "交易设置", "settings": { "render": "segment", "required": True, "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}], } }, { "type": "number", "name": "price", "label": "价格", "description": "订单的价格", "group": "交易设置", "filter": "tradeType==1", "settings": { "required": True, } }, { "type": "number", "name": "amount", "label": "下单量", "description": "订单的下单量", "group": "交易设置", "settings": { "required": True, } }], } while True: tbl = {"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": []} for m in arrManager: btnOpen = createBtn(tmpBtnOpen, [{"type": "string", "name": "symbol", "label": "交易品种", "default": m["symbol"], "settings": {"required": True}}]) tbl["rows"].append([m["symbol"], btnOpen]) cmd = GetCommand() if cmd != "" and cmd != None: Log("收到交互:", cmd) # 解析交互消息: open:{"symbol":"TA888","tradeType":0,"direction":"buy","amount":111} # 根据第一个冒号:之前的指令判断是哪种按钮模板触发的消息 arrCmd = cmd.split(":") if arrCmd[0] == "open": msg = json.loads(cmd[5:]) Log("交易品种:", msg["symbol"], ",交易方向:", msg["direction"], ",订单类型:", "市价单" if msg["tradeType"] == 0 else "限价单", ",订单价格:当前市价" if msg["tradeType"] == 0 else ",订单价格:" + str(msg["price"]), ",订单数量:", msg["amount"]) # 输出状态栏信息 LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`") Sleep(1000)
    rust
    fn main() { let symbols = ["rb2410", "MA501", "hc2501", "i2501", "TA888"]; // Btn:按钮模板,"group"的第一个元素为交易品种控件,__SYMBOL__为占位符,构造按钮时替换 let tmp_btn_open = String::from(r#"{"type": "button", "cmd": "open", "name": "开仓下单", "group": ["#) + r#"{"type": "string", "name": "symbol", "label": "交易品种", "default": "__SYMBOL__", "settings": {"required": true}},"# + r#"{"type": "selected", "name": "tradeType", "label": "下单类型", "description": "市价单、限价单", "default": 0, "group": "交易设置", "settings": {"options": ["市价单", "限价单"], "required": true}},"# + r#"{"type": "selected", "name": "direction", "label": "交易方向", "description": "买入、卖出", "default": "buy", "group": "交易设置", "settings": {"render": "segment", "required": true, "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}]}},"# + r#"{"type": "number", "name": "price", "label": "价格", "description": "订单的价格", "group": "交易设置", "filter": "tradeType==1", "settings": {"required": true}},"# + r#"{"type": "number", "name": "amount", "label": "下单量", "description": "订单的下单量", "group": "交易设置", "settings": {"required": true}}"# + r#"]}"#; loop { let mut rows: Vec<String> = Vec::new(); for symbol in &symbols { let btn_open = tmp_btn_open.replace("__SYMBOL__", symbol); rows.push(format!(r#"["{}", {}]"#, symbol, btn_open)); } let tbl = format!(r#"{{"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": [{}]}}"#, rows.join(",")); if let Some(cmd) = GetCommand(0) { Log!("收到交互:", &cmd); // 解析交互消息: open:{"symbol":"TA888","tradeType":0,"direction":"buy","amount":111} // 根据第一个冒号:之前的指令判断是哪种按钮模板触发的消息 if cmd.starts_with("open:") { let msg = JSONParse(&cmd[5..]).unwrap(); let trade_type = msg["tradeType"].as_i64().unwrap_or(0); Log!("交易品种:", msg["symbol"].as_str().unwrap_or(""), ",交易方向:", msg["direction"].as_str().unwrap_or(""), ",订单类型:", if trade_type == 0 { "市价单" } else { "限价单" }, if trade_type == 0 { ",订单价格:当前市价".to_string() } else { format!(",订单价格:{}", msg["price"].as_f64().unwrap_or(0.0)) }, ",订单数量:", msg["amount"].as_f64().unwrap_or(0.0)); } } LogStatus!(_D(None), "\n", format!("`{}`", tbl)); Sleep(1000); } }
    c++
    // 略...
  • 横向合并 LogStatus() 函数绘制的表格中的单元格:

    javascript
    function main() { var table = { type: 'table', title: '持仓操作', cols: ['列1', '列2', 'Action'], rows: [ ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': '平仓'}] ] } // 由于是测试代码,未采用商品期货策略的通用架构,此处仅判断 exchange.IO("status") 函数 while(!exchange.IO("status")) { Sleep(1000) } exchange.SetContractType("rb888") var ticker = exchange.GetTicker() // 添加一行数据,将第一个和第二个单元格合并,并在合并后的单元格内输出 ticker 变量 table.rows.push([{body : JSON.stringify(ticker), colspan : 2}, "abc"]) LogStatus('`' + JSON.stringify(table) + '`') }
    python
    import json def main(): table = { "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] } while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") ticker = exchange.GetTicker() table["rows"].append([{"body": json.dumps(ticker), "colspan": 2}, "abc"]) LogStatus("`" + json.dumps(table) + "`")
    rust
    fn main() { let table_tpl = String::from(r#"{"type": "table", "title": "持仓操作", "cols": ["列1", "列2", "Action"], "rows": ["#) + r#"["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}],"# + r#"__ROW2__"# + r#"]}"#; // 由于是测试代码,未采用商品期货策略的通用架构,此处仅判断 exchange.IO("status") 函数 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } exchange.SetContractType("rb888").unwrap(); let ticker = exchange.GetTicker(None).unwrap(); let json_ticker = format!( r#"{{"Buy": {}, "Sell": {}, "High": {}, "Low": {}, "Volume": {}, "Last": {}, "Time": {}}}"#, ticker.Buy, ticker.Sell, ticker.High, ticker.Low, ticker.Volume, ticker.Last, ticker.Time ); // 添加一行数据,将第一个和第二个单元格合并,并在合并后的单元格内输出 ticker 数据 let row2 = format!(r#"[{{"body": {}, "colspan": 2}}, "abc"]"#, json_ticker); let table = table_tpl.replace("__ROW2__", &row2); LogStatus!(format!("`{}`", table)); }
    c++
    void main() { json table = R"({ "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] })"_json; while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); auto ticker = exchange.GetTicker(); json jsonTicker = R"({"Buy": 0, "Sell": 0, "High": 0, "Low": 0, "Volume": 0, "Last": 0, "Time": 0})"_json; jsonTicker["Buy"] = ticker.Buy; jsonTicker["Sell"] = ticker.Sell; jsonTicker["Last"] = ticker.Last; jsonTicker["Volume"] = ticker.Volume; jsonTicker["Time"] = ticker.Time; jsonTicker["High"] = ticker.High; jsonTicker["Low"] = ticker.Low; json arr = R"([{"body": {}, "colspan": 2}, "abc"])"_json; arr[0]["body"] = jsonTicker; table["rows"].push_back(arr); LogStatus("`" + table.dump() + "`"); }
  • 纵向合并 LogStatus() 函数绘制的表格中的单元格:

    javascript
    function main() { var table = { type: 'table', title: '表格演示', cols: ['列A', '列B', '列C'], rows: [ ['A1', 'B1', {'type':'button', 'cmd': 'coverAll', 'name': 'C1'}] ] } // 由于是测试代码,此处不采用商品期货策略的通用架构 while(!exchange.IO("status")) { Sleep(1000) } exchange.SetContractType("rb888") var ticker = exchange.GetTicker() var name = exchange.GetName() table.rows.push([{body : "A2 + B2:" + JSON.stringify(ticker), colspan : 2}, "C2"]) table.rows.push([{body : "A3 + A4 + A5:" + name, rowspan : 3}, "B3", "C3"]) // A3 被上一行的第一个单元格合并 table.rows.push(["B4", "C4"]) // A2 被上一行的第一个单元格合并 table.rows.push(["B5", "C5"]) table.rows.push(["A6", "B6", "C6"]) LogStatus('`' + JSON.stringify(table) + '`') }
    python
    import json def main(): table = { "type" : "table", "title" : "表格演示", "cols" : ["列A", "列B", "列C"], "rows" : [ ["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}] ] } while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") ticker = exchange.GetTicker() name = exchange.GetName() table["rows"].append([{"body": "A2 + B2:" + json.dumps(ticker), "colspan": 2}, "C2"]) table["rows"].append([{"body": "A3 + A4 + A5:" + name, "rowspan": 3}, "B3", "C3"]) table["rows"].append(["B4", "C4"]) table["rows"].append(["B5", "C5"]) table["rows"].append(["A6", "B6", "C6"]) LogStatus("`" + json.dumps(table) + "`")
    rust
    fn main() { // 为了便于测试,代码力求简短易读,此处使用构造的数据 let json_ticker = r#"{"High": 0, "Low": 0, "Buy": 0, "Sell": 0, "Last": 0, "Time": 0, "Volume": 0}"#; let name = exchange.GetName(); let mut rows: Vec<String> = Vec::new(); rows.push(String::from(r#"["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}]"#)); // body 为字符串,其中的引号需转义后再嵌入 JSON let body = format!("A2 + B2:{}", json_ticker).replace('"', "\\\""); rows.push(format!(r#"[{{"body": "{}", "colspan": 2}}, "C2"]"#, body)); rows.push(format!(r#"[{{"body": "A3 + A4 + A5:{}", "rowspan": 3}}, "B3", "C3"]"#, name)); // A3 被上一行的第一个单元格合并 rows.push(String::from(r#"["B4", "C4"]"#)); // A4 被合并 rows.push(String::from(r#"["B5", "C5"]"#)); rows.push(String::from(r#"["A6", "B6", "C6"]"#)); let table = format!(r#"{{"type": "table", "title": "表格演示", "cols": ["列A", "列B", "列C"], "rows": [{}]}}"#, rows.join(",")); LogStatus!(format!("`{}`", table)); }
    c++
    void main() { json table = R"({ "type" : "table", "title" : "表格演示", "cols" : ["列A", "列B", "列C"], "rows" : [ ["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}] ] })"_json; // 为了便于测试,代码力求简短易读,此处使用构造的数据 json jsonTicker = R"({"High": 0, "Low": 0, "Buy": 0, "Sell": 0, "Last": 0, "Time": 0, "Volume": 0})"_json; auto name = exchange.GetName(); json arr1 = R"([{"body": "", "colspan": 2}, "C2"])"_json; arr1[0]["body"] = "A2 + B2:" + jsonTicker.dump(); json arr2 = R"([{"body": "", "rowspan": 3}, "B3", "C3"])"_json; arr2[0]["body"] = "A3 + A4 + A5:" + name; table["rows"].push_back(arr1); table["rows"].push_back(arr2); table["rows"].push_back(R"(["B4", "C4"])"_json); table["rows"].push_back(R"(["B5", "C5"])"_json); table["rows"].push_back(R"(["A6", "B6", "C6"])"_json); LogStatus("`" + table.dump() + "`"); }
  • 状态栏表格分页显示:

    javascript
    function main() { var table1 = {type: 'table', title: 'table1', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]} var table2 = {type: 'table', title: 'table2', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]} LogStatus('`' + JSON.stringify([table1, table2]) + '`') }
    python
    import json def main(): table1 = {"type": "table", "title": "table1", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]} table2 = {"type": "table", "title": "table2", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]} LogStatus("`" + json.dumps([table1, table2]) + "`")
    rust
    fn main() { let table1 = r#"{"type": "table", "title": "table1", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}"#; let table2 = r#"{"type": "table", "title": "table2", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}"#; LogStatus!(format!("`[{},{}]`", table1, table2)); }
    c++
    void main() { json table1 = R"({"type": "table", "title": "table1", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]})"_json; json table2 = R"({"type": "table", "title": "table2", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]})"_json; json arr = R"([])"_json; arr.push_back(table1); arr.push_back(table2); LogStatus("`" + arr.dump() + "`"); }
  • 除了可以分页显示表格外,还可以将多个表格自上而下排列显示:

    javascript
    function main(){ var tab1 = { type : "table", title : "表格1", cols : ["1", "2"], rows : [] } var tab2 = { type : "table", title : "表格2", cols : ["1", "2", "3"], rows : [] } var tab3 = { type : "table", title : "表格3", cols : ["A", "B", "C"], rows : [] } tab1.rows.push(["jack", "lucy"]) tab2.rows.push(["A", "B", "C"]) tab3.rows.push(["A", "B", "C"]) LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n' + '`' + JSON.stringify(tab3) + '`') Log("exit") }
    python
    import json def main(): tab1 = { "type": "table", "title": "表格1", "cols": ["1", "2"], "rows": [] } tab2 = { "type": "table", "title": "表格2", "cols": ["1", "2", "3"], "rows": [] } tab3 = { "type": "table", "title": "表格3", "cols": ["A", "B", "C"], "rows": [] } tab1["rows"].append(["jack", "lucy"]) tab2["rows"].append(["A", "B", "C"]) tab3["rows"].append(["A", "B", "C"]) LogStatus("`" + json.dumps(tab1) + "`\n" + "`" + json.dumps(tab2) + "`\n" + "`" + json.dumps(tab3) + "`")
    rust
    fn main() { // Rust 中直接把行数据写入JSON字符串中 let tab1 = r#"{"type": "table", "title": "表格1", "cols": ["1", "2"], "rows": [["jack", "lucy"]]}"#; let tab2 = r#"{"type": "table", "title": "表格2", "cols": ["1", "2", "3"], "rows": [["A", "B", "C"]]}"#; let tab3 = r#"{"type": "table", "title": "表格3", "cols": ["A", "B", "C"], "rows": [["A", "B", "C"]]}"#; LogStatus!(format!("`{}`\n`{}`\n`{}`", tab1, tab2, tab3)); }
    c++
    void main() { json tab1 = R"({ "type": "table", "title": "表格1", "cols": ["1", "2"], "rows": [] })"_json; json tab2 = R"({ "type": "table", "title": "表格2", "cols": ["1", "2", "3"], "rows": [] })"_json; json tab3 = R"({ "type": "table", "title": "表格3", "cols": ["A", "B", "C"], "rows": [] })"_json; tab1["rows"].push_back(R"(["jack", "lucy"])"_json); tab2["rows"].push_back(R"(["A", "B", "C"])"_json); tab3["rows"].push_back(R"(["A", "B", "C"])"_json); LogStatus("`" + tab1.dump() + "`\n" + "`" + tab2.dump() + "`\n" + "`" + tab3.dump() + "`"); }
  • 支持设置状态栏表格的横向、纵向滚动模式。将scroll属性设置为"auto"后,当状态栏表格的纵向行数超过20行时,内容将自动滚动显示;当横向列数超出页面显示范围时,将进行横向滚动显示。使用scroll属性可以缓解实盘运行时状态栏中因大量写入数据而导致的卡顿问题。请参考以下测试示例:

    javascript
    function main() { var tbl = { type : "table", title : "test scroll", scroll : "auto", cols : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"], rows : [] } for (var i = 1 ; i < 100 ; i++) { tbl.rows.push([i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i]) } LogStatus("`" + JSON.stringify(tbl) + "`") }
    python
    import json def main(): tbl = { "type" : "table", "title" : "test scroll", "scroll" : "auto", "cols" : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"], "rows" : [] } for index in range(1, 100): i = str(index) tbl["rows"].append([i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i]) LogStatus("`" + json.dumps(tbl) + "`")
    rust
    fn main() { let tbl_tpl = String::from(r#"{"type": "table", "title": "test scroll", "scroll": "auto", "cols": ["#) + r#""col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10","# + r#""col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20""# + r#"], "rows": [__ROWS__]}"#; let mut rows: Vec<String> = Vec::new(); for index in 1..100 { let i = index.to_string(); rows.push(format!( r#"["{}", "1,{}", "2,{}", "3,{}", "4,{}", "5,{}", "6,{}", "7,{}", "8,{}", "9,{}", "10,{}", "11,{}", "12,{}", "13,{}", "14,{}", "15,{}", "16,{}", "17,{}", "18,{}", "19,{}", "20,{}"]"#, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i )); } let tbl = tbl_tpl.replace("__ROWS__", &rows.join(",")); LogStatus!(format!("`{}`", tbl)); }
    c++
    void main() { json table = R"({ "type" : "table", "title" : "test scroll", "scroll" : "auto", "cols" : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"], "rows" : [] })"_json; for (int index = 1; index < 100; ++index) { std::string i = std::to_string(index); table["rows"].push_back({i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i}); } LogStatus("`" + table.dump() + "`"); }

参数

名称类型必填描述

msg

string / number / bool / object / array / any (系统支持的所有类型)

参数msg为要输出的内容,且可以传入多个msg参数。

参考

备注

实盘运行时,LogStatus()函数输出的信息不会保存到实盘数据库中,仅更新当前实盘状态栏的内容。

LogStatus()函数支持打印经过base64编码的图片,图片数据需以`开头,并以`结尾。例如:LogStatus("`data:image/png;base64,AAAA`")

LogStatus()函数支持直接传入Pythonmatplotlib.pyplot对象。只要对象包含savefig方法,即可作为参数传入LogStatus()函数,例如:

python
import matplotlib.pyplot as plt def main(): plt.plot([3,6,2,4,7,1]) LogStatus(plt)

策略实盘运行时,若在实盘页面翻看历史记录,状态栏会进入休眠状态并停止更新;只有当日志停留在第一页时,状态栏数据才会刷新。状态栏支持输出经过base64编码的图片,也支持在状态栏显示的表格中输出经过base64编码的图片。由于编码后的图片字符串数据通常很长,因此此处不再展示范例代码。