2 people like it.

Processing Prices & Charting (Setup)

Implements simple library for downloading Yahoo stock prices and displaying charts in Try F#. This snippet loads another one with examples.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
open System
open System.Net
open System.Windows
open System.Windows.Shapes
open System.Windows.Media
open System.Windows.Controls
open System.Threading
open Microsoft.TryFSharp

// ------------------------------------------------------------------
// Downloading & visualizing stock prices from Yahoo

/// Asynchronously downloads stock prices from Yahoo
/// (uses a proxy to enable cross-domain downloads)
let downloadPricesAsync from stock = async {
  // Download price from Yahoo
  let wc = new WebClient()
  let url = "http://ichart.finance.yahoo.com/table.csv?s=" + stock  
  let proxy = "http://tomasp.net/tryjoinads/proxy.aspx?url=" + url
  let! html = wc.AsyncDownloadString(Uri(proxy)) 
  let lines = html.Split([|'\n'; '\r'|], StringSplitOptions.RemoveEmptyEntries)

  // Return sequence that reads the prices
  let data = seq { 
    for line in lines |> Seq.skip 1 do
      let infos = (line:string).Split(',')
      let dt = DateTime.Parse(infos.[0])
      let op = float infos.[1] 
      if dt > from then yield (* dt, *) op } 
  return data |> Array.ofSeq |> Array.rev |> Seq.ofArray }

// ------------------------------------------------------------------
// Helpers & wrappers

module Seq = 
  let rev data = data |> List.ofSeq |> List.rev |> Seq.ofList

// Synchronous wrapper
type Yahoo = 
  static member GetPrices(stock, ?from) = 
    let from = defaultArg from DateTime.MinValue
    downloadPricesAsync from stock |> Async.RunSynchronously

// ------------------------------------------------------------------
// Drawing charts

/// Create a line geometry from a sequence of float values
let createGeometry (min, max) width height data =
  let offsetX, offsetY = 20.0, 20.0
  
  let rec trimData data = 
    if Seq.length data > int width / 2 then
      data |> Seq.mapi (fun i v -> i%2=0, v) 
           |> Seq.filter fst |> Seq.map snd |> trimData
    else data
  let data = trimData data
  let scale v = height - ((v - min) / (max - min) * height)
  let data = data |> Seq.map scale |> Seq.pairwise

  let geometry = new GeometryGroup()
  let step = width / float (Seq.length data)
  for i, (prev, next) in Seq.zip [ 0 .. Seq.length data ] data do
    let f = Point(offsetX + float i * step, prev + offsetY)
    let t = Point(offsetX + float (i + 1) * step, next + offsetY)
    let line = LineGeometry(StartPoint = f, EndPoint = t)
    geometry.Children.Add(line)

  geometry


/// Create line chart - returns a function that can be
/// used to set the data of the line chart
let createLineChart color width height range data =
  let path = new Path(Stroke = new SolidColorBrush(color), StrokeThickness = 2.0)
  App.Console.Canvas.Children.Add(path)
  path.Data <- createGeometry range width height data


/// Runs an F# asynchronous workflow on the GUI thread in TryFSharp
let runUserInterface work = 
  let tok = new CancellationTokenSource()
  App.Dispatch (fun() -> 
    Async.StartImmediate(work, tok.Token)
    App.Console.CanvasPosition <- CanvasPosition.Right) |> ignore
  tok

/// Mutable variable (yeah!) to count number of charts
let plotCount = ref 0
let colors = 
  [| 136,0,21; 34,177,76; 237,28,36
     0,162,232; 255,127,40; 63,72,204
     255,242,0; 163,73,163; 16, 16, 16 |]

type Plot = 
  /// Plot the specified data
  static member Line(data, ?name, ?range) =
    let range = defaultArg range (Seq.min data, Seq.max data)
    let name = defaultArg name (sprintf "Plot %d" plotCount.Value)
    let addControl ctl x y =
      Canvas.SetTop(ctl, y)
      Canvas.SetLeft(ctl, x)
      App.Console.Canvas.Children.Add(ctl)

    /// Add legend to list & create GUI
    let addLegend name color = 
      let box = Rectangle(Width = 30.0, Height = 30.0)
      addControl box 550.0 (20.0 + float (plotCount.Value * 50))
      let block = TextBlock(FontSize = 20.0, Text = name, Width = 200.0)
      addControl block 590.0 (20.0 + float (plotCount.Value * 50))
      box.Fill <- new SolidColorBrush(color)

    App.Dispatch (fun() -> 
      App.Console.CanvasPosition <- CanvasPosition.Right
      let r, g, b = colors.[plotCount.Value % colors.Length]
      let color = Color.FromArgb(255uy, byte r, byte g, byte b)
      addLegend name color
      createLineChart color 500.0 200.0 range data
      incr plotCount )

  // Function that clears the window & resets count
  static member Clear() = 
    App.Dispatch(fun () -> 
      plotCount := 0
      App.Console.Canvas.Children.Clear() ) |> ignore

// Load snippet 'co', which contains examples that use this librar
App.Dispatch (fun () -> 
  App.Console.ClearOutput()
  App.Console.LoadFromUrl("http://fssnip.net/raw/co") )
namespace System
namespace System.Net
namespace System.Windows
namespace System.Media
namespace System.Threading
namespace Microsoft
val downloadPricesAsync : from:DateTime -> stock:string -> Async<seq<float>>

Full name: Script.downloadPricesAsync


 Asynchronously downloads stock prices from Yahoo
 (uses a proxy to enable cross-domain downloads)
val from : DateTime
val stock : string
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val wc : WebClient
Multiple items
type WebClient =
  inherit Component
  new : unit -> WebClient
  member BaseAddress : string with get, set
  member CachePolicy : RequestCachePolicy with get, set
  member CancelAsync : unit -> unit
  member Credentials : ICredentials with get, set
  member DownloadData : address:string -> byte[] + 1 overload
  member DownloadDataAsync : address:Uri -> unit + 1 overload
  member DownloadFile : address:string * fileName:string -> unit + 1 overload
  member DownloadFileAsync : address:Uri * fileName:string -> unit + 1 overload
  member DownloadString : address:string -> string + 1 overload
  ...

Full name: System.Net.WebClient

--------------------
WebClient() : unit
val url : string
val proxy : string
val html : string
member WebClient.AsyncDownloadString : address:Uri -> Async<string>
Multiple items
type Uri =
  new : uriString:string -> Uri + 5 overloads
  member AbsolutePath : string
  member AbsoluteUri : string
  member Authority : string
  member DnsSafeHost : string
  member Equals : comparand:obj -> bool
  member Fragment : string
  member GetComponents : components:UriComponents * format:UriFormat -> string
  member GetHashCode : unit -> int
  member GetLeftPart : part:UriPartial -> string
  ...

Full name: System.Uri

--------------------
Uri(uriString: string) : unit
Uri(uriString: string, uriKind: UriKind) : unit
Uri(baseUri: Uri, relativeUri: string) : unit
Uri(baseUri: Uri, relativeUri: Uri) : unit
val lines : string []
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
type StringSplitOptions =
  | None = 0
  | RemoveEmptyEntries = 1

Full name: System.StringSplitOptions
field StringSplitOptions.RemoveEmptyEntries = 1
val data : seq<float>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val line : string
module Seq

from Microsoft.FSharp.Collections
val skip : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.skip
val infos : string []
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val dt : DateTime
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime.Parse(s: string) : DateTime
DateTime.Parse(s: string, provider: IFormatProvider) : DateTime
DateTime.Parse(s: string, provider: IFormatProvider, styles: Globalization.DateTimeStyles) : DateTime
val op : float
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val ofSeq : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofSeq
val rev : array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.rev
val ofArray : source:'T [] -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.ofArray
val rev : data:seq<'a> -> seq<'a>

Full name: Script.Seq.rev
val data : seq<'a>
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val ofSeq : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.List.ofSeq
val rev : list:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.rev
val ofList : source:'T list -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.ofList
type Yahoo =
  static member GetPrices : stock:string * ?from:DateTime -> seq<float>

Full name: Script.Yahoo
static member Yahoo.GetPrices : stock:string * ?from:DateTime -> seq<float>

Full name: Script.Yahoo.GetPrices
val from : DateTime option
val defaultArg : arg:'T option -> defaultValue:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.defaultArg
field DateTime.MinValue
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
val createGeometry : min:int * max:int -> width:float -> height:int -> data:seq<int> -> 'a

Full name: Script.createGeometry


 Create a line geometry from a sequence of float values
val min : int
val max : int
val width : float
val height : int
val data : seq<int>
val offsetX : float
val offsetY : float
val trimData : (seq<'b> -> seq<'b>)
val data : seq<'b>
Multiple items
module Seq

from Script

--------------------
module Seq

from Microsoft.FSharp.Collections
val length : source:seq<'T> -> int

Full name: Microsoft.FSharp.Collections.Seq.length
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.mapi
val i : int
val v : 'b
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val scale : (int -> int)
val v : int
val data : seq<int * int>
val pairwise : source:seq<'T> -> seq<'T * 'T>

Full name: Microsoft.FSharp.Collections.Seq.pairwise
val geometry : 'a
val step : float
val prev : int
val next : int
val zip : source1:seq<'T1> -> source2:seq<'T2> -> seq<'T1 * 'T2>

Full name: Microsoft.FSharp.Collections.Seq.zip
val f : obj
val t : obj
val line : obj
type EndPoint =
  member AddressFamily : AddressFamily
  member Create : socketAddress:SocketAddress -> EndPoint
  member Serialize : unit -> SocketAddress

Full name: System.Net.EndPoint
val createLineChart : color:'a -> width:'b -> height:'c -> range:'d -> data:'e -> 'f

Full name: Script.createLineChart


 Create line chart - returns a function that can be
 used to set the data of the line chart
val color : 'a
val width : 'b
val height : 'c
val range : 'd
val data : 'e
val path : obj
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...

Full name: System.Console
Multiple items
namespace System.Data

--------------------
namespace Microsoft.FSharp.Data
val runUserInterface : work:'a -> CancellationTokenSource

Full name: Script.runUserInterface


 Runs an F# asynchronous workflow on the GUI thread in TryFSharp
val work : 'a
val tok : CancellationTokenSource
Multiple items
type CancellationTokenSource =
  new : unit -> CancellationTokenSource
  member Cancel : unit -> unit + 1 overload
  member Dispose : unit -> unit
  member IsCancellationRequested : bool
  member Token : CancellationToken
  static member CreateLinkedTokenSource : [<ParamArray>] tokens:CancellationToken[] -> CancellationTokenSource + 1 overload

Full name: System.Threading.CancellationTokenSource

--------------------
CancellationTokenSource() : unit
static member Async.StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
property CancellationTokenSource.Token: CancellationToken
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val plotCount : int ref

Full name: Script.plotCount


 Mutable variable (yeah!) to count number of charts
Multiple items
val ref : value:'T -> 'T ref

Full name: Microsoft.FSharp.Core.Operators.ref

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
val colors : (int * int * int) []

Full name: Script.colors
type Plot =
  static member Clear : unit -> unit
  static member Line : data:seq<'a> * ?name:string * ?range:('a * 'a) -> 'b (requires comparison)

Full name: Script.Plot
static member Plot.Line : data:seq<'a> * ?name:string * ?range:('a * 'a) -> 'b (requires comparison)

Full name: Script.Plot.Line


 Plot the specified data
val data : seq<'a> (requires comparison)
val name : string option
val range : ('a * 'a) option (requires comparison)
val range : 'a * 'a (requires comparison)
val min : source:seq<'T> -> 'T (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.min
val max : source:seq<'T> -> 'T (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.max
val name : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
property Ref.Value: int
val addControl : ('c -> 'd -> 'e -> 'f)
val ctl : 'c
val x : 'd
val y : 'e
val addLegend : ('c -> 'd -> 'e)


 Add legend to list & create GUI
val name : 'c
val color : 'd
val box : obj
val block : obj
namespace System.Text
property Array.Length: int
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
val incr : cell:int ref -> unit

Full name: Microsoft.FSharp.Core.Operators.incr
static member Plot.Clear : unit -> unit

Full name: Script.Plot.Clear

More information

Link:http://fssnip.net/cn
Posted:11 years ago
Author:Tomas Petricek
Tags: try f#