Thanks to the user ID: Professional pet owners of the platform Share this template: The template is relatively simple to use, with instructions for the role of each function, and a better architectural policy can be used when developing the policy, separating the display interface. Extracting, modifying, and updating the status bar data has also become easier, very convenient, and with a small amount of code, it is also relatively scalable.
If you're interested in learning the source code, here's a line-by-line translation. This template is easy to understand and works in a variety of ways. The main function test section can be copied to a separate policy and then referenced to the template test. If you have any bugs or suggestions, please leave a comment ^^
/*
作者: ID 养鸡专业户
翻译: littleDream
*/
var listener = Array(); // 声明一个 全局变量 并且初始化为空数组对象, 用来储存 按钮(button)响应的 函数引用。
// 用于构造 按键 对象的函数
TableButton = function(cmd, name, callback) { // cmd : 用于 GetCommand 捕获的 命令 , name : 按键显示的名称 修改:增加 callback
var self = {} // 构造一个 空对象
self.type = "button"; // 给构造的对象 添加 属性 type 并 赋值 "button" , 参见 API 文档 LogStatus 函数,和论坛帖子“策略状态栏中构造交互按钮功能”
self.cmd = cmd; // 添加 cmd 属性 并用参数 cmd 赋值
self.name = name; // 添加 name 属性
// 下行新增
listener[cmd] = callback; // 给对应的 命令通过 键--键值 绑定 对应的回调函数
return self; // 返回构造好的对象
}
// 模版导出函数, 用于设置 表格信息,返回一个对象可以调用 该对象的成员函数压入 数据
$.TableInfo = function() {
var self = {} // 构造一个 空对象
self.cols = []; // 给构造的空对象 添加属性 cols 并赋值 一个 空数组
self.rows = []; // 给构造的空对象 添加属性 rows 并赋值 一个 空数组
self.pushBtn = function(col, cmd, name, callback) { // 添加 属性 pushBtn 引用一个 匿名函数, 参数为 列名、捕获的命令、按钮名称、回调函数(按钮最终触发的函数)
/* var btn = TableButton(cmd, name) */
self.cols.push(col) // 向列 压入数据 显示为列名
self.rows.push({ // 压入 按钮的 格式(JSON)
'type': 'button', // 类型设置 为 按钮
'cmd': cmd, // 触发的 命令
'name': name // 按钮上显示的名称
})
listener[cmd] = callback; // 给对应的 命令通过 键--键值 绑定 对应的回调函数
}
self.push = function(col, row) { // 压入 普通数据 参数 : col 列名, row : 行上的值
self.cols.push(col) // 压入 数组 操作
self.rows.push(row) // 压入 数组 操作
}
return self; // 返回构造的对象
}
// 构造 table 表格对象, createTable 表格对象的构造函数
function createTable() {
var self = {} // 声明一个 空对象
self.type = "table" // 添加属性 type , 用 “table” 赋值, 定义表格类型用于在状态栏显示 出表格,参见API文档 LogStatus 函数
self.title = "持仓信息" // 表格显示的 分页标题 默认 为 “持仓信息”
self.cols = [] // 用以储存表格的列名
self.rows = [] // 用以储存表格的行数据
// 声明的空对象添加成员函数
self.SetRowByTableInfo = function(index, argument) { // 根据 导出函数 $.TableInfo 返回的对象 去设置 表格的 row 行数据,参数是: 行号,$.TableInfo的返回值
if (argument.cols != null) // 传入的参数 argument.cols 不等于 null
self.cols = argument.cols; // 替换掉 列名
self.rows[index] = argument.rows; // 替换掉 指定 行数 index 的行数据 rows
}
self.SetRow = function(index, rowself) { // 设置行数据,直接设置, 参数 设置的行 index , 要设置的数据rowself
while (self.rows.length < index) // 如果超出 先添加 空白行 , 应该是 -1 if 修改为 while , 添加之间的空行。
self.rows.push(Array(rowself.length)) // self.push("") 修改
self.rows[index] = rowself // 参数 传入的行数据 rowself 赋值给 表格数组中 指定的行的索引位置
}
self.SetRowCount = function(count) { // 设置行数, 传入的参数就是 需要设置的 行数。
// 增加代码
var lengthOfcols = self.cols.length;
while (self.rows.length < count) { // 这里使用一个循环 来 把当前 不足的行数 补充一下。
self.rows.push(Array(lengthOfcols)); // 只要当前的行数 即:self.rows.length 小于 参数 count , 就向 self.rows push 空 ""
}
if (self.rows.length > count) { // 如果 参数 count 小于当前的 已有行数。
self.rows.splice(count, self.rows.length - count) // 调用数组的 元素删除函数 splice 删除 索引count 开始 (self.rows.length - count) 个 元素,即:删除 多于的元素。
}
}
self.GetRow = function(index) { // 获取 指定行数的 表格行数据。
return self.rows[index]
}
self.Init = function(title/*, cols, rows*/) { // 初始化表格 , 参数 : 分页标题
self.title = title; // 表格 对象的 title 属性 设置为 参数传入的 字符串
/*作者删除
if (cols != null) // 如果传入的 cols 不为 null, 把参数cols 赋值给 表格对象的 cols 属性
self.cols = cols;
if (rows != null) { // 如果传入的 rows 不为 null, 对 参数 rows 遍历处理,压入编号
// 此处应该有一个判断 rows 是否是数组。
for (var i = 0; i < rows.length; i++) { // 遍历
self.rows.push(rows[i]); // 修改 rows.push("r" + i)
}
}
*/
}
return self; // 返回 表格对象
}
$.createTableMgr = function() { // 构造表格控制对象
var self = {} // 声明一个 空对象
self.table = [] // 声明一个 空数组, table 感觉 tabls 贴切, 这个table 变量用来存放 表格对象,可以同时显示出多个表格。
self.GetTable = function(index) { // 给表格控制对象添加 成员函数: 获取表格 GetTable , 参数 index 指定获取 哪个表格。
if (typeof(index) === 'number') { // 如果传入的 参数 index 为数值类型 , 返回索引为 index 的 self.table 数组的元素。
return self.table[index] // 如果索引 index 输入 超出, 还是有可能返回 undefined
} else {
for (var i = 0; i < self.table.length; i++) { // 如果传入的 参数 index 不是索引,而是 表格对象的 分页标题 字符串, 则遍历 self.table 数组
if (self.table[i].title == index) // 对比每一个 表格对象的 分页标题, 找到相同的 分页标题 就返回该 表格对象。
return self.table[i] // 返回 表格对象
}
}
}
self.AddTable = function(title, cols, rows) { // 把 表格对象 添加到 表格控制对象的 table 属性。 可以指定 表格的标题 ,列数据 , 行数据
var tb = createTable(); // 调用 createTable 函数 构造一个 表格对象 赋值给 tb
tb.Init(title, cols, rows); // 调用 表格对象的 成员函数 初始化表格 传入参数 title, cols, rows
self.table.push(tb) // 把构造好的 表格对象压入 表格控制对象 的属性 table 数组中。
return tb; // 返回这个 添加 的表格对象。
}
/* 作者删除
self.AddListener = function(key, value) { // 添加 监听函数。
self.listener[key] = value; // 此处测试。
}
*/
self.UpdateCMD = function() { // 检测按钮 触发 命令。
var cmd = GetCommand() // 调用 API 函数 检测 交互有没有触发
if (cmd) { // 如果 cmd 接受到交互信息
var cmdstr = cmd + ""; // 用空字符串 加 cmd 做转换为字符串, 应该可以直接 用cmd
if (!!listener[cmdstr]) { // !!listener[cmdstr] 表达式 返回 false 即 listener 中没有 cmdstr 为 键的值, 如果 为true 则是有值(即:cmdstr 命令对应的回调函数)
listener[cmdstr](cmdstr); // 调用 该命令对应的回调函数 。
} else {
Log("找不到名为:" + cmdstr + "的命令") // 否则 打印日志 : 找不到 命令
}
}
}
self.LogStatus = function(before, end) { // 表格控制对象 添加的 成员函数 LogStatus (即 封装一下 API LogStatus)
self.UpdateCMD(); // 检测交互命令 , 调用 表格控制对象的成员函数 UpdateCMD 。 如果有 按钮按下 ,就会触发相应 命令的 回调函数(在listener 中 Key-value形式储存)
LogStatus(before + '\n`' + JSON.stringify(self.table) + '`\n' + end); // 支持多个表格同时显示, 将以TAB显示到一组里, 把参数 before ,end 添加在显示的表格 前、后, 调用API LogStatus
// 显示表格到状态栏。 要显示的表格都储存在 self.table 这个数组中, 详细的API 参见 文档: https://www.fmz.com/api 全局函数 LogStatus 函数
}
return self;
}
function main() {
// 测试 表格控制对象
var tb_manager = $.createTableMgr();
var tb1 = tb_manager.AddTable("ceshi1");
var tb2 = tb_manager.AddTable("ceshi2");
var tb3 = tb_manager.AddTable("ceshi3");
tb_manager.LogStatus("up", "down");
// 测试 GetTable 函数
var obj_tb2 = tb_manager.GetTable("ceshi2");
Log("obj_tb2:", obj_tb2);
// 测试 $.TableInfo
var info1 = $.TableInfo();
for(var i = 0; i < 5; i++){
info1.push("" + i, "a" + i);
}
tb1.SetRowByTableInfo(0, info1);
// 测试 SetRow 函数
tb1.SetRow(3, ["a", "b", "d"]); // 超出已有索引 ,会再之前插入空行
tb_manager.LogStatus("up", "down");
// 测试 SetRowCount
var info2 = $.TableInfo();
info2.push("name", "Tom");
info2.push("age", 12);
tb2.SetRowByTableInfo(0, info2);
tb2.SetRowCount(6);
tb_manager.LogStatus("up", "down");
// 测试GetRow
var tb2_row = tb2.GetRow(0);
Log("tb2_row:", tb2_row);
// 测试 TableButton
var info3 = $.TableInfo();
info3.push("按钮", TableButton("cover", "平仓", function(cmd){
var time = new Date().getTime();
Log(_D(time), "cmd:", cmd, "全平仓!#FF0000");
}));
tb3.SetRowByTableInfo(0, info3);
tb_manager.LogStatus("up", "down");
// 实盘测试 循环 避免程序 结束, 把 main 函数 复制到 单独的 策略中进行实际测试。
while(true){
// 测试 UpdateCMD
var nowTime = new Date().getTime();
tb_manager.UpdateCMD();
tb_manager.LogStatus("time:" + _D(nowTime), "down");
Sleep(1000);
}
}