F# Monkey

about

FParsecのメモ

たんなる雑記メモですっ

#r @"./packages/FParsec/lib/portable-net45+netcore45+wpa81+wp8/FParsecCS.dll"
#r @"./packages/FParsec/lib/portable-net45+netcore45+wpa81+wp8/FParsec.dll"
open FParsec

"hello world" |> run (many letter) |> printfn "%A"
/// Success: ['h'; 'e'; 'l'; 'l'; 'o']

"hello world" |> run (manyChars letter) |> printfn "%A"
/// Success: "hello"

"hello world" |> run ( sepBy (manyChars letter) (pchar ' ')) |> printfn "%A"
/// Success: ["hello"; "world"]

"hello, world"
|> run (sepBy ( manyChars letter ) ( pstring "," .>> spaces ))
|> fun x -> match x with Success (lst,_,_) -> lst | _ -> []
|> printfn "%A"
/// ["hello"; "world"]

"hello00 world99"
|> run (sepBy (manyChars (letter <|> digit)) (pchar ' ')) |> printfn "%A"
/// Success: ["hello00"; "world99"]

"hello00 world99"
|> run (sepBy ( (manyChars letter) .>> (manyChars digit) ) (pchar ' ')) |> printfn "%A"
/// Success: ["hello"; "world"]
Remove all ads

FParsecをさわってみた!

Summary

文字をパースするFParsecというライブラリを触ってみました

こんなかんじ

#r @"./packages/FParsec/lib/portable-net45+netcore45+wpa81+wp8/FParsecCS.dll"
#r @"./packages/FParsec/lib/portable-net45+netcore45+wpa81+wp8/FParsec.dll"
open FParsec

let test p str =
    match run p str with
    | Success(result, _, _)   -> printfn "Success: %A" result
    | Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg

test pfloat "1.25" /// Success: 1.25

ポイント

dllに優先順位(依存関係)があるので上記のようにFParseCS.dllを上に書いてからFParse.dllをかく

参考

Tutorial

還暦プログラマの挑戦(Haskell に挑む→F#による言語造り)

komorebikoboshi.hatenablog.com

hafuu.hatenablog.com

Remove all ads

ついにできた〜 F#のインテリセンス!

f:id:callmekohei00:20170623120941p:plain


こんにちは!callmekoheiです!

最近だんだんと暑くなってきてアイスの美味しい季節到来ですね〜。

アイスといえばパルムが好きなcallmekoheiですっ。

さてさて、ついにできましたよ。

なにが?

F#のインテリセンス!

Vimで単語が補完できるのです!

いや〜、3ヶ月かかりましたよ!!!

よかったら使ってみてくださいね〜

ダウンロードはこち

github.com

ちょっとした機能説明

deoplete-fsharpは2つの機能でなりたってます。

ひとつは補完機能でひとつは実行機能です。

補完機能は細かく言うと3種類に分かれていて

ピリオドを押すと候補がでるdot hints

一文字押すと候補が出るone word hints

[<を押すと候補が出るattribute hintsです。

実行機能は: QUICKRUNfsを実行すると右側に

実行結果がでます。

ただしこのQUICKRUNfsasyncをうまく実行できません。。。。

のでasyncを多用したコードの実行結果はQuickRun

fsi, fscを指定して実行してください。

ちょっとした技術説明

大まかな仕組みですが、2つのパートにわかれてます。

一つはdeopleteでもうひとつはdeopletefsです。

deopletefsが補完エンジンになります。

deoplete側で

ピリオドが入力された

一文字が入力された

[< が入力された

というタイミングでdeopletefs側に

jsonを送ります。

このjsonを元にdeopletefs側では

単語候補を計算して

jsonで返します。

といった仕組みです。

もう少し詳しい技術説明

補完候補を早く出すためにdeoplete, deopletefsともに

いろいろ工夫してますが

一番の工夫はキャッシュではないでしょうか?

deoplete側ではカーソルの同じ位置での単語候補をキャッシュしていて

素早く単語候補を出せるようになってます。

またdeopletefsではファイル立ち上げ時に、キャッシュをあらかじめ作っておきます。

ので立ち上げ時に5秒ほど(パソコンの性能による)時間を使ってます。

System, List, stdoutなど頻繁に使用するものはキャッシュしてます。

またopenキーワードが入力・削除・コメントアウトされた場合もキャッシュし直します。

それと、deoplete側から飛んでくるjson、つまり処理すべきタスクとみなせますが、

すべてタスクはキューに入れて、かつ負担のかかるタスク(時間のかかるタスク)は

タイムアウトで弾くようにし、シリーズで処理するようにしてます。

またバックグランドで構文解析をやっており、なるべくはやく単語候補が出るようにしてます。

Remove all ads

F#のMailboxProcessorのメモ

シンプルなエージェント

/// エージェントを作成する( Queueに入れるタイプを指定する、async式を返す式を指定する)
let simpleAgent = new MailboxProcessor<string>(fun _ -> async { () })

/// Queueに文字を入れる
simpleAgent.Post("hello")

/// Queueに入ってる文字列の数を調べる
simpleAgent.CurrentQueueLength |> stdout.WriteLine // 1

simpleAgent.Post("world")
simpleAgent.CurrentQueueLength |> stdout.WriteLine // 2

/// Queueに入ってる文字列をすべて調べる
simpleAgent.TryScan( fun x ->
    stdout.WriteLine(x)
    if x = null then Some(async{()}) else None
,timeout = 1) |> Async.RunSynchronously |> ignore
// hello
// world

/// Queueからエージェント側に文字列を取得する
simpleAgent.Receive() |> Async.RunSynchronously |> stdout.WriteLine // hello

/// Queueに入ってる文字列の数を調べる
simpleAgent.CurrentQueueLength |> stdout.WriteLine // 1

simpleAgent.Receive() |> Async.RunSynchronously |> stdout.WriteLine // world
simpleAgent.CurrentQueueLength |> stdout.WriteLine // 0

エージェントから値を取得する

let replyAgent = MailboxProcessor.Start( fun inbox ->
    async {
        let! (ch:AsyncReplyChannel<_>) = inbox.Receive()
        ch.Reply "hello"
    }
)
replyAgent.PostAndReply id |> stdout.WriteLine
/// hello

FizzBuzzしてみた

let (|Div|_|) by n = if n % by = 0 then Some Div else None

let fizzbuzz = function
    | Div 15 -> "FizzBuzz"
    | Div  5 -> "Buzz"
    | Div  3 -> "Fizz"
    | n      -> string n

type Command = Add of int | Fetch of AsyncReplyChannel<string list>

let fizzbuzzAgent = MailboxProcessor.Start( fun inbox ->
    
    let rec loop lst = async{
        let! msg = inbox.Receive()
        match msg with
        | Add value ->
            return! loop ( fizzbuzz value :: lst )
        | Fetch ch ->
            ch.Reply(lst)
            return! loop lst
    }
    loop []
)

[1..100] |> List.iter( fun n -> fizzbuzzAgent.Post(Add n) )

fizzbuzzAgent.PostAndReply(Fetch)
|> List.rev
|> List.iter stdout.WriteLine

結果

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
以下略

ちょっとした電卓

type Command = AllClear | Add of int | Enter of AsyncReplyChannel<int * Command list>
    
let CalcAgent = MailboxProcessor.Start( fun inbox -> 

    let rec loop n lst = async {
        match inbox.Receive() |> Async.RunSynchronously with
        | AllClear   -> return! loop 0 []
        | Enter repl -> repl.Reply( n , lst |> List.rev ) ; return! loop n lst
        | Add value  -> return! loop (value + n) ( Add value   :: lst )
    }
    loop 0 []
)

CalcAgent.Post(Add 8)
CalcAgent.Post(Add 5)
CalcAgent.Post(Add -3)
CalcAgent.PostAndReply(Enter) |> printfn "%A"
/// (10, [Add 8; Add 5; Add -3])

CalcAgent.Post(AllClear)

CalcAgent.Post(Add 1)
CalcAgent.Post(Add 5)
CalcAgent.Post(Add -2)
CalcAgent.PostAndReply(Enter) |> printfn "%A"
/// (4, [Add 1; Add 5; Add -2])
Remove all ads

F#でprintデバッグしてみる〜

sample code

コードはこんな感じで

open System.Diagnostics

/// Debugモードのときだけコンパイルする
#if DEBUG
/// リスナーをインスタンス化する
let listener  = new DefaultTraceListener()
/// logファイルを指定する
let parentDic = System.Reflection.Assembly.GetEntryAssembly().Location |> fun x -> string ( System.IO.Directory.GetParent(x) )
listener.LogFileName <- System.IO.Path.Combine( parentDic, "log.txt" )
/// リスナーに追加する
Debug.Listeners.Add(listener)
#endif

let rec main s (acc:int)=
    match s with
    | "quit" -> () /// quitという文字列で終了する
    | _      -> 
                /// stdoutから出力する
                stdout.WriteLine(s)
                /// log.txtに出力する
                Debug.WriteLine(acc)
                main (stdin.ReadLine()) (acc + 1)

[<EntryPointAttribute>]
let entry arg =
    main arg.[0] 0
    0

デバッグのしかた

まずdebugモードでコンパイル

$ fsharpc -d:DEBUG abc.fsx

で、ログファイルをリッスン

Fを押してForward foreverとする

$ less log.txt

実行してみる

$ mono abc.exe callmekohei
/// 標準出力へ
callmekohei
/// log.txtへ
0
Remove all ads

Neovimでお手軽にF#書けるようにしてみた〜

f:id:callmekohei00:20170608202917p:plain



いままでプログラムを実行するのにbash script別途必要でしたが不要になりました!

下記のコマンドですぐにF#Hello, World!できますっ!

# deinを使ってのインストール例

call dein#add('Shougo/deoplete.nvim')
call dein#add('callmekohei/deoplete-fsharp')

よかったらぜひ〜

ソースはこち

github.com

課題

オートコンプリートでhttpをつかってるのですがこれを普通のアプリに変えたい〜(stdin/stdouを使いたい)

オートコンプリートのOne word hintsを改善したい〜

Remove all ads

Neovim + Python-client で Quickrun もどきをつくってみた!

こんな感じ

Motivation

deoplete-fsharpquickrunしようとすると

thinca/vim-quickrunだとbash scriptが必要になるので

それがめんどくさかったのです、です

感想

neovim + python-client だと、むずかしいvim scriptを書かなくて済むのでたすかる〜

暗黒さん@ShougoMatsuさんのdeopleteのコードをがむしゃらに読んで参考にしました〜

thinca/vim-quickrunneovim(async)に対応しないかな〜 (thincaさん!お願いします!)

課題

ファイルタイプがfsxの時だけ:QuickRunfsがでるようにしたい

実行結果を一時バッファに出してるのですが、その時の画面のちらつき?をなくしたい

ファイルはこち

github.com

fsi(FSharp Interacrive) はこち

こんかいはfsiweb serverに載せずにコンソールアプリにしてみました!

github.com

追記

2017/06/07 21:00

てらむさん@termoshttからファイルタイプがfsxの時にだけ

コマンドが出るようにする方法を教えていただきました!

ありがとうございます!!!!

こんな感じにします!

import neovim

@neovim.plugin
class quickrunfsHeader(object):

    def __init__(self, vim):
        self._vim = vim

    @ neovim.function('PyQuickRunFs', sync=True)
    def fsiShow(self,arg):
        # something...

    @ neovim.autocmd("BufEnter", "*.fsx")
    def reg_quickrun_fs(self):
        self._vim.command("command -buffer QuickRunfs :call PyQuickRunFs()")
Remove all ads

こんにちは世界でF#入門〜

さくっと浅くF#をお勉強してみる〜

こんにちはせかい

"hello world" |> stdout.WriteLine

ラベルをつけてみる

let hello = "hello"
let world = "world"

hello + " " + world |> stdout.WriteLine

大文字にしてみる

hello + " " + world |> fun s -> s.ToUpper() |> stdout.WriteLine

3回こんにちはせかいと言ってみる

/// (ループしてみる)
for i in [1..3] do
    stdout.WriteLine "hello world"


/// (イテレートしてみる)
[1..3]
|> List.iter ( fun _ -> stdout.WriteLine "hello world" )


/// こんにちは世界のシーケンスを先に作ってイテレート
Seq.init 3 ( fun _ -> "hello world" )
|> Seq.iter stdout.WriteLine


/// 文字列を作ってそれを印字
"hello world"
|> fun s -> String.replicate 3 ( s + "\n" )
|> stdout.WriteLine

asyncでやってみる

[ async{return "hello"}; async{return "world"} ]
|> Async.Parallel
|> Async.RunSynchronously
|> Array.iter stdout.WriteLine

RX with eventでやってみる

let e = Event<_>()

e.Publish
|> Observable.add( fun (e:string) -> stdout.WriteLine(e) )

e.Trigger("hello world")




ふむふむ

F#マスターした!www

Remove all ads

Vimの操作を効率的に学ぶための6つのエクササイズ〜

ぜんぜん足りないとはおもいますけど

vimの操作の勘所をエクササイズ形式で

まとめてみました〜 (^_^)/

01

extragrouptexts

↓

extraGroupTexts

hints

f find

~ large letter / small letter

02

abc

↓

bbc

↓

BBC

hints

r replace

viw select word

~ large letter / small letter

03

{apple}"banana"<cherry>{APPLE}"BANANA"<CHERRY>

hints

vi{ select inside {}

~ large letter / small letter

04

.btn-large {
    padding     : 12px 19px ;
    font-size   : 16px      ;
    line-height : normal    ;
    font-weight : bold      ;
}.btn-large {
    font-size   : 16px      ;
    font-weight : bold      ;
    line-height : normal    ;
    padding     : 12px 19px ;
}

hints

vi{ select inside {}

:'<,'>sort sort

05

let abc = {


}let abc = {
    
    }

hints

v(line number)G $ select

shift > indent

06

let Say ( sq:seq<string> ) : unit =
   sq |> Seq.iter stdout.WriteLine

let threeTimes word =
   Seq.init 3 ( fun _ -> word )

threeTimes "hello" |> Say

↓

let threeTimes word =
   Seq.init 3 ( fun _ -> word )

let Say ( sq:seq<string> ) : unit =
   sq |> Seq.iter stdout.WriteLine

threeTimes "hello" |> Say

hints

vjj select

:'<,'>m 6 move


練習用テキスト

( ex1 )
extragrouptexts


( ex2 )
abc


( ex3 )
{apple}"banana"<cherry>


( ex4 )

.btn-large {
    font-size   : 16px      ;
    font-weight : bold      ;
    line-height : normal    ;
    padding     : 12px 19px ;
}


( ex5 )

let abc = {


}

( ex6 )

let Say ( sq:seq<string> ) : unit =
   sq |> Seq.iter stdout.WriteLine

let threeTimes word =
   Seq.init 3 ( fun _ -> word )

threeTimes "hello" |> Say
Remove all ads

Python と同じぐらい書きやすい F# というスクリプト言語をかいてみよう〜 ( せっかくなんでそれVimで!)

こんにちは!最近ポンド円にすっかりやられまくって死んでるcallmekoheiです(何回目?)

さてさてcallmekoheiはプログラムってなに?な感じでF#をはじめたのですが、

で最近気づいたのですがpythonF#は似てるな〜と。

なのでpythonかける人だったらF#は簡単にかけるかな〜と。

で、よく誤解されてるのですがF#スクリプト言語です!

もちろんそうじゃないかもしれないけどそこらへんはよく知りません (^_^;;

F#をはじめるには?

僕がMacなのでMacしか知らないですけどmonoというのをインストールすると使えます!

$ brew install mono

Neovim使いませんか?

せっかくなんでNeovim使いませんか〜?

個人的にはNeovim(vim)が今のところコード書くのに一番使いやすいと思ってます。

まぁ、ここら辺は個人の好みなんで。

で、Neovim使おうかなという風変わりな方がいましたら、

vim-fsharpというプラグインがあるのでおすすめです!

か、もしくは僕が作ってるdeoplete-fsharpも使ってくれると嬉しいです。

deoplete-fsharpvim-fsharpより使いやすいですよ〜(個人の感想です)

まぁF#hello worldするのもいいのではないでしょうか?

多分40分もかからずにいけると思いますよ〜

ではでは

Remove all ads

grep 色情報はいらない〜 はまった〜

Summary

grepで文字列を取り出す時

色情報がついてて

sedしにくかった

Environment

$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.12.4
BuildVersion:   16E195


$ uname -v
Darwin Kernel Version 16.5.0:
Fri Mar  3 16:52:33 PST 2017;
root:xnu-3789.51.2~3/RELEASE_X86_64

こんな感じ

cat ./abc.txt | grep -e '#r'
^[[01;31m^[[K#r^[[m^[[K @"./packages/FSharp.Control.Reactive/lib/net45/FSharp.Control.Reactive.dll"
^[[01;31m^[[K#r^[[m^[[K @"./packages/FSharp.Compiler.Service/lib/net45/FSharp.Compiler.Service.dll"
^[[01;31m^[[K#r^[[m^[[K @"./packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
^[[01;31m^[[K#r^[[m^[[K @"./packages/FsPickler/lib/net45/FsPickler.dll"
^[[01;31m^[[K#r^[[m^[[K @"./packages/FsPickler.Json/lib/net45/FsPickler.Json.dll"
^[[01;31m^[[K#r^[[m^[[K @"./packages/Suave/lib/net40/Suave.dll"

対策〜

cat ./abc.txt | grep --color=never -e '#r'
#r @"./packages/FSharp.Control.Reactive/lib/net45/FSharp.Control.Reactive.dll"
#r @"./packages/FSharp.Compiler.Service/lib/net45/FSharp.Compiler.Service.dll"
#r @"./packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
#r @"./packages/FsPickler/lib/net45/FsPickler.dll"
#r @"./packages/FsPickler.Json/lib/net45/FsPickler.Json.dll"
#r @"./packages/Suave/lib/net40/Suave.dll"
Remove all ads

F#でFXのトレード検証を手軽にできるシステムを作ってみる(その3)

Summary

Oandaサーバーから取得した実際の価格に対して作成した損益算出プログラムを適用してみる

使い方

こんな感じ

module Main =

    let setting : Setting = { 
        Entry      = 138.   /// エントリーする価格
        TakeProfit = 136.   /// 利確する価格
        CutLoss    = 139.   /// 損切りする価格
        Start      = System.DateTime ( 2017,4,3,9,0,0 )    /// 対象期間の開始日時
        Last       = System.DateTime ( 2017,4,13,13,0,0 )  /// 対象期間の終了日時
    }
   
    Oanda.profitAndLoss setting

結果

1 の損失を計上しました〜

Code

最小単位で丸めるのがポイントですっ。かなりはまりました(汗)

#r @"./packages/FSharp.Data/lib/net40/FSharp.Data.dll"
open FSharp.Data

#load @"/./Users/kohei/Documents/01_F#/OANDAfs/oandafs.fsx"
open callmekohei.Oandafs

type Setting = { Entry : float ; TakeProfit : float ; CutLoss : float ; Start : System.DateTime ; Last : System.DateTime }

module Oanda =

    let profitAndLoss (setting:Setting) : unit = 

        (*
            Oanda サーバーからデーターを取得する
        *)
        
        let env   = Environment.Live
        let id    = "your id"
        let token = "your token"
        let info  = API().Init( env, id, token )
        
        let param = [  currency.GPB_JPY                     /// 対象となる通貨
                       granularity.M15                      /// 時間足
                       ("start", setting.Start |> toEET )   /// 開始時刻
                       ("end"  , setting.Last  |> toEET )   /// 終了時刻
                       includeFirst.False                   /// ヘッドは含めない
                       alignmentTimezone.Japan
                       dailyAlignment.H7   
                    ]

        let jsonFromOanda = (Rates(info).Get_History param)


        (*
            取得したデーターを損益が出しやすいように加工する
        *)

        let swapRowColumn lst =
            lst
            |> List.collect List.indexed
            |> List.groupBy fst
            |> List.map snd
            |> List.map (List.map snd)

        let pricesSet =
            JsonValue.Parse jsonFromOanda
            |> fun dt -> dt.GetProperty("candles").AsArray()
            |> Array.map ( fun (x:JsonValue) -> [x.GetProperty("highBid").AsFloat() ; x.GetProperty("lowBid").AsFloat() ])
            |> Array.toList
            |> swapRowColumn

        let highPrices = pricesSet.Item 0
        let lowPrices  = pricesSet.Item 1
        let prices     = (lowPrices,highPrices)
                         /// 高値・安値の間を最小単位で補完する
                         ||>  List.map2 ( fun a b -> [ a .. 0.001 .. b] )
                         ///  最小単位で価格を丸める( ここ重要! )
                         |>   List.map ( fun l -> l |> List.map ( fun n -> System.Math.Round( n , 3 )) )


        (*

            価格に対して自分の仕掛けが掛かっているかどうか
            また掛かっていたらどれだけ損益がでたかを調べる

        *)

        /// util function
        let pricePoint entryPrice prices =
            prices
            |> List.map ( List.tryFind ( fun n -> n = entryPrice) )
            |> List.tryFindIndex ( fun x -> Option.isSome x )

        /// entry ができるかどうか
        let entryPoint = pricePoint setting.Entry prices

        if      entryPoint.IsNone
        then    stdout.WriteLine "エントリーされませんでした"
        else
                /// entry したあとのリストをつくる
                let lst =   prices 
                            |> List.splitAt entryPoint.Value
                            |> snd

                /// tp or cl どちらかが掛かってるかを調べる
                let takeProfitPoint : option<int> = pricePoint setting.TakeProfit lst
                let cutLossPoint    : option<int> = pricePoint setting.CutLoss    lst

                let cutLoss () = 
                    let loss   = System.Math.Abs( setting.Entry - setting.CutLoss )    |> fun n -> System.Math.Round( n , 3 )
                    stdout.WriteLine( string loss   + " の損失を計上しました〜" )

                let takeProfit () =
                    let profit = System.Math.Abs( setting.TakeProfit - setting.Entry ) |> fun n -> System.Math.Round ( n , 3 )
                    stdout.WriteLine( string profit + " の利益を計上しました〜" )

                match takeProfitPoint, cutLossPoint with
                | Some t , Some c when t > c -> cutLoss    ()
                | Some _ , _                 -> takeProfit ()
                | None   , Some _            -> cutLoss    ()
                | _ -> stdout.WriteLine "まだ確定されてません"
Remove all ads

F#でFXのトレード検証を手軽にできるシステムを作ってみる(その2)

adacolaさんに教えてもらったよ〜

Summary

前回の続き

アクティブパターンを使うとif/then/elseが綺麗になるよ、みたいな

code

module FX20170410 =

    /// とりあえず価格はこんな感じでつくってみる
    let highPrices = [99. .. -1. .. 92.]
    let lowPrices  = [97. .. -1. .. 90.]
    let dayprices  = List.map2 ( fun a b -> [a .. 0.001 .. b] ) lowPrices highPrices 

    /// entry ,tp, cl に対しての情報
    type Info = { Entry : float ; TakeProfit : float ; CutLoss : float }

    /// util function
    let pricePoint entryPrice prices =
        prices
        |> List.map ( List.tryFind ( fun n -> n = entryPrice) )
        |> List.tryFindIndex ( fun x -> Option.isSome x )

    let info : Info = { Entry = 99. ; TakeProfit = 95. ; CutLoss = 100. }

    /// entry ができるかどうか
    let entryPoint : option<int> = pricePoint info.Entry dayprices

    if      entryPoint.IsNone
    then    stdout.WriteLine "エントリーされませんでした"
    else
            /// entry したあとのリストをつくる
            let lst =   dayprices 
                        |> List.splitAt entryPoint.Value
                        |> snd

            /// tp or cl どちらかが掛かってるかを調べる
            let takeProfitPoint : option<int> = pricePoint info.TakeProfit lst
            let cutLossPoint    : option<int> = pricePoint info.CutLoss    lst

            let cutLoss () = 
                let loss   = System.Math.Abs( info.Entry - info.CutLoss )
                stdout.WriteLine( string loss   + " の損失を計上しました〜" )

            let takeProfit () =
                let profit = System.Math.Abs( info.TakeProfit - info.Entry )
                stdout.WriteLine( string profit + " の利益を計上しました〜" )

            match takeProfitPoint, cutLossPoint with
            | Some t , Some c when t > c -> cutLoss    ()
            | Some _ , _                 -> takeProfit ()
            | None   , Some _            -> cutLoss    ()
            | _ -> stdout.WriteLine "まだ確定されてません"

結果

4 の利益を計上しました〜

感想

ここをチェック〜

yukitosさん、bleisさん、adacolaさん。ありがとうございます!

gitter.im

Remove all ads

F#でFXのトレード検証を手軽にできるシステムを作ってみる(その1)

Summary

手軽にトレーディングアイディアを試せるシステムをつくってみる!

Motivation

FXトレードの幅がひろがるんじゃないかと・・(もっともっとお金ほしい〜)

今回の骨子

とりあえず下記2つをやってみました

ある価格にたいして

1 entry できる場所があるかどうか
2 takeprofit or cutloss の場所があるかどうか

Code

こんな感じ

module FX20170410 =
    

    /// とりあえず価格はこんな感じでつくってみる
    let lowPrices  = [97. .. 104.]
    let highPrices = [99. .. 106.]
    let dayprices  = List.map2 ( fun a b -> [a .. 0.001 .. b] ) lowPrices highPrices 
    
    /// entry ,tp, cl に対しての情報
    type Info = { Entry : float ; TakeProfit : float ; CutLoss : float }
    
    /// util function
    let pricePoint entryPrice prices =
        prices
        |> List.map ( List.tryFind ( fun n -> n = entryPrice) )
        |> List.tryFindIndex ( fun x -> Option.isSome x )


    /// ---------------------------------------------------------------------


    /// エントリーは100, 利確は105, 損切りは95とする
    let info : Info = { Entry = 100. ; TakeProfit = 105. ; CutLoss = 95. }

    /// entry ができるかどうか
    let entryPoint : option<int> = pricePoint info.Entry dayprices

    if entryPoint.IsSome then
        /// entry したあとのリストをつくる
        let lst =   dayprices 
                    |> List.splitAt entryPoint.Value
                    |> snd
        
        /// tp or cl どちらかが掛かってるかを調べる
        let takeProfitPoint : option<int> = pricePoint info.TakeProfit dayprices
        let cutLossPoint    : option<int> = pricePoint info.CutLoss dayprices

        if  takeProfitPoint.IsSome && cutLossPoint.IsSome then
            stdout.WriteLine "*****"
        elif  takeProfitPoint.IsSome then
            let profit = info.TakeProfit - info.Entry
            stdout.WriteLine( string profit + " の利益を獲得しました〜" )
        elif  cutLossPoint.IsSome then
            stdout.WriteLine "*****"
        else
            stdout.WriteLine "*****"
    else
        stdout.WriteLine "エントリーされませんでした"

結果

5 の利益を獲得しました〜

*** time : 0.139117 s ***

感想

まだまだ何もわかってないのでちょっとずつ作っていきたいです!

Remove all ads

OANDA API からデーター取得のメモ

最新のローソク足を取得

1時間足のローソク足を2本取得する

#load "/./Users/kohei/Documents/01_F#/OANDAfs/oandafs.fsx"
open oandafs.Oandafs

let env   = Environment.Live
let id    = "**********"
let token = "**********"
let info  = API().Init( env, id, token )

let param = [   currency.GPB_JPY         /// 対象となる通貨
                granularity.H1           /// 時間足
                ("count","2")            /// 取得したいローソク足の本数
                 
                /// ここはおまじない
                alignmentTimezone.Japan  /// タイムゾーンはJST
                dailyAlignment.H7        /// ヘッドを調整
            ]

Rates(info).Get_History param |> printfn "%s"

結果

{
    "instrument" : "GBP_JPY",
    "granularity" : "H1",
    "candles" : [
        {
            "time" : "2017-04-07T19:00:00.000000Z",
            "openBid" : 137.583,
            "openAsk" : 137.612,
            "highBid" : 137.723,
            "highAsk" : 137.753,
            "lowBid" : 137.512,
            "lowAsk" : 137.539,
            "closeBid" : 137.571,
            "closeAsk" : 137.598,
            "volume" : 8103,
            "complete" : true
        },
        {
            "time" : "2017-04-07T20:00:00.000000Z",
            "openBid" : 137.57,
            "openAsk" : 137.598,
            "highBid" : 137.622,
            "highAsk" : 137.655,
            "lowBid" : 137.327,
            "lowAsk" : 137.378,
            "closeBid" : 137.372,
            "closeAsk" : 137.448,
            "volume" : 6087,
            "complete" : true
        }
    ]
}

期間を指定してローソク足を取得

期間:2017/4/3 9時から12時までローソク足3本取得する

#load "/./Users/kohei/Documents/01_F#/OANDAfs/oandafs.fsx"
open oandafs.Oandafs

let env   = Environment.Live
let id    = "********"
let token = "********"
let info  = API().Init( env, id, token )

let startDate = System.DateTime( 2017,4,3,9,0,0)  |> toEET /// 日本の時刻をヨーロッパの時刻に変換する
let endDate   = System.DateTime( 2017,4,3,13,0,0) |> toEET /// 日本の時刻をヨーロッパの時刻に変換する

let param = [  currency.GPB_JPY     /// 対象となる通貨
               granularity.H1       /// 時間足
               ("start",startDate)  /// 開始時刻
               ("end"  , endDate )  /// 終了時刻
               includeFirst.False   /// ヘッドは含めない
               
               /// おまじない
               alignmentTimezone.Japan
               dailyAlignment.H7   
            ]

Rates(info).Get_History param |> printfn "%s"

結果

{
    "instrument" : "GBP_JPY",
    "granularity" : "H1",
    "candles" : [
        {
            "time" : "2017-04-03T03:00:00.000000Z",
            "openBid" : 139.66,
            "openAsk" : 139.689,
            "highBid" : 139.717,
            "highAsk" : 139.754,
            "lowBid" : 139.516,
            "lowAsk" : 139.546,
            "closeBid" : 139.553,
            "closeAsk" : 139.583,
            "volume" : 4431,
            "complete" : true
        },
        {
            "time" : "2017-04-03T04:00:00.000000Z",
            "openBid" : 139.547,
            "openAsk" : 139.577,
            "highBid" : 139.686,
            "highAsk" : 139.717,
            "lowBid" : 139.544,
            "lowAsk" : 139.575,
            "closeBid" : 139.625,
            "closeAsk" : 139.656,
            "volume" : 4323,
            "complete" : true
        },
        {
            "time" : "2017-04-03T05:00:00.000000Z",
            "openBid" : 139.625,
            "openAsk" : 139.655,
            "highBid" : 139.89,
            "highAsk" : 139.922,
            "lowBid" : 139.623,
            "lowAsk" : 139.654,
            "closeBid" : 139.724,
            "closeAsk" : 139.758,
            "volume" : 5534,
            "complete" : true
        }
    ]
}
Remove all ads