답변완료
예스스팟 오류메세지 관련 문의
담당자님 안녕하세요.
항상 많은 도움 주셔서 감사드리며 덕분에 많은 발전을 이루고 있습니다.
기존에 올려주신 예스스팟 식을 참고하여 종목검색 후 차트 생성하여 시그널에 따다 매매를 일으키는 식을 작성하였습니다.
테스트를 위해 시험으로 가동하였는데, 첨부 스크린샷과 같이 '*계좌와 종목 불일치' 라는 오류메세지와 함께 매매가 거절당하였는데요 혹시 원인이 무엇인지 알 수 있을까요?
참고로 가려둔 계좌는 모두 동일한 계좌번호 입니다.
계좌 객체도 생성하였으며, 동일한 계좌번호와 연동시켜두었습니다.
참고차 작성한 수식도 공유드리오니 확인해주시면 감사하겠습니다.
-------------------------------------------------------------------------
var 검색주기 = 180;//120초
var 최대종목수 = 30,M1;
var ItemList = [],CT = [];
var req;
var JongmokNum ;
var JongmokCode = new Array(10);
var ChartSet = new Array(10);
var SystemSet = new Array(10);
//스팟 시작할때 파워종목검색의 사용자검색조건 실행
//스팟시작
function Main_OnStart()
{
//종목검색 타이머
Main.SetTimer(1,검색주기*1000)//300초, 1000이 1초
//잔고체크 타이머
Main.SetTimer(2,3000)//3초, 1000이 1초
Main.MessageList("start");
//종목당 매수금
M1 = Math.floor(Account1.GetBalanceETCinfo(0)/최대종목수);//하이기준 예수금
//주문종목갯수
CTcnt = 0;
}
//타이머동작
function Main_OnTimer(nEventID)
{
var d = new Date();
var HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가가 50개 이하일때 반복적으로 검색
if (nEventID == 1 && HHMMSS >= 090000 && CT.length < 50)
{
Main.MessageList("종목검색 요청");
Main.ReqPowerSearch("통합종목검색"); //사용자검색조건명 지정
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.KillTimer(1);
Main.MessageList("종목검색 완료 nCount : ",nCount);
//보유종목수
var num = Account1.GetTheNumberOfBalances();
//검색된 종목이 1개이상
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
//옵션1. 개별 입력 + 최대 종목수 제한
for (var i = 0; i < Math.min(최대종목수-num,nCount); i++ )
{
ItemList.push(aItemList[i]);
}
//옵션2. 배열 전체 입력
//ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].code)
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
if (ItemList.length == 최대종목수-num)
{
break;
Main.MessageList("break: 최대종목수 도달");
}
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 최대종목수)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
1, //거래수량
100000, //자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ALL, // 피라미딩 설정여부
1000, // 최대진입수량
20); // 최대진입횟수
var ChartSet = new ReqChartItem(ItemList[req],3,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("통합시스템", YL_TYPE_NORMAL, null, null, null);
Main.MessageList("현재차트갯수 : ",CT.length);
//다음 차트 객체 요청
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else //검색된 종목이 없으면
{
if (CT.length < 최대종목수)
{
Main.SetTimer(1, 검색주기*1000);//종목검색 타이머 재실행
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx; //차트 종목 코드 저장
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 최대종목수)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
1, //거래수량
100000, //자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ALL, // 피라미딩 설정여부
1000, // 최대진입수량
20); // 최대진입횟수
var ChartSet = new ReqChartItem(ItemList[req],3,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("통합시스템", YL_TYPE_NORMAL, null, null, null);
Main.MessageList("현재차트갯수 : ",CT.length);
//다음 차트 객체 요청
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
//만들어진 차트가 최대종목수 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(1, 검색주기*1000);//120초
}
}
}
}
//신호발생
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//매수신호이고 잔고가 없을때만 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(M1/Signal.price),0,1);
Main.MessageLog("매수주문");
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
Main.MessageLog("미체결 주문취소");
}
}
//잔고수량만큼만 매도
if (Account1.Balance.count > 0)
{
Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,0,1);
Main.MessageLog("매도주문");
}
}
}
답변완료
차트 여러개에 반복 작업하는 경우
초보적인 질문 같은데,어떻게 하는지 감이 안 오네요.
차트1~차트50 : 예스트레이더에 50개의 차트가 있고, 차트객체 생성후 아이디 연결했을경우,
신호 발생시에 아래와 같이, 각각 동일작업을 수행하려 합니다.
이벤트에 같은 코드에 차트이름만 바꿔서 50번 붙여넣기 안 하고
한개만 수정해도 다 적용되게 하는 방법이 있을까요?
function Chart1_OnRiseSignal(Signal)
{
rowNum = Excel1.GetRowCount(1)+1; //엑셀 새 행번호
Excel1.SetData(1, "A"+rowNum, Chart1.GetSDate(1,0)); //신호날짜
Excel1.SetData(1, "B"+rowNum, Chart1.GetSTime(1,0));//신호시간
Excel1.SetData(1, "C"+rowNum, Chart1.GetCode(1));//신호코드
Excel1.SetData(1, "D"+rowNum, Chart1.GetClose(1,0));//신호가격
}
function Chart2_OnRiseSignal(Signal)
{
rowNum = Excel1.GetRowCount(1)+1; //엑셀 새 행번호
Excel1.SetData(1, "A"+rowNum, Chart2.GetSDate(1,0)); //신호날짜
Excel1.SetData(1, "B"+rowNum, Chart2.GetSTime(1,0));//신호시간
Excel1.SetData(1, "C"+rowNum, Chart2.GetCode(1));//신호코드
Excel1.SetData(1, "D"+rowNum, Chart2.GetClose(1,0));//신호가격
}
.
.
.
.
.
.
.
.
.
.
.
.
.
function Chart50_OnRiseSignal(Signal)
{
rowNum = Excel1.GetRowCount(1)+1; //엑셀 새 행번호
Excel1.SetData(1, "A"+rowNum, Chart50.GetSDate(1,0)); //신호날짜
Excel1.SetData(1, "B"+rowNum, Chart50.GetSTime(1,0));//신호시간
Excel1.SetData(1, "C"+rowNum, Chart50.GetCode(1));//신호코드
Excel1.SetData(1, "D"+rowNum, Chart50.GetClose(1,0));//신호가격
}
답변완료
차트신호시 콜옵션 풋옵션 동시매수 청산추가 0.01 도달시
아래 수식은 장종료 시점에 청산시간 조건으로만 exit 합니다.
콜매수 포지션 가격이 0.01 되면 콜포지션 청산
풋매수 포지션 가격이 0.01 되면 풋포지션 청산
위 조건을 추가해 주십시요.
만기일에 매수가격이 없는 경우가 발생하므로 그전에 청산하려고 합니다.
항상 고맙습니다.
******************************************************************************
안녕하세요
예스스타입니다.
1
Account1.OrderBuy(CallOrderCode, 1, Option.GetAskByCode(CallOrderCode, 2), 1);
주문함수의 마지막 옵션은 지정가나 시장가등을 지정하는 옵션입니다.
0이면 지정가, 1이면 시장가입니다.
시장가이면 가격을 지정할 필요가 없어 주문가격은 0으로 지정하시면 됩니다.
Account1.OrderBuy(CallOrderCode, 1, 0, 1);
만약 지정가로 주문한다면 아래와 같이 마지막옵션이 0으로 지정하시면 됩니다.
Account1.OrderBuy(CallOrderCode, 1, Option.GetAskByCode(CallOrderCode, 2), 0);
아래식에는 지정가로 작성해 드립니다.
시장가도 주석처리로 추가해 드립니다.
2
var UNum; var LNum;
var CallCode; var CallPrice;
var PutCode; var PutPrice;
var CC; var PP;
var CallOrderCode; var PutOrderCode;
var CallExit,PutExit;
function Main_OnStart()
{
CallExit = false;
PutExit = false;
Main.SetTimer(1, 5000);
}
//차트에서 신호가 발생하면
function Chart1_OnRiseSignal(Signal)
{
//해당 신호가 매수신호이면
if (Signal.signalKind == 1)
{
Main.MessageList("--------------------------------------------");
Main.MessageList("매수신호 발생");
//1.0이하 중 가장 큰 가격을 가지는 종목을 찾음
//ATM위 행사가 갯수
UNum = Option1.uppersATM;
//ATM아래 행사가 갯수
LNum = Option1.lowersATM;
//각 행사가의 콜종목의 종목코드를 저장할 변수를 배열변수로 선언
CallCode = new Array(UNum+LNum+1);
//각 행사가의 콜종목의 현재가를 저장할 변수를 배열변수로 선언
CallPrice = new Array(UNum+LNum+1);
//각 행사가의 풋종목의 종목코드를 저장할 변수를 배열변수로 선언
PutCode = new Array(UNum+LNum+1);
//각 행사가의 풋종목의 현재가를 저장할 변수를 배열변수로 선언
PutPrice = new Array(UNum+LNum+1);
//콜종목 찾기
//콜옵션은 ATM기준 위행사가 +단계, 아래가 -단계이므로
//for문에서 LNum의 역수부터 시작해서 UNum까지 1씩 증가하면서 수행하도록 함
for (var i = -LNum; i <= UNum; i++)
{
//값이 1.0이하이면
if (Option1.GetCurrent(0, i) <= 1.0)
{
//해당종목의 현재가를 배열변수 CallPrice의 방번호 i+LNum에 저장
CallPrice[i+LNum] = Option1.GetCurrent(0, i);
//해당종목의 종목코드를 배열변수 CallCode의 방번호 i+LNum에 저장
CallCode[i+LNum] = Option1.GetATMCallRecent(i);
//주의
//배열변수의 방(공간)번호은 -가 없으므로 최하단 행사가를 0번방부터
//저장하도록 작성해야 함
}
else//1.0보다 크면
{
//배열변수 CallPrice의 방번호 i+LNum에 -1 저장
CallPrice[i+LNum] = -1;
//배열변수 CallCode의 방번호 i+LNum에 -1 저장
CallCode[i+LNum] = -1;
}
}
//풋종목 찾기
//풋옵션은 ATM기준 아래 행사가 +단계, 위가 -단계이므로
//for문에서 HNum의 역수부터 시작해서 LNum까지 1씩 증가하면서 수행하도록 함
for (var ii = -UNum; ii <= LNum; ii++)
{
//ii단계 풋종목이 1.0이하이면
if (Option1.GetCurrent(1, ii) <= 1.0 )
{
//해당종목의 현재가를 배열변수 PutPrice의 방번호 ii+LNum에 저장
PutPrice[ii+UNum] = Option1.GetCurrent(1, ii);
//해당종목의 현재가를 배열변수 PutCode의 방번호 ii+LNum에 저장
PutCode[ii+UNum] = Option1.GetATMPutRecent(ii);
}
else //1.0보다 크면
{
//배열변수 PutPrice의 방번호 ii+LNum에 -1 저장
PutPrice[ii+UNum] = -1;
//배열변수 PutCode의 방번호 ii+LNum에 -1 저장
PutCode[ii+UNum] = -1;
}
}
//배열변수 CallPrice의 각 배열방의 값중 가장 큰값을 찾아 CC에 저장하고
//CallCode의 동일 방번호의 값을 CallOrderCode에 저장
CC = -1;
CallOrderCode = -1;
for (var iii = -LNum; iii <= UNum; iii++)
{
if (CallPrice[iii+LNum] > CC)
{
CC = CallPrice[iii+LNum];
CallOrderCode = CallCode[iii+LNum]
}
}
//배열변수 PutPrice의 각 배열방의 값중 가장 큰값을 찾아 PP에 저장하고
//PutCode의 동일 방번호의 값을 PutOrderCode에 저장
PP = -1;
PutOrderCode = -1;
for (var iiii = -UNum; iiii <= LNum; iiii++)
{
if (PutPrice[iiii+UNum] > PP)
{
PP = PutPrice[iiii+UNum];
PutOrderCode = PutCode[iiii+UNum];
}
}
Main.MessageList("--------------------------------------------");
Main.MessageList("콜종목코드:",CallOrderCode,"/콜현재가 :",CC);
Main.MessageList("풋종목코드:",PutOrderCode,"/풋현재가 :",PP);
//콜옵션종목 매수
if (CallExit == false)
{
//지정가
Account1.OrderBuy(CallOrderCode, 1, Option1.GetAskByCode(CallOrderCode, 2), 0);
//시장가
//Account1.OrderBuy(CallOrderCode, 1, 0, 1);
}
//콜옵션종목 매수
if (PutExit == false)
{
//지정가
Account1.OrderBuy(PutOrderCode, 1, Option1.GetAskByCode(PutOrderCode, 2), 0);
//시장가
//Account1.OrderBuy(PutOrderCode, 1, 0, 1);
}
}
}
function Main_OnTimer(nEventID)
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
if (nEventID == 1 && CallExit == false && HHMMSS >= 143530)
{
CallExit = true;
var num = Account1.GetTheNumberOfBalances();
if (num > 0)
{
for (var i = 0; i < num; i++)
{
Main.MessageList(Account1.Balance.code,Option1.GetCodeByExercisePrice(0, Option1.GetExercisePrice(Account1.Balance.code)));
Account1.SetBalance(i);
if (Account1.Balance.position == 2 &&
Option1.GetCodeByExercisePrice(0, Option1.GetExercisePrice(Account1.Balance.code)) == Account1.Balance.code)
{
//지정가(매수2호가)
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, Option1.GetBidByCode(Account1.Balance.code, 2), 0);
//시장가
//Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, 0, 1);
}
}
}
}
if (nEventID == 1 && PutExit == false && HHMMSS >= 151530)
{
PutExit = true;
var num = Account1.GetTheNumberOfBalances();
if (num > 0)
{
for (var i = 0; i < num; i++)
{
Main.MessageList(Account1.Balance.code,Option1.GetCodeByExercisePrice(1, Option1.GetExercisePrice(Account1.Balance.code)));
Account1.SetBalance(i);
if (Account1.Balance.position == 2 &&
Option1.GetCodeByExercisePrice(1, Option1.GetExercisePrice(Account1.Balance.code)) == Account1.Balance.code)
{
//지정가(매수2호가)
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, Option1.GetBidByCode(Account1.Balance.code, 2), 0);
//시장가
//Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, 0, 1);
}
}
}
}
}