예스스탁
예스스탁 답변
2021-11-30 14:39:54
안녕하세요
예스스탁입니다.
예 업급하신 내용과 같이 주문응답은 각 전략별로 받게 되지만
체결통보는 전략과 관계없이 모두 수신됩니다.
그러므로 주문응답시 주문번호를 저장하고 수신되는 체결중에 저장한 주문번호와 같은 것으로만 사용하게 구현하셔야 합니다.
일반적으로 식을 작성하실 때 아래와 같은 구조로 작성합니다.
주문함수 동작시 아이디 저장
--> 주문응답 수신시 주문응답의 아이디와 저장한 주문번호와 비교후에 주문번호 저장
--> 체결응답 수신시 저장한 주문번호와 비교해 같은 주문번호 일때를 체크
아래식에서 각 주문함수에 아이디부여된 내용과 주문응답과 체결응답에서 수정된 내용을 참고하시기 바랍니다.
var tableEreum="YESSPOT_IMSI_OIL"; // 마리아디비 테이블 이름 - 종목별. // 골드 종목시 "YESSPOT_IMSI_GOLD"
var sqlSel*ct="0";
var fieldCountVV=0;
var sql_rra_positionGo=new Array();
var jnibSuryang=2;
var hhPythonPositionBalryung=0;
var positionGoSeHengOn=0;
var hhDocDoinpositionGoAnneBun=0;
var position=0;
var hhJnibga=0;
var jumunJunCode="0";
var choKkuenHurum=1;
var sql_rra=0;
var hhGejwaBun=0;
var isNormalVV=0;
var orderNumVV=0;
var orderCountVV=0;
var ID1,ID2,ID3,ID4;
var num1,num2,num3,num4;
function Main_OnStart()
{
Main.MessageList("계좌번호=",hhGejwaBun);
}
////////////////////////// Chart1==AD_position 2틱인.
function Chart1_OnBarAppended(nData)
{
if (nData==1){
if (choKkuenHurum==1){
sqlSel*ct="count(ANNE) from ";
sqlSel*ct+=tableEreum;
sqlSel*ct+=";";
// Main.MessageList("sqlSel*ct=",sqlSel*ct);
DataBase1.Sel*ct(sqlSel*ct,"AD");
sql_rra=DataBase1.GetFieldValue(0);
if (sql_rra>=1){
////////////// 포지션 데이터베이스 읽기
sqlSel*ct="* from ";
sqlSel*ct+=tableEreum;
sqlSel*ct+=" ORDER BY ANNE DESC LIMIT 1;";
// Main.MessageList("sqlSel*ct=",sqlSel*ct);
DataBase1.Sel*ct(sqlSel*ct,"AD");
fieldCountVV=DataBase1.GetFieldCount();
for (var i=0; i<=fieldCountVV-1; i++){
sql_rra_positionGo[i]=DataBase1.GetFieldValue(i);
}
if (Math.abs(sql_rra_positionGo[4])==1){
choKkuenHurum=2; // 실시간 포지션 수출이 시작됐으면 흐름 2 영구 부여.
}
}
}
////////////// 포지션 데이터베이스 읽기
if (choKkuenHurum==2){
sqlSel*ct="* from ";
sqlSel*ct+=tableEreum;
sqlSel*ct+=" ORDER BY ANNE DESC LIMIT 1;";
// Main.MessageList("sqlSel*ct=",sqlSel*ct);
DataBase1.Sel*ct(sqlSel*ct,"AD");
fieldCountVV=DataBase1.GetFieldCount();
for (var i=0; i<=fieldCountVV-1; i++){
sql_rra_positionGo[i]=DataBase1.GetFieldValue(i); // 결. 배열에 마지막 행 배치한.
}
hhPythonPositionBalryung=0;
hhPythonPositionBalryung=sql_rra_positionGo[4];
////////////// 포지션 데이터베이스 새행 온 변수 발령
positionGoSeHengOn=0;
if (sql_rra_positionGo[0]>hhDocDoinpositionGoAnneBun){
positionGoSeHengOn=1; // 파이썬 포지션 새 포지션 발령 1 부여
hhDocDoinpositionGoAnneBun=sql_rra_positionGo[0];
}
Main.MessageList("파이썬 포지션고 새행 온 positionGoSeHengOn=",positionGoSeHengOn);
}
//////////////////////////// 포지션 진입
if (positionGoSeHengOn==1){
if (position==0){ // 포지션 없을 시
if (hhPythonPositionBalryung==1){
position=1; // 상방 1
hhJnibga=Chart1.GetClose(nData,0);
jumunJunCode=Chart1.GetCode(1);
Main.MessageList("상방 진입 주문하는");
ID1 = Account1.OrderBuy(jumunJunCode,jnibSuryang,hhJnibga,2);
} else if (hhPythonPositionBalryung==-1){
position=-1; // 하방 -1
hhJnibga=Chart1.GetClose(nData,0);
jumunJunCode=Chart1.GetCode(1);
Main.MessageList("하방 진입 주문하는");
ID2 = Account1.OrderSell(jumunJunCode,jnibSuryang,hhJnibga,2);
}
} else if (position==1){ // 포지션 상방시
if (hhPythonPositionBalryung==10){
position=0;
hhJnibga=Chart1.GetClose(nData,0);
Main.MessageList("상방 청산 주문하는");
ID3 = Account1.OrderSell(jumunJunCode,jnibSuryang,hhJnibga,2);
}
} else if (position==-1){ // 포지션 하방시
if (hhPythonPositionBalryung==-10){
position=0;
hhJnibga=Chart1.GetClose(nData,0);
Main.MessageList("하방 청산 주문하는");
ID4 = Account1.OrderBuy(jumunJunCode,jnibSuryang,hhJnibga,2);
}
}
}
Main.MessageList("현재 position=",position," hhPythonPositionBalryung=",hhPythonPositionBalryung," jumunJunCode=",jumunJunCode," orderNumVV=",orderNumVV," orderCountVV=",orderCountVV," hhDocDoinpositionGoAnneBun=",hhDocDoinpositionGoAnneBun);
}
}
function Main_OnOrderResponse(OrderResponse)
{
isNormalVV=OrderResponse.isNormal;
orderNumVV=OrderResponse.orderNum;
orderCountVV=OrderResponse.orderCount;
Account1.SetUnfillOrderNumber(orderNumVV); // 미체결
if (OrderResponse.orderID == ID1)
{
Main.MessageList("상방 진입 주문 응답");
num1 = OrderResponse.orderNum;
}
if (OrderResponse.orderID == ID2)
{
Main.MessageList("하방 진입 주문 응답");
num2 = OrderResponse.orderNum;
}
if (OrderResponse.orderID == ID3)
{
Main.MessageList("상방 청산 주문 응답");
num3 = OrderResponse.orderNum;
}
if (OrderResponse.orderID == ID4)
{
Main.MessageList("하방 청산 주문 응답");
num4 = OrderResponse.orderNum;
}
}
function Main_OnNotifyFill(NotifyFill)
{
if (NotifyFill.orderNum == num1)
{
Main.MessageList("상방 진입 주문 체결");
jumunJunCode=NotifyFill.code; // 주문 응답시 코드 재부여
}
if (NotifyFill.orderNum == num2)
{
Main.MessageList("하방 진입 주문 체결");
jumunJunCode=NotifyFill.code; // 주문 응답시 코드 재부여
}
if (NotifyFill.orderNum == num3)
{
Main.MessageList("상방 청산 주문 체결");
jumunJunCode=NotifyFill.code; // 주문 응답시 코드 재부여
}
if (NotifyFill.orderNum == num4)
{
Main.MessageList("하방 청입 주문 체결");
jumunJunCode=NotifyFill.code; // 주문 응답시 코드 재부여
}
}
즐거운 하루되세요
> 로봇짱 님이 쓴 글입니다.
> 제목 : 예스스팟의 주문체결통보 객체가 이상합니다.
> 안녕하세요. 언제나 친절한 답변에 감사드립니다.
파이선 등의 외부 프로그램에서 데이터베이스에 명령값 등을 수출하고, 그걸 예스스팟의 데이터베이스 객체로 읽어 예스스팟의 매매를 실행하는 전략을 만들었습니다. 그런데 이 전략을 오일, 골드 종목별로 여러개 띄울때 문제가 생깁니다. 종목별로 데이터베이스 테이블 명과 Chart1 의 종목 등을 변경 적용했을때, 주문체결통보객체(Main_OnNotifyFill)에서 반환값이 전략간 구분이 안가고 모든게 global 변수 처리돼 섞이는 것 같습니다. 주문접수응답 객체(Main_OnOrderResponse)는 종목별 전략 간에 섞이지 않는 것같습니다. 그런데 주문체결통보객체는 종목별 전략 간에 섞입니다. 이게 원래 그런건지 봐주십시오. 감사합니다.
첨부파일의 전략을 오일용으로 하나, 데이터베이스 테이블명과 Chart1 객체 설정을 바꿔서 골드용으로 또 하나 이렇게 전략 2개를 만들고 실행했을때 Main.MessageList 출력을 보면 jumunJunCode 가 종목별로 달라야 하는데 같은것으로 설정되는 문제를 첨부 파일 그림에서 볼 수 있습니다.
##################### 예스스팟 전략 #########################
var tableEreum="YESSPOT_IMSI_OIL"; // 마리아디비 테이블 이름 - 종목별. // 골드 종목시 "YESSPOT_IMSI_GOLD"
var sqlSel*ct="0";
var fieldCountVV=0;
var sql_rra_positionGo=new Array();
var jnibSuryang=2;
var hhPythonPositionBalryung=0;
var positionGoSeHengOn=0;
var hhDocDoinpositionGoAnneBun=0;
var position=0;
var hhJnibga=0;
var jumunJunCode="0";
var choKkuenHurum=1;
var sql_rra=0;
var hhGejwaBun=0;
var isNormalVV=0;
var orderNumVV=0;
var orderCountVV=0;
function Main_OnStart()
{
Main.MessageList("계좌번호=",hhGejwaBun);
}
////////////////////////// Chart1==AD_position 2틱인.
function Chart1_OnBarAppended(nData)
{
if (nData==1){
if (choKkuenHurum==1){
sqlSel*ct="count(ANNE) from ";
sqlSel*ct+=tableEreum;
sqlSel*ct+=";";
// Main.MessageList("sqlSel*ct=",sqlSel*ct);
DataBase1.Sel*ct(sqlSel*ct,"AD");
sql_rra=DataBase1.GetFieldValue(0);
if (sql_rra>=1){
////////////// 포지션 데이터베이스 읽기
sqlSel*ct="* from ";
sqlSel*ct+=tableEreum;
sqlSel*ct+=" ORDER BY ANNE DESC LIMIT 1;";
// Main.MessageList("sqlSel*ct=",sqlSel*ct);
DataBase1.Sel*ct(sqlSel*ct,"AD");
fieldCountVV=DataBase1.GetFieldCount();
for (var i=0; i<=fieldCountVV-1; i++){
sql_rra_positionGo[i]=DataBase1.GetFieldValue(i);
}
if (Math.abs(sql_rra_positionGo[4])==1){
choKkuenHurum=2; // 실시간 포지션 수출이 시작됐으면 흐름 2 영구 부여.
}
}
}
////////////// 포지션 데이터베이스 읽기
if (choKkuenHurum==2){
sqlSel*ct="* from ";
sqlSel*ct+=tableEreum;
sqlSel*ct+=" ORDER BY ANNE DESC LIMIT 1;";
// Main.MessageList("sqlSel*ct=",sqlSel*ct);
DataBase1.Sel*ct(sqlSel*ct,"AD");
fieldCountVV=DataBase1.GetFieldCount();
for (var i=0; i<=fieldCountVV-1; i++){
sql_rra_positionGo[i]=DataBase1.GetFieldValue(i); // 결. 배열에 마지막 행 배치한.
}
hhPythonPositionBalryung=0;
hhPythonPositionBalryung=sql_rra_positionGo[4];
////////////// 포지션 데이터베이스 새행 온 변수 발령
positionGoSeHengOn=0;
if (sql_rra_positionGo[0]>hhDocDoinpositionGoAnneBun){
positionGoSeHengOn=1; // 파이썬 포지션 새 포지션 발령 1 부여
hhDocDoinpositionGoAnneBun=sql_rra_positionGo[0];
}
Main.MessageList("파이썬 포지션고 새행 온 positionGoSeHengOn=",positionGoSeHengOn);
}
//////////////////////////// 포지션 진입
if (positionGoSeHengOn==1){
if (position==0){ // 포지션 없을 시
if (hhPythonPositionBalryung==1){
position=1; // 상방 1
hhJnibga=Chart1.GetClose(nData,0);
jumunJunCode=Chart1.GetCode(1);
Main.MessageList("상방 진입 주문하는");
Account1.OrderBuy(jumunJunCode,jnibSuryang,hhJnibga,2);
} else if (hhPythonPositionBalryung==-1){
position=-1; // 하방 -1
hhJnibga=Chart1.GetClose(nData,0);
jumunJunCode=Chart1.GetCode(1);
Main.MessageList("하방 진입 주문하는");
Account1.OrderSell(jumunJunCode,jnibSuryang,hhJnibga,2);
}
} else if (position==1){ // 포지션 상방시
if (hhPythonPositionBalryung==10){
position=0;
hhJnibga=Chart1.GetClose(nData,0);
Main.MessageList("상방 청산 주문하는");
Account1.OrderSell(jumunJunCode,jnibSuryang,hhJnibga,2);
}
} else if (position==-1){ // 포지션 하방시
if (hhPythonPositionBalryung==-10){
position=0;
hhJnibga=Chart1.GetClose(nData,0);
Main.MessageList("하방 청산 주문하는");
Account1.OrderBuy(jumunJunCode,jnibSuryang,hhJnibga,2);
}
}
}
Main.MessageList("현재 position=",position," hhPythonPositionBalryung=",hhPythonPositionBalryung," jumunJunCode=",jumunJunCode," orderNumVV=",orderNumVV," orderCountVV=",orderCountVV," hhDocDoinpositionGoAnneBun=",hhDocDoinpositionGoAnneBun);
}
}
function Main_OnOrderResponse(OrderResponse)
{
isNormalVV=OrderResponse.isNormal;
orderNumVV=OrderResponse.orderNum;
orderCountVV=OrderResponse.orderCount;
Account1.SetUnfillOrderNumber(orderNumVV); // 미체결
}
function Main_OnNotifyFill(NotifyFill)
{
jumunJunCode=NotifyFill.code; // 주문 응답시 코드 재부여
}
###################### 데이터베이스 쿼리 #########################
sql="CREATE TABLE yesspot_imsi_oil (ID INT, SDATE INT, STIME BIGINT, C INT, POSITIONBALRYUNG INT, POSITION INT, JANGJUN_GESU INT);"
############# 설명
1. ID 는 행별로 반드시 1증씩 하는 값이 입력돼야 합니다.
2. SDATE, STIME 은 아무 값이 입력돼도 됩니다.
3. POSITIONBALRYUNG 컬럼엔 포지션이 1(매수 진입)이 날시는 1이, 매수 포지션 청산시는 10 이 입력돼야 합니다. 매도 진입시는 -1이 매도 포지션 청산시는 -10 이 입력돼야 합니다.
4. 매수 포지션을 가질 때는 1, 매도 포지션은 -1, 포지션이 없을시는 0 이 입력돼야 합니다.
5. JANGJUN_GESU 는 매번 0 이 입력되면 됩니다.
############# 예시
파이선에서 매수 포지션 진입 명령을 수출할 시.
sql="ins*rt into yesspot_imsi_oil values (1, 1234, 1234, 77.02, 1, 1);"
파이선에서 매수 포지션 청산 명령을 수출할 시.
sql="ins*rt into yesspot_imsi_oil values (2, 1234, 1234, 77.12, 10, 0);"