
이 글에서는 그다지 신뢰할 수 없는 거래 아이디어인 K-라인 영역 거래 전략을 살펴보고, 이 스크립트를 구현해보겠습니다.
K-라인 영역 전략은 가격 K-라인과 이동 평균선 간의 영역 관계를 기반으로 한 거래 전략입니다. 주된 아이디어는 가격 추세의 진폭과 변화, 매수 및 매도 심리의 전환을 분석하여 주가의 가능한 추세를 예측하고, 이를 통해 포지션을 개시하고 청산하는 시점을 결정하는 것입니다. 이 전략은 촛대와 이동 평균선 사이의 영역과 KDJ 지표의 값을 활용하여 롱 및 숏 트레이딩 신호를 생성합니다.
캔들스틱 영역은 가격 캔들스틱과 이동평균선 사이의 공간을 말하며, 이는 각 막대의 종가에서 이동평균선을 뺀 다음 이를 합산하여 계산합니다. 가격이 장기간, 큰 진폭으로 상승할 경우 K-라인의 면적은 커지게 되고, 변동성이 큰 시장이나 변동성 이후 반전 시 K-라인의 면적은 작아지게 됩니다. . “모든 것은 반대 극단으로 간다”는 원리에 따르면 상승 추세가 클수록, 시간이 길수록 해당 K-라인 영역이 커지고 반전 가능성이 커집니다. 이는 스프링과 같습니다. 늘어날수록 반발력이 커진다. 따라서 K-line 영역에 대한 임계값이 설정됩니다. 이 임계값에 도달하면 가격 추세가 완료될 수 있으며 반전 가능성이 더 커집니다.
추세가 반전될 것임을 더욱 확실하게 확인하기 위해 매수 및 매도 심리의 전환을 판단하기 위해 KDJ 지표를 도입했습니다. 이 전략의 임계값과 KDJ 지표 값 설정은 특정 상황과 필요에 따라 조정되어 전략의 정확도를 높일 수 있습니다.
K-라인 영역 전략의 장점은 가격 추세의 진폭과 변화, 매수 및 매도 심리의 전환을 결합하여 비교적 완전한 정량적 거래 전략을 제공한다는 점입니다. 이 제품의 장점은 다음과 같습니다.
캔들스틱 영역 전략에는 특정한 장점이 있지만 다음과 같은 위험도 있습니다.
K-라인 지역 전략을 최적화하기 위해 다음과 같은 방향을 고려할 수 있습니다.
캔들스틱의 면적을 계산해보세요
롱 포지션을 열기 위한 신호:
(1) 하락 추세의 “K-라인 영역”이 임계값에 도달하면 이는 사전에 확립될 수 있습니다.
(2) KDJ 지표값이 80보다 크다
(1) 상승 추세의 “K-라인 영역”이 임계값에 도달하면 이는 사전에 설정될 수 있습니다.
(2) KDJ 지표값이 20보다 작습니다.
코드 구현
// 参数
var maPeriod = 30
var threshold = 50000
var amount = 0.1
// 全局变量
let c = KLineChart({})
let openPrice = 0
let tradeState = "NULL" // NULL BUY SELL
function calculateKLineArea(r, ma) {
var lastCrossUpIndex = null
var lastCrossDownIndex = null
for (var i = r.length - 1 ; i >= 0 ; i--) {
if (ma[i] !== null && r[i].Open < ma[i] && r[i].Close > ma[i]) {
lastCrossUpIndex = i
break
} else if (ma[i] !== null && r[i].Open > ma[i] && r[i].Close < ma[i]) {
lastCrossDownIndex = i
break
}
if (i >= 1 && ma[i] !== null && ma[i - 1] !== null && r[i - 1].Close < ma[i - 1] && r[i].Close > ma[i]) {
lastCrossUpIndex = i
break
} else if (i >= 1 && ma[i] !== null && ma[i - 1] !== null && r[i - 1].Close > ma[i - 1] && r[i].Close < ma[i]) {
lastCrossDownIndex = i
break
}
}
var area = 0
if (lastCrossDownIndex !== null) {
for (var i = r.length - 1 ; i >= lastCrossDownIndex ; i--) {
area -= Math.abs(r[i].Close - ma[i])
}
} else if (lastCrossUpIndex !== null) {
for (var i = r.length - 1 ; i >= lastCrossUpIndex ; i--) {
area += Math.abs(r[i].Close - ma[i])
}
}
return [area, lastCrossUpIndex, lastCrossDownIndex]
}
function onTick() {
var r = _C(exchange.GetRecords)
if (r.length < maPeriod) {
LogStatus(_D(), "K线数量不足")
return
}
var ma = TA.MA(r, maPeriod)
var atr = TA.ATR(r)
var kdj = TA.KDJ(r)
var lineK = kdj[0]
var lineD = kdj[1]
var lineJ = kdj[2]
var areaInfo = calculateKLineArea(r, ma)
var area = _N(areaInfo[0], 0)
var lastCrossUpIndex = areaInfo[1]
var lastCrossDownIndex = areaInfo[2]
r.forEach(function(bar, index) {
c.begin(bar)
c.plotcandle(bar.Open, bar.High, bar.Low, bar.Close, {overlay: true})
let maLine = c.plot(ma[index], "ma", {overlay: true})
let close = c.plot(bar.Close, 'close', {overlay: true})
c.fill(maLine, close, {color: bar.Close > ma[index] ? 'rgba(255, 0, 0, 0.1)' : 'rgba(0, 255, 0, 0.1)'})
if (lastCrossUpIndex !== null) {
c.plotchar(bar.Time, {char: '$:' + area, overlay: true})
} else if (lastCrossDownIndex !== null) {
c.plotchar(bar.Time, {char: '$:' + area, overlay: true})
}
c.plot(lineK[index], "K")
c.plot(lineD[index], "D")
c.plot(lineJ[index], "J")
c.close()
})
if (tradeState == "NULL" && area < -threshold && lineK[lineK.length - 1] > 70) {
// long
let tradeInfo = $.Buy(amount)
if (tradeInfo) {
openPrice = tradeInfo.price
tradeState = "BUY"
}
} else if (tradeState == "NULL" && area > threshold && lineK[lineK.length - 1] < 30) {
// short
let tradeInfo = $.Sell(amount)
if (tradeInfo) {
openPrice = tradeInfo.price
tradeState = "SELL"
}
}
let stopBase = tradeState == "BUY" ? Math.max(openPrice, r[r.length - 2].Close) : Math.min(openPrice, r[r.length - 2].Close)
if (tradeState == "BUY" && r[r.length - 1].Close < stopBase - atr[atr.length - 2]) {
// cover long
let tradeInfo = $.Sell(amount)
if (tradeInfo) {
tradeState = "NULL"
openPrice = 0
}
} else if (tradeState == "SELL" && r[r.length - 1].Close > stopBase + atr[atr.length - 2]) {
// cover short
let tradeInfo = $.Buy(amount)
if (tradeInfo) {
tradeState = "NULL"
openPrice = 0
}
}
LogStatus(_D(), "area:", area, ", lineK[lineK.length - 2]:", lineK[lineK.length - 2])
}
function main() {
if (exchange.GetName().includes("_Futures")) {
throw "not support Futures"
}
while (true) {
onTick()
Sleep(1000)
}
}
전략적 논리는 매우 간단합니다.
전략 매개변수
전역 변수
계산 함수
메인루프 기능
a. 최신 K-라인 데이터를 가져와서 K-라인의 수가 maPeriod보다 작지 않은지 확인하고, 그렇지 않으면 상태를 기록하고 반환합니다.
b. 이동평균 ma와 ATR 지표 atr, 그리고 KDJ 지표를 계산합니다.
c. areaInfo에서 영역 정보, 마지막 교차-위쪽 K-라인 인덱스, 마지막 교차-아래쪽 K-라인 인덱스를 가져옵니다.
d. 촛대 차트 객체 c를 사용하여 촛대와 지표 선을 그린 다음 가격과 이동 평균의 관계에 따라 다른 색상으로 채웁니다.
e. 조건에 따라 매수 및 매도 시점을 결정하십시오.
tradeState가 “NULL”이고, 영역이 -threshold보다 작고 KDJ 캔들스틱 값이 70보다 큰 경우 매수 작업이 수행됩니다. tradeState가 “NULL”이고, 영역이 임계값보다 크고 KDJ 캔들스틱 값이 30보다 작은 경우 매도 작업을 실행합니다. f. 손절매 및 이익 실현 조건을 설정하고 조건이 충족되면 포지션을 종료합니다.
매수 상태인 경우, 전 거래일의 종가에서 전 거래일의 ATR을 뺀 가격보다 가격이 낮을 경우 해당 포지션은 종료됩니다. 매도 상태인 경우, 가격이 전 거래일 종가와 전 거래일 ATR을 합한 가격보다 높을 때 포지션은 종료됩니다. 주요 기능: 이것은 거래소 이름에 “가 포함되어 있는지 확인하는 주요 실행 진입점입니다._“Futures”가 포함되어 있으면 예외가 발생하고, 그렇지 않으면 무한 루프에 빠지고, 각 루프에서 onTick 함수를 실행하고 1초 동안 대기합니다.
일반적으로 이 전략은 매수 및 매도 결정을 내리기 위해 주로 K-라인 차트와 기술 지표에 의존하는 반면, 손절매 및 이익실현 전략을 사용하여 위험을 관리합니다. 이는 단지 예시 전략일 뿐이며, 실제 사용은 시장 상황과 특정 요구 사항에 따라 조정 및 최적화되어야 합니다.
이 모델은 FMZ.COM에서 JavaScript를 사용하여 많은 줄의 코드를 사용하지 않고도 쉽게 구현되었습니다. 그리고 K-라인 영역의 그래픽 표현은 KLineChart 함수를 사용하여 쉽게 구현할 수 있습니다. 이 전략은 암호화폐 현물 시장을 위해 설계되었으며 “디지털 통화 현물 거래 라이브러리” 템플릿을 사용합니다. 템플릿에 캡슐화된 함수를 사용하여 주문을 하는 것도 매우 간단하고, 사용하기 쉽고 이해하기 쉽습니다.


나는 백테스팅 기간을 무작위로 선택했습니다. 돈을 잃지는 않았지만, 지속적으로 수익을 축적하지 않았기 때문에 드로다운 문제는 여전히 상당히 컸습니다. 이 전략에는 다른 최적화 방향과 여유 공간이 있어야 합니다. 관심이 있는 분들은 이 전략을 업그레이드해 보세요.

이 전략을 통해 우리는 더욱 대안적인 거래 아이디어를 배웠을 뿐만 아니라 차트를 그리는 방법, K-라인과 이동 평균선으로 둘러싸인 영역을 표현하는 방법, KDJ 지표를 그리는 방법 등을 배웠습니다.
K-라인 영역 전략은 가격 추세 진폭과 KDJ 지표를 기반으로 하는 거래 전략입니다. K-라인과 이동 평균 사이의 영역과 매수 및 매도 감정의 전환을 분석하여 거래자가 시장 추세를 예측하는 데 도움이 됩니다. 특정 위험은 존재하지만, 지속적인 최적화와 조정을 통해 이 전략은 트레이더가 시장 변동에 더 잘 대처하는 데 도움이 되는 강력한 거래 도구를 제공할 수 있습니다. 더 나은 거래 성과를 달성하기 위해서는 거래자가 특정 상황과 시장 조건에 맞춰 전략의 매개변수와 규칙을 유연하게 조정하는 것이 중요합니다.