커뮤니티

관심종목 중에서 매수, 계좌보유종목수 제한 등에 대해 문의합니다.

프로필 이미지
늘그렇게
2026-03-08 16:18:18
558
글번호 230977
답변완료

전체 종목을 대상으로 써치하여 종목을 매수하는 프로그램입니다.

1. 미리 관심종목 그룹에 등록해둔 특정관심종목 폴더에서 중에서 종목을 써치해서 매수하게 하고 싶습니다.

2. 1차 매수(지정금액01) 후 당일 내에 매수금액에서 2%하락 시 2차매수(지정금액01)를  하고, 1.2차 평균매수가가 3%하락시 3차매수(지정금액02)를 하는 로직을 만들고 싶습니다.

3. 1차 매수(지정금액01) 후 당일이 아닌 다음날에 평균매수가 대비 5%하락 시 2차매수(지정금액01)를  하고, 평균매수가 대비 다시 5%하락시 3차매수(지정금액02)를 하는 로직을 만들고 싶습니다.

4. 해당 계좌의 보유 종목수를 제한하여 매수하고자 합니다.(계좌에 20종목만 보유, 1 종목 매도하면 1종목 매수)

5. NXT에서도 자동매매가 가능하게 하고 싶습니다.

부탁드립니다.


=====================

var M_Buy = 500000;//종목당 1회 매수금액

var OPEN_T = 090000;

var CLOSE_T = 150000;

var SearchName = "224이평 돌파 및 지지";  //PowerSearch Name

var 당일매수제한종목수 = 10, BuyCount;

var timer = 5;   //매수 매도 초(시간) 간격

var Earning_Rate = 1.3;  //계좌평가금액이 스팟시작시 평가금액대비 30% 이상이면 전종목 전량매도

var Trailing_Stop  = 0.1;  // 종목당 -10%이하 손실이면 전량 손절

var Earning_Sale  = 1.25;   // 종목당 25%이상 수익이면 전량 익절

var OrderList = [];

var MKList = [];

var req;



function Main_OnStart()

{

      //1번 타이머, 5초

   Main.SetTimer(1, timer*1000);

      // 오늘 매수한 종목 관리 배열 초기화

   MKList = [];

      //스팟 시작시 잔고평가금액

   V1 = Account1.GetBalanceETCinfo(100);   

   BuyCount = 0;

}


function Main_OnTimer(nEventID)

{

   var d = new Date();

   YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate();

   HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();


   if (nEventID == 1 && HHMMSS >= OPEN_T && HHMMSS < CLOSE_T && BuyCount < 당일매수제한종목수)

   {

      //종목검색 수행

      Main.ReqPowerSearch(SearchName)

      Main.MessageList("ReqPowerSearch1");      

   }


   if (nEventID == 1)

   {

      //계좌보유종수

      var num = Account1.GetTheNumberOfBalances();

            

      //9시~15시 15분  사이

      if (HHMMSS >= OPEN_T && HHMMSS < CLOSE_T)

      {

        //보유종목이 1개 이상

        if (num >= 1)

        {

          //계좌평가금액이 스팟시작시 평가금액대비 30% 이상이면 전종목 전량매도

          if (Account1.GetBalanceETCinfo(100) >= V1*Earning_Rate)

          {

            //1번 타이머 종료

            Main.KillTimer(1);


            //계좌리스트의 순서대로

            for (var i = 0; i < num; i++)

            {

              //잔고를 셋팅

              Account1.SetBalance(i);

              //수량이 있고 Earning_Rate(30%)수익이거나 손실이면 시장가 매도

              if (Account1.Balance.count > 0)

              {

                 Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);

              }

            }

          }                              

          else //아니면 개별종목 25% Earning_Sale, -10% Trailing_Stop 체크

          {

            //계좌리스트의 순서대로

            for (var i = 0; i < num; i++)

            {

              //잔고를 셋팅

              Account1.SetBalance(i);

              //수량이 있고 "Earning_Sale" 25% 수익이거나 "Trailing_Stop" -10% 손실이면 시장가 전량매도

              if (Account1.Balance.count > 0 &&

                 (Account1.Balance.current >= Account1.Balance.avgUnitCost*Earning_Sale ||

                  Account1.Balance.current <= Account1.Balance.avgUnitCost*Trailing_Stop))

              {

                 Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);

              }

            }

          }

        }

      }

   }


   if (nEventID == 2)

   {

      Main.ReqMarketData(OrderList[req]);

      Main.MessageList("ReqMarketData:",OrderList[req]);

   }

}


function Main_OnRcvItemList(aItemList, nCount)

{

   Main.KillTimer(1);

   Main.MessageList("aItemList:",aItemList);


   OrderList = [];


   if (nCount >= 1)

   {

      if (MKList.length == 0)

      {

         OrderList = aItemList;

      }

      else

      {

         for (var a = 0; a < nCount; a++)

         {

           var Add = true;

           for (var b = 0; b < MKList.length; b++)

           {

             if (aItemList[a] == MKList[b].code)

             {

               Add = false;            

             }

           }

             if (Add == true && !IsStockInAccount(aItemList[a]))

             {

                OrderList.push(aItemList[a]);      

             }

           }

        }

      }

   Main.MessageList("OrderList:",OrderList);       

   if (OrderList.length == 0)

   {

     Main.SetTimer(1, timer*1000);      

   }

   else

   {

     req = 0;

     Main.ReqMarketData(OrderList[req]);

     Main.MessageList("ReqMarketData:",OrderList[req]); ;

   }

}


function Main_OnRcvMarketData(MarketData)

{

    if (MarketData.code == OrderList[req])

    {

            MKList.push(MarketData);

            

      // 계좌에 같은 종목이 있는지 확인

      if (!IsStockInAccount(MarketData.code))

  {

if (BuyCount < 당일매수제한종목수)

{

            // 계좌에 잔고가 없는 경우에만 매수

   Account1.OrderBuy(MarketData.code,1,MarketData.Ask(1),0);  // 종목당 1주 지정가 매수주문

   // Account1.OrderBuy(MarketData.code,1,0,1); // 종목당 1주 시장가 매수주문

    // Account1.OrderBuy(MarketData.code,Math.floor(M_Buy/MarketData.Ask(1)),0,1); // 종목당 지정금액 시장가 매수주문

    //Account1.OrderBuy(MarketData.code,Math.floor(M_Buy/MarketData.Ask(1)),MarketData.Ask(1),0);   // 종목당 지정금액 지정가 매수주문

            

           Main.MessageList(MarketData.code + "주식을 매수합니다.");

    BuyCount = BuyCount+1;

}

    }

  else

  {

         Main.MessageList( MarketData.code + " 주식은 이미 계좌에 있으므로 매수하지 않습니다.");

   }

            

   req = req+1;      

   if (req < OrderList.length && BuyCount < 당일매수제한종목수)            

   {

         var aa = Main.ReqMarketData(OrderList[req]);

  Main.MessageList("ReqMarketData:",OrderList[req]); ;

         if (aa == -1)

         {

            Main.SetTimer(2, 15000);      

         }

     }            

     else

     {

         Main.SetTimer(1, timer*1000);

 Main.MessageList("당일종목수제한 도달 :",BuyCount,"/",당일매수제한종목수);       

      }

   }

}


function IsStockInAccount(stockCode)

{

   // 계좌에 해당 종목이 있는지 확인하는 함수

   var numberOfBalances = Account1.GetTheNumberOfBalances();

   for (var i = 0; i < numberOfBalances; i++)

   {

      Account1.SetBalance(i);

      if (stockCode == Account1.Balance.code)

  {

         return true; // 계좌에 같은 종목이 있으면 true 반환

      }

   }

   return false; // 계좌에 같은 종목이 없으면 false 반환

}

답변 2
프로필 이미지

예스스탁 예스스탁 답변

2026-03-23 15:07:22

안녕하세요
예스스탁입니다. 전화주시기 바랍니다. 02-3453-1060 즐거운 하루되세요
프로필 이미지

예스스탁 예스스탁 답변

2026-03-25 17:03:07

안녕하세요 예스스탁입니다. 1 전화가 없으셔서 식을 먼저 올려드립니다. 스팟 수식은 식작성의 가이드입니다. 수식 내용 참고해서 수정보완해 사용하시기 바랍니다. 수석에 주석을 붙여드립니다. 2 분할매수시에는 매수일이나 분할매수 횟수 등을 변수에 저장해서 관리하셔야 하는데 스팟은 실행중에만 변수의 값이 유효합니다. 수식을 적용을 해제하거나 재접속하면 모두 사라지게 됩니다. 그러므로 내부 파일에 SetUserValue로 필요한 값들을 저장하고 GetUserValue로 필요시 호출해서 사용하기 구현하셔야 합니다. 3 각 주문함수에 주석으로 nxt,sor처리에 대해 따라 남겨드립니다. 4 var 지정금액01 = 500000; var 지정금액02 = 500000; var OPEN_T = 090000; var CLOSE_T = 150000; var SearchName = "224이평 돌파 및 지지";//PowerSearch Name var 최대보유종목수 = 20; var 관심종목그룹명 = "관심그룹이름"; var timer = 5;//매수 매도 초(시간) 간격 var Earning_Rate = 1.3;//계좌평가금액이 스팟시작시 평가금액대비 30% 이상이면 전종목 전량매도 var Trailing_Stop= 0.1;// 종목당 -10%이하 손실이면 전량 손절 var Earning_Sale= 1.25;// 종목당 25%이상 수익이면 전량 익절 var OrderList = []; var MKList = []; var T, req; var icode = [],B = [], S = [],D = []; //스팟 시작 function Main_OnStart() { var d = new Date(); YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate(); HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds(); //T는 0이 초기값 T = 0; Main.MessageList(HHMMSS,T,"스팟시작"); //종목객체 담을 배열변수 초기화 MKList = []; //스팟 시작시 정산금 저장 V1 = Account1.GetBalanceETCinfo(100); //지정한 관심그룹에서 종목코드를 그져와 icode에 저장 var inum = Main.GetItemCountOfInterest(관심종목그룹명); if (inum > 0) { for (var i = 0; i < inum; i++) { icode.push(Main.GetItemCodeInInterest(관심종목그룹명, i)); } Main.MessageList("관심종목:",icode); } else Main.MessageList("관심종목 없음"); //UserValue파일에서 기존 저장한 주문정보들 가져와 각 변수에 저장 if (Main.GetUserValue("B") != "") { B = JSON.parse(Main.GetUserValue("B")); S = JSON.parse(Main.GetUserValue("S")); D = JSON.parse(Main.GetUserValue("D")); } //B에 저장된 종목코드가 없으면 타이머 동작 if (B.length == 0) { //1번 타이머, 5초 Main.SetTimer(1, timer*1000); //T는 1 T = 1; } else //코드가 있으면 추가매수등을 위해 종목객체 생성 { req = 0; Main.ReqMarketData(B[req]); } } function Main_OnTimer(nEventID) { var d = new Date(); YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate(); HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds(); //1번타이머이고 지정시간사이이고 최대보유종목수 이하이면 종목검색 요청 if (nEventID == 1 && HHMMSS >= OPEN_T && HHMMSS < CLOSE_T && B.length < 최대보유종목수) { //종목검색 수행 Main.ReqPowerSearch(SearchName) Main.MessageList("ReqPowerSearch1"); //T는 2 T = 2; } if (nEventID == 1 ) { //계좌보유종수 var num = Account1.GetTheNumberOfBalances(); //9시~15시 15분사이 if (HHMMSS >= OPEN_T && HHMMSS < CLOSE_T) { //보유종목이 1개 이상 if (num >= 1) { //계좌평가금액이 스팟시작시 평가금액대비 30% 이상이면 전종목 전량매도 if (Account1.GetBalanceETCinfo(100) >= V1*Earning_Rate) { //1번 타이머 종료 Main.KillTimer(1); //계좌리스트의 순서대로 for (var i = 0; i < num; i++) { //잔고를 셋팅 Account1.SetBalance(i); //수량이 있고 Earning_Rate(30%)수익이거나 손실이면 시장가 매도 if (Account1.Balance.count > 0) { Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1); } } } else //아니면 개별종목 25% Earning_Sale, -10% Trailing_Stop 체크 { //계좌리스트의 순서대로 for (var i = 0; i < num; i++) { //잔고를 셋팅 Account1.SetBalance(i); //수량이 있고 "Earning_Sale" 25% 수익이거나 "Trailing_Stop" -10% 손실이면 시장가 전량매도 if (Account1.Balance.count > 0 && (Account1.Balance.current >= Account1.Balance.avgUnitCost*Earning_Sale || Account1.Balance.current <= Account1.Balance.avgUnitCost*Trailing_Stop)) { Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1); } } } if (B.length > 0) { for (var i = 0; i < B.length; i++) { Account1.SetBalance(B[i],0); if (S[i] == 1) { if (YYYYMMDD == D[i] && Account1.Balance.count > 0 && Account1.Balance.current <= Account1.Balance.avgUnitCost*0.98) { D[i] = 2; var vol = Math.floor(지정금액01/MarketData.Ask(1)); if (vol > 0) { //krx주문 Account1.OrderBuy(MarketData.code,vol,MarketData.Ask(1),0); //nxt주문 //Account.OrderBuy({exchangeKind :4, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); //sor주문 //Account.OrderBuy({exchangeKind :1, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); Main.MessageList(MarketData.code,"주식을 2차 매수합니다."); } } if (YYYYMMDD > D[i] && Account1.Balance.count > 0 && Account1.Balance.current <= Account1.Balance.avgUnitCost*0.95) { D[i] = 2; var vol = Math.floor(지정금액01/MarketData.Ask(1)); if (vol > 0) { //krx주문 Account1.OrderBuy(MarketData.code,vol,MarketData.Ask(1),0); //nxt주문 //Account.OrderBuy({exchangeKind :4, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); //sor주문 //Account.OrderBuy({exchangeKind :1, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); Main.MessageList(MarketData.code,"주식을 2차 매수합니다."); } } } else { if (S[i] == 2) { Account1.SetBalance(B[i],0); if (YYYYMMDD == D[i] && Account1.Balance.count > 0 && Account1.Balance.current <= Account1.Balance.avgUnitCost*0.97) { D[i] = 3; var vol = Math.floor(지정금액02/MarketData.Ask(1)); if (vol > 0) { //krx주문 Account1.OrderBuy(MarketData.code,vol,MarketData.Ask(1),0); //nxt주문 //Account.OrderBuy({exchangeKind :4, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); //sor주문 //Account.OrderBuy({exchangeKind :1, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); Main.MessageList(MarketData.code,"주식을 2차 매수합니다."); } } if (YYYYMMDD > D[i] && Account1.Balance.count > 0 && Account1.Balance.current <= Account1.Balance.avgUnitCost*0.95) { D[i] = 3; var vol = Math.floor(지정금액02/MarketData.Ask(1)); if (vol > 0) { //krx주문 Account1.OrderBuy(MarketData.code,vol,MarketData.Ask(1),0); //nxt주문 //Account.OrderBuy({exchangeKind :4, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); //sor주문 //Account.OrderBuy({exchangeKind :1, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); Main.MessageList(MarketData.code,"주식을 2차 매수합니다."); } } } } } } } } } if (nEventID == 2) { if (T == 0) { Main.ReqMarketData(B[req]); Main.MessageList("ReqMarketData:",B[req]); } else { Main.ReqMarketData(OrderList[req]); Main.MessageList("ReqMarketData:",OrderList[req]); } } } function Main_OnRcvItemList(aItemList, nCount) { Main.KillTimer(1); Main.MessageList("aItemList:",aItemList); OrderList = []; if (nCount >= 1) { if (MKList.length == 0) { OrderList = aItemList; } else { for (var x = 0; x < nCount; x++) { //기본 false var Add = false; //관심종목에 있으면 true for (var y = 0; y < icode.length; y++) { if (aItemList[x] == icode[y]) { Add = false; } } //기존 매수리스트에 있으면 false for (var z = 0; z < MKList.length; z++) { if (aItemList[x] == MKList[z].code) { Add = false; } } //Add가 true이고 계좌에 없는 종목이면 if (Add == true && !IsStockInAccount(aItemList[x])) { //OrderList에 추가 OrderList.push(aItemList[x]); } } } } Main.MessageList("OrderList:",OrderList); //OrderList에 저장된게 없으면 타이머 가동해 종목검색으로 이동 if (OrderList.length == 0) { Main.SetTimer(1, timer*1000); } else //OrderList에 저장된 종목코드가 있으면 { //종목객체 순차적으로 요청 req = 0; Main.ReqMarketData(OrderList[req]); Main.MessageList("ReqMarketData:",OrderList[req]); ; } } function Main_OnRcvMarketData(MarketData) { var d = new Date(); YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate(); HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds(); //스팟 실행후 종목객체 생성 if (T == 0 && MarketData.code == B[req]) { //MKList에 저장 MKList.push(MarketData); req = req+1; //다음 종목 종목객체 요청 if (req < B.length) { var aa = Main.ReqMarketData(B[req]); Main.MessageList("ReqMarketData:",B[req]); ; if (aa == -1) { Main.SetTimer(2, 15000); } } else //종목객체 요청이 모두 완료되면 { //T는 1 T = 1; //타이머 셋팅 Main.SetTimer(1, timer*1000); } } //종목검색 후 생성한 종목객 if (T == 2 && MarketData.code == OrderList[req]) { MKList.push(MarketData); //계좌에 잔고가 없는 경우에만 매수 //Account1.OrderBuy(MarketData.code,1,MarketData.Ask(1),0);// 종목당 1주 지정가 매수주문 //Account1.OrderBuy(MarketData.code,1,0,1); // 종목당 1주 시장가 매수주문 //Account1.OrderBuy(MarketData.code,Math.floor(M_Buy/MarketData.Ask(1)),0,1); // 종목당 지정금액 시장가 매수주문 //Account1.OrderBuy(MarketData.code,Math.floor(M_Buy/MarketData.Ask(1)),MarketData.Ask(1),0);// 종목당 지정금액 지정가 매수주문 var vol = Math.floor(지정금액01/MarketData.Ask(1)); if (vol > 0) { //krx주문 Account1.OrderBuy(MarketData.code,vol,MarketData.Ask(1),0); //nxt주문 //Account.OrderBuy({exchangeKind :4, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); //sor주문 //Account.OrderBuy({exchangeKind :1, code:MarketData.code, count:vol, orderPrice:MarketData.Ask(1), priceKind:0}); //B배열변수에 순차적으로 매수종목 종목코드저장 B.push(MarketData.code); //S배열변수에 순차적으로 매수단계 저장 첫매수이므로 1 S.push(1); //배열변수에 순차적으로 첫매수 날짜장 첫매수이므로 1 D.push(YYYYMMDD); Main.MessageList(MarketData.code + "주식을 매수합니다."); } else Main.MessageList("지정금액으로 수량이 0으로 매수주문 불가"); req = req+1; if (req < OrderList.length && B.length < 당일매수제한종목수) { var aa = Main.ReqMarketData(OrderList[req]); Main.MessageList("ReqMarketData:",OrderList[req]); ; if (aa == -1) { Main.SetTimer(2, 15000); } } else { Main.SetTimer(1, timer*1000); Main.MessageList("당일종목수제한 도달 :",B.length,"/",당일매수제한종목수); } } } function IsStockInAccount(stockCode) { // 계좌에 해당 종목이 있는지 확인하는 함수 var numberOfBalances = Account1.GetTheNumberOfBalances(); for (var i = 0; i < numberOfBalances; i++) { Account1.SetBalance(i); if (stockCode == Account1.Balance.code) { return true; // 계좌에 같은 종목이 있으면 true 반환 } } return false; // 계좌에 같은 종목이 없으면 false 반환 } //계좌 이벤트 function Main_OnUpdateAccount(sAccntNum, sItemCode, lUpdateID) { //계좌에서 종목삭제(전량매도발생) if (lUpdateID == 30003) { //B,S,D에서 제외종목 정보 제거 if (B.length > 0) { //전량 매도된 종목이 B리스트에 있는 종목이면 동일 S,D,종목객체,MKList도 삭제 for (var i = B.length - 1; i >= 0; i--) { if (B[i] == sItemCode) { B.splice(i, 1); S.splice(i, 1); D.splice(i, 1); Main.RemoveMarketData(MKList[i]) MKList.splice(i, 1); } } } } } //스팟 종료 function Main_OnClose() { //B,S,D에 저장된 값은 내부파일에 B,S,D라는 이름느로 저장 Main.SetUserValue("B", JSON.stringify(B)); Main.SetUserValue("S", JSON.stringify(S)); Main.SetUserValue("D", JSON.stringify(D)); } 즐거운 하루되세요