Backtrader学習途上

Backtrader

サンプルスクリプトを弄っています。Ta-Libのインストールを終えて一通りインジケーターを表示してみました。
最終的にはMT4やMT5のインジケーターをBacktrader用に書き換えられたらいいなと思っています。

しかしながらMQLと違っていてなかなか大変です。MQLのときもだいぶ苦労しましたけれども、あのとき以来の手探り状態です。
クラスのコンストラクタでインジケーターのラインオブジェクトやパラメーターを宣言して計算式を入力。そしてCerebro.Runする。
というのがおおまかな流れのようです。ほかにもNextメソッドとかRunonceメソッドとか紹介されてましたが全容が掴めてません・・・。なにか高機能なものらしいです。

誰か日本語で解説記事を書いてくれないでしょうか?切なる願いです・・・。


f:id:xxsoutosi:20200131200638p:plain
Talib_rsi

Pythonのトレーディング用ライブラリー比較 その2

Backtrader

日本語の情報が少ないような気がする。Ziplineで苦戦した後だったので動作するか不安だったが、Quickstartページのサンプルスクリプトは問題なく動作した。

ただしサンプルスクリプト内で使われているYahooファイナンスCSVデータはBacktraderといっしょにダウンロードされない。(バージョンによって同梱されてない場合がある?)

「datas/orcl-1995-2014.txt」
このファイルが必要なのでBactraderのGitページからコピーしてくる。どこか適当な場所に保存してスクリプト内のファイルパス指定部分を書き換える。

datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt')

#これを下記みたいに書き換えるといい

datapath = 'C:\\Users\\○○○\\orcl-1995-2014.txt'

ドキュメントをざっと読んだ感じだと、私でも扱えそうな気がする。
Backtesting.pyの日本語記事はいくつか見掛けたけどBacktraderのは少ない気がする。
Backtraderもっと普及してほしい。一助になれば幸いです。

Pythonのトレーディング用ライブラリー比較

Zipline

Gitで頻繁に更新されていたので導入しやすいのではないかと予想。しかしそれは表面上であって公式サポートがしっかりと行われている訳ではない様子。
QuickStartページの一番簡単なサンプルスクリプトですらエラーが発生、いろいろな質問サイトで同様の質問が繰り返されているのに公式ページに長い間反映されていない。以前は動作していたのにデータ提供元の変更でスクリプトが動かなくなってしまったといった情報もちらほら見かける。ユーザー同士で問題解決のため頻繁に情報がやり取りされてはいるがやはり公式なフォローはなく初心者には敷居が高い印象。やはりもう一方の有料バージョン(Quantopian?)でないと実用的なレベルにはならないのだろうか?

WindowsMacLinuxの情報が混在していて大変だったが、なんとか価格データテーブル?を読み込むところまではうまくいった。しかし実際にバックテストをしようとするとアップルのデータがJSONREADERROR?になってしまう。調べてみるとbenchmark.pyというファイルを書き換えるといいらしいのだが、同名のファイルが複数存在していて、且つ機能的に重要そうだったため一旦中止した。そして放置。

Python・Anacondaの豊富な情報と導入のしやすさを体験してしまうと、もはやZiplineには魅力を感じなくなる。少なくとも現時点では。
というか普及させるつもりあるんだろうか? 悪い意味でPerlっぽい。情報がたくさんあるように見えて本当に必要なものはないように感じる。バージョンアップして内容が充実したらまたチャレンジするかも。

For ループの中にアラート呼び出しを書くと初回起動したときに過去のアラートが全部表示される問題対策

 
if (counted_bars==0) limit=Bars-MathMax(PerNR,PerATR);
if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
if(counted_bars>0) limit=Bars-counted_bars;
limit--;


//---- main loop
for(int i=limit; i>=0; i--)
{
tempval=0.0;

//-----------------------------------------------
if (High[i+2]<High[i+3]&&Low[i+2]>Low[i+3])
{
//-----------------------------------------------



if (High[i+1]<High[i+2]&&Low[i+1]>Low[i+2]){

minATR=iATR(NULL,0,PerATR,i+1);

for(int cnt=i+2;cnt<(i+1+PerNR);cnt++){
currATR=iATR(NULL,0,PerATR,cnt);
if (currATR<minATR) minATR=currATR;
}

if (minATR==iATR(NULL,0,PerATR,i+1)){
tempval=(High[i+1]+Low[i+1])/2;
ExtMapBuffer1[i+1]= tempval;



if (counted_bars !=0 && alertsOn) {
doAlert(i+1,TimeToStr(Time[i+1],TIME_MINUTES)+"NR4 On");
}
}
}



}

Perl ベストプラクティス 気になったもの

3.1. Identifiers
Use grammatical templates when forming identifiers.



4.5. Constants
Use named constants, but don't use constant.


4.10. Heredoc Indentation
Use a "theredoc" when a heredoc would compromise your indentation.



4.18. List Membership
Use table-lookup to test for membership in lists of strings; use any( ) for membership of lists of anything else.



5.2. Package Variables
Don't use package variables in your own development.


5.4. Initialization
Initialize any variable you localize.


5.11. Slice Layout
Use a tabular layout for slices.



6.10. List Generation
Use map instead of for when generating new lists from old.


7.11. Defensive Documentation
Comment anything that has puzzled or tricked you.


7.12. Indicative Documentation
Consider whether it's better to rewrite than to comment.


7.13. Discursive Documentation
Use "invisible" POD sections for longer technical discussions


8.1. Sorting
Don't recompute sort keys inside a sort.


8.4. Fixed-Width Data
Use unpack to extract fixed-width fields.


8.5. Separated Data
Use split to extract simple variable-width fields.


8.6. Variable-Width Data
Use Text::CSV_XS to extract complex variable-width fields.


8.14. Utilities
Use the "non-builtin builtins".


9.1. Call Syntax
Call subroutines with parentheses but without a leading &.


9.3. Argument Lists
Always unpack @_first.


10.7. Input Loops
Use while (<>), not for (<>).


10.9. Simple Slurping
Slurp a filehandle with a do block for purity.


10.10. Power Slurping
Slurp a stream with Perl6::Slurp for power and simplicity.


10.17. Automatic Progress Indicators
Consider using the Smart::Comments module to automate your progress indicators.


12.20. Canned Regexes
Consider using Regexp::Common instead of writing your own regexes.


18.13. Semi-Automatic Debugging
Consider using "smart comments" when debugging, rather than warn statements.









dispatch メソッド

class Parent:
    def __init__(self):
        self.child1 = u"太郎"
        self.child2 = u"次郎"
        self.child3 = u"三郎"

parent = Parent()
for i in xrange(1,4):
    print i,u"番目の子供は", getattr(parent,"child" + str(i))

getattrは文字列として引数を受け取るのでディスパッチテーブルのような分岐処理が実現できる。

関数を作り出す関数...それが高階関数

# curry.pl
 
sub curry {
	my $func = shift;
	my @capture_arg = @_;
	return sub { return $func->(@capture_arg, @_); }
}
 
 
my $for_print = sub { print "@_\n"; };


 
my $printer = curry($for_print, "Hello,"); # 引数をキャプチャする
$printer->("world!");
$printer->("perl!");


 

 
my $for_multiply = sub {
	           $answer = 1;
	           for (@_) { $answer *= $_; }
	           return $answer;
               };

print $for_multiply->(2, 3, 4), "\n";


 
my $multipler = curry($for_multiply, 10); # 引数をキャプチャする
print $multipler->(5), "\n";

Shift()でサブルーチン


# ref6.pl
 
sub hellofunc {
	my $func = shift;
	return $func->("Hello!");
}
 
hellofunc( sub { print "@_\n"; } );         # (1)
hellofunc( sub { print "@_ World!\n"; } );  # (2)
 
my $decorator = sub {
	return "***" . shift() . "***";     #shift()で受け取ったコードを実行できる! 知らなかった
};
print hellofunc($decorator), "\n";          # (3) 

perldocより

以下の違いを考えてみてください。 CASE 0 は、CASE 1 を短くしたものであり、CASE 2 を 短くしたものでは ありません:

    # CASE 0
    $$hashref{"KEY"}   = "VALUE";    # $hashrefはリファレンスで特定のハッシュを指していてその"KEY"キーの値をデリファレンスしている
                                     # $hashref->{"KEY"}と同じ
       
    # CASE 1
    ${$hashref}{"KEY"} = "VALUE";    # CASE0を極端に表した例
              ^^


    # CASE 2
    ${$hashref{"KEY"}} = "VALUE";    # %hashrefが存在していて、その"KEY"キーの値はリファレンスで、それをデリファレンスしている   
     ^               ^



    # CASE 3
    ${$hashref->{"KEY"}} = "VALUE";  # $hashref->{"KEY"}の値がリファレンスで、それをデリファレンスしている

CASE 2 もまた間違えやすいもので、%hashref という変数にアクセスするものです。 $hashref を仲介して、それが指すことになっているハッシュを デリファレンスしているものではありません。 それは、CASE 3 です。

iBarshift関数の位置を実際に見てみよう

#property strict
#property indicator_chart_window

void OnInit(){
// オブジェクト全削除
ObjectsDeleteAll();


datetime StartTime =D'2017.02.17 15:48:30';
int iStart = iBarShift( NULL, 0, StartTime);

// 垂直線オブジェクト(Time[iStart]の位置に作成)

ObjectCreate("垂直線",OBJ_VLINE,0,Time[iStart],0);


}

//

int start()
{
return(0);
}

Property Strict設定


datetime date = D'2014.03.05 15:46:58';
string str = "mydate="+date;

Print(str);
// mydate=1394034418 - 古いMQL4での結果
// mydate=1394034418 - 新しいMQL4で#property strict無しの時の結果
// mydate=2014.03.05 15:46:58 - 新しいMQL4で#property strict有りの時の結果