예스스탁
예스스탁 답변
2014-06-12 15:24:59
안녕하세요
예스스탁입니다.
아래 내용 참고하시기 바랍니다.
2개식 모두 스크립트 객체화면엣
설정할 내용은 동일합니다.
옵션객체 추가
종목객체 추가 --> 객체명 MarketData1, 종목은 선물
계좌객체 추가 --> 객체명 Account1, 계좌번호 지정
1.
var BuyId;
var BuyStep;
var BuyPr;
var BuyFill;
function Main_OnStart()
{
BuyStep = 0;
DayEnd = 0;
}
function Main_OnUp*dateMarket(sItemCode, lUp*dateID)//*제거
{
if (BuyStep == 0 &&
lUp*dateID == 20001 && //시세변동 *제거
MarketData1.time >= 900000000 && //9시 이후
((Option.GetRemainDays(0, 0) > 1 && MarketData1.time < 1500000000)|| //만기일 아닌경우
(Option.GetRemainDays(0, 0) == 1 && MarketData1.time < 1430000000))) //만기일
{
var v1 = MarketData1.Bid(1)*500000*0.12;
var v2 = Math.max(Math.floor((Account1.GetBalanceETCinfo(0)*0.2)/v1),1);
BuyPr = MarketData1.Bid(1);
BuyId = Account1.OrderBuy(Main.GetOrderCode(MarketData1.code), v2,BuyPr, 0);
BuyStep = 1;
}
//BuyStep이 2이고
if (BuyStep == 2)
{
//현재 매수1호가가 매수주문시 매수1호가보다 크면
var Pr = MarketData1.Bid(1);
if (Pr > BuyPr)
{
//현재매수1호가로 정정주문
BuyPr = pr;
BuyID = Account1.OrderReplacePrice(BuyNum,BuyPr)
//BuyStep은 다시 1
BuyStep = 1;
}
}
//BuyStep이 3이고
if (BuyStep == 3)
{
//현재 매수1호가가 매수주문시 매수1호가보다 크면
var Pr = MarketData1.Bid(1);
if (Pr > BuyPr)
{
//기존 주문잔량이 있으면 취소
Account1.SetUnfillOrderNumber(BuyNum);
if (Account1.Unfill.count > 0)
{
Account1.OrderCancel(BuyNum);
}
}
//잔고가 있는 상태에서 매수1호가가 체결가 +5틱이상이거나 이하이면
if (Bxstep == 0 && Account1.Balance.count > 0 && (Pr >= BuyFill+MarketData1.GetTickSize()*5 || Pr <= BuyFill-MarketData1.GetTickSize()*5))
{
if (MarketData1.BidAmount(1) < MarketData1.AskAmount(1)*0.5)
var BxPr = MarketData1.Bid(1);
else
var BxPr = MarketData1.Ask(1);
Account1.OrderSell(Main.GetOrderCode(MarketData1.code), Account1.Balance.count, BxPr, 0);
}
//체결후 해당 종목의 잔고수량이 0이면 BuyStep과 BxStep은 0으로
if (Account1.Balance.count == 0)
{
BuyStep = 0;
}
}
//당일청산
if (DayEnd == 0 &&
((Option.GetRemainDays(0, 0) > 1 && MarketData1.time >= 1500000000)|| //만기일 아닌경우
(Option.GetRemainDays(0, 0) == 1 && MarketData1.time >= 1430000000))) //만기일
{
//DayEnd를 1로 바꿔 한번만 동작하게 함
DayEnd = 1;
//지정한 종목의 미체결이 있으면 전부 취소
var AA = Account1.GetTheNumberOfUnfills();
if (AA >= 1)
{
for (var i = 0; i < AA; i++)
{
Account1.SetUnfillIndex(i);
if (Account1.Unfill.code == Main.GetOrderCode(MarketData1.code))
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//지정 종목의 잔고가 있으면 청산
Account1.SetBalanceItem(Main.GetOrderCode(MarketData1.code), 0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 1)
{
Account1.OrderBuy(Account1.Balance.code,Account1.Balance.count,0,1);
}
if (Account1.Balance.count > 0 && Account1.Balance.position == 2)
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);
}
}
}
//주문응답수신
function Main_OnOrderResponse(OrderResponse)
{
//BuyStep은 1이고 수신된 주문응답 아이디가 BuyID와 같으면
if (BuyStep == 1 && BuyId == OrderResponse.orderID)
{
//주문번호 저장
BuyNum = OrderResponse.orderNum;
//BuyStep은 2
BuyStep = 2;
}
}
//체결통보수신
function Main_OnNotifyFill(NotifyFill)
{
//BuyStep이 2이고 체결된 주문의 주문번호가 BuyNum과 같으면
if (BuyStep == 2 && BuyNum == NotifyFill.orderNum)
{
//BuyStep은 3
BuyStep = 3;
//체결가격 저장
BuyFill = NotifyFill.fillPrice;
//잔고셋팅
Account1.SetBalanceItem(NotifyFill.code, 0);
}
}
2.
var BuyId;
var BuyStep;
var BuyPr;
var BuyFill;
function Main_OnStart()
{
BuyStep = 0;
DayEnd = 0;
}
function Main_OnUp*dateMarket(sItemCode, lUp*dateID)//*제거
{
if (BuyStep == 0 &&
lUp*dateID == 20001 && //시세변동 *제거
MarketData1.time >= 900000000 && //9시 이후
((Option.GetRemainDays(0, 0) > 1 && MarketData1.time < 1500000000)|| //만기일 아닌경우
(Option.GetRemainDays(0, 0) == 1 && MarketData1.time < 1430000000))) //만기일
{
//ATM위 행사가 갯수
UNum = Option.uppersATM;
//ATM아래 행사가 갯수
LNum = Option.lowersATM;
//각 행사가의 콜종목의 종목코드를 저장할 변수를 배열변수로 선언
CallCode = new Array(UNum+LNum+1);
//각 행사가의 콜종목의 현재가를 저장할 변수를 배열변수로 선언
CallPrice = new Array(UNum+LNum+1);
//콜종목 찾기
//콜옵션은 ATM기준 위행사가 +단계, 아래가 -단계이므로
//for문에서 LNum의 역수부터 시작해서 UNum까지 1씩 증가하면서 수행하도록 함
for (var i = -LNum; i <= UNum; i++)
{
//값이 1.5이상이면
if (Option.GetCurrent(0, i) >= 1.5)
{
//해당종목의 현재가를 배열변수 CallPrice의 방번호 i+LNum에 저장
CallPrice[i+LNum] = Option.GetCurrent(0, i);
//해당종목의 종목코드를 배열변수 CallCode의 방번호 i+LNum에 저장
CallCode[i+LNum] = Option.GetATMCallRecent(i);
//주의
//배열변수의 방(공간)번호은 -가 없으므로 최하단 행사가를 0번방부터
//저장하도록 작성해야 함
}
else//1.5보다 작으면
{
//배열변수 CallPrice의 방번호 i+LNum에 99999999 저장
CallPrice[i+LNum] = 99999999;
//배열변수 CallCode의 방번호 i+LNum에 99999999 저장
CallCode[i+LNum] = 99999999;
}
}
//배열변수 CallPrice의 각 배열방의 값중 가장 큰값을 찾아 CC에 저장하고
//CallCode의 동일 방번호의 값을 CallOrderCode에 저장
var CC = 99999999;
var CallOrderCode = 99999999;
for (var iii = -LNum; iii <= UNum; iii++)
{
if (CallPrice[iii+LNum] > CC)
{
CC = CallPrice[iii+LNum];
CallOrderCode = CallCode[iii+LNum]
}
}
if (CC < 99999999)
{
var v1 = Option.GetBid(CallOrderCode, 1)*500000;
var v2 = Math.max(Math.floor((Account1.GetBalanceETCinfo(0)*0.1)/v1),1);
BuyPr = V1;
BuyId = Account1.OrderBuy(CallOrderCode, v2,BuyPr, 0);
BuyStep = 1;
}
}
//BuyStep이 2이고
if (BuyStep == 2)
{
//현재 매수1호가가 매수주문시 매수1호가보다 크면
var Pr = MarketData1.Bid(1);
if (Pr > BuyPr)
{
//현재매수1호가로 정정주문
BuyPr = pr;
BuyID = Account1.OrderReplacePrice(BuyNum,BuyPr)
//BuyStep은 다시 1
BuyStep = 1;
}
}
//BuyStep이 3이고
if (BuyStep == 3)
{
//현재 매수1호가가 매수주문시 매수1호가보다 크면
var Pr = MarketData1.Bid(1);
if (Pr > BuyPr)
{
//기존 주문잔량이 있으면 취소
Account1.SetUnfillOrderNumber(BuyNum);
if (Account1.Unfill.count > 0)
{
Account1.OrderCancel(BuyNum);
}
}
//잔고가 있는 상태에서 매수1호가가 체결가 +-5%이상이면
if (Bxstep == 0 && Account1.Balance.count > 0 && (Pr >= BuyFill*1.05 || Pr <= BuyFill*0.95))
{
if (MarketData1.BidAmount(1) < MarketData1.AskAmount(1)*0.5)
var BxPr = MarketData1.Bid(1);
else
var BxPr = MarketData1.Ask(1);
Account1.OrderSell(CallOrderCode, Account1.Balance.count, BxPr, 0);
}
//체결후 해당 종목의 잔고수량이 0이면 BuyStep과 BxStep은 0으로
if (Account1.Balance.count == 0)
{
BuyStep = 0;
}
}
//당일청산
if (DayEnd == 0 &&
((Option.GetRemainDays(0, 0) > 1 && MarketData1.time >= 1500000000)|| //만기일 아닌경우
(Option.GetRemainDays(0, 0) == 1 && MarketData1.time >= 1430000000))) //만기일
{
//DayEnd를 1로 바꿔 한번만 동작하게 함
DayEnd = 1;
//지정한 종목의 미체결이 있으면 전부 취소
var AA = Account1.GetTheNumberOfUnfills();
if (AA >= 1)
{
for (var i = 0; i < AA; i++)
{
Account1.SetUnfillIndex(i);
if (Account1.Unfill.code == Main.GetOrderCode(MarketData1.code))
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//지정 종목의 잔고가 있으면 청산
Account1.SetBalanceItem(CallOrderCode, 0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 1)
{
Account1.OrderBuy(Account1.Balance.code,Account1.Balance.count,0,1);
}
if (Account1.Balance.count > 0 && Account1.Balance.position == 2)
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);
}
}
}
//주문응답수신
function Main_OnOrderResponse(OrderResponse)
{
//BuyStep은 1이고 수신된 주문응답 아이디가 BuyID와 같으면
if (BuyStep == 1 && BuyId == OrderResponse.orderID)
{
//주문번호 저장
BuyNum = OrderResponse.orderNum;
//BuyStep은 2
BuyStep = 2;
}
}
//체결통보수신
function Main_OnNotifyFill(NotifyFill)
{
//BuyStep이 2이고 체결된 주문의 주문번호가 BuyNum과 같으면
if (BuyStep == 2 && BuyNum == NotifyFill.orderNum)
{
//BuyStep은 3
BuyStep = 3;
//체결가격 저장
BuyFill = NotifyFill.fillPrice;
//잔고셋팅
Account1.SetBalanceItem(NotifyFill.code, 0);
}
}
해당식 내용은 모두 주문을 내보면서 컨트롤 해야 하는 내용이라
테스트를 거의 해보지 못했습니다.
주석 참고하셔서 식작성 흐름을 판단하는 용도로 사용하시기 바랍니다.
해당 내용 중 청산부분에 추적되는 부분은 작성이 잘 되지 않아 추적까지는 되지 않습니다.
해당 부분은 직접 처리해 보셔야 할것 같습니다.
가이드를 작성하는데 너무 많은 시간이 소모되면 답변을 드리기 어려습니다. 양해 부탁드립니다.
수식에서 게시판 금칙어가 있습니다.
영문 없데이트가 Up*date로 중간에 *이 있으므로 제거하시기 바랍니다.
즐거운 하루되세요
> 한걸음씩 님이 쓴 글입니다.
> 제목 : 문의
> 더운데 수고하십니다.
스팟 수식 문의 드립니다.
우선 하나의 계좌에서 지수 선물과 콜옵션, 풋옵션을 거래하려 합니다.
다 컨셉은 똑 같지만 총 6개의 전략입니다.
당일 청산 전략이며,
선물은 전략당 계좌 잔고의 20% 금액으로 거래하고 (선물 매수/매도 2개의 전략)
옵션은 전략당 10% 금액으로 거래하려 합니다. (옵션 콜풋 각가 2개의 전략 총 4개의 전략)
계좌 잔고를 실시간으로 체크하면서 만약 10억원이라면,
1. 계좌 잔고 10억 중 2억원은 선물 매수 후 청산 전략에만 사용.
(캐시 2억원으로 max로 살 수 있는 계약수)
2. 계좌 잔고 10억 중 2억원은 선물 매도 후 청산 전략에만 사용.
3. 계좌 잔고 10억 중 1억원은 콜옵션 1.5 이상 최근접가 매수 후 청산 전략에만 사용.
(캐시 1억원으로 max로 살 수 있는 계약수)
4. 계좌 잔고 10억 중 1억원은 콜옵션 1.5 이하 최근접가 매수 후 청산 전략에만 사용.
5. 계좌 잔고 10억 중 1억원은 풋옵션 1.5 이상 최근접가 매수 후 청산 전략에만 사용.
6. 계좌 잔고 10억 중 1억원은 풋옵션 1.5 이하 최근접가 매수 후 청산 전략에만 사용.
이렇게 6개의 전략을 만들려고 하는데 실질적으로는 1, 3 전략만 짜주시면 나머지는 주석 달아주시면 조금 변경해서 사용할 수 있겠습니다.
전략 1) 선물 매수 후 청산
#아웃라인
거래시간은 오전 9시부터 오후 3시까지 (옵션만기일은 2시 45분까지)
호가가 변하는 이벤트를 이용해서 포지션을 실시간 체크하면서 거래합니다.
#진입
해당 계약수 (예탁금의 20%로 살수 있는 최대 선물 계약수, 최소 1계약)
를 Bid(1) 즉, 최우선 매수호가에 주문을 내 놓고,
1계약이라도 체결이 되고 가격이 오르면 즉, Bid(1)이 오르면 청산 준비를 하고,
체결이 안되고 가격이 오르면 기존 주문을 취소 후 이미 오른 Bid(1)에 새로운 주문을 냅니다.
이 경우는 체결이 하나도 안된 경우이기 때문에 가격정정 주문을 이용해도 될 듯 합니다.
즉, 1계약이라도 체결 될 때까지 매수호가에 걸어놓으면서 시장을 따라 갑니다.
만약 1계약이라도 부분 체결되고 Bid(1) 가격이 체결 가격 대비 한 호가라도 올라버린 경우에는 기존 미체결 부분은 취소합니다.
#청산
부분 체결이나 전체 체결 모두
체결가 대비 5호가 아래로 Bid(1)가 떨어지거나
체결가 대비 5호가 위로 Bid(1)이 오르면 청산모드 시작.
청산 모드 시작 후.
Bid(1) 호가 잔량이 Ask(1)의 호가 잔량의 50%보다 적으면 Bid(1)에 주문
Bid(1) 호가 잔량이 Ask(1)의 호가 잔량의 50%보다 많으면 Ask(1)에 주문
일부나 전체 미체결된 (즉, 청산이 다 되지 않은) 상태로 가격이 하락하면
위의 Bid(1) / Ask(1) 호가 잔량 비율 원칙에 입각해서 모두 청산될 때까지 추적 청산.
전부 청산 되면 다시 진입 준비.
#거래시간 종료시
만약 거래시간 종료시 해당 종목 포지션이 있을 경우 전체 청산 및 미체결 주문 취소.
전략 3) 콜옵션 매수 후 청산
#아웃라인
선물 거래와 동일하나 실시간으로
가격이 1.5 이상인 최근접가 옵션(1.5 이상의 가격대중 가장 저렴한 행사가)를 선택해서 거래하고,
청산 조건이 발동 될 때 5호가가 아닌 5%를 이용해서 수식 작성.
즉, 5%가 오르거나 5%가 내렸을 때 청산 조건 발동.
사정상 다양한 종목을 한 계좌에서 거래 하려고 합니다. (위에 언급한 선물 2개 옵션 4개)
옵션은 콜옵션 2개 행사가 풋옵션 2개 행사가입니다.
그리고 선물은 매수 후 청산 시스템과 매도 후 청산 시스템을 동시에 한 계좌에서 돌립니다.
선물과 옵션에 대해서 작성해주시는 수식이
하나의 계좌에서 각각의 종목 포지션을 참고하면서 잘 돌아갈 수 있게 수식 작성해주시면 감사하겠습니다.