커뮤니티

선물에서 난 신호로 옵션에 적용하기

프로필 이미지
sambuck
2026-08-26 16:08:24
117
글번호 233392
답변완료

선물 시스템식이 신호가 나면 지정된 옵션프리미엄을 정하고 거기에 가장 가까운 값을 내는 식을 예스스팟편집기로 만들었는데 작동을 하지 않습니다.

살펴봐 주세요






/ ====================================================================

// ★ [사용자 지정 변수 설정 (Input 값)] ★

// ====================================================================

var TargetPremium = 1.5; // ?? 원하는 옵션 기준 가격 (예: 1.5)

var MyVolume = 1; // ?? 진입할 고정 계약수

var CallTargetIdx = 1100.0; // ?? 콜옵션 매수 후, '선물 가격'이 이 수치 이상으로 올라가면 익절 청산!

var PutTargetIdx = 1000.0; // ?? 풋옵션 매수 후, '선물 가격'이 이 수치 이하로 내려가면 익절 청산!

// ====================================================================


function Main_OnStart()

{

Main.MessageLog("★ [선물 지수 기준 위클리 옵션 실시간 익절 시스템] 가동 ★");

Main.MessageLog("설정 프리미엄: " + TargetPremium + " / 콜익절선물가: " + CallTargetIdx + " / 풋익절선물가: " + PutTargetIdx);

}


// 옵션의 가격대에 맞게 3호가 단위 값을 자동으로 계산해주는 함수

function GetThreeTicks(currentPrice)

{

if (currentPrice >= 3.00) {

return 0.15;

} else {

return 0.03;

}

}


// 지정한 프리미엄에 가장 가까운 콜옵션 코드를 찾는 함수

function GetNearPriceCallCode()

{

var minDiff = 9999; var bestCode = "";

for (var i = -10; i <= 10; i++) {

var code = Option1.GetATMCallCode(i);

var price = Option1.GetCurrent(code);

if (price > 0) {

var diff = Math.abs(price - TargetPremium);

if (diff < minDiff) { minDiff = diff; bestCode = code; }

}

}

return bestCode;

}


// 지정한 프리미엄에 가장 가까운 풋옵션 코드를 찾는 함수

function GetNearPricePutCode()

{

var minDiff = 9999; var bestCode = "";

for (var i = -10; i <= 10; i++) {

var code = Option1.GetATMPutCode(i);

var price = Option1.GetCurrent(code);

if (price > 0) {

var diff = Math.abs(price - TargetPremium);

if (diff < minDiff) { minDiff = diff; bestCode = code; }

}

}

return bestCode;

}


// [핵심] 차트의 주가 데이터(선물 현재가)가 실시간으로 수신될 때마다 1초에 수십 번씩 호출되는 함수

function Chart1_OnJuGaDataRecv(ChartEx)

{

// 현재 실시간 코스피 200 선물 가격을 가져옵니다.

var CurrentFuturePrice = Chart1.GetClose(1, 0);


// 1. 콜옵션 실시간 선물 지수 익절 감시

var TargetCallCode = GetNearPriceCallCode();

Account1.SetBalanceItem(TargetCallCode, 0);

if (Account1.Balance.count > 0) // 현재 계좌에 콜옵션 잔고가 있을 때만 감시

{

// 실시간 선물 지수가 설정해 둔 콜 익절 목표가보다 커지면 즉시 청산!

if (CurrentFuturePrice >= CallTargetIdx)

{

var currentPrice = Option1.GetCurrent(TargetCallCode);

var OrderPrice = currentPrice - GetThreeTicks(currentPrice); // -3호가 아래로 던짐

Account1.OrderSell(TargetCallCode, Account1.Balance.count, OrderPrice, 0);

Main.MessageLog("?? [선물 지수 콜 익절 도달!] 선물가: " + CurrentFuturePrice + " -> 콜옵션 전량 익절 청산 완료");

}

}


// 2. 풋옵션 실시간 선물 지수 익절 감시

var TargetPutCode = GetNearPricePutCode();

Account1.SetBalanceItem(TargetPutCode, 0);

if (Account1.Balance.count > 0) // 현재 계좌에 풋옵션 잔고가 있을 때만 감시

{

// 실시간 선물 지수가 설정해 둔 풋 익절 목표가보다 작아지면 즉시 청산!

if (CurrentFuturePrice <= PutTargetIdx)

{

var currentPrice = Option1.GetCurrent(TargetPutCode);

var OrderPrice = currentPrice - GetThreeTicks(currentPrice); // -3호가 아래로 던짐

Account1.OrderSell(TargetPutCode, Account1.Balance.count, OrderPrice, 0);

Main.MessageLog("?? [선물 지수 풋 익절 도달!] 선물가: " + CurrentFuturePrice + " -> 풋옵션 전량 익절 청산 완료");

}

}

}


// Chart1(선물 차트)에서 시스템 신호가 발생할 때 실행되는 함수 (진입 및 일반 청산용)

function Chart1_OnRiseSignal(Signal)

{

// 1. 선물 매수 신호 (Buy) 발생 시 -> 콜옵션 추격 매수

if (Signal.signalKind == 1)

{

var TargetCallCode = GetNearPriceCallCode();

var currentPrice = Option1.GetCurrent(TargetCallCode);

if (TargetCallCode != "") {

var OrderPrice = currentPrice + GetThreeTicks(currentPrice);

Account1.OrderBuy(TargetCallCode, MyVolume, OrderPrice, 0);

Main.MessageLog(">> 위클리 콜 자동 발굴 매수: " + TargetCallCode + " (주문가: " + OrderPrice + ")");

}

}


// 2. 선물 매수청산 신호 (ExitLong) 발생 시 -> 보유 콜옵션 일반 전량 청산

if (Signal.signalKind == 2)

{

var TargetCallCode = GetNearPriceCallCode();

Account1.SetBalanceItem(TargetCallCode, 0);

if (Account1.Balance.count > 0) {

var currentPrice = Option1.GetCurrent(TargetCallCode);

var OrderPrice = currentPrice - GetThreeTicks(currentPrice);

Account1.OrderSell(TargetCallCode, Account1.Balance.count, OrderPrice, 0);

Main.MessageLog(">> 선물 시스템 신호에 의한 콜 청산완료: " + TargetCallCode);

}

}


// 3. 선물 매도 신호 (Sell) 발생 시 -> 풋옵션 추격 매수

if (Signal.signalKind == 3)

{

var TargetPutCode = GetNearPricePutCode();

var currentPrice = Option1.GetCurrent(TargetPutCode);

if (TargetPutCode != "") {

var OrderPrice = currentPrice + GetThreeTicks(currentPrice);

Account1.OrderBuy(TargetPutCode, MyVolume, OrderPrice, 0);

Main.MessageLog(">> 위클리 풋 자동 발굴 매수: " + TargetPutCode + " (주문가: " + OrderPrice + ")");

}

}


// 4. 선물 매도청산 신호 (ExitShort) 발생 시 -> 보유 풋옵션 일반 전량 청산

if (Signal.signalKind == 4)

{

var TargetPutCode = GetNearPricePutCode();

Account1.SetBalanceItem(TargetPutCode, 0);

if (Account1.Balance.count > 0) {

var currentPrice = Option1.GetCurrent(TargetPutCode);

var OrderPrice = currentPrice - GetThreeTicks(currentPrice);

Account1.OrderSell(TargetPutCode, Account1.Balance.count, OrderPrice, 0);

Main.MessageLog(">> 선물 시스템 신호에 의한 풋 청산완료: " + TargetPutCode);

}

}

}

image.png

답변 1
프로필 이미지

예스스탁 예스스탁 답변

2026-08-28 13:53:55

안녕하세요 예스스탁입니다. 올리신 수식에 제공하지 않는 이벤트나 함수가 사용되어 있습니다. 스팟 수식답변은 작성 가이드이므로 아래 내용 참고하셔서 수정보완해 사용하시기 바랍니다. 스크립트 객체설정 차트객체 추가 -> 속성에서 객체명 Chart1, 차트와 동일아이디 지정 계좌객체 추가 -> 속성에서 객체명 Account1, 주문낼 계좌번호 지정 옵션객체 추가 -> 속성에서 객체명 Option1, 상품지정 // ==================================================================== // ★ [사용자 지정 변수 설정 (Input 값)] ★ // ==================================================================== var TargetPremium = 1.5; // ?? 원하는 옵션 기준 가격 (예: 1.5) var MyVolume = 1; // ?? 진입할 고정 계약수 var CallTargetIdx = 1100.0; // ?? 콜옵션 매수 후, '선물 가격'이 이 수치 이상으로 올라가면 익절 청산! var PutTargetIdx = 1000.0; // ?? 풋옵션 매수 후, '선물 가격'이 이 수치 이하로 내려가면 익절 청산! // ==================================================================== var ChartCode,T; var CallCode,PutCode; var CallPrice,PutPrice; var BID,BNUM,SID,SNUM; function Main_OnStart() { Main.MessageList("★ [선물 지수 기준 위클리 옵션 실시간 익절 시스템] 가동 ★"); Main.MessageList("설정 프리미엄: " , TargetPremium , " / 콜익절선물가: " , CallTargetIdx , " / 풋익절선물가: " , PutTargetIdx); ChartCode = Main.GetOrderCode(Chart1.GetCode(1)); Main.ReqMarketData(ChartCode); T = 0; } //차트에서 신호가 발생하면 function Chart1_OnRiseSignal(Signal) { //차트에서 매수진입신호 발생 if (Signal.signalKind == 1) { Main.MessageList("매수진입신호 발생"); //콜 종목 찾기 var minDiff = NaN; CallPrice = 0; CallCode = ""; for (var i = -Option1.lowersATM; i <= Option1.uppersATM; i++) { var diff = Math.abs(Option1.GetCurrent(0, i)-TargetPremium); if (CallPrice == 0 || (CallPrice > 0 && diff < minDiff)) { minDiff = diff; CallPrice = Option1.GetCurrent(0, i); CallCode = Option1.GetATMCallRecent(i, 0); } } Main.MessageList("콜종목코드:",CallCode,"|콜현재가 :",CallPrice); if (CallPrice > 0) { //콜옵션종목 매수 BID = Account1.OrderBuy(CallCode, MyVolume, Option1.GetAskByCode(CallCode, 3), 0); T = 1; } } //차트에서 매수청산신호 발생 if (T == 1 && Signal.signalKind == 2) { Main.MessageList("매수청산신호 발생"); Account1.SetUnfill(BNUM); var UV = 0; if (Account1.Unfill.count > 0) { UV = Account1.Unfill.count; Account1.OrderCancel(BNUM) Main.MessageList("콜매수주문 미체결 취소"); } var XV = MyVolume-UV; Account1.SetBalance(CallCode, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2 && XV > 0) { //콜옵션종목 매도 Account1.OrderSell(CallCode, Math.min(MyVolume,Account1.Balance.count), Option1.GetBidByCode(CallCode, 3), 0); } T = 0; } //차트에서 매도진입신호발생 if (Signal.signalKind == 3) { Main.MessageList("매도진입신호 발생"); //풋 종목 찾기 var minDiff = NaN; PutPrice = 0; PutCode = ""; for (var i = -Option1.uppersATM; i <= Option1.lowersATM; i++) { var diff = Math.abs(Option1.GetCurrent(1, i)-TargetPremium); if (PutPrice == 0 || (PutPrice > 0 && diff < minDiff)) { minDiff = diff; PutPrice = Option1.GetCurrent(1, i); PutCode = Option1.GetATMPutRecent(i, 0); } } Main.MessageList("풋종목코드:",PutCode,"|풋현재가 :",PutPrice); if (PutPrice > 0) { //풋옵션종목 매수 SID = Account1.OrderBuy(PutCode, 1, Option1.GetAskByCode(PutCode, 3), 0); T = -1; } } //차트에서 매도청산신호 발생 if (T == -1 && Signal.signalKind == 4) { Main.MessageList("매도청산신호 발생"); Account1.SetUnfill(SNUM); var UV = 0; if (Account1.Unfill.count > 0) { UV = Account1.Unfill.count; Account1.OrderCancel(SNUM) Main.MessageList("풋매수주문 미체결 취소"); } var XV = MyVolume-UV; Account1.SetBalance(PutCode, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2 && XV > 0) { //콜옵션종목 매도 Account1.OrderSell(PutCode, Math.min(MyVolume,Account1.Balance.count), Option1.GetBidByCode(PutCode, 3), 0); } T = 0; } } function Main_OnRcvMarketData(MarketData) { if (ChartCode == MarketData.code) { MK = MarketData; } } function Main_OnOrderResponse(OrderResponse) { if (OrderResponse.orderID == BID) { BNUM = OrderResponse.orderNum; } if (OrderResponse.orderID == SID) { SNUM = OrderResponse.orderNum; } } function Main_OnUpdateMarket(itemcode, updateID, exchangeKind) { if (updateID == 20001) { if (T == 1 && MK.current >= CallTargetIdx ) { Main.MessageList("콜매수 익절발생"); Account1.SetUnfill(BNUM); var UV = 0; if (Account1.Unfill.count > 0) { UV = Account1.Unfill.count; Account1.OrderCancel(BNUM) Main.MessageList("콜매수주문 미체결 취소"); } var XV = MyVolume-UV; Account1.SetBalance(CallCode, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2 && XV > 0) { //콜옵션종목 매도 Account1.OrderSell(CallCode, Math.min(MyVolume,Account1.Balance.count), Option1.GetBidByCode(CallCode, 3), 0); } T = 0; } if (T == -1 && MK.current <= PutTargetIdx ) { Main.MessageList("풋매수매 익절발생"); Account1.SetUnfill(SNUM); var UV = 0; if (Account1.Unfill.count > 0) { UV = Account1.Unfill.count; Account1.OrderCancel(SNUM) Main.MessageList("풋매수주문 미체결 취소"); } var XV = MyVolume-UV; Account1.SetBalance(PutCode, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2 && XV > 0) { //콜옵션종목 매도 Account1.OrderSell(PutCode, Math.min(MyVolume,Account1.Balance.count), Option1.GetBidByCode(PutCode, 3), 0); } T = 0; } } } 즐거운 하루되세요