예스스탁
예스스탁 답변
2013-08-26 19:41:48
안녕하세요
예스스탁입니다.
기존 식이 매수와 매도를 할때는 2.0이하에서 가장 큰 옵션을 주문하지만
차트에서 청산 주문 발생시에 신호상 손실이면
같은 행사가의 반대 콜이나 풋을 주문하도록 되어 있는 식입니다.
그러므로 청산신호가 발생할때는 2.0이하의 종목이 아닌 종목이 주문이 나갈수가 있습니다.
의도하시는 내용이 명확치 않으므로 우선
차트에서 매수(buy)신호가 발생하면 2.0이하에서 가장 큰 풋옵션매도
차트에서 매도(sell)신호가 발생하면 2.0이하에서 가장 큰 콜옵션매도
매수청산(exitlong) 신호가 발생할때 차트상 해당신호가
수익이면 매도한 풋옵션 청산
손실이면 2.0이하의 콜옵션 중 가장 큰 콜옵션 매도
매도청산(exitshort) 신호가 발생할때 차트상 해당신호가
수익이면 매도한 콜옵션 청산
손실이면 2.0이하의 풋옵션 중 가장 큰 콜옵션 매도
모든 매도주문은 매수5호가로, 매수주문은 매도5호가로 지정했습니다.
해당식 시험으로 적용하시면 차트에서 신호발생시 디버깅창에 메세지를 출력하게 했습니다.
시험적용으로 메세지 보시면서 테스트 하시면 됩니다.
스팟이 시뮬레이션이 되지 않아 주문이후의 내용들을 테스트를 해드릴수가 없습니다.
식상 궁금하신 내용이나 의도와 다른부분 있으시면 02-3453-1060으로 전화주시기 바랍니다.
var Start;
var CC; var CallOrderCode;
var xCC; var xCallOrderCode;
var PP; var PutOrderCode;
var xPP; var xPutOrderCode;
var BuyEntryPrice; var SellEntryPrice;
var BuyStep; var SellStep;
function Main_OnStart()
{
Start = 0;
BuyStep = 0;
SellStep = 0;
Main.SetTimer(1, 10000);
}
function Chart1_OnRiseSignal(Signal)
{
//buy신호 발생시
if (Signal.signalKind == 1)
{
Main.MessageList("매수신호발생:"+Signal.signalKind);
//2.0이하의 풋종목 중 가격이 가장 큰 종목 선정
var BUNum = Option.uppersATM;
var BLNum = Option.lowersATM;
var BPutCode = new Array(BUNum+BLNum+1);
var BPutPrice = new Array(BUNum+BLNum+1);
for (var bi = -BUNum; bi <= BLNum; bi++)
{
if (Option.GetCurrent(1, bi) <= 2.0)
{
BPutPrice[bi+BUNum] = Option.GetCurrent(1, bi);
BPutCode[bi+BUNum] = Option.GetATMPutRecent(bi);
}
else
{
BPutPrice[bi+BUNum] = -1;
BPutCode[bi+BUNum] = -1;
}
}
PP = -1;
PutOrderCode = -1;
for (var bii = -BUNum; bii <= BLNum; bii++)
{
if (BPutPrice[bii+BUNum] > PP)
{
PP = BPutPrice[bii+BUNum];
PutOrderCode = BPutCode[bii+BUNum];
}
}
if (PP > 0)
{
Main.MessageList("풋옵션매도 - 종목코드 : ",PutOrderCode," 현재가 :",PP);
Account1.OrderSell(PutOrderCode, 1, Option.GetBidByCode(PutOrderCode, 5), 0);
BuyEntryPrice = Signal.price; //매수신호시 신호가격
BuyStep = 1;
Start = 1;
}
else
{
Main.MessageList("풋옵션 종목코드: 지정한 가격대 종목이 없음");
}
}
//exitlong신호 발생시
if ( Start == 1 && Signal.signalKind == 2)
{
Main.MessageList("매수청산신호 발생",Signal.signalKind);
Start = 0;
if (PP > 0 && Signal.price > BuyEntryPrice) //차트신호 수익
{
Main.MessageList("차트신호 수익 - ",PutOrderCode,"청산");
Account1.OrderBuy(PutOrderCode, 1, Option.GetAskByCode(PutOrderCode, 5), 0);
BuyStep = 0;
}
if (PP > 0 && Signal.price < BuyEntryPrice) //차트신호 손실
{
Main.MessageList("차트신호 손실");
var BxUNum = Option.uppersATM;
var BxLNum = Option.lowersATM;
var BxCallCode = new Array(BxUNum+BxLNum+1);
var BxCallPrice = new Array(BxUNum+BxLNum+1);
for (var exi = -BxLNum; exi <= BxUNum; exi++)
{
if (Option.GetCurrent(0, exi) <= 2.0)
{
BxCallPrice[exi+BxLNum] = Option.GetCurrent(0, exi);
BxCallCode[exi+BxLNum] = Option.GetATMCallRecent(exi);
}
else
{
BxCallPrice[exi+BxLNum] = -1;
BxCallCode[exi+BxLNum] = -1;
}
}
xCC = -1;
xCallOrderCode = -1;
for (var exii = -BxLNum; exii <= BxUNum; exii++)
{
if (BxCallPrice[exii+BxLNum] > xCC)
{
xCC = BxCallPrice[exii+BxLNum];
xCallOrderCode = BxCallCode[exii+BxLNum]; //2.0이하 중 가장큰 콜종목의 종목코드
}
}
if (xCC > 0)
{
Main.MessageList("반대옵션(콜) 매도 - 종목코드 :",xCallOrderCode," 현재가 :",xCC);
Account1.OrderSell(xCallOrderCode, 1, Option.GetBidByCode(xCallOrderCode, 5), 0);
BuyStep = 2;
}
}
}
//sell신호 발생시
if (Signal.signalKind == 3)
{
Main.MessageList("매도신호발생:"+Signal.signalKind);
Start = -1;
var SUNum = Option.uppersATM;
var SLNum = Option.lowersATM;
var SCallCode = new Array(SUNum+SLNum+1);
var SCallPrice = new Array(SUNum+SLNum+1);
for (var ci = -SLNum; ci <= SUNum; ci++)
{
if (Option.GetCurrent(0, ci) <= 2.0)
{
SCallPrice[ci+SLNum] = Option.GetCurrent(0, ci);
SCallCode[ci+SLNum] = Option.GetATMCallRecent(ci);
}
else
{
SCallPrice[ci+SLNum] = -1;
SCallCode[ci+SLNum] = -1;
}
}
CC = -1;
CallOrderCode = -1;
for (var cii = -SLNum; cii <= SUNum; cii++)
{
if (SCallPrice[cii+SLNum] > CC)
{
CC = SCallPrice[cii+SLNum];
CallOrderCode = SCallCode[cii+SLNum]; //2.0이하 중 가장큰 콜종목의 종목코드
}
}
if (CC > 0)
{
Account1.OrderSell(CallOrderCode, 1, Option.GetBidByCode(CallOrderCode, 5),0);
SellStep = 1;
Main.MessageList("콜옵션 매도 -","종목코드 :",CallOrderCode," 현재가 :",CC);
}
else
{
Main.MessageList("콜옵션 매도 : 지정한 가격대 종목이 없음");
}
}
// Exitshort신호 발생시
if (Start == -1 && Signal.signalKind == 4)
{
Main.MessageList("매도청산신호 발생",Signal.signalKind);
Start = 0;
if (CC > 0 && Signal.price < SellEntryPrice)//차트신호수익
{
Main.MessageList("차트신호 수익 - ",CallOrderCode,"청산");
Account1.OrderBuy(CallOrderCode, 1, Option.GetAskByCode(CallOrderCode, 5), 0);
SellStep = 0;
}
if (CC > 0 && Signal.price > SellEntryPrice)//차트신호손실
{
Main.MessageList("차트신호 손실");
var SxUNum = Option.uppersATM;
var SxLNum = Option.lowersATM;
var SxPutCode = new Array(SxUNum+SxLNum+1);
var SxPutPrice = new Array(SxUNum+SxLNum+1);
for (var sxi = -SxUNum; sxi <= SxLNum; sxi++)
{
if (Option.GetCurrent(1, sxi) <= 2.0)
{
SxPutPrice[sxi+SxUNum] = Option.GetCurrent(1, sxi);
SxPutCode[sxi+SxUNum] = Option.GetATMPutRecent(sxi);
}
else
{
SxPutPrice[sxi+SxUNum] = -1;
SxPutCode[sxi+SxUNum] = -1;
}
}
xPP = -1;
xPutOrderCode = -1;
for (var sxii = -SxUNum; sxii <= SxLNum; sxii++)
{
if (SxPutPrice[sxii+SxUNum] > xPP)
{
xPP = SxPutPrice[sxii+SxUNum];
xPutOrderCode = SxPutCode[sxii+SxUNum];
}
}
if (xPP > 0)
{
Main.MessageList("반대옵션(풋) 매도 - 종목코드 :",xPutOrderCode," 현재가 :",xPP);
Account1.OrderSell(xPutOrderCode, 1, Option.GetBidByCode(xPutOrderCode, 5), 0);
SellStep = 2;
}
}
}
}
function Main_OnTimer(nEventID)
{
var d = new Date();
var HHMMDD = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
if (BuyStep == 2)
{
var TotalPL = 0;
Account1.SetBalanceItem(PutOrderCode, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
Account1.SetBalanceItem(xCallOrderCode, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
if (TotalPL <= -1000000)
{
Account1.SetBalanceItem(PutOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
Account1.SetBalanceItem(xCallOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
BuyStep = 0;
}
}
if (SellStep == 2)
{
var TotalPL = 0;
Account1.SetBalanceItem(CallOrderCode, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
Account1.SetBalanceItem(xPutOrderCode, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
if (TotalPL <= -1000000)
{
SellStep = 0;
Account1.SetBalanceItem(CallOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
Account1.SetBalanceItem(xPutOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
}
}
//15시 분에 종목청산
if (nEventID == 1 && HHMMDD >= 150000)
{
Main.KillTimer(1);
if (BuyStep == 2)
{
Account1.SetBalanceItem(PutOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
Account1.SetBalanceItem(xCallOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
BuyStep = 0;
}
if (SellStep == 2)
{
Account1.SetBalanceItem(CallOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
Account1.SetBalanceItem(xPutOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,Option.GetAskByCode(Account1.Balance.code, 5),0);
SellStep = 0;
}
}
}
즐거운 하루되세요
> 먼지의추억 님이 쓴 글입니다.
> 제목 : 수정부탁해요
> 수고많습니다.
에스스팟Q&A의 577번질문에 대한 예스스탁의 RE에 나와있는 것인데요.
저의 전략으로 신호를 발생시키니 작동은 하는데요.
첨부에 체결중 콜7.0의 매도가 발생하엿는데요.
매매하는 종목들을 공히 2.0이하로,
아울러 현재가+-5호가에 주문이 나갈 수 있게 해 주시면
감사하겠습니다.
추가) 중간에 간혹 신호가 없는데 주문이 나가는 경우가 있고요(테스트전략은 bids&asks를 사용(10분) 첫봉매도,2번째봉매수,3번째봉 매도후 15:00;00에 청산)
15:00:05에 접수오류([check_order_ok] 주문수량을 확인하세요란 메세지가 나오고요.
풋만 청산됩니다.
이건 아마 call240 7.0에 매도한 것을 청산하다 보니,시스템은 콜2개매도,풋1개매도가 잇는걸로 인지하는 루틴이 있나봅니다...
bids & asks로 신호가 나올때 아래의 시스템이 2.0이하의 콜과 풋으로 잘 돌아가는지 테스트해 봐 주시면 고맙겠습니다요.
차트에
매수신호 발생하면 2.0 이하 중 가장 큰 풋옵션 매도하고
매도신호 발생하면 2.0 이하 중 가장 큰 콜옵션 매도합니다.
매수청산신호 발생시 신호상 수익이면 풋옵션 매도청산하고
손실이면 행사가의 반대 콜옵션을 매도합니다.
매도청산신호 발생시 신호상 수익이면 콜옵션 매도청산하고
손실이면 행사가의 반대 픗옵션을 매도합니다.
각 청산후 양매도상태이면 손실 100만원 발생하면 모두 청산합니다.
기본틀이므로 테스트 충분히 하신후에 수정보완해 사용하시기 바랍니다.
옵션객체
차트객체 : 객체명 chart1 --> 속송에서 차트아이디 차트와 동일하게 부여
계좌객체 : 객체명 Account1 --> 속성에서 계좌지정
var Start;
var UNum; var LNum;
var CallCode; var CallPrice;
var PutCode; var PutPrice;
var CC; var PP;
var CallOrderCode; var PutOrderCode;
var CallOrderCodeR; var PutOrderCodeR;
var BuyEntryPrice; var SellEntryPrice;
var BuyStep; var SellStep;
function Main_OnStart()
{
Start = 0;
BuyStep = 0;
SellStep = 0;
Main.SetTimer(1, 10000);
}
function Chart1_OnRiseSignal(Signal)
{
UNum = Option.uppersATM;
LNum = Option.lowersATM;
CallCode = new Array(UNum+LNum+1);
PutCode = new Array(UNum+LNum+1);
CallPrice = new Array(UNum+LNum+1);
PutPrice = new Array(UNum+LNum+1);
for (var i = -LNum; i <= UNum; i++)
{
if (Option.GetCurrent(0, i) <= 2.0)
{
CallPrice[i+LNum] = Option.GetCurrent(0, i);
CallCode[i+LNum] = Option.GetATMCallRecent(i);
}
else
{
CallPrice[i+LNum] = -1;
CallCode[i+LNum] = -1;
}
}
for (var ii = -UNum; ii <= LNum; ii++)
{
if (Option.GetCurrent(1, ii) <= 2.0)
{
PutPrice[ii+UNum] = Option.GetCurrent(1, ii);
PutCode[ii+UNum] = Option.GetATMPutRecent(ii);
}
else
{
PutPrice[ii+UNum] = -1;
PutCode[ii+UNum] = -1;
}
}
//buy신호 발생시
if (Signal.signalKind == 1)
{
Start = 1;
PP = -1;
PutOrderCode = -1;
PutOrderCodeR = -1;
for (var iiii = -UNum; iiii <= LNum; iiii++)
{
if (PutPrice[iiii+UNum] > PP)
{
PP = PutPrice[iiii+UNum];
PutOrderCode = PutCode[iiii+UNum]; //2.0이하 중 가장 큰 풋옵션의 종목코드
PutOrderCodeR = Option.GetATMCallRecent(-iiii); //반대 콜옵션의 종목코드
}
}
if (PP > 0)
{
Account1.OrderSell(PutOrderCode, 1, 0, 1);
BuyEntryPrice = Signal.price; //매수신호시 신호가격
BuyStep = 1;
Main.MessageLog("차트신호종류:"+Signal.signalKind+" /종목코드:"+PutOrderCode+" /START:"+Start);
}
else
{
Main.MessageLog("차트신호종류:"+Signal.signalKind+" /종목코드: 지정한 가격대 종목이 없음"+" /START:"+Start);
}
}
//exitlong신호 발생시
if ( Start == 1 && Signal.signalKind == 2)
{
Start = 0;
if (PP > 0 && Signal.price > BuyEntryPrice) //차트신호 수익
{
Account1.OrderBuy(PutOrderCode, 1, 0, 1);
BuyStep = 0;
Main.MessageLog("차트신호종류: 수익:"+Signal.signalKind+" /종목코드:"+PutOrderCode+" /START:"+Start);
}
if (PP > 0 && Signal.price < BuyEntryPrice)//차트신호 손실
{
Account1.OrderSell(PutOrderCodeR, 1, 0, 1);
BuyStep = 2;
Main.MessageLog("차트신호종류 : 손실:"+Signal.signalKind+" /종목코드:"+PutOrderCodeR+" /START:"+Start);
}
}
//sell신호 발생시
if (Signal.signalKind == 3)
{
Start = -1;
CC = -1;
CallOrderCode = -1;
CallOrderCodeR = -1;
for (var iii = -LNum; iii <= UNum; iii++)
{
if (CallPrice[iii+LNum] > CC)
{
CC = CallPrice[iii+LNum];
CallOrderCode = CallCode[iii+LNum]; //2.0이하 중 가장큰 콜종목의 종목코드
CallOrderCodeR = Option.GetATMPutRecent(-iii) //반대 풋옵션의 종목코드
}
}
if (CC > 0)
{
Account1.OrderSell(CallOrderCode, 1, 0, 1);
SellStep = 1;
Main.MessageLog("차트신호종류:"+Signal.signalKind+" /종목코드:"+CallOrderCode+" /START:"+Start);
}
else
{
Main.MessageLog("차트신호종류:"+Signal.signalKind+" /종목코드: 지정한 가격대 종목이 없음"+" /START:"+Start);
}
}
// Exitshort신호 발생시
if (Start == -1 && Signal.signalKind == 4)
{
Start = 0;
if (CC > 0 && Signal.price < SellEntryPrice)//차트신호수익
{
Account1.OrderBuy(CallOrderCode, 1, 0, 1);
SellStep = 0;
Main.MessageLog("차트신호종류: 수익 : "+Signal.signalKind+" /종목코드:"+CallOrderCode+" /START:"+Start);
}
if (CC > 0 && Signal.price > SellEntryPrice)//차트신호손실
{
Account1.OrderSell(CallOrderCodeR, 1, 0, 1);
SellStep = 2;
Main.MessageLog("차트신호종류: 손"+Signal.signalKind+" /종목코드:"+CallOrderCodeR+" /START:"+Start);
}
}
}
function Main_OnTimer(nEventID)
{
var d = new Date();
var HHMMDD = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
if (BuyStep == 2)
{
var TotalPL = 0;
Account1.SetBalanceItem(PutOrderCode, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
Account1.SetBalanceItem(PutOrderCodeR, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
if (TotalPL <= -1000000)
{
Account1.SetBalanceItem(PutOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
Account1.SetBalanceItem(PutOrderCodeR, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
BuyStep = 0;
}
}
if (SellStep == 2)
{
var TotalPL = 0;
Account1.SetBalanceItem(CallOrderCode, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
Account1.SetBalanceItem(CallOrderCodeR, 1);
TotalPL = TotalPL + (Account1.Balance.avgUnitCost-Account1.Balance.current)*Account1.Balance.count*500000;
if (TotalPL <= -1000000)
{
SellStep = 0;
Account1.SetBalanceItem(CallOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
Account1.SetBalanceItem(CallOrderCodeR, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
}
}
//15시 분에 종목청산
if (nEventID == 1 && HHMMDD >= 150000)
{
Main.KillTimer(1);
if (BuyStep == 2)
{
Account1.SetBalanceItem(PutOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
Account1.SetBalanceItem(PutOrderCodeR, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
BuyStep = 0;
}
if (SellStep == 2)
{
Account1.SetBalanceItem(CallOrderCode, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
Account1.SetBalanceItem(CallOrderCodeR, 1);
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
SellStep = 0;
}
}
}