53歳限界プログラマの憂鬱

SU/CAR-ST-APplication-cellsから派生したプログラマのブログ

本家はこちら↓
f:id:sucar:20151115183011p:plain

SU/CAR-ST-APplication-cellsのmix of AB(安倍野ミックス)と申します
来訪ありがとうございます
シストレツールを自作してます
自分用の記事が多いのであまり役には立たないブログでしたが
2018/10月以降、多少は役立つブログになるかもしれません
と思いましたが、しばらくは自分用記事が多いかも・・・

f:id:sucar:20150414193802p:plain

自作システム詳細目次

後から1をORでくっ付け条件を殺す仕組み

自作シストレツールのEsgrsdnlというDSL

条件を書いておいて後からその条件を殺す仕組みを作った

例えば

(
        ?       Dc2>Vpc2
        ?       Dc0>Dc2+Vpcp
_OR
        ?       Dc0<Vpc2
)

というある種のフィルタ

()内の_ORで結合されているどこかが1(TRUE)になれば全体が1(TRUE)になるので条件が殺される

なので

(
        ?       Dc2>Vpc2
        ?       Dc0>Dc2+Vpcp
_OR
        ?       Dc0<Vpc2
_OR
        ?       1
)

と最後に1をORでくっ付ければすべての条件を殺せる

この「1をORでくっ付ける」というのをマクロを使って後からスマートに行える仕組みを作った

 まず

(
        ?       Dc2>Vpc2
        ?       Dc0>Dc2+Vpcp
_OR
        ?       Dc0<Vpc2
        __AfterOR__
)

と書いとく(後からORが来ますの意味:和製英語?)

通常はこの__AfterOR__という字句には意味がないので

  • Compileで無視され
  • Assembleでも無視され

と何の影響も及ぼさない

しかし上の方に

	/#AftOR_1/

と書くと

define(`__AfterOR__',`_OR
	? 1')

というm4マクロが定義され、

()内全体が殺されてしまう という仕組み

# AfterOR
s:/#AftOR_1/\(.*\):define(`__AfterOR_\1_',`_OR\n\t\? 1'):g

というsed script でm4のdifineに置換してる

複数個別に制御したい場合は

__AfterOR_1_
__AfterOR_2_

とでもしといて

/#AftOR_1/1
/#AftOR_1/2

で制御できる

sed は便利だ

 

Esgrsdnl(自作のシストレ言語)内に直接C言語で記述できるようにの工夫

Esgrsdnlという自作のシストレ言語(DSL

f:id:sucar:20200716210855p:plain

流れ図みたいなやつ

 Esgrsdnlソース内に直接C言語で記述できるようする工夫

(図で tmp C src を抜き出す部分)

car_m4 というshell script がCompile 処理してるのですが・・・

cat << 'EOS' | sed -f /dev/stdin ./tmpinc.m4 |tee tmpm4.txt|m4 -R ./esgrs/esgrs.m4f |sed -e 's/^\s\+//g' -e 's/\s\+/,/g' -e '/^$/d' > ${OUTPUT}

# _C_
\://_C_SRC_:i DEF C_SRC
\://_C_SRC_:,\://_C_END: {
	w ./main/mt/tmp/func.h
	d
}

#
\://_C_CLC_:i DEF C_CLC
\://_C_CLC_:,\://_C_END: {
	w ./main/mt/tmp/calc.mt
	d
}

(中略)

EOS

の処理

これで

//_C_SRC_
(何らかのC言語ソース)
//_C_END_

または

//_C_CLC_
(何らかのC言語ソース)
//_C_END_

と記述すれば、template C src の中で

#ifdef C_SRC
#include "tmp/func.h"
#endif

または

#ifdef C_CLC
#include "tmp/calc.mt"
#endif

と記述している部分にincludeしてくれる

 _C_SRC_ に関数書いて

_C_CLC_ でその関数を呼び出す

って感じの使い方

これでtemplate C srcを弄らずにいろいろ試せるはず・・・

めんどくさいが・・・

 

sed でセミコロンあるいは波括弧{}がおかしい(w コマンド たぶんrコマンドも)

バグなのか? 仕様なのか?

{}で複数のコマンドを纏めたら変なエラーが出て・・・

 sed '/_start_/,/_end_/ {w testest.txt;d}

これを実行すると

sed: -e expression #1, char 0: `{' が不一致です

と}を認識してくれない???

 sed -e '/_start_/,/_end_/ w testest.txt' -e '/_start_/,/_end_/d'

コマンドを分けて書けば問題ない

しかし同じアドレスを2回も書くのは不満だ

何のための波括弧{}と;セミコロンなのか???

さっぱりわからずorz

試しに

 sed '/_start_/,/_end_/ {w testest.txt}

これを実行するとなぜかやはり

sed: -e expression #1, char 0: `{' が不一致です

と}を認識してくれない???

 勿論コマンド一つなので{}は不要で{}を消せばエラーは出ない

さらに試しに

 sed '/_start_/,/_end_/ {d}

これを実行するとなぜかエラーは出ない

まったく???なんだけども 結局のところ・・・

ja.stackoverflow.com

これ見て納得

rコマンドでそうならWコマンドでそうなるんだろう

しかしバグなのか? 仕様なのか?

なので

 sed '/_start_/,/_end_/ {w testest.txt
    d}'

と2行に分けて(セミコロンは不要)書くことで解決

まあ普通ソース読まないですorz

 

 

sedで強引にインクルード処理

sed にrコマンドというのがありinclude処理的なことができます

現在の自作シストレシステムの自作言語(DSL:Esgrsdnlと命名)のコンパイル処理の流れ図

f:id:sucar:20200716210855p:plain

インクルード処理に2つあって

  • sedによるCompile前の処理
  • m4によるAseemble前の処理

注:C言語へのトランスパイルDSLなので本当の意味のComplie Assembleではありません

のうちのsedによる~の方

m4で2回とも処理してもいいのですが2回も通すと変な副作用がある可能性が・・・

なのでsedで・・・・

結局sedも2回通すのでm4でもよかったかもしれませんが・・・

どうもm4のマクロ名が[a-zA-Z_][0-9a-zA-Z_]*しか使えず、かならず

マクロ名(引数,‥)となるのがちょっと好みに合わない・・・

ただ問題があって・・・

処理するソース内にincludeするfile名を直接書けず、sed scriptの方に書くことになる

という・・・

ただ何でもかんでもどこにあるfileでも自由にincludeできる仕様でも好みではないので

includeしたいファイルを置いた時点でコマンド発行して、include処理するscriptを自動生成するようにした

./suQ2/inc/fix にincludeできるファイルがあって

f:id:sucar:20200718094705p:plain

このうち 末尾が"__"のファイルがesgrsdnlで書かれたincludeファイルということにしておいて

$suQ2/mkinc

を実行 中身はshell scriptで

cd `dirname $0`
cd ./inc/fix
pwd
ls *__ | awk '{printf("\\:^[ \\t]*//#__%s:r ./inc/fix/%s\n",$1,$1)}' > ../../esgrs/sedinc.sed

となってる

 これで

./suQ2/esgrs/sedinc.sedが生成され 中身は

\:^[ \t]*//#__05c9y00__:r ./inc/fix/05c9y00__
\:^[ \t]*//#__05cOR00__:r ./inc/fix/05cOR00__
\:^[ \t]*//#__mp16_3__:r ./inc/fix/mp16_3__
\:^[ \t]*//#__test__:r ./inc/fix/test__

こうなる

 あとはソースに

//#__05cOR00__

と書いておけば

その個所に05cOR00__がincludeされる

ちなみにさらに処理が進むと//~はコメントになるのでソース処理後に

//#__05cOR00__

は消える

 

正規表現はややこしいですがテクニック的には

 sed正規表現のアドレス部分に / があるので

/~/の代わりに¥:~:を使って

ただawkのprintf文""のなかで¥がエスケープされるので¥¥にしとく

とか

^[ \t]*//

としてるので,

行頭 0個以上の空白文字後の//が対象になるので

コメントアウトしたければ

; //#__05cOR00__
または
// //#__05cOR00__

コメントアウトできる

ややこしい

 

 

 

 

 

自作システムのC言語sub以下をライブラリ化

自作システムのエンジン部分はC言語で分割ファイル活用してちょっとだけ本格的に構築してる(グダグダですが)

で個別のsubファイルは

suQ2/main/sub に入ってて、そのフォルダでmake一発でオブジェクトファイルにコンパイルできる

しかし、機能UPよりオブジェクトが増えてくるとそれをmainコンパイルshellスクリプトコンパイルするんだが、増えたオブジェクトファイル名をいちいち書き足さないといけなかった

折角なので ar を使ってライブラリ化してみた

suQ2/main/sub/makefile

# Makefile_other
# プログラム名とオブジェクトファイル名
PROGRAM = main
OBJS = read_kd.o read_kd0.o check0.o read_kd2.o matome.o sngrx.o common_y.o output.o bnkt.o dump.o import.o

# 定義済みマクロの再定義
CC = gcc
#CFLAGS = -Wall -O2
CFLAGS =  -O2
AR = ar
ARFLAG = crsv
LFILE = libSucar.a
# サフィックスルール適用対象の拡張子の定義
.SUFFIXES: .c .o

# プライマリターゲット
$(PROGRAM): $(OBJS)
	#$(CC) -o $(PROGRAM) $^
	ls -l  $(OBJS)
	$(AR) $(ARFLAG) $(LFILE) $(OBJS)
	@echo "libSucar.a make success"


# サフィックスルール
.c.o:
	$(CC) $(CFLAGS) -c $<

# ファイル削除用ターゲット
.PHONY: clean
clean:
	$(RM) $(OBJS)

# ヘッダファイルの依存関係
read_kd.o: check0.h read_kd.h env.h
read_kd0.o: check0.h read_kd0.h env.h
read_kd2.o: check0.h read_kd2.h env.h
cheack0.o: check0.h env.h
matome.o: matome.h env.h
sngrx.o: sngrx.h env.h
common_y.o: sngrx.h env.h common_y.h
output.o: sngrx.h env.h common_y.h output.h
bnkt.o: env.h bnkt.h
dump.o: env.h dump.h
import.o: env.h import.h

ここを参考にさせていただきました

programmer-toy-box.sblo.jp

コンパイルスクリプトの方は

suQ2/main/mk_MAIN_

MAIN=`cat _MAIN_`
echo mk_MAIN_  '('${MAIN}')'
gcc -c ${MAIN}.c -o simxp8trsu_nobug2.o

echo compile and link Sucar.a
gcc  simxp8trsu_nobug2.o -L./sub -lSucar -o simxp8trsu_nobug2.exe
exit

でうまく行った

signal import の拡張

suQ2/main/main_000.c

double *V[100];
char *imfn;
char *imdir;

char *imdir;を追加して

#ifdef _SG_IMPORT_
	//ここにsignal import処理
	//ck[i][j]==0 だとシグナルになる
	//つまり何もしないとすべてにシグナルが立っている
	imfn=_SG_IMPORT_;
#ifndef _SG_IMP_DIR_
	import(imfn);
#else
	imdir=_SG_IMP_DIR_;
	import2(imfn,imdir);
#endif
#endif

 _SG_IMP_DIR_が定義されていると import2()を呼ぶ

suQ2/main/sub/import.h

int import(char *);
int import2(char *,char *);

suQ2/main/sub/import.c

int import2(char *imfn,char *imdir) {
	int i,j,n;
	char buf[40];
	char impfilename[100];
	char Dt[11];
	int date,jdate;
	uint8_t imCode[8];
	FILE *fp;
	sprintf(impfilename,"./import/%s/signal%s.txt",imdir,imfn);
	for (j=0;j<DtMax;j++){
		for (i=0;i<CodeMax;i++){
			ck[i][j]=-1;
		}
	}
	fp=fopen(impfilename, "rt");
	if (fp) {
		fprintf(stderr,"%s import\n",impfilename);
		j=0;
		while ( fgets(buf,40,fp)!=NULL) { 
			n=check0(buf);
			if (n!=0) {
				sscanf(buf,"%s %s",Dt,imCode);
				date=dt2int(Dt);
				for (;j<DtMax;j++) {
					jdate=dt2int(dt[j]);
					if (date==jdate) break;
				}
				if (j==DtMax) break;
				if (date==jdate){ //念のため
					for (i=0;i<CodeMax;i++) {
						if (strcmp(imCode,code[i])==0) {
							ck[i][j]=0;
							//debug
							//fprintf(stderr,"%s:: %s %d %d\n",code[i],imCord,i,j);
							break;
						}
					}
				}
				
			}
		}
		fclose(fp);
	}
	else fprintf(stderr,"cannot open import%s\n",imfn);
	return 0;
}

 

 import2()を追加

awk/mt_h_2.awk

$1=="_SG_IMP_" || $1=="SG_IMP" {
	printf("#define _SG_IMPORT_ \"%s\"\n",$2)
	if ($3!="") {
		printf("#define _SG_IMP_DIR_ \"%s\"\n",$3)
	}
	}

_SG_IMP_に処理追加

これで

	_SG_IMP_	ALL	subdir

とやるとimportするsub dir を指定できる

 

 

R_NOW_IMP.m4にexportされるrule(9-12)

suR1/rule9.R

2019/7/27追加)

 

#暫定1号
#25日移動平均乖離率が小さい順の下から0.1%
#
if (lmt==0) {lmt<-10}
#
s$h25<-hei25(s) ans<-tapply(s$h25,s$j,quantile,0.001,na.rm=TRUE) ans0<-hei(ans,10) q <- subset(s , #M525 s5m(sp0m)+5*s25m(sp0m)<(-10) & # h25<ans0[j+1]& ##h25< (-20)& h25< (-20)& dai>100000000& TRUE ) #ソートしていないので猿ダーツ index<-tapply(-q$dai,q$j,order) ans<-NULL for (i in 1:length(index)) { ans<-c(ans,index[ [i] ]) } q$ord<-ans p<-subset(q,ord<=lmt) #p<-q rm(q) #-5%で指値5日後引け成り売り kai_k<- 5.0 uri_k<- 6.0 kai<-0 uri<-3 kap<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8) urp<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8)

となってる

無駄な部分もあるが、壊すといけないので整理はせずこのまま

 バックテスト

f:id:sucar:20190629135521p:plain

最近好調!

 suR1/rule10.R

#暫定2号
#75日移動平均乖離率が小さい順の下から0.1%
#
if (lmt==0) {lmt<-10}
#
s$h75<-hei75(s) ans<-tapply(s$h75,s$j,quantile,0.001,na.rm=TRUE) ans0<-hei(ans,10) q <- subset(s , #M575 s5m(sp0m)+5*s75m(sp0m)<(10) & # h75<ans0[j+1]& h75< (-30)& ##h75< (-25)& dai>100000000& TRUE ) #ソートしていないので猿ダーツ index<-tapply(-q$dai,q$j,order) ans<-NULL for (i in 1:length(index)) { ans<-c(ans,index[ [i] ]) } q$ord<-ans p<-subset(q,ord<=lmt) #p<-q rm(q) #-5%で指値5日後引け成り売り kai_k<- 5.0 uri_k<- 6.0 kai<-0 uri<-3 kap<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8) urp<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8)

バックテスト

f:id:sucar:20190629135843p:plain

これもいい感じ

 suR1/rule11.R

#暫定3号
#125日移動平均乖離率が小さい順の下から0.1%
#
if (lmt==0) {lmt<-10}
#
s$h125<-hei125(s) ans<-tapply(s$h125,s$j,quantile,0.001,na.rm=TRUE) ans0<-hei(ans,10) q <- subset(s , #M5125 s5m(sp0m)+5*s125m(sp0m)<(-10) & # h125<ans0[j+1]& ##h125< (-25)& h125< (-30)& dai>100000000& TRUE ) #ソートしていないので猿ダーツ index<-tapply(-q$dai,q$j,order) ans<-NULL for (i in 1:length(index)) { ans<-c(ans,index[ [i] ]) } q$ord<-ans p<-subset(q,ord<=lmt) #p<-q rm(q) #-5%で指値5日後引け成り売り kai_k<- 5.0 uri_k<- 6.0 kai<-0 uri<-3 kap<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8) urp<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8)

バックテスト

f:id:sucar:20190629140024p:plain

これもいい感じ

 suR1/rule12.R

#暫定4号
#15日移動平均乖離率が小さい順の下から0.1%
#
if (lmt==0) {lmt<-10}
#
s$h15<-hei15(s) ans<-tapply(s$h15,s$j,quantile,0.001,na.rm=TRUE) ans0<-hei(ans,10) q <- subset(s , #M515 s5m(sp0m)+5*s15m(sp0m)<(-10) & # h15<ans0[j+1]& ##h15< (-15)& h15< (-15)& dai>100000000& TRUE ) #ソートしていないので猿ダーツ index<-tapply(-q$dai,q$j,order) ans<-NULL for (i in 1:length(index)) { ans<-c(ans,index[ [i] ]) } q$ord<-ans p<-subset(q,ord<=lmt) #p<-q rm(q) #-5%で指値5日後引け成り売り kai_k<- 5.0 uri_k<- 6.0 kai<-0 uri<-3 kap<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8) urp<- abs((p$owa0-p$h10j0)/p$h10j0*100.0*0.8)

バックテスト

f:id:sucar:20190629140251p:plain

これも好調