종목검색으로 고른 종목을 지정가로 매수할 때,
지정한 단계의 호가가 아직 없으면 존재하는 호가를 찾아 주문하는 예제입니다.
주문시 매도5호가 Ask(5)로 지정했는데 해당 호가가 없으면 0값이 반환됩니다.
이때 0 을 그대로 지정가 주문가격으로 쓰면
"주문단가가 하한가보다 낮습니다" 오류와 함께 원장에서 주문이 거부됩니다.
아래 내용은 기본가격을 현재가로 두고 매도5호가부터 매도1호가까지 내려가며
존재하는 첫 호가로 주문하는 방법입니다.
다른 지정가 주문에도 같은 규칙을 응용할 수 있습니다.
1.
전략내용
스팟을 실행하면 사용자검색조건으로 종목검색을 한 번 실행하고
검색된 종목마다 종목객체를 만든 뒤 종목당 매수금만큼 지정가로 매수합니다.
주문가격은 다음 순서로 정합니다. 기본가격은 현재가입니다.
매도5호가부터 매도1호가까지 차례로 확인해 0 보다 큰 첫 호가가 있으면 그 호가를 주문가격으로 씁니다.
어느 단계에도 호가가 없으면 현재가로 주문하고, 현재가마저 없으면 그 주문은 내지 않고 메시지를 남깁니다.
주문은 거래소를 SOR로 지정한 JSON 객체형 매수주문입니다.
2.
스크립트 객체화면 설정
계좌객체를 추가한 후 속성에서 객체명은 Account1 으로 지정하고 계좌번호를 지정합니다.
종목객체는 추가하지 않습니다. 수식 안에서 Main.ReqMarketData 로 만들어 씁니다.
3.
사용자검색조건 설정
스팟에서는 Main.ReqPowerSearch("사용자검색조건명"); 함수로 종목검색을 수행합니다.
이때 지정하는 사용자검색조건명은 예스랭귀지로 작성한 종목검색식의 이름이 아닙니다.
파워종목검색 화면 좌측의 리스트에서 작성한 종목검색식이나 시장검색 등을 선택해서
우측 조건리스트에 추가하고 주기 등 필요한 설정을 완료한 후에
조건저장 버튼을 클릭하면 이름을 지정해서 사용자검색조건으로 저장이 되고
스팟수식의 SearchName 변수에는 이렇게 저장한 사용자검색조건명을 지정해 주셔야 합니다.
4.
스팟수식
//동시호가 시간대처럼 지정한 단계의 호가가 아직 없을 때, 존재하는 호가를 찾아 지정가로 매수하는 예제
//게시판 문의: 08시 50분부터 09시 사이 동시호가 주문에서 매도5호가 Ask(5) 가 0 으로 돌아와
//지정가 0 원 주문이 나가면서 "주문단가가 하한가보다 낮습니다" 오류가 났다
//아래 세 값은 사용자가 바꿔 쓰는 값이라 코드 맨 위에 모아 둔다
var SearchName = "사용자검색조건명"; //파워종목검색 화면에서 조건저장으로 만든 사용자검색조건명
var BuyAmount = 1000000; //종목당 매수금
var Exchange = 1; //시세주문 거래소 - 1:시세(통합)/주문(SOR,스마트), 2: 시세(KRX)/주문(KRX) , 4 시세(NXT)/주문(NXT)
var StockList = []; //검색된 종목의 종목코드
var Stock = {}; //종목객체를 종목코드로 찾기 위한 보관소
var rcv; //종목객체를 요청한 순번
//스팟 시작. 동시호가 시간대에 스팟을 실행하면 바로 검색을 한 번 실행한다
function Main_OnStart()
{
Main.MessageList("검색 시작", SearchName);
Main.ReqPowerSearch(SearchName);
}
//타이머 동작. 2번 타이머는 종목객체 생성 제한에 걸렸을 때의 재요청용이다
function Main_OnTimer(nEventID)
{
if (nEventID == 2)
{
Main.KillTimer(2);
Main.ReqMarketData({code:StockList[rcv], exchangeKind:Exchange});
}
}
//종목검색 완료. 검색된 종목의 종목객체를 첫 종목부터 차례로 요청한다
function Main_OnRcvItemList(aItemList, nCount, aValues)
{
Main.MessageList("검색된 종목수", nCount);
if (nCount < 1)
{
return;
}
StockList = [];
for (var a = 0; a < nCount; a++)
{
StockList.push(aItemList[a]);
}
rcv = 0;
Main.ReqMarketData({code:StockList[rcv], exchangeKind:Exchange});
}
//요청한 종목객체가 만들어지면 보관하고 매수한 뒤 다음 종목객체를 요청한다
function Main_OnRcvMarketData(MarketData)
{
if (MarketData.code != StockList[rcv])
{
return;
}
Stock[MarketData.code] = MarketData;
BuyWithExistingAsk(MarketData.code);
rcv = rcv + 1;
if (rcv < StockList.length)
{
var XX = Main.ReqMarketData({code:StockList[rcv], exchangeKind:Exchange});
//종목객체 생성 제한이면 15초 뒤에 다시 요청한다
if (XX == -1)
{
Main.SetTimer(2, 15000);
}
}
else
{
Main.MessageList("종목객체 요청 끝");
}
}
//주문가격을 정해 매수한다
//기본가격은 현재가이고, 매도5호가부터 매도1호가까지 내려가며 0 보다 큰 첫 호가를 주문가격으로 쓴다
//동시호가 시간대에는 5호가까지 채워지지 않아 Ask(5) 가 0 으로 돌아올 수 있다
function BuyWithExistingAsk(codex)
{
var Price = Stock[codex].current;
for (var i = 5; i >= 1; i--)
{
if (Stock[codex].Ask(i) > 0)
{
Price = Stock[codex].Ask(i);
break;
}
}
//호가도 현재가도 아직 없으면 0 원 지정가 주문이 나가지 않게 이번 주문은 내지 않는다
if (Price <= 0)
{
Main.MessageList("호가와 현재가가 아직 없어 주문을 내지 않음", codex);
return;
}
var buyN = Math.floor(BuyAmount / Price);
if (buyN > 0)
{
Account1.OrderBuy({exchangeKind:Exchange, code:codex, count:buyN, orderPrice:Price, priceKind:0});
Main.MessageList("매수주문", codex, "가격", Price, "수량", buyN);
}
else
{
Main.MessageList("매수금 부족", codex);
}
}
JavaScript
복사