水平線到達で音を鳴らすだけのインジケーター
久しぶりにcTraderプログラムのサンプルコード代わりの単純インジケーターを公開してみます。
コメント欄から「水平線で音鳴らすcBotできませんか?」という感じのコメントをいただいたため作ってみました。(コメントありがとうございます!)
機能としては「チャート上の水平線に価格が到達したら設定したサウンドファイルを再生する」というだけのものです。
cBotではなくIndicatorとして作ってあります。
単純ですが人によっては有用に使えるのではないでしょうか。
ソースコード解説
全ソースコード
using System.Linq;
using cAlgo.API;
namespace cAlgo {
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HorizontalLineChaim : Indicator {
[Parameter(DefaultValue = "Alarm01.wav")]
public string SoundFile1 { get; set; }
[Parameter(DefaultValue = "Alarm02.wav")]
public string SoundFile2 { get; set; }
private double _exBid;
protected override void Initialize() {
_exBid = Bid;
}
public override void Calculate(int index) {
if (!IsLastBar) return;
var lines = Chart.FindAllObjects < ChartHorizontalLine >();
if (lines.Select(l => l.Y).Any(price => price < _exBid && price >= Bid)) {
Notifications.PlaySound("C:\\Windows\\Media\\" + SoundFile1);
} else if (lines.Select(l => l.Y).Any(price => price > _exBid && price <= Bid)) {
Notifications.PlaySound("C:\\Windows\\Media\\" + SoundFile2);
}
_exBid = Bid;
}
}
}
はい、これだけです。短いですよね。自動生成されたテンプレートに数行追加しただけです。
インジケーター始めてで自動生成コードの意味がさっぱりわからんという方は先にこちらをどうぞ。
-
はじめてのインジケーター
インジケーターも作ってみよう cBotに続いてインジケーターも一つ作ってみたいと思います。はじめてのcBotは終わってる前提で進めます。 エンベロープ エンベロープ(Envelope)というインジケー ...
続きを見る
今回は表示させるものがないので5行目のIsOverlayはfalseからtrueに変更しておいてください。falseだと空っぽの別窓が出てきてしまいます。
7~10行目はインジケーターのパラメータとして音声ファイル名を指定するようにしました。
"C:\Windows\Mediaフォルダ内ファイルで指定する形にしてありますが、自分で使うために改変するならパラメータ自体なくしてしまって21,23行目の命令文に直接ファイル名指定してやっても構いません。
「到達したら音を鳴らす」やり方
「到達したら音を鳴らす」をプログラムで表現するにはどうしたらいいでしょう。
単純に値動きがあるたびに「その値動きにより水平線をまたいだ(もしくは重なった)か」を確認して、音を鳴らせばいいですよね。
式で表すなら上抜けなら「1Tick前の価格」<「水平線の価格」<=「動いた今の価格」、下抜けなら「1Tick前の価格」>「水平線の価格」>=「動いた今の価格」ということです。
インジケーターにはCalculateという毎Tick実行される関数がありますので、そこで上記の判定をして音鳴らす処理を入れてあげるだけの話です。
・・・と、その前に「今の価格」はBidという変数が用意されてるのですが、「1Tick前の価格」というのはIndicator側で用意してくれていないため、自分で用意する必要があります。
12行目で定義してる_exBidがそれです。毎Tick更新する必要があるためCalculateの最後(26行目)で_exBid=Bidというように更新しています。
Calculateのコード
if (!IsLastBar) return;
18行目のこれは今計算してるのが最後の(=今現在の)ローソク足分じゃなかったらなにもしないようにするためのおまじないです。
インジケーターは初期化後ローソク足の本数分だけCalculate()を実行します。このインジについては過去ローク足分の計算は不要なのでこうしてます。
var lines = Chart.FindAllObjects();
19行目のここでChartのFindAllObjectsメソッドを使ってチャート上の水平線を全部集めてます。
毎Tickこの処理をするのに抵抗があれば、初期化時に集めてフィールド(メンバ変数)に持たせておいても構いません。ただし、その場合は水平線の追加削除時にフィールドの値も変更する必要がありますので注意してください。
次の20~24行目部分が本インジケーターのメイン機能部分ですね。処理としてはこうしてます。
if(価格が水平線のどれかを上に抜けてたら){
File1の音を鳴らす
}else if(価格が水平線のどれかを下に抜けてたら){
File2の音を鳴らす
}
ifの中はC#のLinqという機能を使ってるため、知らない方にはわかりにくいかもしれませんが、下記と全く同じことをしています。
foreach(var line in lines){
var price = line.Y;
if(price < _exBid && price >= Bid){
Notifications.PlaySound("C:\\Windows\\Media\\" + SoundFile1);
}
break;
}
(「価格が水平線のどれかを上に抜けてたらFile1の音を鳴らす」部分のみ)
Notirications.PlaySoundはcAlgoの機能で指定した音声ファイルを再生してくれます。
注意点としてはフルファイルパスを指定すること、文字列内のパス区切りは\\で表現すること、ぐらいでしょうか。
これで完成です。
これだけじゃさすがに機能少なすぎるかもしれませんが、自分で作るならここから好きに編集していくことができます。
ぜひ理想のインジケーターを作ってみてください。
(2022/8/12 追記)
現時点ではcTrader4.2で機能しません(泣)
先日アップデートされたcTrader4.2ではFindAllObjectsが効かず機能しないようです。明らかにcTrader(Automate)側のバグですね。
cTrader4.2で機能させるためには18行目あたりに以下の1行を追加してください。
Chart.Objects.Count();
コード自体に意味は無いです。意味は無いですがこれで機能するようになります。
FindAllObjectsが普通に使えないというのは結構致命的なので早く修正してほしいです・・・
(2023/8/18 追記)
上記気づいたら直ってるようです。cTrader4.8で追記なしでこのまま動くこと確認済み。