커뮤니티

문의

프로필 이미지
한걸음씩
2014-05-27 21:05:44
949
글번호 223000
답변완료
더운데 수고하십니다. 스팟 수식 문의 드립니다. 우선 하나의 계좌에서 지수 선물과 콜옵션, 풋옵션을 거래하려 합니다. 다 컨셉은 똑 같지만 총 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개 행사가입니다. 그리고 선물은 매수 후 청산 시스템과 매도 후 청산 시스템을 동시에 한 계좌에서 돌립니다. 선물과 옵션에 대해서 작성해주시는 수식이 하나의 계좌에서 각각의 종목 포지션을 참고하면서 잘 돌아갈 수 있게 수식 작성해주시면 감사하겠습니다.
답변 1
프로필 이미지

예스스탁 예스스탁 답변

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개 행사가입니다. 그리고 선물은 매수 후 청산 시스템과 매도 후 청산 시스템을 동시에 한 계좌에서 돌립니다. 선물과 옵션에 대해서 작성해주시는 수식이 하나의 계좌에서 각각의 종목 포지션을 참고하면서 잘 돌아갈 수 있게 수식 작성해주시면 감사하겠습니다.