예스스탁
예스스탁 답변
2020-10-08 17:50:46
안녕하세요
예스스탁입니다.
업무상 시간을 많이 할애하지 못해 4번 내용까지만 처리해 드립니다.
아래식 참고하셔서 추가해 보시고 적용이 잘 안되시면 다시 글 올려주시기 바랍니다.
스크립트 객체화면 설정
계좌객체 추가 --> 속성에서 객체명은 Account1, 주문낼 계좌번호 지정
옵션객체 추가 --> 속성에서 객체명은 Option1, 코스피200지수옵션으로 지정
종목객체 추가 --> 속성에서 객체명은 MarketData1, 종목은 코스피지수로 지정, 일간데이타사용 10일
var HHMMSS,HHMMSS,YYYYMMDD;
var Call,Put;
var AMCallList = [],AMCallDate = [],AMCallVol = [];
var PMCallList = [],PMCallDate = [],PMCallVol = [];
var AMPutList = [],AMPutDate = [],AMPutVol = [];
var PMPutList = [],PMPutDate = [],PMPutVol = [];
var AMCallID,AMPutID,PMCallID,PMPutID;
var AMCallNum,AMPutNum,PMCallNum,PMPutNum;
var AMCallVol,AMPutVol,PMCallVol,PMPutVol;
//스팟 시작
function Main_OnStart()
{
//날짜시간 객체
var d = new Date();
//시간을 6자리 숫자로 표현
HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate();
Main.MessageList(HHMMSS,": Start");
//타이머 셋팅(1번타이머, 1초)
Main.SetTimer(1,1000);
//내부 파일에서 값 호출해서 변수에 저장
AMCallDate = JSON.parse(Main.GetUserValue("AMCallDate"));
AMCallList = JSON.parse(Main.GetUserValue("AMCallList"));
AMCallVol = JSON.parse(Main.GetUserValue("AMCallVol"));
AMPutDate = JSON.parse(Main.GetUserValue("AMPutDate"));
AMPutList = JSON.parse(Main.GetUserValue("AMPutList"));
AMPutVol = JSON.parse(Main.GetUserValue("AMPutVol"));
PMCallDate = JSON.parse(Main.GetUserValue("PMCallDate"));
PMCallList = JSON.parse(Main.GetUserValue("PMCallList"));
PMCallVol = JSON.parse(Main.GetUserValue("PMCallVol"));
PMPutDate = JSON.parse(Main.GetUserValue("PMPutDate"));
PMPutList = JSON.parse(Main.GetUserValue("PMPutList"));
PMPutVol = JSON.parse(Main.GetUserValue("PMPutVol"));
}
//타이머 동작
function Main_OnTimer(nEventID)
{
//날짜시간 객체
var d = new Date();
//직전 타이머 동작시 시간
HHMMSS1 = HHMMSS;
//현재 시간
HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
//9시00분이 되면 (5일 경과된 종목 청산)
if (HHMMSS >= 90000 && HHMMSS1 < 90000)
{
//5일전(거래일로 5일전을 알수 없어 종목객체의 일간데이타에서 5일전 날짜를 가져와 비교)
var D5 = MarketData1.GetPrevDate(5);
//오전 콜매도 리스트 배열사이즈(저장된 값의 갯수)
var AMCL = AMCallList.length;
//오전 풋매도 리스트 배열사이즈(저장된 값의 갯수)
var AMPL = AMCallList.length;
//오전 콜매도 청산
if (AMCL > 0)
{
for (var i = AMCL-1; i >= 0; i--)
{
if (AMCallDate[i] >= D5 && AMCallVol[i] > 0)
{
Account1.SetBalance(AMCallList[i],0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 1)
{
//청산을 위해 매수주문
Account1.OrderBuy(Account1.Balance.code,Math.min(AMCallVol[i],Account1.Balance.count),Option1.GetAsk(Account1.Balance.code, 3), 0);
//각 리스트에서 삭제
AMCallDate.splice(i,1);
AMCallList.splice(i,1);
AMCallVol.splice(i,1);
}
}
}
}
//오전 풋매도 청산
if (AMPL > 0)
{
for (var i = AMPL-1; i >= 0; i--)
{
if (AMPutDate[i] >= D5 && AMPutVol[i] > 0)
{
Account1.SetBalance(AMPutList[i],0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 1)
{
//청산을 위해 매수주문
Account1.OrderBuy(Account1.Balance.code,Math.min(AMPutVol[i],Account1.Balance.count),Option1.GetAsk(Account1.Balance.code, 3), 0);
//각 리스트에서 삭제
AMPutDate.splice(i,1);
AMPutList.splice(i,1);
AMPutVol.splice(i,1);
}
}
}
}
}
//9시1분이 되면
if (HHMMSS >= 90100 && HHMMSS1 < 90100)
{
//잔존일이 7일 초과시는 근원물
if (Option1.GetRemainDays(0, 0) >= 7)
{
//매도할 콜종목 (ATM+2단계 콜)
Call = Option1.GetATMCallRecent(2,0);
//매도할 풋종목 (ATM-2단계 풋) --> 풋은 양수가 아랫쪽 행사가
Put = Option1.GetATMPutRecent(2,0)
}
else //잔존일이 7일 이하는 차원물
{
//매도할 콜종목 (ATM+2단계 콜)
Call = Option1.GetATMCallRecent(2,1);
//매도할 풋종목 (ATM-2단계 풋) --> 풋은 양수가 아랫쪽 행사가
Put = Option1.GetATMPutRecent(2,1)
}
if (Call != "")
{
//Call 종목을 매수3호가로 1계약 매도주문
AMCallID = Account1.OrderSell(Call, 1,Option1.GetBid(Call, 3) ,0);
//최종 체결 수량 저장할 변수
AMCallVol = 0;
}
if (Put != "")
{
//Put 종목을 매수3호가로 1계약 매도주문
AMPutID = Account1.OrderSell(Put, 1,Option1.GetBid(Put, 3) ,0);
//최종 체결 수량 저장할 변수
AMPutVol = 0;
}
}
//15시00분이 되면 (5일 경과된 종목 청산)
if (HHMMSS >= 150000 && HHMMSS1 < 150000)
{
//5일전(거래일로 5일전을 알수 없어 종목객체의 일간데이타에서 5일전 날짜를 가져와 비교)
var D5 = MarketData1.GetPrevDate(5);
//오전 콜매도 리스트 배열사이즈(저장된 값의 갯수)
var PLCL = PLCallList.length;
//오전 풋매도 리스트 배열사이즈(저장된 값의 갯수)
var PLPL = PLCallList.length;
//오후 콜매도 청산
if (PLCL > 0)
{
for (var i = PLCL-1; i >= 0; i--)
{
if (PLCallDate[i] >= D5 && PLCallVol[i] > 0)
{
Account1.SetBalance(PLCallList[i],0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 1)
{
//청산을 위해 매수주문
Account1.OrderBuy(Account1.Balance.code,Math.min(PLCallVol[i],Account1.Balance.count),Option1.GetAsk(Account1.Balance.code, 3), 0);
//각 리스트에서 삭제
PLCallDate.splice(i,1);
PLCallList.splice(i,1);
PLCallVol.splice(i,1);
}
}
}
}
//오후 풋매도 청산
if (PLPL > 0)
{
for (var i = PLPL-1; i >= 0; i--)
{
if (PLPutDate[i] >= D5 && PLPutVol[i] > 0)
{
Account1.SetBalance(PLPutList[i],0);
if (Account1.Balance.count > 0 && Account1.Balance.position == 1)
{
//청산을 위해 매수주문
Account1.OrderBuy(Account1.Balance.code,Math.min(PLPutVol[i],Account1.Balance.count),Option1.GetAsk(Account1.Balance.code, 3), 0);
//각 리스트에서 삭제
PLPutDate.splice(i,1);
PLPutList.splice(i,1);
PLPutVol.splice(i,1);
}
}
}
}
}
//15시01분이 되면
if (HHMMSS >= 150100 && HHMMSS1 < 150100)
{
//Call변수에 종목코드가 저장되어 있으면
if (Call != "")
{
//Call 종목을 매수3호가로 1계약 매도주문
PMCallID = Account1.OrderSell(Call, 1,Option1.GetBid(Call, 3) ,0);
//최종 체결 수량 저장할 변수
PMCallVol = 0;
}
//Put변수에 종목코드가 저장되어 있으면
if (Put != "")
{
//Put 종목을 매수3호가로 1계약 매도주문
PMPutID = Account1.OrderSell(Put, 1,Option1.GetBid(Put, 3) ,0);
//최종 체결 수량 저장할 변수
PMPutVol = 0;
}
}
}
//주문 응답수신될떄
//각 주문별로 주문번호 저장
function Main_OnOrderResponse(OrderResponse)
{
//오전 콜매도 주문에 대한 응답이면 AMCallNum에 주문번호 저장
if (OrderResponse.orderID == AMCallID)
{
AMCallNum = OrderResponse.orderNum;
}
//오전 풋매도 주문에 대한 응답이면 AMPutNum에 주문번호 저장
if (OrderResponse.orderID == AMPutID)
{
AMPutNum = OrderResponse.orderNum;
}
//오후 콜매도 주문에 대한 응답이면 PMCallNum에 주문번호 저장
if (OrderResponse.orderID == PMCallID)
{
PMCallNum = OrderResponse.orderNum;
}
//오후 풋매도 주문에 대한 응답이면 PMPutNum에 주문번호 저장
if (OrderResponse.orderID == PMPutID)
{
PMPutNum = OrderResponse.orderNum;
}
}
//체결응답 발생
function Main_OnNotifyFill(NotifyFill)
{
//오전 콜매도 체결응답이면
if (NotifyFill.orderNum == AMCallNum)
{
//체결수량 누적
AMCallVol = AMCallVol + NotifyFill.fillCount;
}
//오전 풋매도 체결응답이면
if (NotifyFill.orderNum == AMPutNum)
{
//체결수량 누적
AMPutVol = AMPutVol + NotifyFill.fillCount;
}
//오후 콜매도 체결응답이면
if (NotifyFill.orderNum == PMCallNum)
{
//체결수량 누적
PMCallVol = PMCallVol + NotifyFill.fillCount;
}
//오후 풋매도 체결응답이면
if (NotifyFill.orderNum == PMPutNum)
{
//체결수량 누적
PMPutVol = PMPutVol + NotifyFill.fillCount;
}
}
//프로그램 종료시
function Main_OnClose()
{
//각 배열에 값 저장
if (AMCallVol > 0)
{
AMCallList.push(Call);
AMCallDate.push(YYYYMMDD);
AMCallVol.push(AMCallVol);
}
if (AMPutVol > 0)
{
AMPutList.push(Put);
AMPutDate.push(YYYYMMDD);
AMPutVol.push(AMPutVol);
}
if (PMCallVol > 0)
{
PMCallList.push(Call);
PMCallDate.push(YYYYMMDD);
PMCallVol.push(PMCallVol);
}
if (PMPutVol > 0)
{
PMPutList.push(Put);
PMPutDate.push(YYYYMMDD);
PMPutVol.push(PMPutVol);
}
//내부파일에 값 저장
Main.SetUserValue("AMCallList", JSON.stringify(AMCallList));
Main.SetUserValue("AMCallDate", JSON.stringify(AMCallDate));
Main.SetUserValue("AMCallVol", JSON.stringify(AMCallVol));
Main.SetUserValue("AMPutList", JSON.stringify(AMPutList));
Main.SetUserValue("AMPutDate", JSON.stringify(AMPutDate));
Main.SetUserValue("AMPutVol", JSON.stringify(AMPutVol));
Main.SetUserValue("PMCallList", JSON.stringify(PMCallList));
Main.SetUserValue("PMCallDate", JSON.stringify(PMCallDate));
Main.SetUserValue("PMCallVol", JSON.stringify(PMCallVol));
Main.SetUserValue("PMPutList", JSON.stringify(PMPutList));
Main.SetUserValue("PMPutDate", JSON.stringify(PMPutDate));
Main.SetUserValue("PMPutVol", JSON.stringify(PMPutVol));
}
즐거운 하루되세요
> 비오80 님이 쓴 글입니다.
> 제목 : 예스 스팟 수식 부탁드립니다.
> 안녕하세요? 항상 애써주시는 데 대해 감사드립니다.
양매도 관련 스팟 수식 부탁드립니다.
-전략-
1. 종목 선정
09:01 KOSPI200 선물 기준, 등가 +5p(2호가) 콜옵션 1계약 매도
09:01 KOSPI200 선물 기준, 등가 -5p(2호가) 풋옵션 1계약 매도
15:00 이후 위에 진입한 콜옵션 1계약 추가 매도
15:00 이후 위에 진입한 풋옵션 1계약 추가 매도
<오전장/오후장 두번에 걸친 매매로 하루 가격 변동성 헷지>
2. 매일 같은 방법으로 진입
3. 선입선출 방법으로 D+5 일째 첫날 진입한 물량 청산
8월 31일(월) 진입한 종목 -> D+5일째인 9월 7일(월) 청산
청산 역시 09:00이후 콜, 풋 1계약 청산
15:00이후 콜, 풋 1계약 청산
4. 만기 다가올수록 먹을 수 있는 프리가 별로 없어서 변동폭이 커질 시 손실이 커지는 경우가 발생
-> 만기 - 7영업일에 당월물에서 차월물로 종목 변경, 만기이후 당월물로 전환
5. 로스컷 기준
① 당일 진입한 평균가격 + (콜옵션 매도 평균가격 + 풋옵션 매도 평균가격)
ⓐ 만기전후 5영업일(만기전 5영업일, 만기후 5영업일) 은 손절만 실시
ⓑ 만기 후 5영업일 부터 다음 만기전 5영업일까지는 로스컷 후 바로 양매수 각각 2계약 실시->양매수 진입물량은 만기전날 일괄 청산(만기전일 시가 1계약 청산, 종가 1계약 청산)
일단 청산과 진입 수식을 부탁드립니다. 제가 아직 프로그램에는 서툴러서 주석도 첨부해 주시면 정말 감사드리겠습니다.