
이 전략은 달력 날짜 기반의 암호화폐 거래 방법이며, 달력 주기 중 특정 날짜를 활용하여 구매 및 판매 작업을 수행한다. 이 전략은 달력 신년에서 시작하여 그 해의 달력 12월 말까지 계속되며, 간단한 규칙을 따르고 있다. 매 달의 5일 구매하고 매 달의 26일 판매한다. 이 방법은 달력 주기와 관련된 시장 패턴을 포착하려고 하며, 트레이더에게 구조화되고 쉽게 따라갈 수 있는 거래 프레임워크를 제공한다. 이 전략은 수수료와 슬라이드 요소를 고려하고 있으며, 100%의 사용 가능한 자본 투자를 사용하여 2020 년부터 2026 년까지 적용된다.
이 전략의 핵심 원칙은 달력 주기에서 암호화폐 시장에 발생할 수 있는 영향에 기초하고 있다. 코드는 다음과 같은 방법으로 이 개념을 구현한다:
전략은 정확한 날짜 계산 방법을 사용하여, 각 달의 날을 배열로 저장하고, 달의 새해부터 시작되는 총 날을 누적하여 현재의 달력 날짜를 정확하게 결정합니다. 이 방법은 거래 신호의 정확한 촉발을 보장합니다.
이 전략의 코드를 분석하면 다음과 같은 장점을 찾을 수 있습니다:
이러한 장점에도 불구하고, 이 전략에는 몇 가지 잠재적인 위험도 있습니다.
이러한 위험을 줄이기 위해, 거래자는 다른 기술 지표와 함께 거래 확인을 고려할 수 있습니다. 또는 단일 거래의 손실을 제한하기 위해 고정된 중지 손실을 설정할 수 있습니다.
코드 분석을 통해 다음과 같은 몇 가지 최적화 방향을 제시할 수 있습니다.
손절매 메커니즘 소개: 퍼센트 또는 절대 금액의 중지 조건을 추가하여 손실이 특정 하락값에 도달하면 자동으로 청산하여 큰 손실을 피하십시오. 최적화 코드는 비슷한 것을 추가할 수 있습니다.if strategy.position_size > 0 and close < entry_price * (1 - stop_loss_percent)조건적 판단.
통합 기술 지표 확인: 트렌드 지표 (如移动平均线) 또는 동력 지표 (如相对强弱指数 RSI) 와 결합하여 보조 조건으로, 기술 지표가 유리한 신호를 제공 할 때만 달력 날짜 거래를 수행하십시오. 이것은 신호 품질을 향상시킬 수 있습니다.
구매 날짜를 최적화하세요: 5일과 26일을 고정적으로 사용하는 대신, 어떤 달력 날짜가 조합에 실제로 가장 좋은 구매 및 판매 시간을 제공하는지 분석하기 위해 역사 데이터를 회수하십시오. 특정 날짜 조합이 더 잘 작동 할 수 있습니다.
일부 포지션 관리전략 변경: 100%의 자금 대신 일부 자금을 사용하여 거래하거나, 시장의 변동성에 따라 포지션 크기를 조정하여 위험을 분산하십시오.
시장 상태 필터를 추가합니다.극단적인 시장 조건에서 (예: 높은 변동성 또는 명백한 곰 시장 추세) 전략 실행을 중지하고 불리한 환경에서 거래하는 것을 피하십시오.
적용할 수 있는 시간 범위를 넓혀라: 더 많은 연도의 달력 데이터를 추가하거나, 달력 날짜를 자동으로 계산하는 함수를 개발하여 전략을 무한히 실행할 수 있습니다.
다종류 거래 증가: 여러 암호화폐나 다른 자산 클래스로 전략을 확장하고, 달력 주기 상의 다른 시장에서의 성과 차이를 관찰한다.
이러한 최적화 방향의 구현은 전략의 강성과 적응력을 크게 향상시킬 수 있지만, 핵심적인 아이디어는 간단하고 직관적입니다.
달력 주기 기반의 암호화폐 거래 전략은 특정 달력 날짜를 활용한 구매 및 판매 작업을 수행하는 독특한 거래 관점을 제공합니다. 이 전략의 가장 큰 장점은 간단한 명확한 규칙과 쉽게 실행할 수 있는 특성으로, 달력 주기라는 고유한 요소와 결합하여 일반적인 기술적 분석에서 무시되는 시장 패턴을 포착 할 수 있습니다.
그러나, 이 전략은 또한 위험 관리 및 시장 적응성의 부족에 직면하고 있습니다. 전략의 효과를 높이기 위해, 손실 방지 장치, 기술 지표 확인 및 구매 및 판매 날짜의 최적화와 같은 개선 조치를 도입하는 것이 좋습니다. 이러한 최적화는 잠재적인 위험을 줄일 수있을뿐만 아니라 다양한 시장 환경에서 전략의 적응력을 향상시킬 수 있습니다.
참고로, 모든 거래 전략은 실제 시장 조건에서 그 성능을 검증하기 위해 충분한 역시험과 전향 테스트를 받아야합니다. 거래자는 자신의 위험 용량과 투자 목표에 따라 적절한 조정을 수행하고 다른 분석 방법과 결합하여 더 포괄적인 거래 결정을 내릴 수 있습니다.
/*backtest
start: 2024-08-11 00:00:00
end: 2025-08-09 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=5
strategy("Lunar ETHUSDT Trading 100% Invest with Fee & Slippage (2020~2026)", overlay=true, commission_type=strategy.commission.percent, commission_value=0.1)
// Fee and slippage settings
feePercent = 0.1 // 0.1%
slippageTicks = 3
tickSize = syminfo.mintick
slippage = slippageTicks * tickSize
// Function for lunar new year start date and monthly lengths by year
f_get_lunar_data() =>
y = year(time)
if y == 2020
[timestamp("Asia/Seoul", 2020, 1, 25, 0, 0), array.from(29,30,29,30,29,30,29,30,29,30,30,29)]
else if y == 2021
[timestamp("Asia/Seoul", 2021, 2, 12, 0, 0), array.from(30,29,30,29,30,29,30,29,30,29,30,30)]
else if y == 2022
[timestamp("Asia/Seoul", 2022, 2, 1, 0, 0), array.from(29,30,29,30,29,30,29,30,30,29,30,29)]
else if y == 2023
[timestamp("Asia/Seoul", 2023, 1, 22, 0, 0), array.from(30,29,30,29,30,29,30,30,29,30,29,30)]
else if y == 2024
[timestamp("Asia/Seoul", 2024, 2, 10, 0, 0), array.from(30,29,30,29,30,29,30,29,30,29,30,30,29)]
else if y == 2025
[timestamp("Asia/Seoul", 2025, 1, 29, 0, 0), array.from(29,30,29,30,29,30,29,30,30,29,30,29)]
else if y == 2026
[timestamp("Asia/Seoul", 2026, 2, 17, 0, 0), array.from(30,29,30,29,30,29,30,30,29,30,29,30)]
else
[na, array.new_int()]
// Function to create cumulative monthly days array
f_get_lunar_md(days_arr) =>
arr = array.new_int()
sum = 0
for i = 0 to array.size(days_arr) - 1
sum += array.get(days_arr, i)
array.push(arr, sum)
arr
// Get lunar start date and monthly lengths
[ts_start, lunar_lengths] = f_get_lunar_data()
valid = not na(ts_start)
days_since = valid ? math.floor((time - ts_start) / 86400000) : na
cumulative = valid ? f_get_lunar_md(lunar_lengths) : na
// Declare lunar month, day, last day variables
var int lunar_month = na
var int lunar_day = na
var int lunar_last_day = na
// Calculate lunar date
if valid and not na(days_since) and days_since >= 0
lunar_month := na
lunar_day := na
lunar_last_day := na
for i = 0 to array.size(cumulative) - 1
cum = array.get(cumulative, i)
prev = i == 0 ? 0 : array.get(cumulative, i - 1)
if days_since < cum
lunar_month := i + 1
lunar_day := days_since - prev + 1
lunar_last_day := array.get(lunar_lengths, i)
break
else
lunar_month := na
lunar_day := na
lunar_last_day := na
// Buy condition: Lunar day 5 and no current position
buy_condition = not na(lunar_day) and lunar_day == 5 and strategy.position_size == 0
// Sell condition: Lunar day 26 and holding position
sell_condition = not na(lunar_day) and lunar_day == 26 and strategy.position_size > 0
// Buy/sell price adjusted for slippage and fee
price_buy = close + slippage
price_buy_with_fee = price_buy * (1 + feePercent * 0.01)
price_sell = close - slippage
price_sell_with_fee = price_sell * (1 - feePercent * 0.01)
// Calculate buy quantity using 100% of equity
qty = math.floor(strategy.equity / price_buy_with_fee)
// Buy order (limit)
if buy_condition and qty > 0
strategy.entry("Lunar Buy", strategy.long, qty, limit=price_buy)
// Sell order (close all)
if sell_condition and strategy.position_size > 0
strategy.close("Lunar Buy")
// True range variable (for label position adjustment)
tr = ta.tr(true)
// Date format creation
yr = year(time)
mo = month(time)
dy = dayofmonth(time)
mo_str = mo < 10 ? "0" + str.tostring(mo) : str.tostring(mo)
dy_str = dy < 10 ? "0" + str.tostring(dy) : str.tostring(dy)
solar_str = str.tostring(yr) + "-" + mo_str + "-" + dy_str
// Display solar and lunar date and position label (on bar close)
if barstate.islastconfirmedhistory and not na(lunar_day)
label.new(bar_index, high - tr * 6, "Solar: " + solar_str + "\nLunar: " + str.tostring(lunar_month) + "-" + str.tostring(lunar_day) ,
style=label.style_label_up, size=size.normal, color=color.new(color.teal, 50), textcolor=color.white)
// Display "15" label at bottom on lunar day 15 (lowest of last 50 bars - 1 true range)
if not na(lunar_day) and lunar_day == 15
low_offset = ta.lowest(low, 50) - tr
label.new(bar_index, low_offset, "15", style=label.style_label_down, color=color.orange, textcolor=color.white, size=size.normal)