답변완료
청산이 제대로 안되네요 ㅠㅠ
input : GapUP(0.5), GapDN(0.5),BAD(10),GOOD(10);
if sDate != sDate[1] Then {
if O > C[1] * (1+GapUP/100) then {
if C >= O AND data2(O) < Data2(C) Then
buy("Gap-run-buy", atStop, C);
Else If C < O AND data2(O) > Data2(C) Then
Sell("Gap-fill-sell", atStop, C);
}
if O < C[1] * (1-GapDN/100) then {
if C >= O AND DATA2(C) > DATA2(O) Then
buy("Gapfill-buy", atStop, C);
Else if C < O AND DATA2(C) < DATA2(O) Then
Sell("Gap-run-sell", atStop, C);
}
}
setstoploss(2,pointstop);
SETSTOPTRAILING(BAD,GOOD,PERCENTSTOP);
setstopendofday;
--------------------------------------------------------------------------------------
setstoploss가 제대로 구동 안되고...
setstoptrailing을 저렇게 하는게 맞는지 여쭤볼 수 있을까요.. ㅜ ㅜㅜ
식은 외국인선물순매수금액이랑 갭런필 전략을 합쳐서 진입을 더 엄격하게 설정한 것입니다.
2018-11-27
2765
글번호 224673
답변완료
질문드립니다.
아래와 같은 yeslanguage 전략을 이용하는 걸 테스트 중인데요.
예스 검색식에서 만들어서 파워검색식이나 종목검색식에서는 결과가 잘 나옵니다.
그런데 스팟의 아래식에 test 종목(만든것) 이름을 넣어서 해보니,
"파일을 열 수 없습니다."
라는 에러가 뜨면서 안됩니다.
해결방법을 알려주시면 감사하겠습니다.
아래 업데이트는 *처리 하였습니다.
var cond,rcvChart,rcvMK, RcvChartEnd = false;
var item,itemcnt;
//아래 배열변수를 사용하는 이유는 동일종목의 정보는 배열변수의 동일방번호에 저장하기 위함입니다.
var CT = [];//차트객체 저장할 배열변수
var MK = [];//종목객체 저장할 배열변수
var IS = [];//미완성 신호횟수 저장할 배열변수
var VV = [];//주문수량 저장할 변수
var C1 = [];//첫 매수가격을 저장할 변수
var CC = [];//다음 하락시 가격을 저장할 변수
//스팟 시작시 종목검색 요청
function Main_OnStart()
{
Main.ReqPowerSearch("test");//사용자검색조건명 지정
var d = new Date();
var HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
rcvChart = 0;
}
//종목검색 완료(aItemList : 종목리스트), (nCount : 종목수)
function Main_OnRcvItemList(aItemList, nCount)
{
item = aItemList;
itemcnt = nCount;
RcvChart = 0;
RcvChartEnd = false;
//확장 챠트요청(최대 100개까지만 가능)
// 확장챠트의 생성과 적용될 시스템의 세부 설정
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
1, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
1000, // 최대진입수량
20); // 최대진입횟수
//종목검색된 종목의 차트와 종목객체 요청
for (var i = 0; i < Math.min(itemcnt,100); i++)
{
//생성할 차트 셋팅
var C1 = new ReqChartItem(item[i], 1, CHART_PERIOD_DAILY, 499,CHART_REQCOUNT_BAR,false, false);
//차트에 적용할 시스템명 및 설정
var S1 = new SystemInfo("DMI스팟",YL_TYPE_NORMAL,null,TradeSet,null);
Main.ReqChartEx(C1,S1);
Main.ReqMarketData(item[i]);
}
}
//차트객체 수신받으면
//해당 종목의 종목검색순번과 같은 번호의 배열방에 차트객체저장
function Main_OnRcvChartEx(ChartEx)
{
for (var i = 0; i < Math.min(itemcnt,100); i++)
{
if (ChartEx.code == item[i])
{
CT[i] = ChartEx;
}
}
}
//차트객체 수신받으면
//해당 종목의 종목검색순번과 같은 번호의 배열방에 종목객체저장
function Main_OnRcvMarketData(MarketData)
{
for (var i = 0; i < Math.min(itemcnt,100); i++)
{
if (MarketData.code == item[i])
{
MK[i] = MarketData;
}
}
}
//각 차트의 새로운 봉이 생성
function Main_OnBarAppended(ChartEx, nData)
{
//차트와 종목객체 전체가 수신이 완료된 상태이고
if (CT.length == Math.min(itemcnt,100) && MK.length == Math.min(itemcnt,100) )
{
//새로운봉이 생성된 종목과 CT배열의 종목과 비교해
//같은 종목을 찾으면 미완성신호를 카운트 하는 배열변수의 동일방번호를 0으로 초기화
for (i = 0; i < Math.min(itemcnt,100); i++)
{
if (ChartEx.code == CT[i].code)
{
IS[i] = 0;
}
}
}
}
//확장챠트에서 발생한 신호에 의해 주문을 넣는 단계
function Main_OnRiseIncompleteSignal(ChartEx, IncompleteSignal)
{
//차트와 종목객체 전체가 수신이 완료된 상태이고
if (CT.length == Math.min(itemcnt,100) && MK.length == Math.min(itemcnt,100) )
{
//잔고세팅
A1.SetBalance(IncompleteSignal.code, nPosition);
//buy신호 발생
if (IncompleteSignal.signalKind == 1)
{
//해당 종목의 방번호를 찾아서
for (i = 0; i < Math.min(itemcnt,100); i++)
{
if (ChartEx.code == CT[i].code && ChartEx.code == MK[i].code)
{
//카운트 1증가
IS[i] = IS[i]+1;
//현재 미완성신호 발생하고 해당종목의 잔고가 0이고 첫번째 매수미완성신호이면 매수
if (A1.Balance.count == 0 && IS[i] == 1)
{
// 매수주문
A1.OrderBuy(IncompleteSignal.code, IncompleteSignal.count , MK[i].Ask(3), 0);
//수량과 가격 저장
C1[i] = IncompleteSignal.price ;//최초매수가
CC[i] = 0.1;//하락시 가격 계산할 변수
VV[i] = (IncompleteSignal.price * IncompleteSignal.count)*0.1;//최초매수금의 10%
}
}
}
}
//잔고에 수량이 있고 청산신호 발생하면 청산
if (A1.Balance.count > 0 && IncompleteSignal.signalKind == 2)
{
// 매도주문
A1.OrderSell(IncompleteSignal.code, A1.Balance.count, MK[i].Bid(3), 0);
}
}
}
function Main_OnUp*dateMarket(sItemCode, lUp*dateID)
{
//체결데이터 수신 업데이트
if (lUp*dateID == 20001)
{
//루프를 돌아 생성된 종목중 어떤 종목인지 파악
for (i = 0; i < Math.min(itemcnt,100); i++)
{
//어떤 배열방의 종목인지 찾았으면
if (sItemCode == MK[i])
{
//해당 종목 잔고셋팅
A1.SetBalance(MK[i].code, 0);
//잔고 수량이 있을때만
if (A1.Balance.count > 0)
{
//최초 매수가격의 2% 이상 상승하면 전량청산
if (MK[i].current >= C1[i]*1.02)
{
A1.OrderSell(MK[i].code,A1.Balance.count, MK[i].Bid(3), 0);
}
//하락시 매수할 가격이하이면 추가매수
if (MK[i].current <= Ci[i]*(1-CC[i]))
{
A1.OrderBuy(MK[i].code,Math.floor(VV[i]/MK[i].Ask(3)),MK[i].Ask(3), 0);
CC[i] = CC[i]+0.1;//0.1을 추가해줌
}
}
}
}
}
}
2018-11-27
2941
글번호 224672
답변완료
매수매도 청산
매수신호: ATM 5초간격 콜매수
매수청산 신호: 종목관계 없이 잔고가 있으면 5초간격 콜매도 청산
매도신호: 어떤 종목 5초간격 풋매수
매도청산 신호: 종목관계 없이 잔고가 있으면 5초간격 풋매도 청산
var CallCode,PutCode;
var BEcnt,BXcnt,SEcnt,SXcnt;
var MaxEntryVol = 3;
var MaxExitVol;
function C1_OnRiseSignal(Signal)
{
if (Signal.signalKind == 1 )
{
Main.MessageList("매수신호발생");
CallCode = Option.GetATMCallRecent(0);
var CallPrice = Option.GetAskByCode(CallCode,2);
A1.OrderBuy(CallCode, 1, CallPrice, 0);
BEcnt = 1;
//1번 타이머 5초 셋팅
Main.SetTimer(1,5000);
}
if (Signal.signalKind == 2 )
{
Main.MessageList("매수청산신호발생");
var BxPrice = Option.GetBidByCode(CallCode, 2);
A1.OrderSell(CallCode, 1, BxPrice, 0);
BXcnt = 1;
//보유수량이 2계약 이상이면
if (MaxExitVol >= 2)
//2번 타이머 5초 셋팅
Main.SetTimer(2,5000);
}
if (Signal.signalKind == 3 )
{
Main.MessageList("매도신호발생");
PutCode = Option.GetATMPutRecent(0);
var PutPrice = Option.GetAskByCode(PutCode, 2);
A1.OrderBuy(PutCode, 1, PutPrice, 0);
SEcnt = 1;
//3번 타이머 5초 셋팅
Main.SetTimer(3,5000);
}
if (Signal.signalKind == 4 )
{
Main.MessageList("매도청산발생");
var SxPrice = Option.GetAskByCode(PutCode, 2);
A1.OrderSell(PutCode, Vo, SxPrice, 0);
SXcnt = 1;
//보유수량이 2계약 이상이면
if (MaxExitVol >= 2)
//4번 타이머 5초 셋팅
Main.SetTimer(4,5000);
}
}
//타이머 동작
function Main_OnTimer(nEventID)
{
//1번 타이머 동작할 때마다
if (nEventID == 1)
{
//카운트
BEcnt = BEcnt+1;
//카운트가 최대진입수량 이하이면
if (BEcnt <= MaxEntryVol)
{
//1계약씩 추가매수
A1.OrderBuy(Code, 1, Option.GetAskByCode(Code,2), 0);
}
//최대진입수량에 도달하면 타이머종료
if (BEcnt == MaxEntryVol)
{
Main.KillTimer(1);
}
}
//2번타이머 동작할때마다
if (nEventID == 2)
{
//카운트
BXcnt = BXcnt+1;
//카운트가 보유수량 이하이면
if (BXcnt <= MaxExitVol)
{
//1계약씩 매도주문
A1.OrderSell(Code, 1, Option.GetBidByCode(Code,2), 0);
}
//카운트가 보유수량에 도달하면 타이머 종료
if (BXcnt == MaxExitVol)
{
Main.KillTimer(2);
}
}
if (nEventID == 3)
{
SEcnt = SEcnt+1;
if (SEcnt <= MaxEntryVol)
{
A1.OrderBuy(Code, 1, Option.GetAskByCode(Code,2), 0);
}
if (SEcnt == MaxEntryVol)
{
Main.KillTimer(3);
}
}
if (nEventID == 4)
{
SXcnt = SXcnt+1;
if (SXcnt <= MaxExitVol)
{
A1.OrderSell(Code, 1, Option.GetBidByCode(Code,2), 0);
}
if (SXcnt == MaxExitVol)
{
Main.KillTimer(4);
}
}
}
2018-12-09
2939
글번호 224670
답변완료
양매도 수식 추가
안녕하세요
양매도 진입 수식에 다음 2가지 방식의 추가수식 부탁드립니다.
<< 방식1. 전일data 조건 추가 >>
1) 전일 종가기준으로 각행사가별 콜,풋 가격중 동일 행사가의 콜풋 양합의 최저치를 계산
2) 당일 진입봉 시점에서 각행사가별 콜,풋 가격중 동일 행사가의 콜풋 양합의 최저치를 계산
3) 진입수식에 2)값이 1)값보다 작을 때라는 조건 추가 <--- 진입봉 startN
'전일 콜풋 동일 행사가의 양합최저치 > 당일 진입시점 콜풋 동일 행사가의 양합최저치' 입니다.
<< 방식2. 이전봉data 조건 추가 >>
1) 당일 진입봉 이전3개봉 각각의 각행사가별 콜,풋 가격중 동일 행사가의 콜풋 양합의 최저치를 계산한 후, 3개값의 평균을 구함
2) 당일 진입봉 시점에서 각행사가별 콜,풋 가격중 동일 행사가의 콜풋 양합의 최저치를 계산
3) 진입수식에 2)값이 1)값보다 작을 때라는 조건 추가 <--- 진입봉 startN
'당일 진입봉이전 3개봉 콜풋 동일 행사가 각각의 양합최저치의 평균 > 당일 진입시점 동일 행사가의 양합최저치' 입니다.
** 마지막으로, 현재 진입후 E1 = 0 에서 청산시 E1 = 1 로 전환되는데
이럴경우 실제로 진입수량이 없음에도 불구하고 청산이 발생하고 있습니다.
1) 진입수량이 완전히 체결된 경우만 청산이 발생하도록 하고
2) 청산수량이 완전히 체결된 후, 조건에 의해서 재진입이 가능하도록
수식 변경 부탁드립니다.
3) 동일계좌에 여러 시스템이 운용되고 있어서, 해당 시스템 수량에 한합니다.
** 글쓰기가 안되서, OnUp*ateMarket, lUp*ateID 로 표시했습니다.
이상입니다.
감사합니다 !!
----------------------------
// YT 'dayindex' 지표 사용
//내부변수지정
var C1,E1;
var SellC_code;
var SellP_code;
//ATM-50~+50까지 옵션종목의 가격과 코드를 담을 배열변수
var CPrice = new Array(101);
var CCode = new Array(101);
var PPrice = new Array(101);
var PCode = new Array(101);
//가격 0.00이상~UpLt이하의 옵션중 최고가 콜옵션,풋옵션 저장변수
var MaxCall;
var MaxCallCode;
var MaxPut;
var MaxPutCode;
//콜옵션,풋옵션 베팅수량변수
var CVol;
var PVol;
// 현재가 추적
var Chart1,ChartReq;
function Main_OnStart()
{
//차트설정 MarketData1종목 1분봉 1개
var SetChart = new ReqChartItem(MarketData1.code, 1, CHART_PERIOD_MINUTE,500,CHART_REQCOUNT_BAR,false, false);
//지표설정 (dayindex라는 이름의 지표적용)
var SetInd = new IndicatorInfo("dayindex");
//차트생성
Main.ReqChartEx(SetChart,null,new Array(SetInd));
ChartReq = false;
Main.MessageLog("Start");
}
function Main_OnRcvChartEx(ChartEx)
{
Chart1 = ChartEx;
ChartReq = true;
}
function Main_OnBarAppended(ChartEx, nData)
{
Main.MessageList("봉완성",ChartEx.GetIndicatorData("dayindex",1,0));
if (ChartEx.GetCode(1) == MarketData1.code)
{
//startN번째 봉 완성
if (ChartEx.GetIndicatorData("dayindex",1,0) == startN && MarketData1.time < 1500000000)
{
C1 = Chart1.GetClose(1,1);
//UpLt보다 작은 종목의 코드와 가격을 배열에 저장 ---------------------> start
for(var i = -50; i <= 50; i++)
{
if (Option.GetCurrent(0,i) < UpLt && Option.GetCurrent(0,i) > 0) //---> UpLt
{
CPrice[50+i] = Option.GetCurrent(0,i);
CCode[50+i] = Option.GetATMCallRecent(i);
}
else
{
CPrice[50+i] = -1;
CCode[50+i] = -1;
}
if (Option.GetCurrent(1,i) < UpLt && Option.GetCurrent(1,i) > 0) //---> UpLt
{
PPrice[50+i] = Option.GetCurrent(1,i);
PCode[50+i] = Option.GetATMPutRecent(i);
}
else
{
PPrice[50+i] = -1;
PCode[50+i] = -1;
}
}
//저장된 CPrice,PPrice값중 최고값 계산
MaxCall = -1;
MaxCallcode = -1;
MaxPut = -1;
MaxPutcode = -1;
for(var A = 0; A <= 100; A++)
{
if (CPrice[A] > MaxCall)
{
MaxCall = CPrice[A];
MaxCallcode = CCode[A];
}
if (PPrice[A] > MaxPut)
{
MaxPut = PPrice[A];
MaxPutcode = PCode[A];
}
} //-------------------------------------------------------------------> end
SellC_code = MaxCallcode;
var SellC_price = MaxCall;
CVol = Math.floor(SeedMoney/(SellC_price*100000*MultiN)); //---> SeedMoney이내 콜매도
var SellCC_price = Option.GetBidByCode(SellC_code,5); //---> Call 5호가 매도
SellP_code = MaxPutcode;
var SellP_price = MaxPut;
PVol = Math.floor(SeedMoney/(SellP_price*100000*MultiN)); //---> SeedMoney이내 풋매도
var SellPP_price = Option.GetBidByCode(SellP_code,5); //---> Put 5호가 매도
if (MaxCall > 1 && MaxPut > 1 && MaxCall+MaxPut > 2.5)
{
Account1.OrderSell(SellC_code, CVol, SellCC_price-0.3, 0);
Account1.OrderSell(SellP_code, PVol, SellPP_price-0.3, 0);
}
Main.MessageList("양매도 진입");
E1 = 0;
}
//endN번째봉 청산
if (ChartEx.GetIndicatorData("dayindex",1,0) == endN && E1 == 0)
{
E1 = 1;
Main.MessageList("End 청산");
var xC_price = Option.GetAskByCode(SellC_code,5); //---> Call 5호가 청산
Account1.OrderBuy(SellC_code, CVol, xC_price+0.3, 0);
var xP_price = Option.GetAskByCode(SellP_code,5); //---> Put 5호가 청산
Account1.OrderBuy(SellP_code, PVol, xP_price+0.3, 0);
}
}
}
function Main_OnUp*ateMarket(sItemCode, lUp*ateID)
{
if (ChartReq == true && Chart1.GetCode(1) == MarketData1.code && lUp*ateID == 20001)
{
//startN~endN번째봉 가격차 청산 - 현재가 기준
if (Chart1.GetIndicatorData("dayindex",1,0) > startN && Chart1.GetIndicatorData("dayindex",1,0) < endN &&
Math.abs(MarketData1.current-C1) >= 가격차 && E1 == 0)
{
E1 = 1;
Main.MessageList("가격차 청산");
var xC_price = Option.GetAskByCode(SellC_code,5); //---> Call 5호가 청산
Account1.OrderBuy(SellC_code, CVol, xC_price+0.3, 0);
var xP_price = Option.GetAskByCode(SellP_code,5); //---> Put 5호가 청산
Account1.OrderBuy(SellP_code, PVol, xP_price+0.3, 0);
}
}
}
2018-12-13
2872
글번호 224669
답변완료
엑셀 연동 및 주문관련
수고하십니다.
다음과 같이 구현하려고 합니다.
1. MACD Signal 중 날짜와 시간, 종가, 시그널 수치를 각 180분 종가를 바로 엑셀로 받고 싶습니다.(9시, 11시, 14시, 17시, 20시, 23시, 02시, 05시, 8시)
2. 엑셀작업을 통해 특정 셀에 매수 또는 매도 결과 값이 나오게 합니다.
3. 특정 셀 값을 180분 간격으로 yes global로 발신하여 주문을 합니다. 아래는 11시에 매수할 경우의 예입니다.
if sTime == 110000 Then
Buy();
if MarketPosition == 1 Then
ExitLong("bx",AtStop,EntryPrice-PriceScale*10);
if sTime == 140000 Then
{
ExitLong();
ExitShort();
}
4. 위의 동작을 완전자동으로 구현할 수 있는지 궁금하고 관련 수식을 부탁드립니다.
2018-11-12
2777
글번호 224661