답변완료
안녕하세요..
안녕하세요 //부장님
부장님이 해결해주신 내용입니다.
그런데 가격이 3.5이상에서는 시스템이 아웃되어 버립니다.
종목을 지정해서 불어오면 실행되는데
동시 거래가 있는 종목은 상관없는데 동시거래가 없으면 시스템이 아웃되는 현상이 일어나므로
추가해서
즉 입력란에서 임의 선택된 콜은 250부터 5개 풋은 245부터 5개 강제적으로 불러오는 곳을 추가하고 싶습니다.
동시시세가 없더라도 불러오고 싶네요
전략실행차트 여실때 자동으로 종목이 선정되게는 가능하지 않습니다.
스팟안에서 차트객체를 이용하신다면 스팟수식안에서 종목선정해 차트를 만들 수 있습니다.
기본차트는 KP200연결선물이고 콜/풋 옵션을 참조데이터로 추가하는데
4.0에 가까운 순서로 5개씩 추가합니다.
스크립트 객체설정
종목객체 추가 -> 속성에서 객체명 MarketData1, KP200연결선물로 지정
옵션객체 추가 -> 속성에서 객체명 Option1, KP200지수옵션으로 지정
var FutrueOpen;
var 콜기준 = 4.0;
var 풋기준 = 4.0;
var CallOrderCode1,CallOrderCode2,CallOrderCode3,CallOrderCode4,CallOrderCode5;
var PutOrderCode1,PutOrderCode2,PutOrderCode3,PutOrderCode4,PutOrderCode5;
function Main_OnStart()
{
FutrueOpen = false;
Main.SetTimer(1, 1000);
}
function Main_OnTimer(nEventID)
{
if (FutrueOpen == false && MarketData1.open > 0)
{
FutrueOpen = true;
Main.KillTimer(1);
var Calldiff = [];
if (콜기준 > 0)
{
var a = 0;
for (var i = -Option1.lowersATM; i < Option1.uppersATM; i++)
{
Calldiff[a] = new Array(Math.abs(콜기준-Option1.GetCurrent(0,i)),Option1.GetATMCallRecent(i));
a = a+1;
}
Calldiff.sort(CompareForSort);
CallOrderCode1 = Calldiff[0][1];
CallOrderCode2 = Calldiff[1][1];
CallOrderCode3 = Calldiff[2][1];
CallOrderCode4 = Calldiff[3][1];
CallOrderCode5 = Calldiff[4][1];
}
var Putdiff = [];
if (풋기준 > 0)
{
a = 0;
for (var i = -Option1.lowersATM; i < Option1.uppersATM; i++)
{
Putdiff[a] = new Array(Math.abs(풋기준-Option1.GetCurrent(1,-i)),Option1.GetATMPutRecent(-i));
a = a+1;
}
Putdiff.sort(CompareForSort);
PutOrderCode1 = Putdiff[0][1];
PutOrderCode2 = Putdiff[1][1];
PutOrderCode3 = Putdiff[2][1];
PutOrderCode4 = Putdiff[3][1];
PutOrderCode5 = Putdiff[4][1];
}
var ChartSet = new ReqChartItem("00000000",1,CHART_PERIOD_MINUTE,10000,CHART_REQCOUNT_BAR,false,false);
var R11 = new ReqChartItem(CallOrderCode1,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R12 = new ReqChartItem(CallOrderCode2,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R13 = new ReqChartItem(CallOrderCode3,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R14 = new ReqChartItem(CallOrderCode4,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R15 = new ReqChartItem(CallOrderCode5,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R21 = new ReqChartItem(PutOrderCode1,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R22 = new ReqChartItem(PutOrderCode2,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R23 = new ReqChartItem(PutOrderCode3,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R24 = new ReqChartItem(PutOrderCode4,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var R25 = new ReqChartItem(PutOrderCode5,1,CHART_PERIOD_MINUTE,1000,CHART_REQCOUNT_BAR,false,false);
var ReferDataSet = new Array(R11,R12,R13,R14,R15,R21,R22,R23,R24,R25);
Main.ReqChartEx(ChartSet,null,null,ReferDataSet);
}
}
function CompareForSort(a, b)
{
return( a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0 );
}
2025-05-20
256
글번호 226302
답변완료
스크립트 실행시에 오류보고에 에러 발생 코드
referenceError: handleError is not defined 와 같은 에러가 지속 발생 됩니다.
원인 파악을 못하겠네요.
스팟 스크립트 적용하고 3초뒤에 발생되네요.
--------------------------------------------이하 스팟 코드
var timer5 = 5; //5초
var 매수금 = 100000;
var 손절 = 0.95;
var 익절 = 1.05;
var OrderList = [];
var MKList = [];
var req;
var orderId; // 주문 ID 저장용 전역 변수
var orderNumber; // 주문 번호 저장용 전역 변수
var orderFailurePrice = {}; // 주문 실패 시점의 가격 저장용 객체
var initialPrice = {}; // 초기 주문 가격 저장용 객체
var currentPrice; // 현재가 저장용 변수
function Main_OnStart()
{
try {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[시작] 스팟 전략 시작");
//1번 타이머, 5초
Main.SetTimer(1, timer5*1000);
Main.MessageLog("[타이머] 5초 타이머 설정 완료");
// 오늘 매수한 종목 관리 배열 초기화
MKList = [];
Main.MessageLog("[초기화] 매수 종목 관리 배열 초기화 완료");
//스팟 시작시 잔고평가금액
V1 = A1.GetBalanceETCinfo(100);
Main.MessageLog("[잔고] 초기 평가금액: " + V1);
Main.MessageLog("--------------------------------------------");
} catch (error) {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[에러] 스팟 시작 중 오류 발생: " + error.message);
Main.MessageLog("--------------------------------------------");
}
}
/**
* 주문 처리 함수
* @param {string} code - 종목코드
* @param {number} quantity - 주문수량
* @param {string} orderType - 주문타입 ('BUY' or 'SELL')
*/
function processOrder(code, quantity, orderType) {
var localOrderId; // 지역 변수로 주문 ID 선언
try {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[주문] 주문 처리 시작");
Main.MessageLog("- 종목코드: " + code);
Main.MessageLog("- 주문수량: " + quantity);
Main.MessageLog("- 주문유형: " + orderType);
// 시장가 주문으로 진행 (가격 0, 가격구분 1)
Main.MessageLog("[주문] 시장가 주문 진행");
if (orderType === 'BUY') {
// 매수 시장가 주문
localOrderId = A1.OrderBuy(code, quantity, 0, 1);
orderId = localOrderId; // 전역 변수에 할당
Main.MessageLog("[주문] 매수 시장가 주문 완료");
} else {
// 매도 시장가 주문
localOrderId = A1.OrderSell(code, quantity, 0, 1);
orderId = localOrderId; // 전역 변수에 할당
Main.MessageLog("[주문] 매도 시장가 주문 완료");
}
Main.MessageLog("--------------------------------------------");
return localOrderId;
} catch (error) {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[에러] 주문 처리 중 오류 발생: " + error.message);
Main.MessageLog("--------------------------------------------");
return null;
}
}
/**
* 가격 상승률 체크 함수
* @param {string} code - 종목코드
* @returns {boolean} - 가격 상승률이 3% 이상이면 true
*/
function isPriceIncreased(code) {
if (!orderFailurePrice[code]) return false;
const currentPrice = MarketData.Ask(1);
const priceIncrease = ((currentPrice - orderFailurePrice[code]) / orderFailurePrice[code]) * 100;
return priceIncrease >= 3;
}
/**
* 주문 응답 처리
* @param {Object} OrderResponse - 주문 응답 객체
*/
function Main_OnOrderResponse(OrderResponse) {
try {
if (OrderResponse.orderID === orderId) {
orderNumber = OrderResponse.orderNum;
// 주문 실패 시 시장가로 재시도
if (OrderResponse.orderResult === 'FAIL') {
const code = OrderResponse.code;
const quantity = OrderResponse.count;
const orderType = OrderResponse.orderType;
if (orderType === 'BUY') {
// 매수 주문 실패 시 시장가로 재시도
A1.OrderBuy(code, quantity, 0, 1);
Main.MessageLog(code + " 주식을 시장가로 매수합니다.");
} else {
// 매도 주문 실패 시 시장가로 재시도
A1.OrderSell(code, quantity, 0, 1);
Main.MessageLog(code + " 주식을 시장가로 매도합니다.");
}
}
}
} catch (error) {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[에러] 주문 응답 처리 중 오류 발생: " + error.message);
Main.MessageLog("--------------------------------------------");
}
}
function Main_OnTimer(nEventID)
{
try {
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) {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[타이머] 이벤트 발생 - 현재시간: " + HHMMSS);
if (HHMMSS >= 90000 && HHMMSS < 151500) {
Main.MessageLog("[검색] 종목 검색 시작");
var searchResult = Main.ReqPowerSearch("power2");
if (searchResult === false) {
Main.MessageLog("[에러] 종목 검색 요청 실패");
} else {
Main.MessageLog("[검색] 종목 검색 요청 성공");
}
} else {
Main.MessageLog("[시간] 거래 시간이 아닙니다. (현재: " + HHMMSS + ")");
}
Main.MessageLog("--------------------------------------------");
}
if (nEventID == 1 && HHMMSS >= 90000 && HHMMSS < 151500)
{
//계좌보유종수
var num = A1.GetTheNumberOfBalances();
//9시~15시 15분 사이
if (HHMMSS >= 90000 && HHMMSS < 151500)
{
//보유종목이 1개 이상
if (num >= 1)
{
//계좌평가금액이 스팟시작시 평가금액대비 5% 이상이면 전종목 전량매도
if (A1.GetBalanceETCinfo(100) >= V1*1.05)
{
//1번 타이머 종료
Main.KillTimer(1);
//계좌리스트의 순서대로
for (var i = 0; i < num; i++)
{
//잔고를 셋팅
A1.SetBalance(i);
//수량이 있고 5%수익이거나 5% 손실이면 시장가 매도
if (A1.Balance.count > 0)
{
processOrder(A1.Balance.code, A1.Balance.count, 'SELL');
}
}
}
else //아니면 개별종목 5%익절, -5%손절 체크
{
//계좌리스트의 순서대로
for (var i = 0; i < num; i++)
{
//잔고를 셋팅
A1.SetBalance(i);
//수량이 있고 5%수익이거나 5% 손실이면 시장가 매도
if (A1.Balance.count > 0 &&
(A1.Balance.current >= A1.Balance.avgUnitCost * 1.015 ||
A1.Balance.current <= A1.Balance.avgUnitCost * 0.98))
{
processOrder(A1.Balance.code, A1.Balance.count, 'SELL');
}
}
}
}
}
//15시 15분이후이면
if (HHMMSS >= 151500)
{
//1번 타이머 종료
Main.KillTimer(1);
//계좌리스트의 순서대로
for (var i = 0; i < num; i++)
{
//잔고를 셋팅
A1.SetBalance(i);
//수량이 있고 5%수익이거나 5% 손실이면 시장가 매도
if (A1.Balance.count > 0)
{
processOrder(A1.Balance.code, A1.Balance.count, 'SELL');
}
}
}
}
if (nEventID == 2)
{
Main.ReqMarketData(OrderList[req]);
}
} catch (error) {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[에러] 타이머 이벤트 처리 중 오류 발생: " + error.message);
Main.MessageLog("--------------------------------------------");
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
try {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[검색결과] 수신된 종목 수: " + nCount);
Main.KillTimer(1);
OrderList = [];
if (nCount >= 1)
{
if (MKList.length == 0)
{
OrderList = aItemList;
Main.MessageLog("[검색결과] 신규 종목 목록 설정 완료");
}
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 && !IsStockInAccount(aItemList[a]))
{
OrderList.push(aItemList[a]);
}
}
Main.MessageLog("[검색결과] 기존 종목 제외 후 남은 종목 수: " + OrderList.length);
}
}
if (OrderList.length == 0)
{
Main.MessageLog("[검색결과] 처리할 종목이 없습니다. 5초 후 재시도");
Main.SetTimer(1, timer5*1000);
}
else
{
req = 0;
Main.MessageLog("[검색결과] 첫 번째 종목 시세 조회 시작: " + OrderList[req]);
Main.ReqMarketData(OrderList[req]);
}
Main.MessageLog("--------------------------------------------");
} catch (error) {
Main.MessageLog("--------------------------------------------");
Main.MessageLog("[에러] 종목 목록 처리 중 오류 발생: " + error.message);
Main.MessageLog("--------------------------------------------");
Main.SetTimer(1, timer5*1000); // 에러 발생 시 5초 후 재시도
}
}
function Main_OnRcvMarketData(MarketData)
{
if (MarketData.code == OrderList[req])
{
MKList.push(MarketData);
// 계좌에 같은 종목이 있는지 확인
if (!IsStockInAccount(MarketData.code)) {
// 계좌에 없는 경우에만 매수
const quantity = Math.floor(매수금/MarketData.Ask(1));
if (quantity > 0) {
processOrder(MarketData.code, quantity, 'BUY');
}
Main.MessageLog(MarketData.code + " 주식을 매수합니다.");
} else {
Main.MessageLog( MarketData.code + " 주식은 이미 계좌에 있으므로 매수하지 않습니다.");
}
req = req+1;
if (req < OrderList.length)
{
var aa = Main.ReqMarketData(OrderList[req]);
if (aa == -1)
{
Main.SetTimer(2, 15000);
}
}
else
{
Main.SetTimer(1, timer5*1000);
}
}
}
function IsStockInAccount(stockCode) {
// 계좌에 해당 종목이 있는지 확인하는 함수
var numberOfBalances = A1.GetTheNumberOfBalances();
for (var i = 0; i < numberOfBalances; i++) {
A1.SetBalance(i);
if (stockCode == A1.Balance.code) {
return true; // 계좌에 같은 종목이 있으면 true 반환
}
}
return false; // 계좌에 같은 종목이 없으면 false 반환
}
2025-05-19
260
글번호 226301
답변완료
진입제한 시간 추가
본문쓰기 금지단어가 있어 (Ex*ecuted)로 표현했습니다.
아래 수식은 093000~151500까지 매수진입이 오픈되어 있습니다.
103000까지 매수가 실행되지 않으면 거래중지 하는 수식을 추가해 주십시요.
수식내용 요약
093000 이후 0.03 체결이 발생한 콜옵션행사가를 기준으로
1행사가 내가격에 매수주문을 내는 것입니다.
ex) 094500에 콜행사가 345.00 에서 0.03 체결이 발생함.
094500에 콜행사가 342.50 에서 0.50 체결이 발생함. <--- 매수주문
항상 고맙습니다.
*******************************************************************************
var OrderList = [];
var IsBuyEx*ecuted = false; // 매수가 실행되었는지 확인하는 변수
var IsSellEx*ecuted = false; // 매도가 실행되었는지 확인하는 변수
function Main_OnStart()
{
Main.SetTimer(1, 1000);
}
function Main_OnTimer(nEventID)
{
var d = new Date();
HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
// 타이머 종료 후 09:30:00 이후
if (nEventID == 1 && HHMMSS >= 093000)
{
// 15:15:00 이전
if (HHMMSS < 151500)
{
// 매수 후 추가 매수가 발생하지 않도록 확인
if (!IsBuyEx*ecuted)
{
// 전체 콜 종목 대상
for (var x = -Option1.lowersATM; x <= Option1.uppersATM; x++)
{
// 현재가 0.03 발생
if (Option1.GetCurrent(0, x) == 0.03)
{
// 내가 주문한 종목인지 판별
var Order = true;
if (OrderList.length > 0)
{
for (var y = 0; y < OrderList.length; y++)
{
if (Option1.GetATMCallRecent(x-1) == OrderList[y])
{
Order = false;
}
}
}
// 주문을 낸 적이 없으면 매수 주문
if (Order == true)
{
// 첫 매수 실행
OrderList.push(Option1.GetATMCallRecent(x-1));
Account1.OrderBuy(Option1.GetATMCallRecent(x-1), 1, Option1.GetAsk(0, x-1, 5), 0);
IsBuyEx*ecuted = true; // 매수가 실행되었음을 표시
}
}
}
}
// 매수 후 2.5 이상 수익이면 청산
if (IsBuyEx*ecuted && !IsSellEx*ecuted)
{
for (var i = 0; i < OrderList.length; i++)
{
Account1.SetBalance(OrderList[i], 0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 2 &&
Account1.Balance.current >= Account1.Balance.avgUnitCost + 2.5)
{
// 익절 조건 충족 시 매도
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, Option1.GetBid(Account1.Balance.code, 5), 0);
IsSellEx*ecuted = true; // 매도가 실행되었음을 표시
}
}
}
}
else // 15:15:00 이후
{
// 모든 주문을 청산 (시간 종료)
if (IsBuyEx*ecuted && !IsSellEx*ecuted)
{
if (OrderList.length > 0)
{
for (var i = 0; i < OrderList.length; i++)
{
Account1.SetBalance(OrderList[i], 0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 2)
{
// 시간 종료로 매도
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, Option1.GetBid(Account1.Balance.code, 5), 0);
IsSellEx*ecuted = true; // 매도가 실행되었음을 표시
}
}
}
}
}
}
}
2025-04-30
255
글번호 226291