
Khi thiết kế một chiến lược, thường cần phải thiết kế biểu đồ chiến lược hiển thị khi sử dụng JavaScript hoặc Python để viết chiến lược. Người dùng không quen với lập trình hoặc thư viện biểu đồ được nền tảng FMZ sử dụng thường gặp khó khăn với thiết kế mã để vẽ trên biểu đồ tùy chỉnh. Vậy làm sao chúng ta có thể vẽ biểu đồ chiến lược có nội dung phong phú chỉ bằng cách viết một lượng nhỏ mã?
Phương pháp vẽ đơn giản nhưng mạnh mẽ này có thể được thấy trong ngôn ngữ Pine, nổi tiếng với các chức năng vẽ phong phú. Nếu giao diện vẽ của ngôn ngữ Pine có thể được kết nối với các chiến lược của ngôn ngữ JavaScript và Python, thì các nhà phát triển sẽ dễ dàng hơn nhiều trong việc thiết kế chức năng vẽ của chiến lược. Dựa trên nhu cầu này, nền tảng FMZ đã nâng cấp chức năng vẽ tùy chỉnh và mở rộng phạm vi sử dụng.KLineChartChức năng này thực hiện vẽ biểu đồ tùy chỉnh. Bạn có thể tham khảo tài liệu API: https://www.fmz.com/api#klinechart
Hãy sử dụng JavaScript để viết một ví dụ đơn giản nhằm thực hiện quá trình chuyển đổi.
/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 30m
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
function main() {
var c = KLineChart()
while (true) {
var bars = _C(exchange.GetRecords)
for (var i = 0 ; i < bars.length ; i++) {
var bar = bars[i]
c.begin(bar)
c.plot(bar.Volume, "volume")
c.close()
}
Sleep(1000)
}
}
Ví dụ này rất đơn giản. Nó chỉ vẽ một biểu đồ nến trong vùng vẽ tùy chỉnh của chiến lược và vẽ một đường cong khối lượng tương ứng với mỗi BAR nến ở vị trí biểu đồ phụ của biểu đồ.

Trong mã đầu tiên chúng ta sử dụngvar c = KLineChart()Tạo một đối tượng biểu đồ và sau đó gọi phương thức của nó để vẽ. Sau đó trong vòng lặp, chúng ta lấy dữ liệu dòng K (cấu trúc mảng) và duyệt qua mảng dòng K. Bạn có thể sử dụng vòng lặp for đơn giản để duyệt như trong ví dụ hoặc có thể sử dụng các phương pháp khác để duyệt.
Các thao tác vẽ phải được thực hiện từc.begin(bar)Chức năng bắt đầu,c.close()Chức năng kết thúc.begin、closeHàm là phương thức của đối tượng biểu đồ c. Tiếp theo, sử dụng chức năng vẽ được sử dụng phổ biến nhấtplotVẽ đường cong thể tích trên mỗi thanh.
Giả sử chúng ta muốn thiết kế biểu đồ bằng chỉ báo Bollinger. Ồ vâng! Ngoài ra, cần phải đính kèm biểu đồ khối lượng cho mỗi BAR, có thể thiết kế như sau:
/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
function main() {
var c = KLineChart()
// 策略主循环
while(true) {
// 轮询间隔
Sleep(500)
// 获取K线数据
let bars = exchange.GetRecords()
if (!bars || bars.length <= 20) {
continue
}
// 计算布林指标
var boll = TA.BOLL(bars)
bars.forEach(function(bar, index) {
c.begin(bar)
// 画图操作
c.plot(boll[0][index], "Boll_Up", {overlay: true}) // 画在图表主图
c.plot(boll[1][index], "Boll_Mid", {overlay: true}) // 画在图表主图
c.plot(boll[2][index], "Boll_Down", {overlay: true}) // 画在图表主图
c.plot(bar.Volume, "volume") // 画在图表副图
c.close()
})
// 策略交易逻辑
// ...
// ..
}
}
Bạn có thể thấy trong mã rằng thông tin cấu hình kiểm tra ngược của chúng tôi trên nền tảng FMZ là:
/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
Cấu hình này được kiểm tra ngược bằng cách sử dụng đối tượng sàn giao dịch Binance spot. Kết quả kiểm tra ngược được hiển thị trong hình:

Có thể thấy rằng chúng ta sử dụng phương pháp vẽ của Pine để đơn giản hóa đáng kể mã vẽ trong ngôn ngữ JavaScript.
Các hoạt động như thu thập dữ liệu đường K và tính toán các chỉ số rất phổ biến và rất đơn giản trong các ví dụ về chiến lược và tài liệu API của nền tảng strategy square.
// 获取K线数据
let bars = exchange.GetRecords()
if (!bars || bars.length <= 20) {
// 如果获取K线失败,即!bar为真则执行continue,忽略之后的代码,重新执行循环
// 如果bars.length小于等于20,即K线BAR(柱)数量小于20,无法计算指标,也执行continue
continue
}
// 计算布林指标
var boll = TA.BOLL(bars)
Hàm tính toán chỉ báo Bollinger TA.BOLL, nếu bạn không chỉ định các tham số chỉ báo Bollinger, các tham số mặc định sẽ được sử dụngBOLL(20, 2). Chỉ báo Bollinger có ba đường, do đó dữ liệu trả về bởi hàm TA.BOLL là mảng hai chiều. quả bóng[0]、boll[1]、boll[2] là ba phần tử của mảng boll, mỗi phần tử biểu diễn một đường thẳng và là một mảng.
Sau đó, chúng ta sẽ xem cách vẽ khối lượng dữ liệu đường K, tức là khối lượng giao dịch và dữ liệu chỉ báo Bollinger được tính toán trên biểu đồ.
Chúng ta vẽ dữ liệu K-line theo từng thanh, do đó chúng ta cần phải duyệt toàn bộ mảng K-line, tức là duyệt mảng thanh trong mã. Ở đây chúng tôi sử dụngforEachPhương pháp duyệt cũng có thể được duyệt bằng cách sử dụng vòng lặp for.
bars.forEach(function(bar, index) {
c.begin(bar)
// 画图操作
c.plot(boll[0][index], "Boll_Up", {overlay: true}) // {overlay: true}参数控制,画在图表主图
c.plot(boll[1][index], "Boll_Mid", {overlay: true}) // 画在图表主图
c.plot(boll[2][index], "Boll_Down", {overlay: true}) // 画在图表主图
c.plot(bar.Volume, "volume") // 画在图表副图
c.close()
})
Cần lưu ý rằng mỗi lần bạn bắt đầu vẽ biểu đồ trên thanh, trước tiên bạn phảic.begin(bar)Gọi hàm,beginHàm là phương thức của đối tượng biểu đồ c. Khi kết thúc thao tác vẽ, bạn cần gọic.close(). hiện hữubeginChức năng vàcloseTrong số các hàm đó có các hàm vẽ mà chúng ta gọi là tương tự như phương pháp vẽ của ngôn ngữ Pine. ủng hộ:barcolor bgcolor plot fill hline plotarrow plotshape plotchar plotcandle signal, bạn có thể vẽ đường thẳng, mũi tên, đánh dấu thông tin, v.v. Các tham số của các hàm này nhất quán với các tham số hàm tương ứng của ngôn ngữ Pine và các hàm vẽ cũng nhất quán.
Thêm một số mũi tên tín hiệu giao dịch, điểm đánh dấu và đường ngang vào ví dụ vẽ chỉ báo Bollinger ở trên.
/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
function main() {
var c = KLineChart()
// 策略主循环
while(true) {
// 轮询间隔
Sleep(500)
// 获取K线数据
let bars = exchange.GetRecords()
if (!bars || bars.length <= 20) {
continue
}
// 计算布林指标
var boll = TA.BOLL(bars)
bars.forEach(function(bar, index) {
c.begin(bar)
// 画图操作
c.plot(boll[0][index], "Boll_Up", {overlay: true}) // 画在图表主图
c.plot(boll[1][index], "Boll_Mid", {overlay: true}) // 画在图表主图
c.plot(boll[2][index], "Boll_Down", {overlay: true}) // 画在图表主图
c.plot(bar.Volume, "volume") // 画在图表副图
c.hline(bar.Open, {overlay: true}) // 水平线
c.plotarrow(bar.Close - bar.Open, {overlay: true}) // 箭头
c.plotshape(bar.Close - bar.Open > 0, {style: 'square', overlay: true}) // 画方块标记
c.plotchar(bar.Close - bar.Open < 0, {char: '❄', size: "20px", overlay: true}) // 画出字符❄
if (boll[0][index] && bar.Close > boll[0][index]) {
c.signal("long", bar.Close, 1.5)
} else if (boll[2][index] && bar.Close < boll[2][index]) {
c.signal("closelong", bar.Close, 1.5)
}
c.close()
})
// 策略交易逻辑
// ...
// ..
}
}

Vì lệnh chiến lược ngôn ngữ Pine sẽ tự động đánh dấu tín hiệu trên biểu đồ,KLineChartĐối tượng biểu đồ được tạo bởi hàm này cũng được mở rộng bằng hàm để vẽ các điểm đánh dấu tín hiệu mua và bán:c.signal。
Bạn có thể khai báo một cấu trúc để cấu hình kiểu biểu đồ. Ví dụ, biến chartCfg sau đây biểu diễn thông tin cấu hình của một đường lưới.
var chartCfg = {
grid: {
show: true,
// 网格水平线
horizontal: {
show: true,
size: 2,
color: '#FF0000', // 水平网格线的颜色
// 'solid'|'dash'
style: 'dash', // 线的类型
dashValue: [2, 2]
},
// 网格垂直线
vertical: {
show: true,
size: 2,
color: '#32CD32',
// 'solid'|'dash'
style: 'solid',
dashValue: [2, 2]
}
},
}
Đối tượng cấu hình biểu đồ là một cấu trúc dữ liệu thiết lập một số thuộc tính và giao diện của biểu đồ. Ví dụ, ví dụ sử dụng cấu hình kiểu đường lưới. Ngoài ra còn có nhiều tùy chọn có thể được cấu hình và sửa đổi, chẳng hạn như các thiết lập liên quan của trục X và trục Y, các thiết lập của dòng con trỏ, các thiết lập của thông tin nhắc nhở, các thiết lập của kiểu chỉ báo kỹ thuật, cài đặt kiểu thanh K-line BAR, v.v.
Tất nhiên, nếu bạn không quen thuộc với những điều này,KLineChartHàm này không cần phải truyền vào đối tượng cấu hình biểu đồ khi tạo đối tượng biểu đồ. Biểu đồ được tạo theo phong cách mặc định. Sử dụng các chức năng API của nền tảng FMZKLineChartChức năng tạo đối tượng biểu đồ:
var c = KLineChart(chartCfg)
Mã kiểm tra để vẽ đường lưới:
/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
function main() {
var chartCfg = {
grid: {
show: true,
// 网格水平线
horizontal: {
show: true,
size: 2,
color: '#FF0000',
// 'solid'|'dash'
style: 'dash',
dashValue: [2, 2]
},
// 网格垂直线
vertical: {
show: true,
size: 2,
color: '#32CD32',
// 'solid'|'dash'
style: 'solid',
dashValue: [2, 2]
}
},
}
var c = KLineChart(chartCfg)
// 策略主循环
while(true) {
// 轮询间隔
Sleep(500)
// 获取K线数据
var bars = _C(exchange.GetRecords)
bars.forEach(function(bar, index) {
c.begin(bar)
c.close()
})
// 策略交易逻辑
// ...
// ..
}
}

Có thể được sử dụng để tham chiếu các thiết lập của kiểu cấu hình biểu đồ.
{
// 网格线
grid: {
show: true,
// 网格水平线
horizontal: {
show: true,
size: 1,
color: '#393939',
// 'solid'|'dash'
style: 'dash',
dashValue: [2, 2]
},
// 网格垂直线
vertical: {
show: false,
size: 1,
color: '#393939',
// 'solid'|'dash'
style: 'dash',
dashValue: [2, 2]
}
},
// 蜡烛图
candle: {
// 蜡烛图上下间距,大于1为绝对值,大于0小余1则为比例
margin: {
top: 0.2,
bottom: 0.1
},
// 蜡烛图类型 'candle_solid'|'candle_stroke'|'candle_up_stroke'|'candle_down_stroke'|'ohlc'|'area'
type: 'candle_solid',
// 蜡烛柱
bar: {
upColor: '#26A69A',
downColor: '#EF5350',
noChangeColor: '#888888'
},
// 面积图
area: {
lineSize: 2,
lineColor: '#2196F3',
value: 'close',
backgroundColor: [{
offset: 0,
color: 'rgba(33, 150, 243, 0.01)'
}, {
offset: 1,
color: 'rgba(33, 150, 243, 0.2)'
}]
},
priceMark: {
show: true,
// 最高价标记
high: {
show: true,
color: '#D9D9D9',
textMargin: 5,
textSize: 10,
textFamily: 'Helvetica Neue',
textWeight: 'normal'
},
// 最低价标记
low: {
show: true,
color: '#D9D9D9',
textMargin: 5,
textSize: 10,
textFamily: 'Helvetica Neue',
textWeight: 'normal',
},
// 最新价标记
last: {
show: true,
upColor: '#26A69A',
downColor: '#EF5350',
noChangeColor: '#888888',
line: {
show: true,
// 'solid'|'dash'
style: 'dash',
dashValue: [4, 4],
size: 1
},
text: {
show: true,
size: 12,
paddingLeft: 2,
paddingTop: 2,
paddingRight: 2,
paddingBottom: 2,
color: '#FFFFFF',
family: 'Helvetica Neue',
weight: 'normal',
borderRadius: 2
}
}
},
// 提示
tooltip: {
// 'always' | 'follow_cross' | 'none'
showRule: 'always',
// 'standard' | 'rect'
showType: 'standard',
labels: ['时间', '开', '收', '高', '低', '成交量'],
values: null,
defaultValue: 'n/a',
rect: {
paddingLeft: 0,
paddingRight: 0,
paddingTop: 0,
paddingBottom: 6,
offsetLeft: 8,
offsetTop: 8,
offsetRight: 8,
borderRadius: 4,
borderSize: 1,
borderColor: '#3f4254',
backgroundColor: 'rgba(17, 17, 17, .3)'
},
text: {
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
color: '#D9D9D9',
marginLeft: 8,
marginTop: 6,
marginRight: 8,
marginBottom: 0
}
}
},
// 技术指标
technicalIndicator: {
margin: {
top: 0.2,
bottom: 0.1
},
bar: {
upColor: '#26A69A',
downColor: '#EF5350',
noChangeColor: '#888888'
},
line: {
size: 1,
colors: ['#FF9600', '#9D65C9', '#2196F3', '#E11D74', '#01C5C4']
},
circle: {
upColor: '#26A69A',
downColor: '#EF5350',
noChangeColor: '#888888'
},
// 最新值标记
lastValueMark: {
show: false,
text: {
show: false,
color: '#ffffff',
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
paddingLeft: 3,
paddingTop: 2,
paddingRight: 3,
paddingBottom: 2,
borderRadius: 2
}
},
// 提示
tooltip: {
// 'always' | 'follow_cross' | 'none'
showRule: 'always',
// 'standard' | 'rect'
showType: 'standard',
showName: true,
showParams: true,
defaultValue: 'n/a',
text: {
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
color: '#D9D9D9',
marginTop: 6,
marginRight: 8,
marginBottom: 0,
marginLeft: 8
}
}
},
// x轴
xAxis: {
show: true,
height: null,
// x轴线
axisLine: {
show: true,
color: '#888888',
size: 1
},
// x轴分割文字
tickText: {
show: true,
color: '#D9D9D9',
family: 'Helvetica Neue',
weight: 'normal',
size: 12,
paddingTop: 3,
paddingBottom: 6
},
// x轴分割线
tickLine: {
show: true,
size: 1,
length: 3,
color: '#888888'
}
},
// y轴
yAxis: {
show: true,
width: null,
// 'left' | 'right'
position: 'right',
// 'normal' | 'percentage' | 'log'
type: 'normal',
inside: false,
reverse: false,
// y轴线
axisLine: {
show: true,
color: '#888888',
size: 1
},
// y轴分割文字
tickText: {
show: true,
color: '#D9D9D9',
family: 'Helvetica Neue',
weight: 'normal',
size: 12,
paddingLeft: 3,
paddingRight: 6
},
// y轴分割线
tickLine: {
show: true,
size: 1,
length: 3,
color: '#888888'
}
},
// 图表之间的分割线
separator: {
size: 1,
color: '#888888',
fill: true,
activeBackgroundColor: 'rgba(230, 230, 230, .15)'
},
// 十字光标
crosshair: {
show: true,
// 十字光标水平线及文字
horizontal: {
show: true,
line: {
show: true,
// 'solid'|'dash'
style: 'dash',
dashValue: [4, 2],
size: 1,
color: '#888888'
},
text: {
show: true,
color: '#D9D9D9',
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
paddingLeft: 2,
paddingRight: 2,
paddingTop: 2,
paddingBottom: 2,
borderSize: 1,
borderColor: '#505050',
borderRadius: 2,
backgroundColor: '#505050'
}
},
// 十字光标垂直线及文字
vertical: {
show: true,
line: {
show: true,
// 'solid'|'dash'
style: 'dash',
dashValue: [4, 2],
size: 1,
color: '#888888'
},
text: {
show: true,
color: '#D9D9D9',
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
paddingLeft: 2,
paddingRight: 2,
paddingTop: 2,
paddingBottom: 2,
borderSize: 1,
borderColor: '#505050',
borderRadius: 2,
backgroundColor: '#505050'
}
}
},
// 图形
shape: {
point: {
backgroundColor: '#2196F3',
borderColor: '#2196F3',
borderSize: 1,
radius: 4,
activeBackgroundColor: '#2196F3',
activeBorderColor: '#2196F3',
activeBorderSize: 1,
activeRadius: 6
},
line: {
// 'solid'|'dash'
style: 'solid'
color: '#2196F3',
size: 1,
dashValue: [2, 2]
},
polygon: {
// 'stroke'|'fill'
style: 'stroke',
stroke: {
// 'solid'|'dash'
style: 'solid',
size: 1,
color: '#2196F3',
dashValue: [2, 2]
},
fill: {
color: 'rgba(33, 150, 243, 0.1)'
}
},
arc: {
// 'stroke'|'fill'
style: 'stroke',
stroke: {
// 'solid'|'dash'
style: 'solid',
size: 1,
color: '#2196F3',
dashValue: [2, 2]
},
fill: {
color: '#2196F3'
}
},
text: {
style: 'fill',
color: '#2196F3',
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
offset: [0, 0]
}
},
annotation: {
// 'top' | 'bottom' | 'point'
position: 'top',
offset: [20, 0]
symbol: {
// 'diamond' | 'circle' | 'rect' | 'triangle' | 'custom' | 'none'
type: 'diamond',
size: 8,
color: '#2196F3',
activeSize: 10,
activeColor: '#FF9600'
}
},
tag: {
// 'top' | 'bottom' | 'point'
position: 'point',
offset: 0,
line: {
show: true,
style: LineStyle.DASH,
dashValue: [4, 2],
size: 1,
color: '#2196F3'
},
text: {
color: '#FFFFFF',
backgroundColor: '#2196F3',
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
paddingLeft: 2,
paddingRight: 2,
paddingTop: 2,
paddingBottom: 2,
borderRadius: 2,
borderSize: 1,
borderColor: '#2196F3'
},
mark: {
offset: 0,
color: '#FFFFFF',
backgroundColor: '#2196F3',
size: 12,
family: 'Helvetica Neue',
weight: 'normal',
paddingLeft: 2,
paddingRight: 2,
paddingTop: 2,
paddingBottom: 2,
borderRadius: 2,
borderSize: 1,
borderColor: '#2196F3'
}
}
}
Điều này không làm cho việc thiết kế và lập chiến lược trở nên dễ dàng hơn sao?