2009年1月8日木曜日

今日の戦績

Lv1.00(整数部がmini発注枚数の半分の切り上げ値)
---------------------------

---------------------------
トータル損益は+4992円です。

このうち手数料の支払いが1008円含まれます。

買い注文回数は10回, 売り注文回数は11回です。

未返済の建て玉1枚の見込み損益は手数料を含まずに+2452円です。


---------------------------
OK
---------------------------
夕場に変な参戦の仕方をしたので訂正。
夕場が、調子に乗って下げすぎだろう、という感じだったのだが、これ、引けにかけて今日の日経平均の終値付近まで戻す展開になれば売り建てして持ち越しするのも面白そうだな、と思い8880で指値しておいた。引けにかけて戻す展開を想定していたのでずっと場を見ていなかったのだが、ふと見たらとっくに約定している!で、オーバーシュートせずにドンピシャで8900で切り替えしていた。こえー。

さて、明日は下げるなら25MAに向けてどかんと下げる。上げるなら今日の終値付近からという展開になるというてっきとーな読みでこういう事をしたわけですが、目はどう出るでしょうか。

Lv1.00(整数部がmini発注枚数の半分の切り上げ値)
---------------------------

---------------------------
トータル損益は+5040円です。

このうち手数料の支払いが960円含まれます。

買い注文回数は10回, 売り注文回数は10回です。

未返済の建て玉0枚の見込み損益は手数料を含まずに±0円です。


---------------------------
OK
---------------------------

午前はともかく午後は一方的に下げるだけで値幅も大きかったのにこの程度の利益とは・・・がっくし。動きがなくなって余りの眠さに頭をはっきりさせようとスキップリストのライブラリに手をつけていたら一気に8900まで下げちゃうんだもんなあ。その後は逃がした魚は大きいという奴で欲が出て底値付近でショートして損きりになったり逆にリバウンドを狙ってロングしてやっぱり損きりになったりを繰り返してしまった。しかし引けにかけては一段の下げがあってどうにか体裁を保てたという所。まあ二日連勝は素直に喜ぼう。

以下午前中の愚痴

前場は、日経平均だけ見ると反落の後半値戻しという分かり易い展開なんだけど、先物は、完膚なきまでにランダムウォークなんだよなあ。やりにくい。夕場で先行して下げたというのもあるんだろうけれど。ちなみに、時間の平方根を取る表示なのでランダムウォークが種々の長さの直線運動の連なりとして視覚的に分かり易くなるのだ。

9005S-8975Cで3000円利益が出せたけど、その後小幅のリバウンドを待ってさらにショートしたら大きい戻しに捕まってしまった。損きりと言えないくらいの大きな損を出して手仕舞いした後改めて9040S。現在その含み損益は入れずに-5000円くらい。後場の終値が9000円を割らないという事はないと思うけれど、もうそうそう-3%とかの下げにもならないだろうから、どこかでうまくロングポジションを取らないと、この損を取り返すだけで終わってしまいそう。

スキップリストの.net実装を更新

スキップリストの.net上の実装を少し更新した。いつもと同様ファイル置き場に置いてある。とは言っても、ヘルプに記載しているサンプルコードに手を入れたのと、パブリックなメソッドの引数名を先頭大文字にした事だけ。この辺の標準的な名前付け規約はまだ良く分かっていないので時々変えるかも。

今回のサンプルコードの変更では、以前は

totalVolume[depth] = SkipList<MyItem, MyNode>
.GetEnumerableInOrder(start, true, end, true, depth - 1)
.Sum((n) => n.totalVolume[depth - 1]);
vwap[depth] = SkipList<MyItem, MyNode>
.GetEnumerableInOrder(start, true, end, true, depth - 1)
.Aggregate<MyNode, VolumeVwapPair>(new VolumeVwapPair() {
Volume = 0,
Vwap = 0
}, (pair, node) =>
VolumeVwapPair.Composite(pair, new VolumeVwapPair() {
Volume = node.TotalVolume[depth - 1],
Vwap = node.Vwap[depth - 1]
})).Vwap;

とごちゃごちゃしていた所を、

VolumeVwapPair ret = SkipList<MyItem, MyNode>
.GetEnumerableInOrder(start, true, end, true, depth - 1)
.Select((node) => new VolumeVwapPair
(node.TotalVolume[depth - 1], node.Vwap[depth - 1]))
.Aggregate(VolumeVwapPair.Composite);
totalVolume[depth] = ret.Volume;
vwap[depth] = ret.Vwap;

とすっきりした記述にした、等等、匿名メソッドを闇雲に使う代わりにSystem.LinqのSelect拡張メソッドを一段階挟んで、VolumeVwapPair.Compositeメソッドが可換半群の合成規則を与えている事が明瞭になるようにした。この変更は「身も蓋もない」のコードにも反映してある。もちろん以前のコードと等価な範囲の変更である。

サンプルコードの全体は以下のようになっている。可換半群の任意の区間に渡る総和計算をスキップリストのツリー状の構造を用いて高速に行う事が実際に簡単に実装できるようになっているのが分かると思う。

使用例

時刻、値、出来高を持つ株価の歩み値データを考えます。このデータを時刻によりソートし、任意の区間に対して出来高の総和と出来高を重みとした加重平均値(VWAP値)を高速に計算できるようにしたい場合には次のようにします。なお、以下のコードではEnumerableで定義される拡張メソッドが用いられているためコードの先頭でusing System.Linq;が記述されている必要があります。

まずMyItemクラスを次のように定義します。

C#
class MyItem
{
private DateTime time;
private double price;
private double volume;
public MyItem(DateTime time, double price, double volume)
{
this.time = time;
this.price = price;
this.volume = volume;
}
public DateTime Time { get { return time; } }
public double Price { get { return price; } }
public double Volume { get { return volume; } }
}

次に(重み,平均値)ペアがなす可換半群を表すVolumeVwapPairクラスを定義します。なお、重みが0である全てのペアは同一視されこの可換半群の単位元としての役割を果たします。

C#
class VolumeVwapPair
{
public double Volume;
public double Vwap;
public VolumeVwapPair(double Volume, double Vwap)
{
this.Volume = Volume;
this.Vwap = Vwap;
}
public static VolumeVwapPair Composite(VolumeVwapPair pair1,
VolumeVwapPair pair2)
{
double totalVolume = pair1.Volume + pair2.Volume;
if (totalVolume == 0) return new VolumeVwapPair(0, 0);
return new VolumeVwapPair(totalVolume,
(pair1.Volume * pair1.Vwap + pair2.Volume * pair2.Vwap)
/ totalVolume);
}
}
そしてMyNodeクラスを次のように定義します。
C#
class MyNode : SkipListNode<MyItem, MyNode>
{
private double[] totalVolume;
private double[] vwap;
protected override void OnHeightDecided()
{
base.OnHeightDecided();
InitializeParameters(ref totalVolume);
InitializeParameters(ref vwap);
}
protected override void OnMaintainance(int depth)
{
base.OnMaintainance(depth);
if (IsHeader || IsFooter) return;
if (depth == 0) {
totalVolume[0] = Item.Volume;
vwap[0] = Item.Price;
} else {
MyNode start = this;
MyNode end = this.Next[depth].Prev[depth - 1];
VolumeVwapPair ret = SkipList<MyItem, MyNode>
.GetEnumerableInOrder(start, true, end, true, depth - 1)
.Select((node) => new VolumeVwapPair
(node.TotalVolume[depth - 1], node.Vwap[depth - 1]))
.Aggregate(VolumeVwapPair.Composite);
totalVolume[depth] = ret.Volume;
vwap[depth] = ret.Vwap;
}
}
protected override int Compare(MyItem item1, MyItem item2)
{
return item1.Time.CompareTo(item2.Time);
}
public double[] TotalVolume { get { return totalVolume; } }
public double[] Vwap { get { return vwap; } }
}

最後にMySequenceクラスを次のように定義します。

C#
class MySequence : SkipList<MyItem, MyNode>
{
public double TotalVolume(MyNode former, MyNode latter)
{
return Sum(former, latter, (node, depth) => (node.TotalVolume[depth]));
}
public double Vwap(MyNode former, MyNode latter)
{
return Aggregate(former, latter,
VolumeVwapPair.Composite,
(node, depth) => new VolumeVwapPair
(node.TotalVolume[depth], node.Vwap[depth]),
new VolumeVwapPair(0, 0)).Vwap;
}
}

この例では重みの総和に関してはDouble型の総和を計算するSum(TNode, TNode, Func<TNode, Int32, Double>)メソッドを用いて計算し、全平均値に関しては通常の意味での加法によって合成されない可換半群の典型例である(重み,平均値)ペア(重みは通常の和で、平均値は加重平均によって合成される)に対して一般的な可換半群の総和を計算するAggregate<T>(TNode, TNode, Func<T, T, T>, Func<TNode, Int32, T>, T)メソッドを適用する事で計算しています。

ほとんどの場合、可換半群は通常の意味での加法群と等価である事に注意してください。実際、(重み,平均値)ペアと(重み,重み*平均値)ペアとは重みが0である場合を除いて一対一に対応します。そして重み及び重み*平均値はそれぞれ独立に通常の意味での加法によって合成されます。従ってMyNodeクラスのOnMaintainanceメソッド及びMySequenceクラスのVwapメソッドはそれぞれ

C#
protected override void OnMaintainance(int depth)
{
base.OnMaintainance(depth);
if (IsHeader || IsFooter) return;
if (depth == 0) {
totalVolume[0] = Item.Volume;
vwap[0] = Item.Price;
} else {
MyNode start = this;
MyNode end = this.Next[depth].Prev[depth - 1];
totalVolume[depth] = SkipList<MyItem, MyNode>
.GetEnumerableInOrder(start, true, end, true, depth - 1)
.Select((node) => node.TotalVolume[depth - 1])
.Sum();
vwap[depth] = SkipList<MyItem, MyNode>
.GetEnumerableInOrder(start, true, end, true, depth - 1)
.Select((node) => node.Vwap[depth - 1]
      * node.TotalVolume[depth - 1])
.Sum() / totalVolume[depth];
}
}
及び
C#
public double Vwap(MyNode former, MyNode latter)
{
double totalVolume = TotalVolume(former, latter);
if (totalVolume == 0) return 0;
return Sum(former, latter,
(node, depth) => node.Vwap[depth] * node.TotalVolume[depth])
       / totalVolume;
}
と書く事もできます。

2009年1月7日水曜日

体調

今日は睡眠の質は低くはなかったと思うのだが、まるで一睡もしていないかのように強烈に眠い。眼の奥と額が強烈にツーンとしている。体中がだるい。肩~腕の筋肉痛もすごい。咳・痰が少しだけだけど激しくなってきたのと、起きた時に風邪気味な感じ。でも、動いているうちにそれは大した事はなくなる。それと、朝から日中にかけて凄く低体温。お茶を何杯も飲んでも体が温まらない。

体を動かさないのも却ってストレスになって、時々腕立て伏せなんかしたりするのだが、一日やったら二日空けるペースでも肩の筋肉痛とだるさが全くとれない。まるでわざわざ自分を痛めつけているかのよう。

スキップリストのライブラリもバージョンアップ

アドイン製作の副産物のスキップリストを.net Framework上で実装したライブラリもバージョンアップした。今まで継承先で実装していたメソッドのうち汎用性のあるものをライブラリに移した。具体的にはSkipListNodeクラスのInitializeParametersメソッドとSkipListクラスのSum, Aggregateメソッドとか。

これで可換半群の区間に渡っての総和計算がかなり実装し易くなったはず。

ダウンロードはここから。

「身も蓋もない」バージョンアップ

「身も蓋もない」は、実用上の違いはありませんが内部的な処理をいくつかより好ましいものに変えました。できるだけアップデートしてください。

具体的には寄り付き前にログインした場合に受信されるデータの時刻・日付がおかしい問題への対処を変更しました。これに伴い「現時刻より大幅に未来の/過去の~」というメッセージが表示される事がありますが、ザラ場外に表示される限りは気にしなくて問題ありません。

「身も蓋もない」のダウンロードは詳細サイトのファイル置き場から。

今日の戦績

9295Sの売り建て玉はふてねする前に返済買いを9155,指成の指定にしておいたんだけど、指成って大引けじゃなくて前場引けでも有効なのを失念していた。9290で返済でまた薄利。ていうか、後場に下げる事を見越しての指値だったんだが、良く前場引けまでに利益が乗る所まで下がったな。ふてねから目覚めて相場を見たら9260まで下げているんだから悲しくなるけどこれは自分のミスで損にならなかっただけラッキーと思うべき。ネットワークはやはりまだ不調みたいだし、自分の操作ミスも出てしまったし今日はこれで止めておく。いろいろ縁起が悪すぎる。

現在Lv1.00(整数部分がmini発注可能枚数の半分の切り上げ値)
---------------------------

---------------------------
トータル損益は+4876円です。

このうち手数料の支払いが624円含まれます。

買い注文回数は7回, 売り注文回数は6回です。

未返済の建て玉0枚の見込み損益は手数料を含まずに±0円です。


---------------------------
OK
---------------------------

今日の
  • 最近にしては大きめの値幅
  • 強い方向感を持った動き
  • 行って来いの展開
という状況でこの程度の利益って泣きたくなる。最近損を繰り返しているだけに絶好のチャンスをここまで見事に逃すとは呆れ果てるしかない。精進しよう。

以下午前中に書いた愚痴:

何じゃ今日は。

まず9170Sの持ち越しはほとんど意味がなかったけど、寄付き後に下げて+30ほどになった。そこで利確のため返済買いをしたら、散々遅延したあげくに9165で約定しやがった。

これがけちのつき始めで、ひたすらにネットワークが不安定。

前場の9300までとても強い動きで上げていく場面でも、参戦した後長い間相場データが受信できなくなり仕方なく薄利で手仕舞いせざるを得なくなった。その後一度ログアウトしてログインして様子を見てみたら、ログアウトにもログインにも凄く時間がかかった上に既に9300。ひでえ。スルスルと上がっていくだけの場面でロングポジションを取れないなんてそんなんじゃトレードになりゃしねえ。

すごく損した気になって、合理的でないと理解しつつも堪えきれずに、そこで9295S。さすがにトレンドが転換したわけでもないので、小さく押す場面を捕まえれば良いや、と思っていたのだが、ここでまた接続が途切れて相場データが受信できず。再開したらもう9330までいっている。そしてまたデータを受信できなくなる。暗闇の中でやっているようなもの。もう今日は後場に上げ幅を消していく展開と決め付けて、後場に手仕舞う事にしてふてね。まあ例によって強烈な眠さを我慢してのトレードだし。

こういうツールやネットワークの調子が悪いというのもリスクの一つと考えてトレードを控えるべきで、昨日反省した、いつもの参戦すべき理由がない状況で我慢できずに無理やり参戦する癖がこういう形でまた出てしまったという面は確かにある。でも、散々方向感のない動きに損を出させられて苛立たせられ続け、やっと巡ってきた強い方向感のある日にこれじゃあ一体どうやって利益を出せというのか。むがー。

2009年1月6日火曜日

今日の戦績

現在Lv1.00(整数部がmini発注可能枚数の半分の切り上げ値)
---------------------------

---------------------------
トータル損益は-4508円です。

このうち手数料の支払いが1008円含まれます。

買い注文回数は10回, 売り注文回数は11回です。

未返済の建て玉1枚の見込み損益は手数料を含まずに-2048円です。


---------------------------
OK
---------------------------
新年早々負け続け。
前場はGUの後に完全にランダムウォークという、例によって海の向こうで寝ている間に値が決まるパターン。強烈に眠い最悪のコンディションでそこに無理矢理参戦。この時点で少しの損だったが、後場に持ち越した買い建て玉が強い下げに捕まって一気に-12000円くらいの損に。その代わり後場は方向感のある動きをしていたので夕場も使ってどうにか損失を小さくできた。夕場は出来高が少ない割りに上げるだけという簡単な相場だった。参戦するのが遅かったのが悔やまれる。

それにしても、後場では上げている時に定期的に1000枚単位の売り物がぶつけられて強気でロングできないという、日本市場はどんだけ弱気なんだ、という動きだった。昨日のCMEの日経225先物を見習えよ。現物の市場が空いていない状況で9300円台まで行ったぞ。

で、諸々の負けを取り戻すために掟破りの9170S博打持ち越し。これ失敗したらオバマ着任までは頭を冷やすために休みます。いやでもさすがに日経もNYもチャート的に一度大きく下げるよね?下値は切り上げていくとしても。オバマ就任までは基本的に微上げを続けていくという観測が大半だけど、だからと言って総楽観という環境じゃないだろう。

ここから反省:

本当に、方向感なく動いている所に無理やり参戦する癖は改めないと、これじゃパチンコに万札飲み込ませているのと変わらないぞ。それでもパチンコなら射幸心を煽るために定期的に大勝させてくれるので大人のゲームセンターと割り切れば娯楽にもなるけれど、相場で丁半博打をやっても容赦ない結果が突きつけられるだけだ。遊びじゃなくてトレンドをフォローしての投資に徹する事を学ばなければ。

それができなければ、投資は「身も蓋もない」のユーザの皆さんに任せよう。元々自分の投資用に作ったツールじゃなくて、CFSの症状で何も手に付かない状況に絶えられなくて自分に機械的にできるタスクとして簡単なプログラミングを与えるのが目的だったのだからデバッグ以上の目的でトレード自体にのめりこむべきじゃない。戒め戒め。