커뮤니티

문의드립니다.

프로필 이미지
nobound
2014-06-18 10:54:03
1153
글번호 223032
답변완료
안녕하십니까? 수고가 많으십니다. 옵션 포지션을 청산하는 로직을 부탁드립니다. 진입은 손 매매로 하고, 콜, 풋옵션 매도, 매수가 모두 들어간 4가지 옵션의 포지션 손실이 일정금액을 넘어서면 포지션 전체를 청산하는 로직을 원합니다. 1. 계좌의 포지션을 모두 읽어들입니다. 2. 계좌 전체 손실이 진입대비 100만원(금액은 변경가능하게 변수로 처리)을 초과하면 청산을 시작 3. 먼저, 매도포지션 가운데 손해가 큰 옵션(예를 들어, put옵션매도)부터 청산 시작 - 현재가로 주문 - 10초(기간도 변경가능하게 변수로 처리)까지 put옵션 매도포지션이 완전 청산되지 않으면 (put옵션매도 갯수가 여러 개여서 한 번 주문으로 모두 청상되지 않을 가능성에 대비해서) 상대1호가로 주문 변경 - 15초(기간도 변경가능하게 변수로 처리)까지 모두 청산되지 않으면 상대 4호가로 주문 변경 4. put 옵션매도가 모두 청산된 것을 확인한 후 put 옵션 매수 포지션 청산 시작 - 청산 주문과정은 위의 3과 동일하게 함 5. put옵션의 반대쪽 call옵션 매도를 청산하기 시작 - 주문과정은 위와 동일 6. call옵션 매수 포지션 청산 으로 모든 포지션을 순차적으로 청산하는 로직이 필요합니다. 위는 put옵션 매도 손실>call옵션 매도 손실인 경우를 예로 들었습니다. 반대로 put옵션 매도손실<call옵션 매도손실 인 경우는 1. call 매도 청산 2. call 매수 청산 3. put 매도 청산 4. put 매수 청산의 순서로 하면 됩니다. 항상 수고해주셔서 감사드립니다. 부탁드립니다.
답변 1
프로필 이미지

예스스탁 예스스탁 답변

2014-06-27 15:02:13

안녕하세요 예스스탁입니다. 아래내용 참고하셔서 수정보완해 사용하시기 바랍니다. 스크립트 객체화면에 아래와 같이 설정하셔야 합니다. 계좌객체 추가 --> 속성에서 계좌지정 외부변수 추가 --> 속성에서 변수병 Loss, 초기값 -1000000, 데이터형 숫자 외부변수 추가 --> 속성에서 변수병 T1, 초기값 10000, 데이터형 숫자 외부변수 추가 --> 속성에서 변수병 T2, 초기값 15000, 데이터형 숫자 수식안에 게시판금칙어가 있습니다. 영문업데이트가 Up*date로 되어 있으므로 종목객체 업데이트 이벤트 내용에 *제거 하시기 바랍니다. 기본 흐름은 아래와 같습니다. 스팟시작후 5초단위로 잔고를 체크해서 콜매수, 콜매도, 풋매수, 풋매도가 모두 있으면 해당 종목의 종목객체를 생성합니다. 종목객체 생성이 완료되면 시세가 업데이트 될때마다 해당 종목들의 손익을 파악해서 합계가 백만원이상 손실이 발생하면 손실이 큰 매도포지션 쪽으로 주문을 합니다. 콜매도 손실이 크면 콜매도청산 --> 콜매수청산 --> 풋매도청산 --> 풋매수청산 풋매도 손실이 크면 풋매도청산 --> 풋매수청산 --> 콜매도청산 --> 콜매수청산 각각 10초, 15초 단위로 정정주문을 하고 체결통보 받을때 체결통보 받은 종목의 잔고가 0이 되면 다음종목에 대해 주문을 하게 됩니다. 이용에 참고하시기 바랍니다. var Start, Req; var CLong, CLongEntry, CLongCode, CLongPrice, CLongPL; var CShort, CShortEntry, CShortCode , CLongPrice, CShortPL; var PLong, PLongEntry, PLongCode , PLongPrice, PLongPL; var PShort, PShortEntry, PShortCode, PLongPrice, PShortPL; var LossCond,Xcount, T); function Main_OnStart() { Main.SetTimer(1, 5000); Start = 0; Xcount = 0; CLongEntry = false; CShortEntry = false; PLongEntry = false; PShortEntry = false; Main.MessageList("스팟개시",Start,CLongEntry,CShortEntry,PLongEntry,PShortEntry); } function Main_OnTimer(nEventID) { //5초 간격으로 계좌에 콜매수,콜매도,풋매수,풋매도 포지션이 모두 있는지 확인 if (nEventID == 1) { CLongEntry = false; CShortEntry = false; PLongEntry = false; PShortEntry = false; var num = Account1.GetTheNumberOfBalances() for (var i = 0; i < num; i++) { Account1.SetBalanceIndex(i); //콜 매수포지션이면 if (Account1.Balance.code.substring(0,1) == "2" && Account1.Balance.position == 2) { CLongEntry = true; CLongCode = Account1.Balance.code; //종목코드 } //콜 매도포지션이면 if (Account1.Balance.code.substring(0,1) == "2" && Account1.Balance.position == 1) { CShortEntry = true; CShortCode = Account1.Balance.code; } //풋 매수포지션이면 if (Account1.Balance.code.substring(0,1) == "3" && Account1.Balance.position == 2) { PLongEntry = true; PLongCode = Account1.Balance.code; } //풋 매도포지션이면 if (Account1.Balance.code.substring(0,1) == "3" && Account1.Balance.position == 1) { PShortEntry = true; PShortCode = Account1.Balance.code; } } //모두 포지션이 있으면 각 종목객체 생성 if (CLongEntry == true && CShortEntry == true && PLongEntry == true && PShortEntry == true) { Start = 1; Main.MessageList("종목요건 만족-종목생성 요청",CLongCode,CShortCode,PLongCode,PShortCode); Main.KillTimer(1); Main.ReqMarketData(CLongCode,0,0); Main.ReqMarketData(CShortCode,0,0); Main.ReqMarketData(PLongCode,0,0); Main.ReqMarketData(PShortCode,0,0); Req = 0; } } if (nEventID == 11 && T == 1) { Main.KillTimer(11); if (Xcount == 1) { Account1.SetUnfillOrderNumber(N1); if ( Account1.Unfill.count > 0) { Replace = 1; ID1 = Account1.OrderReplacePrice(N1, CShort.Bid(1)); } } if (Xcount == 2) { Account1.SetUnfillOrderNumber(N2); if ( Account1.Unfill.count > 0) { Replace = 1; ID2 = Account1.OrderReplacePrice(N2, CLong.Ask(1)); } } if (Xcount == 3) { Account1.SetUnfillOrderNumber(N3); if ( Account1.Unfill.count > 0) { Replace = 1; ID3 = Account1.OrderReplacePrice(N3, PShort.Bid(1)); } } if (Xcount == 4) { Account1.SetUnfillOrderNumber(N4); if ( Account1.Unfill.count > 0) { Replace = 1; ID4 = Account1.OrderReplacePrice(N4, PLong.Ask(1)); } } } if (nEventID == 12 && T == 1) { Main.KillTimer(12); if (Xcount == 1) { Account1.SetUnfillOrderNumber(N1); if ( Account1.Unfill.count > 0) { Replace = 2; ID1 = Account1.OrderReplacePrice(N1, CShort.Bid(5)); } } if (Xcount == 2) { Account1.SetUnfillOrderNumber(N2); if ( Account1.Unfill.count > 0) { Replace = 2; ID2 = Account1.OrderReplacePrice(N2, CLong.Ask(5)); } } if (Xcount == 3) { Account1.SetUnfillOrderNumber(N3); if ( Account1.Unfill.count > 0) { Replace = 2; ID3 = Account1.OrderReplacePrice(N3, PShort.Bid(5)); } } if (Xcount == 4) { Account1.SetUnfillOrderNumber(N4); if ( Account1.Unfill.count > 0) { Replace = 2; ID4 = Account1.OrderReplacePrice(N4, PLong.Ask(5)); } } } if (nEventID == 11 && T == -1) { Main.KillTimer(11); if (Xcount == 1) { Account1.SetUnfillOrderNumber(N1); if ( Account1.Unfill.count > 0) { Replace = 1; ID1 = Account1.OrderReplacePrice(N1, PShort.Bid(1)); } } if (Xcount == 2) { Account1.SetUnfillOrderNumber(N2); if ( Account1.Unfill.count > 0) { Replace = 1; ID2 = Account1.OrderReplacePrice(N2, PLong.Ask(1)); } } if (Xcount == 3) { Account1.SetUnfillOrderNumber(N3); if ( Account1.Unfill.count > 0) { Replace = 1; ID3 = Account1.OrderReplacePrice(N3, CShort.Bid(1)); } } if (Xcount == 4) { Account1.SetUnfillOrderNumber(N4); if ( Account1.Unfill.count > 0) { Replace = 1; ID4 = Account1.OrderReplacePrice(N4, CLong.Ask(1)); } } } if (nEventID == 12 && T == -1) { Main.KillTimer(12); if (Xcount == 1) { Account1.SetUnfillOrderNumber(N1); if ( Account1.Unfill.count > 0) { Replace = 1; ID1 = Account1.OrderReplacePrice(N1, PShort.Bid(5)); } } if (Xcount == 2) { Account1.SetUnfillOrderNumber(N2); if ( Account1.Unfill.count > 0) { Replace = 1; ID2 = Account1.OrderReplacePrice(N2, PLong.Ask(5)); } } if (Xcount == 3) { Account1.SetUnfillOrderNumber(N3); if ( Account1.Unfill.count > 0) { Replace = 1; ID3 = Account1.OrderReplacePrice(N3, CShort.Bid(5)); } } if (Xcount == 4) { Account1.SetUnfillOrderNumber(N4); if ( Account1.Unfill.count > 0) { Replace = 1; ID4 = Account1.OrderReplacePrice(N4, CLong.Ask(5)); } } } } //요청한 4개 종목객체 생성이 완료가 되면 시작 function Main_OnRcvMarketData(MarketData) { if (MarketData.code == CLongCode) { Req = Req+1; CLong = MarketData; Main.MessageList(" CL생성",CLong.code); } if (MarketData.code == CShortCode) { Req = Req+1; CShort = MarketData; Main.MessageList(" CS생성",CShort.code); } if (MarketData.code == PLongCode) { Req = Req+1; PLong = MarketData; Main.MessageList(" PL생성",PLong.code); } if (MarketData.code == PShortCode) { Req = Req+1; PShort = MarketData; Main.MessageList(" PS생성",PShort.code); } if (Req == 4) { Start = 2; Main.MessageList("감시시작",Start,CLong.current, CShort.current, PLong.current, PShort.current ); } } function Main_OnUp*dateMarket(sItemCode, lUp*dateID) { if (lUp*dateID == 20001 && Start == 2) { if (LossCond == false) { Account1.SetBalanceItem(CLong.code, 0); CLongPL = Math.round(((CLong.current - Account1.Balance.avgUnitCost)*Account1.Balance.count)*500000); Account1.SetBalanceItem(CShort.code, 0); CShortPL = Math.round(((Account1.Balance.avgUnitCost - CShort.current)*Account1.Balance.count)*500000); Account1.SetBalanceItem(PLong.code, 0); PLongPL = Math.round(((PLong.current - Account1.Balance.avgUnitCost)*Account1.Balance.count)*500000); Account1.SetBalanceItem(PShort.code, 0); PShortPL = Math.round(((Account1.Balance.avgUnitCost - PShort.current)*Account1.Balance.count)*500000); Main.MessageList("손익",CLong.code,CLongPL,CShort.code,CShortPL,PLong.code,PLongPL,PShort.code, PShortPL ); if (CLongPL+CShortPL+PLongPL+PShortPL <= Loss) { Main.MessageList("손실조건만족",CLongPL+CShortPL+PLongPL+PShortPL); LossCond = true; Xcount = 0; } } } if (LossCond == true) { //콜매도손익이 풋매도손익보다 작음 if (CShortPL < PShortPL) { T = 1; if (Xcount == 0) { //잔고가 0이상이고 콜매도 청산 Account1.SetBalanceItem(CShort.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 1) { Xcount = 1; Replace = 0; ID1 = Account1.OrderBuy(Account1.Balance.code,Account1.Balance.count,CShort.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); } } } //풋매도손익이 콜매도손익보다 작음 if (CShortPL >= PShortPL) { T = -1; if (Xcount == 0) { //잔고가 0이상이고 풋매도 청산 Account1.SetBalanceItem(PShort.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 1) { Xcount = 1; Replace = 0; ID1 = Account1.OrderBuy(Account1.Balance.code,Account1.Balance.count,PShort.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); } } } } } var ID1,N1,ID2,N2,ID3,N3,ID4,N4; function Main_OnOrderResponse(OrderResponse) { if (Xcount == 1 && ID1 == OrderResponse.orderID) { N1 = OrderResponse.orderNum; } if (Xcount == 2 && ID2 == OrderResponse.orderID) { N2 = OrderResponse.orderNum; } if (Xcount == 3 && ID3 == OrderResponse.orderID) { N3 = OrderResponse.orderNum; } if (Xcount == 4 && ID4 == OrderResponse.orderID) { N4 = OrderResponse.orderNum; } } //체결통보 function Main_OnNotifyFill(NotifyFill) { if (Xcount == 1 && N1 == NotifyFill.orderNum) { //체결수신받은 종목의 잔고가 0인지 확인해 0이면 Account1.SetBalanceItem(NotifyFill.code,0); if (Account1.Balance.count == 0) { //타이머 종료 if (Replace == 0) { Main.KillTimer(11); Main.KillTimer(12); } if (Replace == 1) { Main.KillTimer(12); } if (T == 1) { //콜매수 청산주문 Account1.SetBalanceItem(CLong.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2) { Xcount = 2; ID2 = Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,CLong.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); Replace = 0; } } if (T == -1) { //풋매수 청산주문 Account1.SetBalanceItem(PLong.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2) { Xcount = 2; ID2 = Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,PLong.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); Replace = 0; } } } } if (Xcount == 2 && N2 == NotifyFill.orderNum) { //체결수신받은 종목의 잔고가 0인지 확인해 0이면 Account1.SetBalanceItem(NotifyFill.code,0); if (Account1.Balance.count == 0) { //타이머 종료 if (Replace == 0) { Main.KillTimer(11); Main.KillTimer(12); } if (Replace == 1) { Main.KillTimer(12); } if (T == 1) { //풋매도 청산 Account1.SetBalanceItem(PShort.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 1) { Xcount = 3; ID3 = Account1.OrderBuy(Account1.Balance.code,Account1.Balance.count,PShort.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); Replace = 0; } } if (T == -1) { //콜매도 청산 Account1.SetBalanceItem(CShort.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 1) { Xcount = 3; ID3 = Account1.OrderBuy(Account1.Balance.code,Account1.Balance.count,CShort.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); Replace = 0; } } } } if (Xcount == 3 && N3 == NotifyFill.orderNum) { //체결수신받은 종목의 잔고가 0인지 확인해 0이면 Account1.SetBalanceItem(NotifyFill.code,0); if (Account1.Balance.count == 0) { //타이머 종료 if (Replace == 0) { Main.KillTimer(11); Main.KillTimer(12); } if (Replace == 1) { Main.KillTimer(12); } if (T == 1) { //풋매수 청산 Account1.SetBalanceItem(PLong.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2) { Xcount = 4; ID3 = Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,PLong.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); Replace = 0; } } if (T == -1) { //콜매수 청산 Account1.SetBalanceItem(CLong.code, 0); if (Account1.Balance.count > 0 && Account1.Balance.position == 2) { Xcount = 4; ID3 = Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,CLong.current,0); Main.SetTimer(11, T1); Main.SetTimer(12, T2); Replace = 0; } } } } if (Xcount == 4 && N4 == NotifyFill.orderNum) { //체결수신받은 종목의 잔고가 0인지 확인해 0이면 Account1.SetBalanceItem(NotifyFill.code,0); if (Account1.Balance.count == 0) { //타이머 종료 if (Replace == 0) { Main.KillTimer(11); Main.KillTimer(12); } if (Replace == 1) { Main.KillTimer(12); } } } } 즐거운 하루되세요 > nobound 님이 쓴 글입니다. > 제목 : 문의드립니다. > 안녕하십니까? 수고가 많으십니다. 옵션 포지션을 청산하는 로직을 부탁드립니다. 진입은 손 매매로 하고, 콜, 풋옵션 매도, 매수가 모두 들어간 4가지 옵션의 포지션 손실이 일정금액을 넘어서면 포지션 전체를 청산하는 로직을 원합니다. 1. 계좌의 포지션을 모두 읽어들입니다. 2. 계좌 전체 손실이 진입대비 100만원(금액은 변경가능하게 변수로 처리)을 초과하면 청산을 시작 3. 먼저, 매도포지션 가운데 손해가 큰 옵션(예를 들어, put옵션매도)부터 청산 시작 - 현재가로 주문 - 10초(기간도 변경가능하게 변수로 처리)까지 put옵션 매도포지션이 완전 청산되지 않으면 (put옵션매도 갯수가 여러 개여서 한 번 주문으로 모두 청상되지 않을 가능성에 대비해서) 상대1호가로 주문 변경 - 15초(기간도 변경가능하게 변수로 처리)까지 모두 청산되지 않으면 상대 4호가로 주문 변경 4. put 옵션매도가 모두 청산된 것을 확인한 후 put 옵션 매수 포지션 청산 시작 - 청산 주문과정은 위의 3과 동일하게 함 5. put옵션의 반대쪽 call옵션 매도를 청산하기 시작 - 주문과정은 위와 동일 6. call옵션 매수 포지션 청산 으로 모든 포지션을 순차적으로 청산하는 로직이 필요합니다. 위는 put옵션 매도 손실>call옵션 매도 손실인 경우를 예로 들었습니다. 반대로 put옵션 매도손실<call옵션 매도손실 인 경우는 1. call 매도 청산 2. call 매수 청산 3. put 매도 청산 4. put 매수 청산의 순서로 하면 됩니다. 항상 수고해주셔서 감사드립니다. 부탁드립니다.