커뮤니티

예스스팟 Q&A

답변완료

문의드립니다.

안녕하세요. 로그 메세지를 텔레그램봇에 보낼수도 있나요? 안되면 텍스트파일에라도 기록이 가능할까요.
프로필 이미지
율담
2025-03-28
245
글번호 226260
답변완료

수식 문의드립니다.

수고하십니다. 국내옵션 진입수식 문의드립니다. 아침 8시에 예스스팟을 작동시작하면 당일 오후 3시 30분에 코스피200지수 기준으로 위아래 30포인트 외가 콜옵션,풋옵션을 현재가 기준-4틱에 12계약 지정가 양매도진입하는 수식을 만들고 싶습니다. (변수로 지정가능하게 ex: 10포인트외가옵션, 20포인트외가외가옵션, 30포인트외가외가옵션)
프로필 이미지
수다리
2025-03-27
253
글번호 226259
답변완료

부동소수점 주문처리 오류 해결되었는지

스팟에서 종목값을 불러오면 부동소수점이 포함되어 수신되는 경우가 가끔 있습니다. 게시판을 검색해보니 12년(글번호 236) 경에는 주문시 사용자가 직접 이 오류를 수정하도록 되어있는데 현재도 마찬가지인가요? 아니면 예스스팟에서 부동소수점을 자동으로 제거하고 주문하도록 개선되었나요?
프로필 이미지
훈sys
2025-03-26
230
글번호 226258
답변완료

수식 문의드립니다.

답변 미리 감사드립니다. 질문답변 대기가 오래걸리네요. 주문변경 구현이 안됩니다. 나스닥에서 매수진입시, 지정가(신호가) 진입 주문후, 3초후 미체결시 신호가-3틱, 3초후 미체결시 시장가로 부탁합니다. 예스스팟이 미체결물량을 인식하는지 궁금하네요. 최초 지정가 진입 주문시.. 어떠한이유로 주문이 안나갔을경우.. 3초후 신호가-3틱으로 지정가 주문이 다시 나가게 되는건가요. 지정가 주문후 이주문을 취소하고.. 다시 주문을 내는것인지.. 아님 주문변경 로직인지 궁금하네요.
프로필 이미지
율담
2025-04-01
272
글번호 226257
답변완료

수식 문의드립니다.

안녕하세요. 예스스팟 전략을 시작할때 로그로 날짜 시간을 출력하고 싶습니다. 어떻게 해야하나요.
프로필 이미지
율담
2025-03-24
222
글번호 226256
답변완료

매수 매도 신호를 받으면 오류가 발생합니다.

var List; var ListCnt; var ReqCount; var initCash = 1000000; // 초기 매수 금액 (100만원 예시) var firstQty = 0; // 첫 매수 수량 var addQty = 0; // 추가 매수 수량 var firstEntryP = 0; // 첫 매수 진입가 var addEntryP = 0; // 추가 매수 진입가 var isFirstPos = false; // 첫 매수 포지션 보유 여부 var isAddPos = false; // 추가 매수 포지션 보유 여부 var price = 0; // 신호 발생 시점의 주가 // 동적으로 생성된 차트 객체를 저장할 배열 var chartArray = []; // BL 배열 : 새로 생성해야 할 종목코드를 저장 (CT 배열 대신 chartArray 사용) var BL = []; // req : BL 배열 순회용 인덱스 var req = 0; //-------------------------------------------------------------------- // 스팟 첫 실행시 //-------------------------------------------------------------------- function Main_OnStart() { Main.ReqPowerSearch("기준봉-1"); Main.MessageLog("종목 검색 요청"); // 10분(60000ms 테스트용)마다 재검색 타이머 설정 (nEventID = 9) Main.SetTimer(9, 60000); } //-------------------------------------------------------------------- // 종목검색 완료(검색된 종목코드) 수신 //-------------------------------------------------------------------- function Main_OnRcvItemList(aItemList, nCount) { // 여기서는 기존 백그라운드 차트 삭제는 별도로 처리하지 않고, // 기존 chartArray는 계속 유지될 수 있습니다. // 만약 필요하다면 삭제 로직을 별도로 구현하세요. List = aItemList; ListCnt = nCount; Main.MessageLog("검색된 종목수: " + nCount); for (var i = 0; i < nCount; i++) { Main.MessageLog("List[" + i + "] = " + aItemList[i]); } // --------------------------- // 검색된 종목과 기존에 생성된 차트(CT 배열)의 종목 코드를 비교해서, // 차트가 만들어지지 않은 종목만 BL 배열에 추가하는 부분 // BL 배열 초기화 BL = []; // aItemList는 새로 검색된 종목 리스트 (배열) for (var i = 0; i < aItemList.length; i++) { var symbol = aItemList[i]; var addFlag = true; // CT 배열은 기존에 생성된 차트 객체들이 저장되어 있음 for (var z = 0; z < chartArray.length; z++) { if (symbol == chartArray[z].GetCode(1)) { addFlag = false; break; } } if (addFlag) { BL.push(symbol); } } Main.MessageList("BL : ", BL); // 차트가 만들어져야 할 종목이 있으면 BL 배열의 모든 종목에 대해 차트 요청 if (BL.length >= 1) { for (var i = 0; i < BL.length; i++) { // 아래 코드와 동일하게 차트를 생성 var C1 = new ReqChartItem(BL[i], 15, CHART_PERIOD_MINUTE, 3000, CHART_REQCOUNT_BAR, false, false); var S1 = new SystemInfo("W", YL_TYPE_NORMAL, null, null, null); Main.ReqChartEx(C1, S1); Main.MessageList("차트객체요청 :", BL[i]); } } else { // 차트가 생성되어야 할 종목이 없으면, 타이머 재설정 (예: 15초 후 재검색) Main.SetTimer(1, 15000); } // [추가] 1초 간격으로 익절·손절 로직 검사 Main.SetTimer(2, 1000); } //-------------------------------------------------------------------- // 백그라운드 차트 생성 시, 차트 객체를 배열에 저장 (이벤트) //-------------------------------------------------------------------- function Main_OnRcvChartEx(ChartEx) { chartArray.push(ChartEx); Main.MessageLog("차트 생성 완료: " + ChartEx.GetCode(1)); } //-------------------------------------------------------------------- // 타이머 이벤트 처리 //-------------------------------------------------------------------- function Main_OnTimer(nEventID) { // (A) 10분 타이머: 재검색 if (nEventID == 9) { Main.MessageLog("[10분 타이머] 종목 재검색 요청"); Main.ReqPowerSearch("기준봉-1"); } // (1) 2초 타이머: 기존 코드에서 차트 요청 (별도 로직이 있다면 유지) // 만약 BL 배열을 통한 차트 요청으로 모두 처리한다면, 기존 2초 타이머 코드가 필요 없을 수 있음. // 여기서는 기존 코드와 BL 기반 요청이 동시에 존재하지 않도록 주의. // (2) 1초 타이머: 익절·손절 퍼센트 체크 else if (nEventID == 2) { checkProfitLoss(); } } // 헬퍼 함수: 지정된 종목 코드의 현재 가격(현재 봉의 종가)을 chartArray에서 찾기 function getCurrentPrice(code) { for (var i = 0; i < chartArray.length; i++) { if (chartArray[i].GetCode(1) == code) { // nData=1, nIndex=0: 현재 봉의 종가 (문서에 맞게 수정 가능) return chartArray[i].GetClose(1, 0); } } // 만약 해당 차트를 찾지 못하면 0 반환 (이 경우 오류 처리 필요) return 0; } //-------------------------------------------------------------------- // 익절/손절 퍼센트 비교 로직 (실제 현재가를 가져오는 로직 추가) //-------------------------------------------------------------------- function checkProfitLoss() { // 매수 포지션이 존재하는 경우 if (Account1.Balance.position == 2) { var code = Account1.Balance.code; // 매수 종목코드 var holdQty = Account1.Balance.count; // 보유 수량 if (holdQty <= 0) return; // chartArray에서 해당 종목의 현재가를 가져옴 var currentPrice = getCurrentPrice(code); if (currentPrice <= 0) { Main.MessageLog("현재가를 가져오지 못했습니다. code=" + code); return; } // 첫 매수 상태 (추가매수 아직 없음) if (!isAddPos && isFirstPos) { // +7% 익절 조건: 현재가가 첫 진입가의 1.07배 이상이면 if (currentPrice >= firstEntryP * 1.07) { Main.MessageLog("[첫 매수 +7% 익절] 전량 청산: 현재가=" + currentPrice + ", 진입가=" + firstEntryP); Account1.OrderSell(Main.GetOrderCode(code), holdQty, 0, 1); resetPosition(); } // -8% 손절 조건: 현재가가 첫 진입가의 0.92배 이하이면 else if (currentPrice <= firstEntryP * 0.92) { Main.MessageLog("[첫 매수 -8% 손절] 전량 청산: 현재가=" + currentPrice + ", 진입가=" + firstEntryP); Account1.OrderSell(Main.GetOrderCode(code), holdQty, 0, 1); resetPosition(); } } // 추가 매수 상태 else if (isAddPos) { // +3% 익절 조건: 현재가가 추가 매수가격의 1.03배 이상이면 if (currentPrice >= addEntryP * 1.03) { Main.MessageLog("[추가 매수 +3% 익절] 전량 청산: 현재가=" + currentPrice + ", 추가 진입가=" + addEntryP); Account1.OrderSell(Main.GetOrderCode(code), holdQty, 0, 1); resetPosition(); } // -5% 손절 조건: 현재가가 추가 매수가격의 0.95배 이하이면 else if (currentPrice <= addEntryP * 0.95) { Main.MessageLog("[추가 매수 -5% 손절] 전량 청산: 현재가=" + currentPrice + ", 추가 진입가=" + addEntryP); Account1.OrderSell(Main.GetOrderCode(code), holdQty, 0, 1); resetPosition(); } } } } //-------------------------------------------------------------------- // 생성된 차트에서 신호 발생 시 (매수/매도 로직) //-------------------------------------------------------------------- function Main_OnRiseSignal(ChartEx, Signal) { Account1.SetBalance(Main.GetOrderCode(Signal.code), 0); var code = ChartEx.GetCode(1); var price = ChartEx.GetClose(1, 0); if (Signal.signalKind == 1) { if (Account1.Balance.count == 0) { firstQty = Math.floor(initCash / price); if (firstQty < 1) firstQty = 1; Main.MessageLog("첫 매수 신호 발생: 종목코드=" + code + ", 수량=" + firstQty + ", 매수가격=시장가"); Account1.OrderBuy(Main.GetOrderCode(code), firstQty, 0, 1); isFirstPos = true; isAddPos = false; firstEntryP = price; addEntryP = 0; } else if (Account1.Balance.position == 2) { addQty = firstQty * 3; Main.MessageLog("추가매수 신호 발생: 종목코드=" + code + ", 수량=" + addQty + ", 매수가격=시장가"); Account1.OrderBuy(Main.GetOrderCode(code), addQty, 0, 1); isAddPos = true; addEntryP = price; } } else if (Signal.signalKind == 2) { Main.MessageLog("청산 신호 발생(무시, 퍼센트 체크는 타이머에서 처리): 종목코드=" + code); } } //-------------------------------------------------------------------- // 포지션 상태 초기화 함수 //-------------------------------------------------------------------- function resetPosition() { firstQty = 0; addQty = 0; firstEntryP = 0; addEntryP = 0; isFirstPos = false; isAddPos = false; Main.MessageLog("[resetPosition] 포지션 상태 초기화"); } 검색된 종목에서 신호발생시, 매수매도 코드에 진입하면 getclose 지정된 매개변수가 비정상적입니다. 오류가 발생합니다. 매매를 할 수가 없는데 검토부탁드립니다.
프로필 이미지
망고맨
2025-03-25
242
글번호 226255
답변완료

옵션 종목선정 오류가 있는거 같아요

안녕하세요. 완전초보입니다 월물옵션, 위클리옵션 스팟으로 매매중이며 아래수식은 그중 종목선정 부분만 발췌한 사항입니다. 작동은 되는데 가끔 엉뚱한 종목이 선정됩니다. (증상) 콜풋 1.5에 가까운 종목 찾아서 SC, SP로 지정하되 그 차이가 0.8보다 크면 콜풋 0.9에 가까운 종목으로 SC, SP로 변경 지정하라 인데 가끔 풋옵션이 3.X 또는 4.X 가격이 지정됩니다. 분명 종목선정 시기에 1.5 또는 0.9에 가까운 풋옵션 종목이 있는데도 말입니다. 풋옵션만 좀 더 내가쪽에서 종목이 선정되는거 같습니다. 수식 자체는 작동하나 종목 선정시에는 문제가 있는거 같은데 꼭 수정 부탁드립니다. 아래식은 제가 사용하는 수식이며 이수식도 예전에 운영자님께서 도움주셔서 작성한 수식입니다. (요청사항 1) 지정된 가격의 종목이 선정될수 있도록 수식의 오류사항을 수정해주세요 (요청사항 2) 콜가격1(1.5근접), 콜가격2(0.9근접), 풋가격1, 풋가격2에서 콜가격1-풋가격1, 콜가격1-풋가격2, 콜가격2-풋가격1, 콜가격2-풋가격2 차이의 절대값을 구하고 그 차이가 가장 적은 경우의 콜과 풋을 SC, SP로 지정하는 수식도 부탁드립니다. //아래는 종목선정 수식이며 답변 미리감사드립니다. ----------------------------------------------------------------------- function Main_OnTimer(nEventID) { var d = new Date(); var HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds(); if (Option.GetRemainDays(0,0) >= 4 && nEventID == 1 && HHMMSS >= 090030) { Main.MessageList("당일목클진입없음"); Main.KillTimer(1); } if (Option.GetRemainDays(0,0) >= 2 && Option.GetRemainDays(0,0) <= 3 && nEventID == 1 && HHMMSS >= 090040 && Entry1 == false) { var UNum = Option.uppersATM; var LNum = Option.lowersATM; var CallCode = new Array(UNum+LNum+1); var CallPrice = new Array(UNum+LNum+1); var CallPrice1 = new Array(UNum+LNum+1); var CallPrice2 = new Array(UNum+LNum+1); var PutCode = new Array(UNum+LNum+1); var PutPrice = new Array(UNum+LNum+1); var PutPrice1 = new Array(UNum+LNum+1); var PutPrice2 = new Array(UNum+LNum+1); for (var i = -LNum; i <= UNum; i++) { if (Option.GetCurrent(0, i) >= 0.7 && Option.GetCurrent(0, i) <= 2.5 && Math.abs(Option.GetDelta(0, i)) < 0.95) { CallPrice[i+LNum] = Option.GetCurrent(0, i); //콜별 현재가 CallPrice1[i+LNum] = Math.abs(Option.GetCurrent(0, i)-1.5); //1.5 근접 CallPrice2[i+LNum] = Math.abs(Option.GetCurrent(0, i)-0.9); //0.9 근접 CallCode[i+LNum] = Option.GetATMCallRecent(i); //종목코드 } } for (var i = -UNum; i <= LNum; i++) { if (Option.GetCurrent(0, i) >= 0.7 && Option.GetCurrent(0, i) <= 2.5 && Math.abs(Option.GetDelta(1, i)) < 0.95) { PutPrice[i+UNum] = Option.GetCurrent(1, i); //풋별 현재가 PutPrice1[i+UNum] = Math.abs(Option.GetCurrent(1, i)-1.5); //1.5 근접 PutPrice2[i+UNum] = Math.abs(Option.GetCurrent(1, i)-0.9); //0.9 근접 PutCode[i+UNum] = Option.GetATMPutRecent(i); //종목코드 } } //콜 종목 찾음 var CC1 = 99999999; var CCPrice1 = 0; var CallOrderCode1 = ""; for (var i = -LNum; i <= UNum; i++) { if (CallPrice1[i+LNum] < CC1) { CC1 = CallPrice1[i+LNum]; CCPrice1 = CallPrice[i+LNum]; CallOrderCode1 = CallCode[i+LNum] } } //풋 종목 찾음 var PP1 = 99999999; var PPPrice1 = 0; var PutOrderCode1 = ""; for (var i = -UNum; i <= LNum; i++) { if (PutPrice1[i+UNum] < PP1) { PP1 = PutPrice1[i+UNum]; PPPrice1 = PutPrice[i+UNum]; PutOrderCode1 = PutCode[i+UNum]; } } //콜풋 모두 찾았으면 if (CC1 < 99999999 && PP1 < 99999999) { //우선 1.5에 가까운 종목을 SC와 SP로 저장 SC = CallOrderCode1; SP = PutOrderCode1; //콜풋 차이가 0.8이상이면 0.9에 가장 가까운 종목을 찾아 SC와 SP를 변경 if (Math.abs(CCPrice1-PPPrice1) >= 0.8) { var CC2 = 99999999; var CCPrice2 = 0; var CallOrderCode2 = ""; for (var i = -LNum; i <= UNum; i++) { if (CallPrice2[i+LNum] < CC2) { CC2 = CallPrice2[i+LNum]; CCPrice2 = CallPrice[i+LNum]; CallOrderCode2 = CallCode[i+LNum] } } var PP2 = 99999999; var PPPrice2 = 0; var PutOrderCode2 = ""; for (var i = -UNum; i <= LNum; i++) { if (PutPrice2[i+UNum] < PP2) { PP2 = PutPrice2[i+UNum]; PPPrice2 = PutPrice[i+UNum]; PutOrderCode2 = PutCode[i+UNum]; } } if (CC2 < 99999999 && PP2 < 99999999) { SC = CallOrderCode2; SP = PutOrderCode2; } } CEntryPrice = Option.GetCurrentByCode(SC); PEntryPrice = Option.GetCurrentByCode(SP); CPEntryPrice = Math.round(CEntryPrice*100 + PEntryPrice*100)/100; Entry1 = true; Main.MessageList("기준양합:", CPEntryPrice, "콜종목:", SC, "콜가격:", CEntryPrice, "풋종목:", SP, "풋가격:", PEntryPrice); //종목선정이 완료되었으므로 타이머 종료 Main.KillTimer(1); //타이머 셋팅(2번, 2초) Main.SetTimer(2, 2000); } } } ------------------------------------------------------------------------------------
프로필 이미지
탄젠트80
2025-03-24
224
글번호 226254
답변완료

문의드립니다.

안녕하세요. 수고가 많으십니다. 예스스팟에서 분할매수 및 청산 수식을 작성하는 데 어려움이 있어 도움을 요청드립니다. 1. 예스스팟 자동매매를 실행했을 때 계좌에 있는 종목(미리 수동매수한 종목)이 0.5%, 1%, 1.5%하락했을 때 10만 원씩 분할매수 2. 8% 상승시 보유 개수의 50% 익절 3. 5%이상 상승했다가 4%로 내려왔을 시 전량 청산(트레일링 스탑) 4. 첫번째 분할매수로 진입한 가격에서 2% 하락시 전량 손절 답변 주시면 정말 감사드리겠습니다.
프로필 이미지
저니0
2025-03-23
249
글번호 226253

망고맨 님에 의해서 삭제되었습니다.

프로필 이미지
망고맨
2025-03-24
8
글번호 226252
답변완료

매수와 동시에 1.5자동매도 수식 부탁드립니다

var 타이머간격 = 5; //5초 var 매수금 = 2000000; var OrderList = []; var MKList = []; var MKOD = []; var req; function Main_OnStart() { //1번 타이머, 5초 Main.SetTimer(1, 타이머간격*1000); } function Main_OnTimer(nEventID) { var d = new Date(); YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate(); HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds(); if (nEventID == 1 && HHMMSS >= 90000 && HHMMSS < 151500) { //종목검색 수행 Main.ReqPowerSearch("ZL") } if (nEventID == 2) { Main.ReqMarketData(OrderList[req]); } } function Main_OnRcvItemList(aItemList, nCount) { Main.KillTimer(1); OrderList = []; if (nCount >= 1) { if (MKList.length == 0) { OrderList = aItemList; } else { for (var a = 0; a < nCount; a++) { var Add = true; for (var b = 0; b < MKList.length; b++) { if (aItemList[a] == MKList[b].code) { Add = false; } } if (Add == true) { OrderList.push(aItemList[a]); } } } } if (OrderList.length == 0) { Main.SetTimer(1, 타이머간격*1000); } else { req = 0; Main.ReqMarketData(OrderList[req]); } } function Main_OnRcvMarketData(MarketData) { if (MarketData.code == OrderList[req]) { MKList.push(MarketData); MKOD.push(0); //Account1.OrderBuy(MarketData.code,1,0,1); //1주를 시장가 주문 // Account1.OrderBuy(MarketData.code,Math.floor(매수금/MarketData.Ask(1)),0,1); //10만원 시장가 주문 Account1.OrderBuy(MarketData.code,Math.floor(매수금/MarketData.Ask(1)),MarketData.Ask(1),0); //10만원 지정가 주문 지정가로 주문하고자 하시면 주문함수 내용을 위와 같이 변경하시면 됩니다. req = req+1; if (req < OrderList.length) { var aa = Main.ReqMarketData(OrderList[req]); if (aa == -1) { Main.SetTimer(2, 15000); } } else { Main.SetTimer(1, 타이머간격*1000); } } } 매수와 동시에 1.5%자동매도 수식 부탁드립니다 스탑주문창 사용시 검색식에 따라 수익을 따로 설정할수 없어요
프로필 이미지
님이랑
2025-03-25
277
글번호 226251