지난 기사 에서전략을 쓰는 법을 가르쳐요. MyLanguage 전략을 이식시켜요., 간단한 MyLanguage 전략이 이식에 테스트되었습니다. 더 복잡한 MyLanguage라면, 어떻게 JavaScript 언어 전략으로 이식 할 수 있습니까? 어떤 기술이 있습니까?
먼저 이식할 전략을 살펴봅시다.
(*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;
이(* backtest... *)
MyLanguage 전략의 시작에는 백테스팅 설정을 위한 구성 코드가 있습니다. 비교를 용이하게 하기 위해, 통일된 백테스팅 구성이 설정됩니다. 이 전략은 또한 너무 복잡하지 않은 (지난 기사보다 더 복잡) 무작위적인 것입니다. 그것은 대표적인 전략입니다. MyLanguage 전략을 이식하려면 먼저 전체 전략을 살펴야합니다. 전략의 코드는 간결하며 전체 전략에 대한 특정 이해를 가질 수 있습니다. 이 전략을 위해 우리는 몇 가지 지표 기능이 있음을 보았습니다.EMA
, SMA
사용되었습니다.
EMA
표시기 기능은 자바스크립트 언어로 전략을 작성할 때 FMZ 플랫폼에서 직접 사용할 수있는 준비 된 표시기 라이브러리 기능이 있습니다. 즉:TA.MA
.
SMA
우리가 해야 할 일은SMA
이 지표는 FMZ의 TA 라이브러리에서 발견된 SMA 지표 기능을 지원하지 않으며, 타리브 라이브러리의 SMA 지표와 MyLanguage의 지표 사이에 차이가 있습니다.
우리가 볼 수 있듯이, 매개 변수 섹션에는 지점 매개 변수 외에도 무게 매개 변수가 있습니다.
FMZ API 문서의 talib 라이브러리의 SMA 지표 함수는 다음과 같이 설명됩니다.
그 결과talib.SMA
단순한 이동평균 지표입니다.
이 방법으로, 우리는 우리 스스로만 SMA를 구현할 수 있습니다. 자브스크립트 언어를 사용하여 전략을 작성하는 개발자로서, 이것은 또한 필요한 기술 중 하나입니다. 결국, 준비가 된 바퀴가 없다면, 프로그램은 여전히 실행되어야합니다. 하나를 만들면 됩니다.
사실, 지표 등에 대한 연구는 많지 않습니다. 일반적으로 사람들은 정보를 이해하지 못하면 정보를 찾습니다. SMA를 찾기 위해 다음과 같습니다.
이 이론의 알고리즘 프로세스는 상당히 신뢰할 수 있는 것으로 보이며 구현 방법은 다음과 같습니다.
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
}
전략 프레임 워크는 기사와 동일한 프레임 워크를 사용합니다.전략을 쓰는 법을 가르쳐요. MyLanguage 전략을 이식시켜요.그리고 주로 두 부분으로 채워집니다.
먼저, 틱어 데이터 처리와 인덱스 계산을 합니다.
MyLanguage의 이 부분을 한번에 하나의 문장으로, 기능별로 살펴봅시다.
AP:=(HIGH+LOW+CLOSE)/3;
K 행 데이터의 각 BAR의 가장 높은 가격, 가장 낮은 가격 및 종료 가격을 더하고 평균 값을 계산하기 위해 3로 나눈 다음 각 BAR에 하나씩 대응하는 배열로 저장해야한다는 것을 이해할 수 있습니다. 다음과 같이 처리할 수 있습니다.
function CalcAP (r) { // AP:=(HIGH+LOW+CLOSE)/3;
var arrAP = [] // Declare an empty array
for (var i = 0; i < r.length; i++) { // r is the incoming K-line data, which is an array, use for to traverse this array.
v = (r[i].High + r[i].Low + r[i].Close) / 3 // Calculate the average value.
arrAP.push(v) // Add to the end of the arrAP array, the end is the first when arrAP is empty.
}
return arrAP // Returns this average array, i.e., the AP calculated in the MyLanguage
}
이 함수는 메인 루프 OnTick 함수에서 호출될 수 있습니다. 예를 들어:
// Calculation of indicators
// AP
var ap = CalcAP(records)
ESA:=EMA(AP,N1);
:여기, 우리는 ESA를 계산하기 위해 이전 단계에서 계산된 AP의 데이터를 사용할 것입니다. 사실, ESA는 AP의
function CalcESA (ap, n1) { // ESA:=EMA(AP,N1);
if (ap.length <= n1) { // If the AP length is less than the indicator parameter, valid data cannot be calculated. At this time, let the function return false.
return false
}
return TA.EMA(ap, n1)
}
D:=EMA(ABS(AP-ESA),N1);
계산된AP
, ESA
데이터를 계산하기 위해D
- 그래요
여기서 코드 코멘트를 읽을 수 있습니다. 몇 가지 팁을 얻을 수 있습니다.
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++) {
// When calculating the value of the indicator, it is necessary to determine the validity of the data, because the first few EMA calculations may be the beginning of the array of data is NaN, or null.
// So it must be judged that the data involved in the calculation are all valid values to proceed, and if there are any invalid values, they are filled with NaN to arrABS_APminusESA.
// The data thus calculated, each position corresponds to the previous data one by one, without misalignment.
if (ap[i] && esa[i] && !isNaN(ap[i]) && !isNaN(esa[i])) {
v = Math.abs(ap[i] - esa[i]) // According to ABS(AP-ESA), the specific value is calculated and put into the arrABS_APminusESA array.
arrABS_APminusESA.push(v)
} else {
arrABS_APminusESA.push(NaN)
}
}
if (arrABS_APminusESA.length <= n1) {
return false
}
return TA.EMA(arrABS_APminusESA, n1) // Calculate the EMA indicator of the array arrABS_APminusESA and get the data D (array structure).
}
CI:=(AP-ESA)/(0.015*D);
계산 방법은 단계 1과 비슷하며 코드는 직접 공개됩니다.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
}
function CalcTCI (ci, n2) { // TCI:=EMA(CI,N2);
if (ci.length <= n2) {
return false
}
return TA.EMA(ci, n2)
}
이 마지막 단계에서는 이전에 만든 바퀴의 SMA 기능을 사용합니다.
function CalcWT2 (wt1) { // WT2:SMA(WT1,4,1);
if (wt1.length <= 4) {
return false
}
return SMA(wt1, 4, 1) // The SMA indicator for wt1 is calculated by using our own implementation of the SMA function.
}
트레이딩 신호의 변환은 매우 간단합니다.
AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;
이 MyLanguage 코드를 읽은 후, 우리는 WT1과 WT2의 골든 크로스와 베어시 크로스오버가 개막 조건으로 사용된다는 것을 알 수 있습니다. 이전 크로스 신호가 사용된다는 점에 유의해야합니다. MyLanguage 전략 백테스트를 직접 사용하여, 우리는 다음과 같은 것을 관찰합니다.
MyLanguage 전략의 실제 작동을 관찰하면 시그널이 시작 위치에서 감지되면 실제로 2 BAR를 앞으로 계산하는 시작 지점에있는 BAR의 위치가 골든 크로스인지 여부를 감지한다는 것을 알 수 있습니다. 위의 그림은 분명히 보여줍니다:
신호 감지 부분의 채식 코드는 다음과 같이 쓸 수 있습니다.
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") // test
}
if (_State == SHORT) {
_State = COVERSHORT
Log("COVERSHORT") // test
}
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") // test
}
if (_State == LONG) {
_State = COVERLONG
Log("COVERLONG") // test
}
isOK = false
}
여기서는 왜 MyLanguage의 SPK와 BPK 명령어가 위의 코드로 구현될 수 있는지 생각해 볼 수 있습니다.
백테스트 구성:
MyLanguage에서 백테스트:
자바스크립트 버전의 백테스트:
OnTick 함수의 시작에 있는 코드는 백테스팅을 더 빠르게 하기 위해 사용된다. 그것은 바 모델에 기반한 전략을 실행하기 위해 사용된다. 당신이 관심이 있다면, 당신은 세부적으로 분석할 수 있다.
function OnTick(){
// The ticker processing part of the driving strategy.
var records = _C(exchange.GetRecords)
if (records[records.length - 1].Time == preTime) {
if (isOK) {
Sleep(500)
return
}
} else {
preTime = records[records.length - 1].Time
}
...
..
.
전체 교육 전략 코드:https://www.fmz.com/strategy/174457