恥は/dev/nullへ by 初心者

プログラミング素人がのろのろと学んだことをつづっています♪

Debian環境設定(1) 名前解決の問題

前置き

近年はMacBookUbuntuを使っていたため(インストール後、そのまま使えてしまうため)、最近のLinuxの設定知識がビミョーです。
そこで、Debian 10(buster)を最小構成でインストールして、勉強しつつ環境作りをしています。

 

名前解決ができていない?

必要なソフトをインストールしようとしてapt-get install を実行しましたが、上手く行きませんでした。
そこで、ネットワークの接続状況を調べてみました。

ping -c 2 8.8.8.8

としてみると応答があったので、ネットには接続できているようです。
しかし、、、

ping -c 2 dns.google

としてみると「ping: dns.google: Temporary failure in name resolution」となってしまいました。

以上のことから、名前解決ができていないと分かりました。

 

/etc/resolv.confとDHCP

名前解決に関するファイルとしては、/etc/hostsや/etc/resolv.confがありますね。
/etc/hosts には問題がなかったので、/etc/resolv.conf を開いてみました。

nameserver 192.168.10.1

となっています。自宅のルーターを指しているので問題なさそうです。
しかし、この設定で名前解決ができていないので、これをGoogleDNSに変更してみました。

nameserver 8.8.8.8

にしてみると、無事に名前解決ができました。
これでaptコマンドが使えるようになったので、manやsudoなどをインストールしました。

 

しかし、Debian再起動すると /etc/resolv.confの内容が元に戻ってしまいます。

インストール時点でネットワークの設定をしていないので、DHCPでネット接続しているはずです。とすれば、DHCPがこのファイルを書き換えているものと思います。

 

/etc/network/interfacesを修正(DHCPを無効にする)

/etc/network/interfacesを開いてみると、次の行が目に留まりました。

allow-hotplug enp0s3
iface enp0s3 inet dhcp

この2行のうち、2行目をコメントアウトして、代わりにstaticなアドレスを割り当てることにしました。

 

そこで、

man interfaces

を実行して斜め読みしてみたら、以下の記述がありました。

f:id:philojuan:20201217174255p:plain


この記述を読んで /etc/network/interfaces の一部を以下のように修正しました。

allow-hotplug enp0s3
auto enp0s3           ← この行を忘れずに追記

# iface enp0s3 inet dhcp

iface enp0s3 inet static
    address   192.168.10.7
    netmask   255.255.255.0
    broadcast 192.168.10.255
    gateway   192.168.10.1

これでDHCPによるresolv.confの書き換えは起きないはずです。

 

ひとまず解決

再起動してから /etc/resolv.conf を開くと

nameserver 8.8.8.8

となっていて、DHCPによる書き換えは起きていませんでした。

ping -c 2 dns.google

を実行してみると無事に応答がありました。

 

課題(DHCPの設定)

DHCPによる割り当てが上手く行っていないことが気になります。
ネットワーク以外の環境を整えてから、この問題に取り組もうと思います。

 

他に使ったコマンド

systemctl status networking.service
service networking restart

2つ目はネットワーク関係のinitスクリプトを実行させるためのものです。
これにより /etc/init.d/networking スクリプトが実行されます。

 

任意のローソク足のvolume値が、過去N本のvolume値の上位 X番目までにランクインしているか調べてみる

任意の足のvolume値が、過去N本のvolume値の上位 X番目までにランクインしているか調べる関数を書いてみました。ただ、これは依頼されて作った関数なので、私は使用していません^^;。(関数のコードは本記事の末尾にあります)

 

関数が行っていること

 a本目のローソク足から過去N本の範囲の出来高(volume)を調べます。
その範囲の上位X番目のvolume値と指定したローソク足pのvolume値を比較します。
指定したローソク足pのvolume値が、上位X番目のvolume値以上ならtrueを返します。

WithinTopXvolume(p, a, N, X)

 

具体例

 2本目のローソク足出来高(volume)が、「3本目から過去10本(3本目~12本目)の出来高のうち、上位5番目」までにランクインしているか調べる場合、引数は以下のようになります。

WithinTopXvolume(2, 3, 10, 5)

 

戻り値

ランクインしている場合は true を返します。
ランクインしていない場合は false を返します。

 

備考

チャート上に存在しない足を検索対象として指定した場合、上述の調査をしない
で処理を中止します。この時、関数はfalseを返し、アラートを出します。
アラートが出た場合の戻り値 falseは、「調査を実行できなかった」という意味のfalseです。

チャート上に存在しない足を検索対象にしないという観点で言えば、第1引数~第3引数は「0以上」でなくてはなりません。

それと、ランキングの先頭は1番目という前提で以下のコードは書かれているので、第4引数は「1以上」でなくてはなりません。

 

コード

//------------------------------------------------------------------------------
// 任意のローソク足のvolume値が、過去N本のvolume値の上位 X番目以内か調べる関数
//------------------------------------------------------------------------------
// [この関数が行っていること]
// a本目のローソク足から過去N本の範囲の出来高(volume)を調べる。
// その範囲の上位X番目のvolume値と指定したローソク足のvolume値を比較する。
// 指定したローソク足のvolume値が、上位X番目のvolume値以上ならtrueを返す。
//
// [使用例]
// 2本目のローソク足出来高(volume)が、「3本目から過去10本(3本目~12本目)
// の出来高のうち、上位5番目」までにランクインしているか調べる場合、引数は
// 以下のとおり。
//
//     WithinTopXvolume(2, 3, 10, 5)
//
// [戻り値]
// ランクインしている場合は true を返す。
// ランクインしていない場合は false を返す。
//
// [備考]
// チャート上に存在しない足を検索対象として指定した場合、上述の調査をしない
// で処理を中止する。この時、関数はfalseを返し、アラートを出す。
// アラートが出た場合、「調査を実行できなかった」という意味でfalse。
//------------------------------------------------------------------------------

bool WithinTopXvolume(int targetShift,    // 対象とする足のシフト
                      int startShift,     // 範囲の開始シフト
                      int bars,           // 範囲(開始シフトを含めてN本)
                      int rank)           // 範囲の上位 X 番目
{
    //-----------------------------------------------------------------------------
    // チャート上に存在しない足を検索対象にした場合、処理を中止してアラートを出す
    //-----------------------------------------------------------------------------
    if(Bars - 1 < startShift + bars - 1) {    // 左辺と右辺の「-1」は無くてもOK
        Alert("Function Error [WithinTopXvolume] : Read the message on Expert.");
        printf("Function Error [WithinTopXvolume] : You tried to access the candle out of range.");
        return(false);
    }

    bool res = false; // 関数の戻り値
    int counter = 0;  // 配列操作用のカウンタ

    long array[];              // iVolume関数の戻り値がlong型なので配列もlong型
    ArrayResize(array, bars);  // 配列の要素数をセット

    // 指定したシフトから過去bars本の出来高を配列に格納
    for(int k = startShift; k < startShift + bars; k++) {
        array[counter] = iVolume(NULL, PERIOD_CURRENT, k);
        counter++;
    }

    //-----------------------------------------------------------------------------
    // 配列内に同じ値が2つ以上あったら、1つは残し、残りは最小値に書き換える
    //-----------------------------------------------------------------------------
    // 最初に配列の中身を降順で並び替えておく
    ArraySort(array, WHOLE_ARRAY, 0, MODE_DESCEND);

    // 配列内の最小値をminValueに格納
    // (降順ソート済なので long minValue = array[bars - 1] でも可)
    long minValue = array[ArrayMinimum(array, WHOLE_ARRAY, 0)];

    long tmp = array[0];            // 配列の先頭要素の値をtmpに代入

    for(int j = 1; j < bars; j++) {
        // 要素の値が最小値と同じならループを抜ける(無駄な処理を減らす)
        if(array[j] == minValue) break;

        // 要素の値がtmpと同じなら、その要素をminValueに書き換える
        if(tmp == array[j]) {
            array[j] = minValue;
        }
        // 要素の値がtmpと違うなら、tmpにその要素の値を代入する
        else {
            tmp = array[j];
        }
    }

    ArraySort(array, WHOLE_ARRAY, 0, MODE_DESCEND);  // 改めて降順で並び替え

    // 比較対象とするローソク足のvolume値をtargetValueに格納
    long targetValue = iVolume(NULL, PERIOD_CURRENT, targetShift);

    // targetValueが上位X番目のvolume値以上ならresにtrueを代入
    if(targetValue >= array[rank - 1])
    {
        res = true;
    }

    return res;
}

 

 追記

この記事を書き終えてから思ったのですが・・・。

for(int j = 1; j < bars; j++) {

この行の「bars」のところは「bars - 1」の方が良かったですね。

降順に並び替えた後なので、配列の最終要素は最小値です。
だから、配列の最終要素に対しては何の処理も不要ですね。

「R」起動時の処理を記述するファイル (.Rprofile)

(前置き)この記事において、ホームディレクトリは /home/juan/ です。

 

Rを起動した時点では、ホームディレクトリにいる状態です。
R用に「R_space」ディレクトリを作成したので、そこを作業ディレクトリにしようと思いました。

 

そこで、作業ディレクトリを指定するsetwdコマンドを使いました。

> setwd("/home/juan/R_space")

 

しかし、Rを再起動してgetwdコマンドを実行すると、作業ディレクトリがホームディレクトリに戻ってしまっています。(備考:getwdコマンドは作業ディレクトリの場所を表示するコマンド。)

 

これではRを使うたびにsetwdで作業ディレクトリを指定しなければならなくて不便です。普通に考えて初期化処理を行う方法があるはずだと思ったのでネット検索をしてみました。

 

以下のページによると、「.Rprofile」というファイルを作れば、初期化処理ができるようです。
https://stats.biopapyrus.jp/r/devel/rprofile.html

 

そこで、ホームディレクトリに.Rprofileファイルを作成し、

setwd("/home/juan/R_space")

と記述しました。

 

そして、Rを再起動して

> getwd()

を実行しました。

 

実行結果は以下のとおりで、「R_space」が作業ディレクトリとなっていました。

[1] "/home/juan/R_space"

 

無事解決です^^。

統計言語「R」をUbuntu 20.04.1 LTSにインストール

タイトルのまんまですが、統計処理に使うRという言語をインストールしました。

同じ作業をしないとも限らないので、備忘録として残しておくことにしました。

 

Ubuntuのバージョン確認

最初にUbuntuのバージョンを確認します。

catコマンドを使って、

cat /etc/os-release

もしくは

cat /etc/lsb-release

で確認できます。

 

catコマンドの出力結果は以下のとおりでした。

 f:id:philojuan:20201104023735p:plain

 この結果からUbuntuのバージョンは「20.04.1 LTS」で、コードネームは「focal」だと確認できます。

 

GPGキーの登録

ネットを調べたところ、GPGキーの登録が必要なようです。

以下のコマンドを実行します。 

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9

 

リポジトリの追加

次はaptコマンド用のリポジトリの追加です。

add-apt-repositoryコマンドで統計数理研究所のRリポジトリを追加します。

sudo add-apt-repository 'deb https://cran.ism.ac.jp/bin/linux/ubuntu focal-cran40/'

 このコマンドの末尾が「focal-cran40」となっていることに御注意ください。先にUbuntuのバージョンを確認しておいたのは、この部分(ディレクトリ名)に何を指定するか決めるためです。

もしバージョン「18.04」、コードネーム「bionic」だった場合、「focal-cran40」ではなく「bionic-cran40」となります。

 

念のため、リポジトリがsources.listファイルに追加されたか確認しておきます。

tailコマンドを使いましょう。

tail -n 4 /etc/apt/sources.list

 これは sources.listファイルのラスト4行を表示せよという意味です。 

 

実行結果は以下のとおりです。ちゃんとリポジトリが追加されていますね(下から2行目)。

f:id:philojuan:20201104024348p:plain

 

Rのインストール

あとは、以下のコマンドを実行するだけです。

sudo apt update
sudo apt install r-base

 インストールはこれで終了です。

 

Rが起動するか確認

念のため、Rが起動するか確認してみましょう。

ターミナルで「R」と入力したら、無事にRの画面が表示されました。

f:id:philojuan:20201104025659p:plain

 

Ubuntuのバージョン確認

Ubuntuのバージョン確認なんて1年に数えるくらいしか行わないので、どのファイルを見ればいいのか忘れてしまい、毎回ネット検索をしています。

 そんなわけで備忘録を残すことにしました。

 

/etc/os-release

を見ればOK。

 

ちなみに、今回バージョン確認をしたのは、統計分析用のRをインストールするためです。Rのリポジトリを開いた折、Ubuntuのバージョンごとにファイルが置かれていたのを見て「我が家のUbuntuのバージョンって何だったっけ?」となった次第です。

 

「os-release」の中を見たらバージョン18のLTSだと判明。

そのままでもRをインストールすることはできたのですが、既にUbuntuの最新バージョンは20になっているので、Ubuntuのバージョンアップを行いました。

 

バージョンアップにかかった時間は22分くらい。これといって問題無く終わり、今はバージョン「20.04.1 LTS (Focal Fossa)」になりました^^。

 

/etc/os-releaseの本体

os-releaseって普通のテキストファイルだよね・・・、と思いつつ、何となく気になったので lsコマンドで調べてみました。

$ ls -l /etc/os-release 
lrwxrwxrwx 1 root root 21 8月 17 22:31 /etc/os-release -> ../usr/lib/os-release

この結果からお分かりのとおり、/usr/lib/os-releaseへの シンボリックリンクになっていました。というわけで、本体は /usr/lib ディレクトリにあるようです。

知らなかった・・・^^;。

 

ヒストリカルデータのインポートとデータ生成(MT4)

EAのバックテストをするために自分が使用している業者のヒストリカルデータをインポートしたのですが、手順を忘れてしまいそうなので、メモ代わりに作業内容を残しておくことにしました。

 

通常は1分足のヒストリカルデータが配布されていると思うので、それを前提にこの記事は書かれています。

 

ヒストリカルデータのインポート

f:id:philojuan:20201102082941p:plain

「ツール」→「ヒストリーセンター」を開きます。

通貨ペアを選択し、「1分足(M1)」をダブルクリックします。

「インポート」ボタンをクリックします。

 

f:id:philojuan:20201102083106p:plain

「ファイル名」枠の右隣にある「参照」ボタンを使って、インポートするファイルを選択します。

 

f:id:philojuan:20201102083230p:plain

選択したファイルのデータが画面に表示されたら「OK」ボタンをクリック。
(これを取り込むファイルの数だけ繰り返します。)

 

これでヒストリカルデータの取り込みは完了です。

 

1分足以外のヒストリカルデータを生成する

現時点では、1分足のデータしか存在しません(5分足や15分足など、他の時間軸のデータがありません)。このため、5分足や1時間足などでバックテストをしようにもできない状況です。そこで、1分足以外のヒストリカルデータを生成します。

 

データを生成するには、通常、MT4の「スクリプト」の中にある「Period Coverter」を使いますが、Period Converter All Timeframesというスクリプトを使えば、5分足から月足のデータを一度に生成できるので便利です。

<Period Converter All Timeframesのある場所>
https://www.mql5.com/ja/code/19839

 

Period Converter All Timeframesを実行する前に、「ツール」→「オプション」→「チャート」の中にある次の2項目をチェックしておく必要があります。

・ヒストリー内の最大バー数
・チャートの最大バー数

これらの数値が小さいとデータの生成が上手く行かないことがあるからです。
ネット上の情報を見ていると、2147483647にしている人が多いようでした(MT4のint型の最大値?)。

 

この数値を変更した後、一度MT4を再起動します。
再起動しないと、変更後の数値が反映しないようです。

 

MT4を再起動したら、

(1)データを作成したい通貨ペアのチャートを開き
(2)チャートの時間軸をM1(1分足)にして
(3)Period Converter All Timeframesスクリプトを実行します。

 

f:id:philojuan:20210922023255p:plain

デフォルトでは日足から月足までのデータを生成しない設定になっています。もし、これらも生成したい場合はfalseとなっている部分をtrueに変更する必要があります。


スクリプトを実行し、データの生成が終わったら、MT4を再起動します。

「ヒストリーセンター」を開くと、1分足以外のヒストリカルデータが生成されていることを確認できるはずです。

 

データの生成に失敗する場合は、データ生成が失敗している時間足のヒストリカルデータを消去して(←間違っても、1分足のデータは消去しないこと)、もう一度Period Converter All Timeframesスクリプトを実行します。

 

ヒストリカルデータの場所については、MT4に付属しているMQL4 ReferenceのFileOpenHistory関数の項目を読むと以下のように書かれています。

history directory (terminal_directory\history\server_name) or in its subfolders

 

 チャートの最大バー数の注意点

ネット情報によると、「チャートの最大バー数」を2147483647にしたままで複数のチャートを開くとMT4が凄く重くなったり固まったりするケースがあるそうです。

自分の環境ではそういうことは起きていないのですが、もしそのような状況になった場合は、もっと少ない数値にした方が良さそうです。

 

大雑把に言うと、5分足を1年分表示する場合、10万本くらいあれば足ります。

よって、過去10年分のデータを5分足チャートに表示する場合、100万本くらいを「チャートの最大バー数」にセットしておくことになります。

 

一応、5分足1年分で10万本くらいと述べた理由を書いておきます。
1年間は525600分です。これを5で割ると105120ですから、1年分の5分足を表示する場合、チャートの本数は105120本です。ただし、相場が動いていない時間(土日など)が存在するので、実際には105120本より少なくなります。


というわけで、1年分の5分足をチャートに表示するのなら、「チャートの最大バー数」に105120を指定しておけば足ります。

robocopyのコマンドオプション

昨年12月からWindowsを使い始めましたが、オンラインストレージにしかバックアップをしていなかったので、外付けHDDにもバックアップすることにしました。

バックアップ用のバッチファイルを作成しようとネットを調べていたら、Windowsにはrobocopyという便利なコマンドがあると知りました。

使ってみたら便利だったので、自分が使うかもしれないコマンドオプションだけメモとして残しておくことにしました。

 

<使っている>
/MIR      ミラーリング
/R:3      ファイルコピーに失敗した場合の再試行回数(この例だと3回)
/W:3      再試行する時の待ち時間(この例だと3秒待つ)
/LOG:     ログの出力先となるファイルを指定(上書き)
/NDL      ディレクトリ名をログに記録しない
/NP       バックアップの進行状況を表示しない

<たまに使うかも>
/L        バックアップのシミュレーションを行う
/XD       指定されたディレクトリを除外する
/XF       指定されたファイルを除外する(/R:0を使って飛ばしてもOK)

<ひょっとすると使うかも>
/TEE      ログをファイルだけでなくコンソール画面にも出力する
/LOG+:    ログの出力先となるファイルを指定(追記)
/UNILOG:  UNICODEでログを出力(上書き)  → 試しに使ったら、UTF-16LEになった。
/UNILOG+: UNICODEでログを出力(追記)
/NFL      ファイル名をログに記録しない

個人的に「/R:」オプションは必須だと思います。再試行回数のデフォルト値が100万回なので、回数を指定しないと危険です(汗)。

 

自分の使用例(ディレクトリ)

rem Pictures Directory
robocopy C:\Users\name\Pictures\ D:\Backup\Pictures\ /MIR /R:3 /W:3 /NP /NDL /LOG:D:\Backup\robocopy_Pictures.log

 

バッチファイルの拡張子 

ネットによると、バッチファイルの拡張子は「.cmd」で良いみたいです(たとえば「roboco.cmd」など)。めちゃくちゃ古い記憶ではMS-DOSのバッチファイルの拡張子は「.bat」だったような気がするのですが、きっと気のせいでしょう。