Bài trướcMột bàn tay dạy bạn viết chiến lược -- chuyển một chiến lược bằng ngôn ngữ của tôi.Trong bài viết này, tôi đã thử nghiệm việc chuyển đổi một chiến lược đơn giản của ngôn ngữ Ma, nếu đó là một ngôn ngữ Ma phức tạp hơn một chút, làm thế nào để chuyển đổi một chiến lược thành ngôn ngữ JavaScript?
Trước tiên, chúng ta hãy xem chiến lược của việc cấy ghép này:
(*backtest
start: 2019-05-01 00:00:00
end: 2019-11-12 00:00:00
period: 1d
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
args: [["SlideTick",10,126961],["ContractType","quarter",126961]]
*)
N1:=10;
N2:=21;
AP:=(HIGH+LOW+CLOSE)/3;
ESA:=EMA(AP,N1);
D:=EMA(ABS(AP-ESA),N1);
CI:=(AP-ESA)/(0.015*D);
TCI:=EMA(CI,N2);
WT1:TCI;
WT2:SMA(WT1,4,1);
AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;
Phần đầu của chiến lược ngôn ngữ này(*backtest...*)
Đây là một chiến lược tìm kiếm ngẫu nhiên, cũng không quá phức tạp (tương tự như trong bài viết trước), là một chiến lược tương đối đại diện. Chuyển một chiến lược ngôn ngữ Mac, trước tiên cần xem nội dung của chính sách, mã chính sách ngôn ngữ Mac khá đơn giản, về cơ bản bạn có thể có một số hiểu biết về chiến lược tổng thể, chiến lược này chúng ta thấy sử dụng một số hàm chỉ số.EMA
,SMA
:
EMA
Chức năng chỉ số này là một chức năng thư viện chỉ số sẵn có khi viết chính sách bằng ngôn ngữ JavaScript trên nền tảng FMZ.TA.MA
SMA
Những gì chúng ta cần phải làm làSMA
Chỉ số này, mà chúng tôi thấy trong thư viện TA của FMZ không hỗ trợ hàm SMA, cũng có sự khác biệt giữa chỉ số SMA trong thư viện talib và trong ngôn ngữ Ma:Như bạn có thể thấy, phần tham số có một tham số trọng lượng ngoài tham số chu kỳ.
Mô tả của hàm chỉ số SMA trong thư viện talib trong tài liệu API FMZ là:
Nhìn thấytalib.SMA
Đây là một chỉ số trung bình di chuyển đơn giản.
Bạn chỉ có thể tự mình thực hiện mộtSMA
Vì vậy, như một nhà phát triển viết các chiến lược bằng ngôn ngữ JavaScript, đây cũng là một trong những kỹ năng cần thiết, sau khi tất cả, nếu không có bánh xe sẵn sàng, xe vẫn phải chạy, chỉ cần tạo ra một.
Thật ra, không có nhiều nghiên cứu về các chỉ số như vậy và thường không hiểu về việc tìm kiếm, tìm kiếm thông tin.
Một số người cho rằng các thuật toán này rất đáng tin cậy và thực hiện được:
function SMA (arr, n, m) {
var sma = []
var currSMA = null
for (var i = 0; i < arr.length; i++) {
if (arr[i] && !isNaN(arr[i])) {
if (!currSMA) {
currSMA = arr[i]
sma.push(currSMA)
continue
}
// [M*C2+(N-M)*S1]/N
currSMA = (m * arr[i] + (n - m) * currSMA) / n
sma.push(currSMA)
} else {
sma.push(NaN)
}
}
return sma
}
Sử dụng khuôn khổ chiến lượcMột bàn tay dạy bạn viết chiến lược -- chuyển một chiến lược bằng ngôn ngữ của tôi.Trong khi đó, các nhà nghiên cứu cũng cho rằng, một số người cho rằng, "thực tế là một điều không thể làm được".
Trước tiên, làm việc với dữ liệu thị trường, tính toán các chỉ số.
Chúng tôi đã xem xét từng câu về chức năng của phần này của tiếng Ma:
1、AP:=(HIGH+LOW+CLOSE)/3;
Điều này có thể được hiểu như là, hãy cộng giá cao nhất, giá thấp nhất, giá đóng cửa của mỗi giá BAR trong dữ liệu đường K và chia cho 3, tính toán giá trung bình, sau đó lưu trữ như một mảng, và tương ứng với mỗi BAR một lần. Có thể xử lý như sau:
function CalcAP (r) { // AP:=(HIGH+LOW+CLOSE)/3;
var arrAP = [] // 声明一个空数组
for (var i = 0; i < r.length; i++) { // r为传入的K线数据,是一个数组,用for遍历这个数组
v = (r[i].High + r[i].Low + r[i].Close) / 3 // 计算 平均值
arrAP.push(v) // 添加在 arrAP数组的尾部,arrAP是空的时候尾部就是第一个。
}
return arrAP // 返回 这个平均值数组,即麦语言中计算的 AP
}
Bạn có thể gọi hàm này trong hàm OnTick trong vòng lặp chính, ví dụ:
// 计算指标
// AP
var ap = CalcAP(records)
Sau khi tính toán AP hoàn tất, tính toán tiếp theoESA:=EMA(AP,N1);
:
Ở đây, chúng ta sẽ tính ESA bằng cách sử dụng dữ liệu AP được tính toán ở bước trước, thực tế ESA là "đường trung bình di chuyển chỉ số" của AP, hoặc chỉ số EMA, vì vậy chúng ta có thể tính EMA bằng AP là dữ liệu, N1 là tham số của chỉ số EMA.
function CalcESA (ap, n1) { // ESA:=EMA(AP,N1);
if (ap.length <= n1) { // 如果AP的长度小于指标参数,是无法计算出有效数据的,这个时候让函数返回false。
return false
}
return TA.EMA(ap, n1)
}
3、D:=EMA(ABS(AP-ESA),N1);
Sử dụng tính toánAP
、ESA
Dữ liệu tính toánD
‖
Có một số kỹ thuật để tính toán các chỉ số.
function CalcD (ap, esa, n1) { // D:=EMA(ABS(AP-ESA),N1);
var arrABS_APminusESA = []
if (ap.length != esa.length) {
throw "ap.length != esa.length"
}
for (var i = 0; i < ap.length; i++) {
// 计算指标数值时,必须判断一下数据的有效性,因为前几次EMA计算可能数组中的开始部分的数据是NaN,或者null
// 所以必须判断,参与计算的数据都是有效数值才能进行,如果有任何无效数值,就用NaN向arrABS_APminusESA填充
// 这样计算得到的数据,每个位置和之前的数据都是一一对应的,不会错位。
if (ap[i] && esa[i] && !isNaN(ap[i]) && !isNaN(esa[i])) {
v = Math.abs(ap[i] - esa[i]) // 根据ABS(AP-ESA) , 具体计算数值,然后放入arrABS_APminusESA数组
arrABS_APminusESA.push(v)
} else {
arrABS_APminusESA.push(NaN)
}
}
if (arrABS_APminusESA.length <= n1) {
return false
}
return TA.EMA(arrABS_APminusESA, n1) // 计算数组arrABS_APminusESA的EMA指标,得到数据D(数组结构)
}
4、CI:=(AP-ESA)/(0.015*D);
Cách tính toán này tương tự như bước 1 và phát ra mã trực tiếp.
function CalcCI (ap, esa, d) { // CI:=(AP-ESA)/(0.015*D);
var arrCI = []
if (ap.length != esa.length || ap.length != d.length) {
throw "ap.length != esa.length || ap.length != d.length"
}
for (var i = 0; i < ap.length; i++) {
if (ap[i] && esa[i] && d[i] && !isNaN(ap[i]) && !isNaN(esa[i]) && !isNaN(d[i])) {
v = (ap[i] - esa[i]) / (0.015 * d[i])
arrCI.push(v)
} else {
arrCI.push(NaN)
}
}
if (arrCI.length == 0) {
return false
}
return arrCI
}
TCI: = EMA ((CI, N2); Chỉ tính EMA của CI.
function CalcTCI (ci, n2) { // TCI:=EMA(CI,N2);
if (ci.length <= n2) {
return false
}
return TA.EMA(ci, n2)
}
WT2:SMA(WT1,4,1);
Và bước cuối cùng là sử dụng bánh xe mà chúng tôi đã chế tạo trước đó.SMA
Chức năng.
function CalcWT2 (wt1) { // WT2:SMA(WT1,4,1);
if (wt1.length <= 4) {
return false
}
return SMA(wt1, 4, 1) // 使用我们自己实现的SMA函数计算出wt1的SMA指标。
}
Việc chuyển tín hiệu giao dịch rất đơn giản.
AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;
Đọc một vài đoạn mã của ngôn ngữ Ma, bạn có thể biết rằng cho hai đường chỉ số WT1 và WT2, đinh vàng, đinh chết được coi là điều kiện để bắt đầu giao dịch, cần lưu ý là sử dụng tín hiệu chéo trước đó. Trong khi đó, một số nghiên cứu khác cũng cho thấy rằng, việc sử dụng các chiến lược này là một cách đơn giản.
Thông qua các chiến lược thực tế của ngôn ngữ Mac, quan sát có thể thấy rằng khi phát hiện tín hiệu tại điểm mở, thực tế là phát hiện vị trí của BAR trước 2 BAR tại điểm mở này có phải là một cái cào vàng không; hình trên có thể thấy rõ:
Mã điền của phần phát hiện tín hiệu có thể được viết như sau:
if ((_State == IDLE || _State == SHORT) && wt1[wt1.length - 4] < wt2[wt2.length - 4] && wt1[wt1.length - 3] > wt2[wt2.length - 3]) {
if (_State == IDLE) {
_State = OPENLONG
Log("OPENLONG") // 测试
}
if (_State == SHORT) {
_State = COVERSHORT
Log("COVERSHORT") // 测试
}
isOK = false
}
if ((_State == IDLE || _State == LONG) && wt1[wt1.length - 4] > wt2[wt2.length - 4] && wt1[wt1.length - 3] < wt2[wt2.length - 3]) {
if (_State == IDLE) {
_State = OPENSHORT
Log("OPENSHORT") // 测试
}
if (_State == LONG) {
_State = COVERLONG
Log("COVERLONG") // 测试
}
isOK = false
}
Tại sao các chỉ dẫn SPK, BPK của ngôn ngữ Ma có thể được thực hiện bằng mã trên?
Đánh giá lại cấu hình:
Những người bị ảnh hưởng bởi các hoạt động này là những người bị ảnh hưởng bởi các hoạt động của chính phủ.
Các phiên bản JavaScript được kiểm tra lại:
Phần mã đầu tiên của hàm OnTick được sử dụng để làm cho tốc độ xem lại nhanh hơn một chút, để cho các chiến lược chạy theo mô hình giá đóng cửa, có thể được phân tích chi tiết.
function OnTick(){
// 驱动策略的行情处理部分
var records = _C(exchange.GetRecords)
if (records[records.length - 1].Time == preTime) {
if (isOK) {
Sleep(500)
return
}
} else {
preTime = records[records.length - 1].Time
}
...
..
.
Có thể đọc toàn bộ mã của chiến lược giảng dạy:https://www.fmz.com/strategy/174457