質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
FORTRAN

FORTRAN(フォートラン)は科学時術計算に向いた手続き型プログラミング言語です。 並列計算の最適化が行いやすい特性上、数値予報および気候モデルなどの大規模な計算を行う分野のスーパーコンピュータで使われています。

Q&A

2回答

1269閲覧

Fortranで時系列データを扱いたい

noob_programmer

総合スコア0

FORTRAN

FORTRAN(フォートラン)は科学時術計算に向いた手続き型プログラミング言語です。 並列計算の最適化が行いやすい特性上、数値予報および気候モデルなどの大規模な計算を行う分野のスーパーコンピュータで使われています。

0グッド

0クリップ

投稿2022/12/22 03:24

編集2023/01/09 05:41

前提

価格の時系列データ

実現したいこと

プログラムの最初に任意の時間間隔での変数を設定して、それに伴って始値等を出力するプログラムを作りたいのですが、どうコードで表現すれば良いのか分からない状態です。

発生している問題・エラーメッセージ

(追記)
回答していただいた内容を元に、プログラムを書いてみました。
実行はされますが、問題点が1つあります。

①時刻の出力がおかしい。

試したこと

とにかく頭の中の考えを紙に書き出したのですが、うまくまとまらないです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2022/12/22 03:54

180が3分なら0.1は100ミリ秒では?
noob_programmer

2022/12/22 04:06 編集

ozwk様、コメントありがとうございます。 質問文の説明が間違っていたので、編集いたしました。
otn

2022/12/22 05:45 編集

桁数が多いので簡略化して書きます。データが、 09:00:01 100円 09:00:02 110円 09:00:10 101円 09:03:10 102円 09:04:00 101円 で、1分単位でまとめるとすると、 09:00 については始100、髙110、低100、終101で、 09:03 については始102、髙102、低102、終102だと思いますが、 09:01 ~ 09:02 についてはどう出力したいのでしょうか?
otn

2022/12/22 05:45

失礼しました。コード中に、 > 飛んでいたら、前の時刻の終値を四本値に代入 と書いてましたね。ということは、 09:00 始100、髙110、低100、終101 09:01 始101、髙101、低101、終101 09:02 始101、髙101、低101、終101 09:03 始102、髙102、低102、終102 か。
noob_programmer

2022/12/22 06:05

otn様、コメントありがとうございます。 はい、その通りです。
guest

回答2

0

②については、
案1:10進数の足し算の繰り上がりの応用で、
1桁目が100万進数、2桁目が60進数、3桁目も60進数であるような変則的な数値の加算だとして処理する。
案2:hh mm ss tttttt にそれぞれの数値が入っているとすると、
((hh*60+mm)*60+ss)*1000000+tttttt でマイクロ秒単位に変換して内部処理は全部これで行い、
最後に文字として出力する時点で逆の変換を行って hh mm ss tttttt を得る。

①については、「DBMSを使わないマスタートランザクション処理(バッチ処理)」の様な感じですね。
マスターデータ自体が無いのでちょっと面倒か。
また、「データが終わっても目標の時刻に達していないときにどうするか?」と言う問題があります。
例えば、午前中のデータで終わってしまったが、17時の分まで出力したい(最終の値をずっと出力し続ける)とか。
下記の「データを読む」でEOFに達していたら、tにどんな時刻よりも大きい値をセットして処理を続けます。
これで、最後の区間のデータを特別扱いして出力する必要も無くなります。
あと、いきなり9:00からデータが無い場合は前日終値を使うんでしょうね。

text

1データ有り = 偽 2データを読む 3開始時刻 bgn と時間間隔を加算した終了時刻 end をセット 4四本値には前日終値をセット 5繰り返し 6  読んだデータの時刻 t が、 7  bgn<=t<endの時 8    データ有りが真の時 9      読んだ値を終値にセットし、高値、低値にも大小判断でセット 10    データ有りが偽の時 11      読んだ値を四本値すべてにセット 12      データ有り = 真 13    どちらの場合も 14    次のデータを読んで繰り返し先頭へ 15  t>=endの時 16    データ有りが真の時 17      bgn,始値,髙値,低値,終値を出力 18    データ有りが偽の時 かつ bgnが開始時刻ではないとき 19      bgn,終値,終値,終値,終値を出力 20    どちらの場合も 21    データ有り = 偽 22    bgnとendを更新 23    bgnが目標の時刻に達していたら終了 24    (次のデータは読まずにループ先頭に戻る) 25繰り返し終わり

実装例(Ruby)
上記の日本語説明で、Fortranプログラムは書けると思いますが、稼働確認のためにコードを書きました(Rubyを知らなくても読めるように書きました)。
細かいテストはしてないです。
他のデータで確認したいときは、ウェブ上でRubyプログラムを実行できるサイトがあると思うので、そこで実行してみてください。

Ruby

1def read_data 2# 時刻と値のペアを返す 3 # __END__行以降のデータを読む 4 line = DATA.gets 5 if line # EOFでない時 6 # 空白で分割して整数値に変換 7 line.split.map(&:to_i) 8 else # EOFの時 9 [999999,0] # 時刻として999999を返す 10 end 11end 12 13data_flag = false 14t, v = read_data 15t_int = 10 # 時間間隔 16t_first = 0 # 開始時刻 17t_last = 100 # 終了時刻 18 19t_bgn = t_first 20t_end = t_bgn + t_int 21 22# 始値 髙値 低値 終値 23v_b = v_h = v_l = v_e = 101 # 前日終値 24 25loop do # 無条件ループ 26 if t < t_end 27 if data_flag 28 v_e = v 29 if v > v_h then v_h = v end 30 if v < v_l then v_l = v end 31 else 32 v_b = v_h = v_l = v_e = v 33 data_flag = true 34 end 35 t, v = read_data 36 else 37 if data_flag 38 puts [t_bgn,v_b,v_h,v_l,v_e].join(" ") 39 elsif t_bgn > t_first 40 puts [t_bgn,v_e,v_e,v_e,v_e].join(" ") 41 end 42 data_flag = false 43 t_bgn = t_end 44 t_end = t_bgn + t_int 45 if t_bgn > t_last 46 break # ループから抜け出す 47 end 48 end 49end 50# この先がデータとして読まれる 51__END__ 5220 100 5321 110 5422 101 5540 102 5651 107

結果:

text

110 101 101 101 101 220 100 110 100 101 330 101 101 101 101 440 102 102 102 102 550 107 107 107 107 660 107 107 107 107 770 107 107 107 107 880 107 107 107 107 990 107 107 107 107 10100 107 107 107 107

投稿2022/12/22 06:46

編集2022/12/22 07:17
otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noob_programmer

2022/12/22 07:03

案2のマイクロ秒換算にして、処理するほうが良さそうと感じました。 問題は、マイクロ秒換算にしてからの時刻更新がなかなか難しくて、悩んでいます。
otn

2022/12/22 07:18

> マイクロ秒換算にしてからの時刻更新がなかなか難しくて 何が難しいのでしょう?
noob_programmer

2022/12/22 07:33 編集

すいません、再度考えます。
noob_programmer

2022/12/22 10:12 編集

>最後に文字として出力する時点で逆の変換を行って hh mm ss tttttt を得る。 すいません単位変換に慣れてなくて、逆の変換の式が分からないです。 何度か元に戻そうしたのですが、変な数になってしまいます。
noob_programmer

2022/12/22 11:08 編集

ozwk様が回答していただいた関係式を用いれば良いと思うのですが、どう使うのでしょうか。
otn

2022/12/22 11:12

マイクロ秒の部分はいいですよね? 「0時ちょうどから10000秒目は何時何分何秒ですか?」 10000を60で割った余り・・・40秒 10000を60で割った商・・・166分 166を60で割った余り・・・46分 166を60で割った商・・・2時 ・・・2時46分40秒
noob_programmer

2022/12/23 03:23 編集

質問本文のプログラムを修正しました。 組み込む関数のmodを使うことによって、元に戻すことにしました。 それでも、無限ループや時刻が更新されないなどの問題点が多く残ります。 可能でしたら、プログラムを一度チェックしてもらいたいです。
otn

2022/12/23 04:29

> 無限ループや時刻が更新されないなどの問題点が多く残ります。 私が回答に書いた通りの処理手順で書いたのでしょうか?
noob_programmer

2022/12/23 05:16

すいません、うまく書けず自分なりに書いている場所が多いです。 『データ有り=偽』とは、時刻がとんでいることを表しているのでしょうか?
otn

2022/12/23 10:01

> 『データ有り=偽』とは そうですね。その時間帯のデータがまだ読まれていないことを表します。 データが来たら真に。
guest

0

時系列データには時刻がとんでいる場合もあり、その場合でも始値等を出力したいです。

「最後に読んだデータの時刻と価格」 = ファイルを読む 「開始時刻」 を 適切に初期化 (どうするか書いてない、最初のデータからスタート?) ファイル最後まで繰り返し 始値、高値、安値、終値 =「最後に読んだデータの価格」 「終了時刻」 = 「開始時刻」 + 「時間間隔」 「最後に読んだデータの時刻」が「終了時刻」を超えるまで繰り返し 「最後に読んだデータの時刻と価格」 = ファイルを読む 高値、安値を「最後に読んだデータの価格」で適宜更新 終値 =「最後に読んだデータの価格」 「開始時刻」 = 「開始時刻」 + 「時間間隔」

12桁の整数で表される時刻を、任意の時間間隔でどのように更新していく

マイクロ秒単位で表されてたら楽なので、マイクロ秒単位に変換します。

hhmmssttttt形式の整数ですからhh部分は
1000000000で割った整数部分ですし、mm部分は
1000000000で割った余りを
10000000で割った整数部分ですし、sstttttt部分は
10000000で割った余りです。

投稿2022/12/22 04:37

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noob_programmer

2022/12/22 06:29

>>12桁の整数で表される時刻を、任意の時間間隔でどのように更新していく の部分の回答なのですが、hhmmssttttttを数で割った整数部分や余り部分に次の時刻の数字を足していくイメージでしょうか?
ozwk

2022/12/22 06:35

いいえ、マイクロ秒に直すことを意図しています。 例えば 1分30秒は(1x60+30)*1000マイクロ秒です
noob_programmer

2022/12/22 06:38

最初に設定した任意の時間間隔をマイクロ秒に変換して、時刻更新するイメージでしょうか?
ozwk

2022/12/22 06:39 編集

はい、そうすれば時刻更新や比較が簡単になります。 ちなみにマイクロ秒単位だと、1日が86,400,000,000秒で32ビットでは足りなくなるので 64ビット整数で保持するか、 常識的に考えてマイクロ秒単位で価格を取得する意味がないとして ミリ秒単位や0.1秒単位になど切り捨てます
noob_programmer

2022/12/22 06:57

>例えば 1分30秒は(1x60+30)*1000マイクロ秒です のところは、マイクロ秒換算なので 1分30秒 = (1×60 + 30)*1000000 ではないでしょうか? 自分の認識が間違ってるかもしれないです...
ozwk

2022/12/22 07:02

すみません、これだとミリ秒でした
noob_programmer

2022/12/23 05:02 編集

回答を参考に、プログラムを作成してみたのですが質問本文に追記した様に問題点があります。 何度修正しても価格が正しく更新されないです。一度客観的にプログラムを見てもらうことはできますか? 開始時刻は9時ちょうどに設定しています。 do whileで書いた部分が何か引っかかる様な気がする....のですがどうでしょうか。よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問