예스스탁
예스스탁 답변
2022-04-05 16:56:17.0
안녕하세요
예스스탁입니다.
1
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
현재 해당식에서 위 내용을 보시면 매도주문시에 수량이 잔고의 전체수량으로 되어 있습니다.
기존식이 매도조건만족시 전량매도를 염두에 두고 작성된 내용입니다.
실제 매수신호수량과 체결수량이 다를수 있으므로
매도신호발생시에 발생한 수량과 잔고수량을 비교해서 더 낮은 수량으로 집행되게 수정하시면 됩니다.
2
내용상 Main.MessageList가 사용되어야 하는데 Main.MessageLog함수가 사용되어 수정했습니다.
3 수정한 식입니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageList("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
var XV = Math.min(Signal.count,Account1.Balance.count);
if (XV > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),XV,MK[ii].current,0);
Main.MessageList("매도주문 : ",Main.GetOrderCode(Signal.code),XV,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
즐거운 하루되세요
> oldforce 님이 쓴 글입니다.
> 제목 : 챠트 매매 신호 중에서 분할 매도시 에러
> 아래 내용은 게시판에서 질문과 답변 중에 나왔던 내용 인데요
주요설명은 정정주문매매에 관련된 내용입니다.
파워종목검색후--->확장차트생성--->차트신호발생--->차트신호 매수/매도 하는 내용인데요
여기서...
궁굼한 점이 매수는 차트 신호가 발생 되면 실제 매수가 이루어 집니다.
매수금액은 사용자 변수처리 하거나 코드에서 직업 입력할 수 있는 내용 이구요
요청내용
1.실제 차트에 적용된 시스템식에 설정해 놓은 설정 되로 매수/매도가 되야 하는데
시스템식에서는 매수는 한번, 매도는 4회 분할 매도로 설정됨
매수--->설정해 놓은 매수금액 만큼 실제 매수가 됩니다
매도--->전량매도가 됩니다
--->전 시스템식에 지표에 따라서 분할매도가 되도록 만들었는데 예스스팟 식에서는 전량매도가 됩니다.
차트에서 발생되는 신호에 갯수가 포함 되어 있는걸로 알고 있는데요
이것을 인식 시킬려면 Signal.count코드를 넣어주면 되는걸로 매뉴얼에 설명 되어 있는데
아래 가이드식에서는 Signal.count코드를 넣을 수가 없는거 같아요
제가 예스스팟은 이제 공부 하는 중 이라서 아래 가이드 식을 수정 하기가 힘드네요
아래 가이드식에서
실제 매도신호 부분에서 시스템식 설정 되로 분할매도가 인식 할 수 있게
시스템식 수정 부탁 드려요.
2.Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
---> TypeError:MessageLog:1개의 매개변수가 필요합니다
에러가 납니다.
이부분도 수정 부탁드려요
////////////////////////////////////////////////////////////////////////////////////
아래 가이드 내용 참고하셔서 수정보완해 사용하시기 바랍니다.
현재가나 매도/매수호가에 주문하기 위해서는
각 종목의 종목객체가 필요합니다.
차트객체 생성시에 동시에 해당 종목에 대한 종목객체도 같이 생성되게 추가했습니다.
차트객체(CT), 종목객체(MK), 타이머횟수(Timer)는 모두 같은 배열번호에 정보가 담기게 됩니다.
예를 들어 CT[10]차트에서 신호가 발생하면 10번 번호로 타이머를 셋팅하고 정정을 수행합니다.
기존에 검색주기 타이머는 1번에서 999번으로 변경했습니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
if (Account1.Balance.count > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
Main.MessageLog("매도주문 : ",Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
oldforce
2022-04-06 10:01:52.0
답변 감사 드려요...
실제 테스트를 해볼께요
실제 테스트를 해보니까요... 매수 주문체결은 문제 없는거 같은데요
매도 주문체결쪽에서 확장차트신호에 따른 매도가 되지 못하고 있네요
아래 코드 부분에서 호가 단위를 체결되도록 루프를 돌릴수 있나요?
//////////////////////////////////////////////////////////////////////////////////
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
////////////////////////////////////////////////////////////////////////////////
수정좀 부탁드려요...
> 예스스탁 님이 쓴 글입니다.
> 제목 : Re : 챠트 매매 신호 중에서 분할 매도시 에러
>
안녕하세요
예스스탁입니다.
1
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
현재 해당식에서 위 내용을 보시면 매도주문시에 수량이 잔고의 전체수량으로 되어 있습니다.
기존식이 매도조건만족시 전량매도를 염두에 두고 작성된 내용입니다.
실제 매수신호수량과 체결수량이 다를수 있으므로
매도신호발생시에 발생한 수량과 잔고수량을 비교해서 더 낮은 수량으로 집행되게 수정하시면 됩니다.
2
내용상 Main.MessageList가 사용되어야 하는데 Main.MessageLog함수가 사용되어 수정했습니다.
3 수정한 식입니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageList("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
var XV = Math.min(Signal.count,Account1.Balance.count);
if (XV > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),XV,MK[ii].current,0);
Main.MessageList("매도주문 : ",Main.GetOrderCode(Signal.code),XV,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
즐거운 하루되세요
> oldforce 님이 쓴 글입니다.
> 제목 : 챠트 매매 신호 중에서 분할 매도시 에러
> 아래 내용은 게시판에서 질문과 답변 중에 나왔던 내용 인데요
주요설명은 정정주문매매에 관련된 내용입니다.
파워종목검색후--->확장차트생성--->차트신호발생--->차트신호 매수/매도 하는 내용인데요
여기서...
궁굼한 점이 매수는 차트 신호가 발생 되면 실제 매수가 이루어 집니다.
매수금액은 사용자 변수처리 하거나 코드에서 직업 입력할 수 있는 내용 이구요
요청내용
1.실제 차트에 적용된 시스템식에 설정해 놓은 설정 되로 매수/매도가 되야 하는데
시스템식에서는 매수는 한번, 매도는 4회 분할 매도로 설정됨
매수--->설정해 놓은 매수금액 만큼 실제 매수가 됩니다
매도--->전량매도가 됩니다
--->전 시스템식에 지표에 따라서 분할매도가 되도록 만들었는데 예스스팟 식에서는 전량매도가 됩니다.
차트에서 발생되는 신호에 갯수가 포함 되어 있는걸로 알고 있는데요
이것을 인식 시킬려면 Signal.count코드를 넣어주면 되는걸로 매뉴얼에 설명 되어 있는데
아래 가이드식에서는 Signal.count코드를 넣을 수가 없는거 같아요
제가 예스스팟은 이제 공부 하는 중 이라서 아래 가이드 식을 수정 하기가 힘드네요
아래 가이드식에서
실제 매도신호 부분에서 시스템식 설정 되로 분할매도가 인식 할 수 있게
시스템식 수정 부탁 드려요.
2.Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
---> TypeError:MessageLog:1개의 매개변수가 필요합니다
에러가 납니다.
이부분도 수정 부탁드려요
////////////////////////////////////////////////////////////////////////////////////
아래 가이드 내용 참고하셔서 수정보완해 사용하시기 바랍니다.
현재가나 매도/매수호가에 주문하기 위해서는
각 종목의 종목객체가 필요합니다.
차트객체 생성시에 동시에 해당 종목에 대한 종목객체도 같이 생성되게 추가했습니다.
차트객체(CT), 종목객체(MK), 타이머횟수(Timer)는 모두 같은 배열번호에 정보가 담기게 됩니다.
예를 들어 CT[10]차트에서 신호가 발생하면 10번 번호로 타이머를 셋팅하고 정정을 수행합니다.
기존에 검색주기 타이머는 1번에서 999번으로 변경했습니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
if (Account1.Balance.count > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
Main.MessageLog("매도주문 : ",Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
oldforce
2022-04-06 10:22:07.0
확장차트 매도 신호발생시 ===> 주문이 작동 하지 않아요
주문메세지를 보면===> 종목코드값 미확인(종목코드)
이렇게 나오네요...
확인좀 부탁드려요
> oldforce 님이 쓴 글입니다.
> 제목 : Re : Re : 챠트 매매 신호 중에서 분할 매도시 에러
> 답변 감사 드려요...
실제 테스트를 해볼께요
실제 테스트를 해보니까요... 매수 주문체결은 문제 없는거 같은데요
매도 주문체결쪽에서 확장차트신호에 따른 매도가 되지 못하고 있네요
아래 코드 부분에서 호가 단위를 체결되도록 루프를 돌릴수 있나요?
//////////////////////////////////////////////////////////////////////////////////
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
////////////////////////////////////////////////////////////////////////////////
수정좀 부탁드려요...
> 예스스탁 님이 쓴 글입니다.
> 제목 : Re : 챠트 매매 신호 중에서 분할 매도시 에러
>
안녕하세요
예스스탁입니다.
1
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
현재 해당식에서 위 내용을 보시면 매도주문시에 수량이 잔고의 전체수량으로 되어 있습니다.
기존식이 매도조건만족시 전량매도를 염두에 두고 작성된 내용입니다.
실제 매수신호수량과 체결수량이 다를수 있으므로
매도신호발생시에 발생한 수량과 잔고수량을 비교해서 더 낮은 수량으로 집행되게 수정하시면 됩니다.
2
내용상 Main.MessageList가 사용되어야 하는데 Main.MessageLog함수가 사용되어 수정했습니다.
3 수정한 식입니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageList("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
var XV = Math.min(Signal.count,Account1.Balance.count);
if (XV > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),XV,MK[ii].current,0);
Main.MessageList("매도주문 : ",Main.GetOrderCode(Signal.code),XV,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
즐거운 하루되세요
> oldforce 님이 쓴 글입니다.
> 제목 : 챠트 매매 신호 중에서 분할 매도시 에러
> 아래 내용은 게시판에서 질문과 답변 중에 나왔던 내용 인데요
주요설명은 정정주문매매에 관련된 내용입니다.
파워종목검색후--->확장차트생성--->차트신호발생--->차트신호 매수/매도 하는 내용인데요
여기서...
궁굼한 점이 매수는 차트 신호가 발생 되면 실제 매수가 이루어 집니다.
매수금액은 사용자 변수처리 하거나 코드에서 직업 입력할 수 있는 내용 이구요
요청내용
1.실제 차트에 적용된 시스템식에 설정해 놓은 설정 되로 매수/매도가 되야 하는데
시스템식에서는 매수는 한번, 매도는 4회 분할 매도로 설정됨
매수--->설정해 놓은 매수금액 만큼 실제 매수가 됩니다
매도--->전량매도가 됩니다
--->전 시스템식에 지표에 따라서 분할매도가 되도록 만들었는데 예스스팟 식에서는 전량매도가 됩니다.
차트에서 발생되는 신호에 갯수가 포함 되어 있는걸로 알고 있는데요
이것을 인식 시킬려면 Signal.count코드를 넣어주면 되는걸로 매뉴얼에 설명 되어 있는데
아래 가이드식에서는 Signal.count코드를 넣을 수가 없는거 같아요
제가 예스스팟은 이제 공부 하는 중 이라서 아래 가이드 식을 수정 하기가 힘드네요
아래 가이드식에서
실제 매도신호 부분에서 시스템식 설정 되로 분할매도가 인식 할 수 있게
시스템식 수정 부탁 드려요.
2.Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
---> TypeError:MessageLog:1개의 매개변수가 필요합니다
에러가 납니다.
이부분도 수정 부탁드려요
////////////////////////////////////////////////////////////////////////////////////
아래 가이드 내용 참고하셔서 수정보완해 사용하시기 바랍니다.
현재가나 매도/매수호가에 주문하기 위해서는
각 종목의 종목객체가 필요합니다.
차트객체 생성시에 동시에 해당 종목에 대한 종목객체도 같이 생성되게 추가했습니다.
차트객체(CT), 종목객체(MK), 타이머횟수(Timer)는 모두 같은 배열번호에 정보가 담기게 됩니다.
예를 들어 CT[10]차트에서 신호가 발생하면 10번 번호로 타이머를 셋팅하고 정정을 수행합니다.
기존에 검색주기 타이머는 1번에서 999번으로 변경했습니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
if (Account1.Balance.count > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
Main.MessageLog("매도주문 : ",Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
예스스탁
예스스탁 답변
2022-04-07 15:29:28.0
안녕하세요
예스스탁입니다.
Main.GetOrderCode(Signal.count.code)
매도주문함수에 종목코드가 잘못지정되어 있었습니다. 아래와 같이 수정해 드립니다.
Main.GetOrderCode(Signal.code)
수정한 식입니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageList("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
var XV = Math.min(Signal.count,Account1.Balance.count);
if (XV > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.code),XV,MK[ii].current,0);
Main.MessageList("매도주문 : ",Main.GetOrderCode(Signal.code),XV,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
즐거운 하루되세요
> oldforce 님이 쓴 글입니다.
> 제목 : Re : Re : Re : 챠트 매매 신호 중에서 분할 매도시 에러
>
확장차트 매도 신호발생시 ===> 주문이 작동 하지 않아요
주문메세지를 보면===> 종목코드값 미확인(종목코드)
이렇게 나오네요...
확인좀 부탁드려요
> oldforce 님이 쓴 글입니다.
> 제목 : Re : Re : 챠트 매매 신호 중에서 분할 매도시 에러
> 답변 감사 드려요...
실제 테스트를 해볼께요
실제 테스트를 해보니까요... 매수 주문체결은 문제 없는거 같은데요
매도 주문체결쪽에서 확장차트신호에 따른 매도가 되지 못하고 있네요
아래 코드 부분에서 호가 단위를 체결되도록 루프를 돌릴수 있나요?
//////////////////////////////////////////////////////////////////////////////////
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
////////////////////////////////////////////////////////////////////////////////
수정좀 부탁드려요...
> 예스스탁 님이 쓴 글입니다.
> 제목 : Re : 챠트 매매 신호 중에서 분할 매도시 에러
>
안녕하세요
예스스탁입니다.
1
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
현재 해당식에서 위 내용을 보시면 매도주문시에 수량이 잔고의 전체수량으로 되어 있습니다.
기존식이 매도조건만족시 전량매도를 염두에 두고 작성된 내용입니다.
실제 매수신호수량과 체결수량이 다를수 있으므로
매도신호발생시에 발생한 수량과 잔고수량을 비교해서 더 낮은 수량으로 집행되게 수정하시면 됩니다.
2
내용상 Main.MessageList가 사용되어야 하는데 Main.MessageLog함수가 사용되어 수정했습니다.
3 수정한 식입니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageList("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
var XV = Math.min(Signal.count,Account1.Balance.count);
if (XV > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),XV,MK[ii].current,0);
Main.MessageList("매도주문 : ",Main.GetOrderCode(Signal.code),XV,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
즐거운 하루되세요
> oldforce 님이 쓴 글입니다.
> 제목 : 챠트 매매 신호 중에서 분할 매도시 에러
> 아래 내용은 게시판에서 질문과 답변 중에 나왔던 내용 인데요
주요설명은 정정주문매매에 관련된 내용입니다.
파워종목검색후--->확장차트생성--->차트신호발생--->차트신호 매수/매도 하는 내용인데요
여기서...
궁굼한 점이 매수는 차트 신호가 발생 되면 실제 매수가 이루어 집니다.
매수금액은 사용자 변수처리 하거나 코드에서 직업 입력할 수 있는 내용 이구요
요청내용
1.실제 차트에 적용된 시스템식에 설정해 놓은 설정 되로 매수/매도가 되야 하는데
시스템식에서는 매수는 한번, 매도는 4회 분할 매도로 설정됨
매수--->설정해 놓은 매수금액 만큼 실제 매수가 됩니다
매도--->전량매도가 됩니다
--->전 시스템식에 지표에 따라서 분할매도가 되도록 만들었는데 예스스팟 식에서는 전량매도가 됩니다.
차트에서 발생되는 신호에 갯수가 포함 되어 있는걸로 알고 있는데요
이것을 인식 시킬려면 Signal.count코드를 넣어주면 되는걸로 매뉴얼에 설명 되어 있는데
아래 가이드식에서는 Signal.count코드를 넣을 수가 없는거 같아요
제가 예스스팟은 이제 공부 하는 중 이라서 아래 가이드 식을 수정 하기가 힘드네요
아래 가이드식에서
실제 매도신호 부분에서 시스템식 설정 되로 분할매도가 인식 할 수 있게
시스템식 수정 부탁 드려요.
2.Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
---> TypeError:MessageLog:1개의 매개변수가 필요합니다
에러가 납니다.
이부분도 수정 부탁드려요
////////////////////////////////////////////////////////////////////////////////////
아래 가이드 내용 참고하셔서 수정보완해 사용하시기 바랍니다.
현재가나 매도/매수호가에 주문하기 위해서는
각 종목의 종목객체가 필요합니다.
차트객체 생성시에 동시에 해당 종목에 대한 종목객체도 같이 생성되게 추가했습니다.
차트객체(CT), 종목객체(MK), 타이머횟수(Timer)는 모두 같은 배열번호에 정보가 담기게 됩니다.
예를 들어 CT[10]차트에서 신호가 발생하면 10번 번호로 타이머를 셋팅하고 정정을 수행합니다.
기존에 검색주기 타이머는 1번에서 999번으로 변경했습니다.
var 검색주기 = 120; //120초
var 최대종목수 = 50;
var ItemList = []; //검색 후 생성할 종목의 리스트를 저장하기 위한 배열변수
var CT = []; //차트객체 배열선언변수
var MK = []; //종목객체 배열선언변수
var ID = [];
var Num = [];
var Timer = [];//타이머햇수 배열변수 선언
var HHMMSS,req;
//예스스팟 시작
function Main_OnStart()
{
CTcnt = 0; //지역변수 선언 차트객체 생성 숫자를 표시
Main.SetTimer(999, 5000); //타이머를 실행 ===> 5000을 입력하면 5초마다 이벤트가 발생
Main.MessageList("YesSpot start");
}
function Main_OnTimer(nEventID) //타이머 설정 시 발생하는 이벤트===>SetTimer에서 설정한 타이머 이벤트 ID
{
var d = new Date();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//9시 이후에 2분간격으로 종목검색 확장차트가 50개 이하일때 반복적으로 검색
if (nEventID == 999 && HHMMSS >= 090000 && CT.length < 50)
{
Main.KillTimer(999);
Main.MessageList("종목검색 요청");
//사용자 파워검색식
Main.ReqPowerSearch("A_2022_BIMS_신호검색종목_Ver1.2")
}
if (nEventID < 최대종목수) //최대종목수 전역변수에 50을 할당===>반복작업이 50개 이하일때
{
Timer[nEventID] = Timer[nEventID]+1;
//1차 정정
if (Timer[nEventID] == 1)
{
//전체 미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills(); //미체결리스트 개수
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결 종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//주문가격과 현재가가 다르면(같으면 정정불가)
if (Account1.Unfill.price != MK[nEventID].current)
{
//현재가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].current);
}
}
}
}
if (Timer[nEventID] == 2)
{
//타이머가 2번 동작했으므로 타이머는 종료
Main.KillTimer(Timer[nEventID]);
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//타이머와 같은 미체결종목을 찾아
if (Account1.Unfill.code == CT[nEventID].GetCode && Account1.Unfill.count > 0)
{
//매수주문이고 주문가격과 매도1호가가 다르면(같으면 정정불가), Unfill:미체결객체, orderKind:주문구분정수(1 : 매도, 2 : 매수)
if (Account1.Unfill.orderKind == 2 && Account1.Unfill.price != MK[nEventID].Ask(1))
{
//매도1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Ask(1)); //OrderReplacePrice:가격정정
}
//매도주문이고 주문가격과 매수1호가가 다르면(같으면 정정불가)
if (Account1.Unfill.orderKind == 1 && Account1.Unfill.price != MK[nEventID].Bid(1))
{
//매수1호가로 정정
Account1.OrderReplacePrice(Account1.Unfill.orderNum, MK[nEventID].Bid(1));
}
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.MessageList("종목검색 완료 nCount : ",nCount);
if (nCount > 0)
{
ItemList = [];
//첫검색일때
if (CT.length == 0)
{
ItemList = aItemList;
}
else //두번쨰 이후(차트가 만들어진 종목을 제외하고 새로운 종목만 집계)
{
for (var i = 0; i < nCount; i++ )
{
var add = true;
for (var x = 0; x < CT.length; x++ )
{
if (aItemList[i] == CT[x].GetCode(1))
{
add = false;
}
}
if (add == true)
{
ItemList.push(aItemList[i]);
}
}
}
Main.MessageList("종목검색 완료 ItemList :",ItemList.length);
//집계된 종목이 1개 이상이면 순차적으로 차트객체 요청
if (ItemList.length > 0 && CT.length < 50)
{
req = 0;
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
//var ChartSet = new ReqChartItem(BL[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false); //참고
var ChartSet = new ReqChartItem(ItemList[req],1,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null,TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
function Main_OnRcvChartEx(ChartEx)
{
if (ItemList[req] == ChartEx.GetCode(1))
{
CT[CTcnt] = ChartEx;
Main.MessageList(CTcnt,"차트객체생성 : ",CT[CTcnt].GetCode(1));
Main.ReqMarketData(ItemList[req]);
Main.MessageList(CTcnt,"종목객체요청 : ",ItemList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (ItemList[req] == MarketData.code)
{
Main.MessageList(CTcnt,"종목객체생성 : ",MarketData.code);
MK[CTcnt] = MarketData;
CTcnt = CTcnt +1;
req = req + 1;
if (req < ItemList.length && CT.length < 50)
{
var TradeSet = new SystemTradeInfo(TRADE_FIXCOUNT,
4, // 거래수량
123456789, // 자산
1, // 단위수량
0, 0, CALCMETHOD_PERCENT, // 진입/청산 수수료
0, 0, CALCMETHOD_POINT, // 진입/청산 슬리피지
PYRAMIDING_ENTRY, // 피라미딩 설정여부
100000, // 최대진입수량
10); // 최대진입횟수
var StopSet = new SystemStopInfo(//new StopLoss(4, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopTrailing(2, 5, CALCMETHOD_PERCENT, 0),
//new StopProfitTarget(10, CALCMETHOD_PERCENT, 0xFFDA93),
//new StopInactivity(0.5, 6, CALCMETHOD_PERCENT, 0xFFDA93),
new StopEndOfDay(151500)
);
var ChartSet = new ReqChartItem(ItemList[req], 1, CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
var SystemSet = new SystemInfo("BIMS_분봉_매매신호", YL_TYPE_NORMAL, null, TradeSet); //사용자 전략
Main.MessageList("현재차트갯수 : ",CT.length);
Main.MessageList(req,"차트객체요청 : ",ItemList[req]);
Main.ReqChartEx(ChartSet,SystemSet);
}
else
{
Main.MessageList("Search1 차트객체요청종료");
for (var i = 0; i < CT.length; i++)
{
Main.MessageList(CT[i].GetCode(1),MK[i].code);
}
//만들어진 차트가 50개 이하이면
if (CT.length < 최대종목수)
{
Main.SetTimer(999, 검색주기*1000);//120초
}
}
}
}
//신호발생 로직
function Main_OnRiseSignal(ChartEx, Signal)
{
//신호발생 종목에 대해 잔고셋팅
Account1.SetBalance(Main.GetOrderCode(Signal.code),0);
//신호발생한 차트객체의 배열번호 찾음
var ii;
if (CT.length > 0)
{
for (var i = 0; i < CT.length; i++)
{
if(CT[i].GetCode(1) == ChartEx.GetCode(1))
{
ii = i;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//신호발생후 매수 매도 로직 시작
//매매 시스템식에서 설정한 값으로 이행 되는 로직
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//매수신호이고 잔고가 없을때만 현재가 매수
if (Signal.signalKind == 1 && Account1.Balance.count == 0)
{
//EntryVol 금액 시장가 매수 EntryVol=투입금액
//var Vol = Math.floor(투입금액/Signal.price);
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
Account1.OrderBuy(Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current,0);
Main.MessageLog("매수주문 : ",Main.GetOrderCode(Signal.code),Math.floor(투입금액/ChartEx.GetClose(1,0)),MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
if (Signal.signalKind == 2)
{
//전체미체결주문 갯수
var num = Account1.GetTheNumberOfUnfills();
//전체 미체결수 만큼 루프를 돌면서
for (var i = 0; i < num; i++)
{
//미체결을 하나씩 셋팅하고
Account1.SetUnfill(i);
//미체결종목이 신호종목과 같고 미체결수량이 있으면
if (Account1.Unfill.code == Main.GetOrderCode(Signal.code) && Account1.Unfill.count > 0)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
//잔고수량만큼만 매도
if (Account1.Balance.count > 0)
{
//신호에서 지정한 매도 수량에 따른 매도 로직 수정 필요 중요함
//Account1.OrderSell(Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current,0);
Account1.OrderSell(Main.GetOrderCode(Signal.count.code),Account1.Balance.count,MK[ii].current,0);
Main.MessageLog("매도주문 : ",Main.GetOrderCode(Signal.code),Account1.Balance.count,MK[ii].current);
if (ii >= 0)
{
Main.SetTimer(ii,60000);
Timer[ii] = 0;
}
}
}
}
oldforce
2022-04-08 11:29:33.0
예스스팟의 이해 부족 으로 인해서 ... 원하는 결과가 안 나왔던 거 같네요.
매뉴얼 서너번 정독은 필수로 해야 할거 같네요^^
친절한 답변 감사 드려요.