커뮤니티
예스랭귀지 Q&A
답변완료
[공지] 예스랭귀지 AI 어시스턴트, '예스나 AI' 출시 및 무료 체험 안내
안녕하세요, 예스스탁 입니다.복잡한 수식 공부 없이 여러분의 아이디어를 말하면 시스템 트레이딩 언어 예스랭귀지로 작성해주는 서비스예스나 AI(YesNa AI)가 출시되었습니다.지금 예스나 AI를 직접 경험해 보실 수 있도록 20크레딧(질문권 20회)를 무료로 증정해 드리고 있습니다.바로 여러분의 아이디어를 코드로 변환해보세요.--------------------------------------------------🚀 YesNa AI 핵심 기능- 지표식/전략식/종목검색식 생성: 자연어로 요청하면 예스랭귀지 문법에 맞는 코드를 작성합니다.- 종목검색식 변환 지원: K증권의 종목 검색식을 예스랭귀지로 변환 지원합니다.- 컴파일 검증: 작성된 코드가 실행 가능한지 컴파일러를 통해 문법 검증을 거쳐 결과물을 제공합니다.상세한 서비스 개요 및 활용 방법은 [서비스 소개 페이지]에서 확인하실 수 있습니다.▶ 서비스 소개 페이지: 바로가기서비스 사용 유의사항 및 결제 환불정책은 [이용약관]을 참고 부탁드립니다.▶ 서비스 이용약관: 바로가기💬 이용 문의사용 중 문의사항은 [프로그램 사용법 Q&A] 게시판에서 [예스나 AI] 카테고리를 설정 후 문의해 주시면 상세히 안내해 드리겠습니다.--------------------------------------------------앞으로도 AI를 활용한 다양한 트레이딩 기능들을 지속적으로 선보일 예정입니다.많은 관심과 기대 부탁드립니다.
2026-02-27
7840
글번호 230811
관리자에 의해 프로그램 사용법 QnA로 이동되었습니다
2005-12-22
5
글번호 9005
답변완료
수식부탁드립니다.
15분봉에서
오늘 오전 9시 00부터 9시15분까지의 봉의 저가가 envelope(30,2) 이하이면
오늘 하루 3시 이전까지 var1값은
var1==1
아니면
var1==2
단 하루동안의 조건식입니다... 3시가 넘게되면 var1의 값은 다시 2가 됩니다.
2005-12-22
896
글번호 9004
[오픈소스] 당일 마켓프로파일 지표식
본 내용은 http://cafe.empas.com/systrader에 게시된 내용입니다.
처음에 만들었던 지표식은 엑셀파일로 구현하는 게 목표였기 때문에 특정일을 입력받아 처리토록 하였습니다만
이번 지표식에서는 특정일에 상관없이 연속적으로 처리토록 하였으며 배열을 3개로 늘려 사용함으로써
가격대 표현의 한계를 300개로 확대시켰습니다.
/*작성자:수식지왕*/
input:interval(15);
var:arr(0),k(0),tick(0),chk_cnt(0),ttm(0),t_val(0),max_tpo(0),tot_tpo(0),
sum(0),acc(0),mdl_prc(0),mdl_arr(0),range_u(0),range_d(0),base(0),
cal_tpo(0),up_tpo(0),dn_tpo(0),up_tail_u(0),up_tail_d(0),dn_tail_u(0),dn_tail_d(0);
array:price_u[100](0),price_m[100](0),price_d[100](0),
status_u[100](0),status_m[100](0),status_d[100](0),
tpo_u[100](0),tpo_m[100](0),tpo_d[100](0);
if CodeCategoryEX() == 11 then //Kospi 주식
{
if C >= 500000 then tick = 1000;
else if C >= 100000 then tick = 500;
else if C >= 50000 then tick = 100;
else if C >= 10000 then tick = 50;
else if C >= 5000 then tick = 10;
else tick = 5;
}
if CodeCategoryEX() == 12 then //Kosdaq 주식
{
if C >= 50000 then tick = 100;
else if C >= 10000 then tick = 50;
else if C >= 5000 then tick = 10;
else tick = 5;
}
if CodeCategoryEX() == 21 then //Kospi200 선물
tick = 0.05;
if CodeCategoryEX() == 31 or CodeCategoryEX() == 32 then //Kospi200 콜옵션,풋옵션
{
if C >= 3.0 then tick = 0.05;
else tick = 0.01;
}
if dayindex()==0 then //매일 첫번째 봉에서 해당 변수들의 값을 0으로 초기화
{
for arr = 0 to 99 {
price_u[arr] = 0;
price_m[arr] = 0;
price_d[arr] = 0;
status_u[arr] = 0;
status_m[arr] = 0;
status_d[arr] = 0;
tpo_u[arr] = 0;
tpo_m[arr] = 0;
tpo_d[arr] = 0;
}
max_tpo = 0;
tot_tpo = 0;
sum = 0;
acc = 0;
mdl_prc = 0;
mdl_arr = 0;
range_u = 0;
range_d = 0;
base = dayopen() + tick * 149; //300개 가격대중 최상단에 해당하는 가격
price_u[0] = base; //지수 배열 상단
for arr = 1 to 99 {
price_u[arr] = price_u[arr-1] - tick;
}
price_m[0] = price_u[99] - tick; //지수 배열 중단
for arr = 1 to 99 {
price_m[arr] = price_m[arr-1] - tick;
}
price_d[0] = price_m[99] - tick; //지수 배열 하단
for arr = 1 to 99 {
price_d[arr] = price_d[arr-1] - tick;
}
}
ttm = TimeToMinutes(stime); //시간을 30분,15분,10분등으로 나누기 쉽도록 환산
t_val = int((ttm-540)/interval) + 1; //540은 09:00. 9시를 빼고 나서 원하는 시간단위로 나눈다
for arr = 0 to 99 {
if l <= price_u[arr] and price_u[arr] <= h then
{
if status_u[arr] < t_val then //A가 찍혔는데 또 A를 찍을 필요가 없음. 그걸 확인
{
status_u[arr] = t_val; //중복을 막기 위해 마지막 time value 저장
tpo_u[arr] = tpo_u[arr] + 1; //현재 가격대의 TPO 누적
tot_tpo = tot_tpo + 1; //전체 TPO 누적
if max_tpo < tpo_u[arr] then //TPO 최빈값
{
max_tpo = tpo_u[arr];
sum = 0; //TPO가 동일한 가격대가 여러가격일 경우
acc = 0; //평균값을 구하기 위해 가격 누적변수와 가격대 수 초기화
}
if max_tpo == tpo_u[arr] then //최빈값과 동일하면
{
sum = sum + price_u[arr]; //해당 가격을 누적
acc = acc + 1; //가격대 개수 누적
}
}
}
//3개의 동일 성격을 지닌 배열에 대해 한꺼번에 처리 못하므로 동일 루틴으로 3회 처리
if l <= price_m[arr] and price_m[arr] <= h then
{
if status_m[arr] < t_val then
{
status_m[arr] = t_val;
tpo_m[arr] = tpo_m[arr] + 1;
tot_tpo = tot_tpo + 1;
if max_tpo < tpo_m[arr] then
{
max_tpo = tpo_m[arr];
sum = 0;
acc = 0;
}
if max_tpo == tpo_m[arr] then
{
sum = sum + price_m[arr];
acc = acc + 1;
}
}
}
if l <= price_d[arr] and price_d[arr] <= h then
{
if status_d[arr] < t_val then
{
status_d[arr] = t_val;
tpo_d[arr] = tpo_d[arr] + 1;
tot_tpo = tot_tpo + 1;
if max_tpo < tpo_d[arr] then
{
max_tpo = tpo_d[arr];
sum = 0;
acc = 0;
}
if max_tpo == tpo_d[arr] then
{
sum = sum + price_d[arr];
acc = acc + 1;
}
}
}
}
mdl_prc = round(sum/acc/tick,0)*tick; //평균하여 중심가격으로 삼음
mdl_arr = int((base-mdl_prc)/tick); //배열변수의 첨자는 정수이어야 함
//처음부터 int()를 생각해 냈던 것은 아니고 디버그 과정에서 알게 됨
range_u = mdl_arr;
range_d = mdl_arr;
// 전체 TPO의 70%가 될 때까지 상하값을 비교하면서 누적
cal_tpo = iff(mdl_arr<100,tpo_u[mdl_arr],iff(mdl_arr<200,tpo_m[mdl_arr-100],tpo_d[mdl_arr-200]));
for k = 0 to 150 {
// range_u는 한단위씩 위로(-1), range_d는 한단위씩 아래로(+1)
// TPO가 많은 쪽의 TPO를 먼저 누적한다
var2 = iff(range_u-1<100,tpo_u[range_u-1],iff(range_u-1<200,tpo_m[range_u-1-100],tpo_d[range_u-1-200]));
var3 = iff(range_d+1<100,tpo_u[range_d+1],iff(range_d+1<200,tpo_m[range_d+1-100],tpo_d[range_d+1-200]));
if var2 > var3 then
{
cal_tpo = cal_tpo + var2;
range_u = range_u - 1;
}
else if var2 < var3 then
{
cal_tpo = cal_tpo + var3;
range_d = range_d + 1;
}
else if var2 == var3 and var2 > 0 and var3 > 0 then
{
cal_tpo = cal_tpo + var2;
range_u = range_u - 1;
}
if cal_tpo >= tot_tpo * 0.7 or var2 + var3 == 0 then
k = 150;
}
up_tpo = 0; //중심가격의 상위 TPO
if tpo_u[0] == 1 then up_tail_u = 0; //윗꼬리 상단 경계선, 0행부터 1이면 윗꼬리 상단은 0행이 됨
else up_tail_u = 299; //윗꼬리를 못 찾을 경우를 대비해서 상단과 하단의 관계를 역으로 만듬
//꼬리 경계값을 찾는 루틴을 성공적으로 마치면 상단값 < 하단값 성립
up_tail_d = 0; //윗꼬리 하단 경계선
//0행부터 중심가격 이전행까지 아래로 내려가면서
for arr = 0 to mdl_arr-1 {
//현재 행의 tpo 값이 0이고 다음 행의 tpo값이 1이면 1의 시작으로 보고 다음 행의 행번호를 윗꼬리 상단으로 봄
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 0 and
iff(arr+1<100,tpo_u[arr+1],iff(arr+1<200,tpo_m[arr-100+1],tpo_d[arr-200+1])) == 1 then
up_tail_u = arr + 1; //윗꼬리 상단 경계선 array
//현재 행의 tpo 값이 1이고 다음 행의 tpo값이 1보다 크면 현재 행의 행번호를 윗꼬리 하단으로 봄
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 1 and
iff(arr+1<100,tpo_u[arr+1],iff(arr+1<200,tpo_m[arr-100+1],tpo_d[arr-200+1])) > 1 and
up_tail_d == 0 then //조건을 만족하는 경우가 여러번 발생하는데 up_tail_d가 0일때만
//즉, 처음에 찾아진 값만 유효한 것로 봄
up_tail_d = arr; //윗꼬리 하단 경계선 array
//TPO가 1보다 큰 상위 TPO 누적
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) > 1 then
up_tpo = up_tpo + iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200]));
}
dn_tpo = 0; //중심가격의 하위 TPO
dn_tail_u = 299; //아래꼬리 상단 경계선
if tpo_d[99] == 1 then dn_tail_d = 299;
else dn_tail_d = 0; //아래꼬리 하단 경계선
//299행부터 중심가격 이전행까지 위로 올라가면서
for arr = 299 downto mdl_arr+1 {
//TPO가 1보다 큰 하위 TPO 누적
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_u[arr-100],tpo_d[arr-200])) > 1 then
dn_tpo = dn_tpo + iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200]));
//현재 행의 tpo 값이 1이고 윗행의 tpo값이 1보다 크면 현재 행의 행번호를 아랫꼬리 상단으로 봄
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 1 and
iff(arr-1<100,tpo_u[arr-1],iff(arr-1<200,tpo_m[arr-100-1],tpo_d[arr-200-1])) > 1 and
dn_tail_u == 299 then
dn_tail_u = arr; //아래꼬리 상단 경계선 array
//현재 행의 tpo 값이 0이고 윗행의 tpo값이 1이면 1의 시작으로 보고 윗행의 행번호를 아랫꼬리 하단으로 봄
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 0 and
iff(arr-1<100,tpo_u[arr-1],iff(arr-1<200,tpo_m[arr-100-1],tpo_d[arr-200-1])) == 1 then
dn_tail_d = arr - 1; //아래꼬리 하단 경계선 array
}
plot1(mdl_prc,"중심가격");
plot2(base-(range_u*tick),"가치영역(상)"); //0행의 값 base가 가장 큰 값이므로 해당 행(row)에
//단위(tick)을 곱해서 차감
plot3(base-(range_d*tick),"가치영역(하)");
if up_tail_u <= up_tail_d then //꼬리의 경계값이 정상적으로 찾아졌다면
{
plot4(base-(up_tail_u*tick),"윗꼬리상단"); //점그래프로 표현
plot5(base-(up_tail_d*tick),"윗꼬리하단");
}
if dn_tail_u <= dn_tail_d then
{
plot6(base-(dn_tail_u*tick),"아랫꼬리상단");
plot7(base-(dn_tail_d*tick),"아랫꼬리하단");
}
//plot8(up_tpo,"상위TPO");
//plot9(dn_tpo,"하위TPO");
2005-12-22
1811
글번호 9003
[오픈소스] 전일 마켓프로파일 지표식
본 내용은 http://cafe.empas.com/systrader에 게시된 내용입니다.
지난번 마켓프로파일 자료를 수집하면서 봤던 내용중에 1~2일전의 중심가격을 금일 차트에 띄워놓고 보는
화면이 있어 이번에는 전일 중심가격 지표식을 만들어 보았습니다.
피봇포인트처럼 전일의 값을 기준으로 저항 및 지지선으로 활용하는 전략 같은데 아직 마켓프로파일을
이용한 전략을 사용해 본 적이 없어 우선 지표식 만드는 과정만 설명드립니다
윗 글에서 설명한 당일의 지표식과 합쳐서 하나의 지표식으로 만들어 보려고 했는데 당일 지표식은 매 봉마다
계산을 새로이 하는 개념이고 전일 지표식은 매일 첫번째 봉에서만 계산하면 되는 로직이라 별도의 지표식으로
분리했습니다.
/*작성자:수식지왕*/
input:n(1),interval(15);
var:arr(0),j(0),k(0),tick(0),chk_cnt(0),ttm(0),t_val(0),max_tpo(0),tot_tpo(0),
sum(0),acc(0),mdl_prc(0),mdl_arr(0),range_u(0),range_d(0),base(0),
cal_tpo(0),up_tpo(0),dn_tpo(0),up_tail_u(0),up_tail_d(0),dn_tail_u(0),dn_tail_d(0);
array:price_u[100](0),price_m[100](0),price_d[100](0),
status_u[100](0),status_m[100](0),status_d[100](0),
tpo_u[100](0),tpo_m[100](0),tpo_d[100](0);
if CodeCategoryEX() == 11 then //Kospi 주식
{
if C >= 500000 then tick = 1000;
else if C >= 100000 then tick = 500;
else if C >= 50000 then tick = 100;
else if C >= 10000 then tick = 50;
else if C >= 5000 then tick = 10;
else tick = 5;
}
if CodeCategoryEX() == 12 then //Kosdaq 주식
{
if C >= 50000 then tick = 100;
else if C >= 10000 then tick = 50;
else if C >= 5000 then tick = 10;
else tick = 5;
}
if CodeCategoryEX() == 21 then //Kospi200 선물
tick = 0.05;
if CodeCategoryEX() == 31 or CodeCategoryEX() == 32 then //Kospi200 콜옵션,풋옵션
{
if C >= 3.0 then tick = 0.05;
else tick = 0.01;
}
var1 = dayindex();
//전일 데이터를 이용하는 로직이므로 과거참조가 들어가는데 dayindex()의 경우
//dayindex()[n]으로 사용할 수 없어 dayindex()값을 일반변수에 move하여 사용하여야 합니다.
//예전에도 이런 경험을 했었는데 기억력이 나쁘다보니 요번에도 여기서 좀 헤맸습니다.
if dayindex()==0 then //당일 첫번째 봉에서만 계산
{
for arr = 0 to 99 {
price_u[arr] = 0;
price_m[arr] = 0;
price_d[arr] = 0;
status_u[arr] = 0;
status_m[arr] = 0;
status_d[arr] = 0;
tpo_u[arr] = 0;
tpo_m[arr] = 0;
tpo_d[arr] = 0;
}
max_tpo = 0;
tot_tpo = 0;
sum = 0;
acc = 0;
mdl_prc = 0;
mdl_arr = 0;
range_u = 0;
range_d = 0;
//n일 동안의 봉의 개수를 계산하여 계산할 첫번째 봉의 위치를 찾음
if n > 0 then
{
var2 = 0;
for j = 1 to i {
if var1[j] == 0 then var2 = var2 + 1; //dayindex()가 0 즉, 09시인 봉을 n번 찾음
if var2 == n then {
var3 = j;
j = i;
}
}
}
base = dayopen(n) + tick * 149; //n일전 시초가를 기준으로 가격대중 가장 상위의 가격 계산
price_u[0] = base; //지수 배열 상단
for arr = 1 to 99 {
price_u[arr] = price_u[arr-1] - tick;
}
price_m[0] = price_u[99] - tick; //지수 배열 중단
for arr = 1 to 99 {
price_m[arr] = price_m[arr-1] - tick;
}
price_d[0] = price_m[99] - tick; //지수 배열 하단
for arr = 1 to 99 {
price_d[arr] = price_d[arr-1] - tick;
}
for j = var3 downto 1 { //n일전 시초봉에서부터 현재봉 1봉 이전 봉까지 순차적으로 계산
//이후 내용은 당일 지표식과 동일하므로 윗글 참조
ttm = TimeToMinutes(stime[j]);
t_val = int((ttm-540)/interval) + 1;
for arr = 0 to 99 {
if l[j] <= price_u[arr] and price_u[arr] <= h[j] then
{
if status_u[arr] < t_val then
{
status_u[arr] = t_val;
tpo_u[arr] = tpo_u[arr] + 1;
tot_tpo = tot_tpo + 1;
if max_tpo < tpo_u[arr] then
{
max_tpo = tpo_u[arr];
sum = 0;
acc = 0;
}
if max_tpo == tpo_u[arr] then
{
sum = sum + price_u[arr];
acc = acc + 1;
}
}
}
if l[j] <= price_m[arr] and price_m[arr] <= h[j] then
{
if status_m[arr] < t_val then
{
status_m[arr] = t_val;
tpo_m[arr] = tpo_m[arr] + 1;
tot_tpo = tot_tpo + 1;
if max_tpo < tpo_m[arr] then
{
max_tpo = tpo_m[arr];
sum = 0;
acc = 0;
}
if max_tpo == tpo_m[arr] then
{
sum = sum + price_m[arr];
acc = acc + 1;
}
}
}
if l[j] <= price_d[arr] and price_d[arr] <= h[j] then
{
if status_d[arr] < t_val then
{
status_d[arr] = t_val;
tpo_d[arr] = tpo_d[arr] + 1;
tot_tpo = tot_tpo + 1;
if max_tpo < tpo_d[arr] then
{
max_tpo = tpo_d[arr];
sum = 0;
acc = 0;
}
if max_tpo == tpo_d[arr] then
{
sum = sum + price_d[arr];
acc = acc + 1;
}
}
}
}
}
mdl_prc = round(sum/acc/tick,0)*tick;
mdl_arr = int((base-mdl_prc)/tick);
range_u = mdl_arr;
range_d = mdl_arr;
cal_tpo = iff(mdl_arr<100,tpo_u[mdl_arr],iff(mdl_arr<200,tpo_m[mdl_arr-100],tpo_d[mdl_arr-200]));
for k = 0 to 150 {
// range_u는 한단위씩 위로(-1), range_d는 한단위씩 아래로(+1)
// TPO가 많은 쪽의 TPO를 먼저 누적한다
var4 = iff(range_u-1<100,tpo_u[range_u-1],iff(range_u-1<200,tpo_m[range_u-1-100],tpo_d[range_u-1-200]));
var5 = iff(range_d+1<100,tpo_u[range_d+1],iff(range_d+1<200,tpo_m[range_d+1-100],tpo_d[range_d+1-200]));
if var4 > var5 then
{
cal_tpo = cal_tpo + var4;
range_u = range_u - 1;
}
else if var4 < var5 then
{
cal_tpo = cal_tpo + var5;
range_d = range_d + 1;
}
else if var4 == var5 and var4 > 0 and var5 > 0 then
{
cal_tpo = cal_tpo + var4;
range_u = range_u - 1;
}
if cal_tpo >= tot_tpo * 0.7 or var4 + var5 == 0 then
k = 150;
}
up_tpo = 0;
dn_tpo = 0;
if tpo_u[0] == 1 then up_tail_u = 0;
else up_tail_u = 299;
up_tail_d = 0;
dn_tail_u = 299;
if tpo_d[99] == 1 then dn_tail_d = 299;
else dn_tail_d = 0;
for arr = 0 to mdl_arr-1 {
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 0 and
iff(arr+1<100,tpo_u[arr+1],iff(arr+1<200,tpo_m[arr-100+1],tpo_d[arr-200+1])) == 1 then
up_tail_u = arr + 1;
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 1 and
iff(arr+1<100,tpo_u[arr+1],iff(arr+1<200,tpo_m[arr-100+1],tpo_d[arr-200+1])) > 1 and
up_tail_d == 0 then
up_tail_d = arr;
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) > 1 then
up_tpo = up_tpo + iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200]));
}
for arr = 299 downto mdl_arr+1 {
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_u[arr-100],tpo_d[arr-200])) > 1 then
dn_tpo = dn_tpo + iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200]));
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 1 and
iff(arr-1<100,tpo_u[arr-1],iff(arr-1<200,tpo_m[arr-100-1],tpo_d[arr-200-1])) > 1 and
dn_tail_u == 299 then
dn_tail_u = arr;
if iff(arr<100,tpo_u[arr],iff(arr<200,tpo_m[arr-100],tpo_d[arr-200])) == 0 and
iff(arr-1<100,tpo_u[arr-1],iff(arr-1<200,tpo_m[arr-100-1],tpo_d[arr-200-1])) == 1 then
dn_tail_d = arr - 1;
}
}
plot1(mdl_prc,"중심가격");
plot2(base-(range_u*tick),"가치영역(상)");
plot3(base-(range_d*tick),"가치영역(하)");
if up_tail_u <= up_tail_d then
{
plot4(base-(up_tail_u*tick),"윗꼬리상단");
plot5(base-(up_tail_d*tick),"윗꼬리하단");
}
if dn_tail_u <= dn_tail_d then
{
plot6(base-(dn_tail_u*tick),"아랫꼬리상단");
plot7(base-(dn_tail_d*tick),"아랫꼬리하단");
}
2005-12-22
1653
글번호 9002
[오픈소스] PnF차트 저항선 돌파종목 검색식
본 내용은 http://cafe.empas.com/systrader에 게시된 내용입니다.
P&F 차트 검색식에 대한 요구가 있었던 것으로 기억됩니다.
많은 시행착오 끝에 만든거다보니 이글을 읽는 분들께 작은 도움이라도 되었으면 하는 바램입니다.
저도 설명드리기 난해합니다만 이런 방법도 있구나 하면서 그냥 읽어봐 주시기 바랍니다.
종목을 검색후 P&F 차트로 보면 일부 종목은 돌파전인 것으로 나오는데 예스트레이더 어플리케이션에서 P&F 차트를 그려주는 소스와
예스편집기에서 지원하는 랭귀지가 상이하므로 100% 동일하게 맞추는데 한계가 있어 오차가 발생할 수 있습니다.
/*작성자:수식지왕*/
input:bar_cnt(200); //검색식 최대 봉수가 200이므로 200을 주었음.
//검색기간에서 봉수를 달리 줄 경우 입력변수도 수정해줘야 함
var:j(0),g(0),r(0),k(0),n(0),point(0),figure(3),u(1),d(-1),type(0),
저항기울기(0),저항선(0),저항표준오차(0),
지지기울기(0),지지선(0),지지표준오차(0);
array:기준가[10](0),Hi[100](0),Lo[100](0),방향[100](0);
#=====================================================#
# main
#=====================================================#
n = bar_cnt - 1; //봉의 개수는 200이지만 index는 0부터 시작하므로 -1
//마지막봉 위치에서 첫번째 봉은 c[199]가 됨
if i == n then {
point = (highest(c,bar_cnt)-lowest(c,bar_cnt))/50;
//예스트레이더에서 여러 종목에 걸쳐 테스트해서 얻은 결과값임
//point값을 어떻게 주느냐에 따라 차트의 모양이 천차만별이므로 가급적
//예스차트에서 제공하는 모양에 가깝게 구현하고자 함
//기간값과 봉의 개수가 동일하므로 마지막봉에서만 계산이 가능함
//여타의 검색식의 로직은 첫번째 봉부터 마지막 봉까지 시간의 흐름에 따라
//계산을 하지만 이 검색식은 마지막봉에서 point를 계산하고
//거꾸로 과거의 데이터를 계산함.
기준가[0] = c[n]; //n 봉전, 즉 첫번째 봉의 종가
k = 0;
방향[0] = 0;
Hi[0] = int(h[n]/point); //첫번째 봉의 고가를 point로 나눈값
Lo[0] = int(l[n]/point); //첫번째 봉의 저가를 point로 나눈값
for g = n - 1 downto 0 { //c[198] ~ c[0]의 수순으로 계산
for r = 9 downto 1 { //기준가를 일반변수로 사용하게되면 1봉전의 값을
기준가[r] = 기준가[r-1]; //기준가[1]로 표현할 수 있겠으나 본 로직에서는
} //마지막 봉에서 모든 계산을 해야 하므로
//기준가를 배열변수로 선언하여 사용함
//99번 글의 지표식과 비교해 보시면 이해가 빠를 것임
//이후 로직은 기존 지표식 로직과 동일
if 방향[0] == 0 then {
if 기준가[0] + (point * figure) <= c[g] then {
기준가[0] = c[g];
방향[0] = u;
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
else if 기준가[0] - (point * figure) >= c[g] then {
기준가[0] = c[g];
방향[0] = d;
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
else {
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
}
else if 방향[0] == d then {
if 기준가[0] + (point * figure) <= c[g] then {
k = k + 1;
for j = min(k,99) downto 1 {
Hi[j] = Hi[j-1];
Lo[j] = Lo[j-1];
방향[j] = 방향[j-1];
}
기준가[0] = c[g];
방향[0] = u;
Hi[0] = int(h[g]/point);
Lo[0] = int(기준가[1]/point);
}
else {
기준가[0] = min(기준가[1],c[g]);
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
}
else if 방향[0] == u then {
if 기준가[0] - (point * figure) >= c[g] then {
k = k + 1;
for j = min(k,99) downto 1 {
Hi[j] = Hi[j-1];
Lo[j] = Lo[j-1];
방향[j] = 방향[j-1];
}
기준가[0] = c[g];
방향[0] = d;
Hi[0] = int(기준가[1]/point);
Lo[0] = int(l[g]/point);
}
else {
기준가[0] = max(기준가[1],c[g]);
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
}
}
/*
저항선,지지선을 회귀선 공식으로 구하면
n∑xy - (∑x)(∑y) ∑y ∑x
기울기 a = --------------------- 절편 b = ----- - aㆍ------
n∑x²- (∑x)² n n
Y = a*(X - ∑x/n) + ∑y/n
∑xy = 0*Lo[3] + 1*Lo[2] + 2*Lo[1] + 3*Lo[0]
∑x = 0 + 1 + 2 + 3 = 6
∑y = Lo[3] + Lo[2] + Lo[1] + Lo[0]
∑x²= 0 + 1 + 4 + 9 = 14
n∑x²- (∑x)²= 4*14 - 6²= 20
표준오차를 구해서 회귀선이 유효한지 점검
_______________________________________________________
/ 1 [n∑xy - (∑x)(∑y)]²
Sxy = / [ ------- ][n∑y²- (∑y)²- ----------------------- ]
√ n(n-2) n∑x²- (∑x)²
*/
if 방향[0]==u then {
type = 0;
저항기울기 = (4*(Hi[3] + 2*Hi[2] + 3*Hi[1]) - 6*(Hi[4]+Hi[3]+Hi[2]+Hi[1]))/20;
저항선 = 저항기울기*2.5 + (Hi[4]+Hi[3]+Hi[2]+Hi[1])/4;
저항표준오차 = sqrt(0.125 * ((4*(Hi[4]^2 + Hi[3]^2 + Hi[2]^2 + Hi[1]^2)) -
((Hi[4]+Hi[3]+Hi[2]+Hi[1])^2) -
(4*(Hi[3] + 2*Hi[2] + 3*Hi[1]) - 6*(Hi[4]+Hi[3]+Hi[2]+Hi[1]))^2 /20));
지지기울기 = (4*(Lo[2] + 2*Lo[1] + 3*Lo[0]) - 6*(Lo[3]+Lo[2]+Lo[1]+Lo[0]))/20;
지지선 = 지지기울기*1.5 + (Lo[3]+Lo[2]+Lo[1]+Lo[0])/4;
지지표준오차 = sqrt(0.125 * ((4*(Lo[3]^2 + Lo[2]^2 + Lo[1]^2 + Lo[0]^2)) -
((Lo[3]+Lo[2]+Lo[1]+Lo[0])^2) -
(4*(Lo[2] + 2*Lo[1] + 3*Lo[0]) - 6*(Lo[3]+Lo[2]+Lo[1]+Lo[0]))^2 /20));
if -0.7 < 저항기울기 and 저항기울기 < 0.7 and max(Hi[4],Hi[2]) < Hi[0] then {
if 저항표준오차 < 1.3 then {
if 지지표준오차 < 1.3 then {
if 0.7 <= 지지기울기 then type = 11;
else if 지지기울기 <= -0.7 then type = 12;
else type = 13;
}
else type = 14;
}
else {
if 지지표준오차 < 1.3 then {
if 0.7 <= 지지기울기 then type = 21;
else if 지지기울기 <= -0.7 then type = 22;
else type = 23;
}
else type = 24;
}
}
else if 저항기울기 <= -0.7 and 저항선 < Hi[0] and 저항표준오차 < 1.3 then {
if 지지표준오차 < 1.3 then {
if 지지기울기 <= -0.7 then type = 31;
else if 0.7 <= 지지기울기 then type = 32;
else type = 33;
}
else type = 34;
}
}
}
/*
11 12 13 14
x x x x
x o x o x x o x o x x x x x x x
x o x o x x o x o x x o x o x x o x o x
x o x o x x o x o x x o x o x x o x o x
x o x o o x o x x o x o x x o x o x
x o x x o x x x o x
x o o x o x
x x o
21 22 23 24
x x x x
x x x x x x x x
x x x x x x x x
x o x o x x o x o x x o x o x x o x o x
x o x o x x o x o x x o x o x x o x o x
x o x o x x o x o x x o x o x x o x o x
x o x o o x o x x o x o x x o x o x
x o x x o x x x o x
x o o x o x
x x o
31 32 33 34
x x x x
x o x o x o x o
x o x x x o x x x o x x x o x x
x o x o x x o x o x x o x o x x o x o x
x o x o x x o x o x x o x o x x o x o x
o x o x x o x o x o x o x x o x o x
x o x x o x x o x o x o x x
o x x o x
x x
*/
#=====================================================#
# 검색식
#=====================================================#
Find(type);
2005-12-22
1298
글번호 9001
[오픈소스] PnF차트 상승전환 종목 검색식
본 내용은 http://cafe.empas.com/systrader에 게시된 내용입니다.
위에서 작성한 검색식은 저항선을 돌파하는지 판별하는 것이었고 이번에는 그것보다 간단한
P&F 차트상에서 상승으로 전환된 종목을 찾는 검색식입니다.
앞의 수식에서 일부 내용을 삭제하고 방향이 하락에서 상승으로 바뀌었는지를 체크합니다.
/*작성자:수식지왕*/
input:bar_cnt(200);
var:j(0),g(0),r(0),k(0),n(0),point(0),figure(3),u(1),d(-1),이전방향(0);
array:기준가[10](0),Hi[100](0),Lo[100](0),방향[100](0);
#=====================================================#
# main
#=====================================================#
n = bar_cnt - 1;
if i == n then {
point = (highest(c,bar_cnt)-lowest(c,bar_cnt))/50;
기준가[0] = c[n];
k = 0;
방향[0] = 0;
Hi[0] = int(h[n]/point);
Lo[0] = int(l[n]/point);
for g = n - 1 downto 0 {
이전방향 = 방향[0]; //보통의 처리 루틴이라면 이전봉의 값은 방향[0][1]로
//표현할 수 있겠으나 본 검색식에서는 마지막봉에서 모든
//계산이 이루어지므로 이전봉에서의 값을 이런 식으로
//별도의 변수에 넣어 처리하여 함
for r = 9 downto 1 {
기준가[r] = 기준가[r-1];
}
if 방향[0] == 0 then {
if 기준가[0] + (point * figure) <= c[g] then {
기준가[0] = c[g];
방향[0] = u;
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
else if 기준가[0] - (point * figure) >= c[g] then {
기준가[0] = c[g];
방향[0] = d;
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
else {
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
}
else if 방향[0] == d then {
if 기준가[0] + (point * figure) <= c[g] then {
k = k + 1;
for j = min(k,99) downto 1 {
Hi[j] = Hi[j-1];
Lo[j] = Lo[j-1];
방향[j] = 방향[j-1];
}
기준가[0] = c[g];
방향[0] = u;
Hi[0] = int(h[g]/point);
Lo[0] = int(기준가[1]/point);
}
else {
기준가[0] = min(기준가[1],c[g]);
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
}
else if 방향[0] == u then {
if 기준가[0] - (point * figure) >= c[g] then {
k = k + 1;
for j = min(k,99) downto 1 {
Hi[j] = Hi[j-1];
Lo[j] = Lo[j-1];
방향[j] = 방향[j-1];
}
기준가[0] = c[g];
방향[0] = d;
Hi[0] = int(기준가[1]/point);
Lo[0] = int(l[g]/point);
}
else {
기준가[0] = max(기준가[1],c[g]);
Hi[0] = max(Hi[0],int(h[g]/point));
Lo[0] = min(Lo[0],int(l[g]/point));
}
}
}
}
#=====================================================#
# 검색식
#=====================================================#
if 이전방향 == d and 방향[0] == u then var1 = Hi[0];
else var1 = 0;
Find(var1);
2005-12-22
1227
글번호 9000
답변완료
아래의 식 보정 부탁드립니다.
아래의 식은 타종목의 BAND%B를 나타내는 것입니다...
이것을 갭보정 BAND%B로 수정부탁드립니다.
Input :bblen(30),D(2.1);
Var : tr2(0),tr3(0),tr4(0),tr5(0),tr6(0);
var1 = data1("C");
tr2=ma(var1,bblen);
tr3=ma(var1,bblen)+(D*std(var1,bblen));
tr4=ma(var1,bblen)-(D*std(var1,bblen));
tr5=((var1-tr4)/(tr3-tr4))*100;
Plot1(tr5, "Band%B");
PlotBaseLine1(0, "기준선1");
PlotBaseLine2(50, "기준선2");
PlotBaseLine3(100, "기준선3");
2005-12-21
1019
글번호 8999
bigmoney 님에 의해서 삭제되었습니다.
2005-12-21
0
글번호 8998
답변완료
검색식 부탁 합니다.
안녕하세요?
다름이 아니고 주봉챠트로 검색시
20-5-60-120(주) 이렇게 역배열된 상태에서 5주선이 20주선을
돌파한 종목을 검색하고 싶습니다.
감사합니다.
2005-12-20
1308
글번호 8995