Commits

Oliver Gu  committed 04cda0f

Simplified examples by factoring out common logic

  • Participants
  • Parent commits 1270a37

Comments (0)

Files changed (16)

File examples/buy_market_order.ml

 open Async.Std
 open Ibx.Std
 
-let main ~enable_logging ~host ~port =
+let run () =
   let aapl = Contract.stock
     ~exchange:`BATS
     ~currency:`USD
     (Symbol.of_string "AAPL")
   in
-  Tws.with_client ~enable_logging ~host ~port
-    ~on_handler_error:`Raise (fun tws ->
-      Stream.iter (Tws.execution_reports tws) ~f:(fun exec_report ->
-        printf "%s\n\n%!"
-          (Sexp.to_string_hum (Execution_report.sexp_of_t exec_report)));
-      Stream.iter (Tws.commission_reports tws) ~f:(fun comm_report ->
-        printf "%s\n\n%!"
-          (Sexp.to_string_hum (Commission_report.sexp_of_t comm_report)));
-      let buy_market = Order.buy_market ~quantity:100 in
-      Tws.submit_order_exn tws
-        ~contract:aapl
-        ~order:buy_market
-      >>= fun (order_status, oid) ->
-      Pipe.iter_without_pushback order_status ~f:(fun status ->
-        printf "%s\n\n%!"
-          (Sexp.to_string_hum (Order_status.sexp_of_t status));
-        begin
-          match Order_status.state status with
-          | `Filled ->
-            after (sec 0.5) >>> (fun () -> Tws.cancel_order_status tws oid)
-          | _ -> ()
-        end))
+  Common.with_tws_client (fun tws ->
+    Stream.iter (Tws.execution_reports tws) ~f:(fun exec_report ->
+      printf "%s\n\n%!"
+        (Sexp.to_string_hum (Execution_report.sexp_of_t exec_report)));
+    Stream.iter (Tws.commission_reports tws) ~f:(fun comm_report ->
+      printf "%s\n\n%!"
+        (Sexp.to_string_hum (Commission_report.sexp_of_t comm_report)));
+    let buy_market = Order.buy_market ~quantity:100 in
+    Tws.submit_order_exn tws
+      ~contract:aapl
+      ~order:buy_market
+    >>= fun (order_status, oid) ->
+    Pipe.iter_without_pushback order_status ~f:(fun status ->
+      printf "%s\n\n%!"
+        (Sexp.to_string_hum (Order_status.sexp_of_t status));
+      begin
+        match Order_status.state status with
+        | `Filled ->
+          after (sec 0.5) >>> (fun () -> Tws.cancel_order_status tws oid)
+        | _ -> ()
+      end))
 
-let main_cmd =
+let command =
   Command.async_basic ~summary:"submit market buy order for AAPL"
     Command.Spec.(
       empty
       +> Common.port_arg ()
     )
     (fun enable_logging host port () ->
-      Monitor.try_with (fun () ->
-        if enable_logging then Common.init_logger ();
-        main ~enable_logging ~host ~port
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
+      run ~enable_logging ~host ~port ()
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run main_cmd
+let () = Command.run command

File examples/client/option_client.ml

-open Core.Std
-open Async.Std
-open Ibx.Std
-
-module Req_intf : sig
-  val req_option_data :
-    (Query.Market_data.t, Tick_option.t) Ib.Streaming_request.t
-end = struct
-  module S = Send_tag
-  module R = Recv_tag
-
-  let req_option_data = Ib.Streaming_request.create
-    ~send_header:(Ib.Header.create ~tag:S.Market_data ~version:9)
-    ~canc_header:(Ib.Header.create ~tag:S.Cancel_market_data ~version:1)
-    ~recv_header:[
-      Ib.Header.create ~tag:R.Tick_option ~version:6;
-    ]
-    ~skip_header:[
-      Ib.Header.create ~tag:R.Tick_price ~version:6;
-      Ib.Header.create ~tag:R.Tick_size ~version:6;
-      Ib.Header.create ~tag:R.Tick_string ~version:6;
-      Ib.Header.create ~tag:R.Tick_generic ~version:6;
-    ]
-    ~tws_query:Query.Market_data.pickler
-    ~tws_response:[
-      Response.Tick_option.unpickler;
-    ] ()
-end
-
-include Ib.Client
-
-let option_data t ~option =
-  let q =
-    Query.Market_data.create
-      ~contract:option
-      ~tick_generics:[]
-      ~snapshot:false
-  in
-  dispatch_streaming_request t Req_intf.req_option_data q
-
-let option_data_exn t ~option = option_data t ~option >>| Or_error.ok_exn
-
-let cancel_option_data t id =
-  cancel_streaming_request t Req_intf.req_option_data id

File examples/client/option_client.mli

-open Core.Std
-open Async.Std
-open Ibx.Std
-
-(** This customized client offers only subscription to option data. *)
-
-type t
-include Client_intf.S with type t := t
-
-val option_data
-  :  t
-  -> option:[ `Option ] Contract.t
-  -> (Tick_option.t Pipe.Reader.t * Query_id.t) Or_error.t Deferred.t
-
-val option_data_exn
-  :  t
-  -> option:[ `Option ] Contract.t
-  -> (Tick_option.t Pipe.Reader.t * Query_id.t) Deferred.t
-
-val cancel_option_data : t -> Query_id.t -> unit

File examples/client/print_option_data.ml

-open Core.Std
-open Async.Std
-open Ibx.Std
-
-let print_option_data ~host ~port ~duration =
-  Option_client.with_client ~host ~port ~on_handler_error:`Raise (fun clt ->
-    (* For current contracts check: http://finance.yahoo.com/q/op?s=GOOG *)
-    let goog_call =
-      Contract.option
-        ~id:(Contract_id.of_string "116034093")
-        ~exchange:`CBOE
-        ~currency:`USD
-        ~option_right:`Call
-        ~expiry:(Date.create_exn ~y:2013 ~m:Month.Jun ~d:21)
-        ~strike:(Price.of_float 850.)
-        (Symbol.of_string "GOOG")
-    in
-    Option_client.option_data_exn clt ~option:goog_call
-    >>= fun (option_ticks, id) ->
-    upon (after duration) (fun () -> Option_client.cancel_option_data clt id);
-    Pipe.iter_without_pushback option_ticks ~f:(fun option_tick ->
-      print_endline (Sexp.to_string_hum (Tick_option.sexp_of_t option_tick)))
-  )
-
-let print_option_data_cmd =
-  Command.async_basic ~summary:"print option data"
-    Command.Spec.(
-      empty
-      +> flag "-host" (optional_with_default "127.0.0.1" string)
-        ~doc:" hostname of TWS or Gateway (default localhost)"
-      +> flag "-port" (optional_with_default 4001 int)
-        ~doc:" TWS port 7496 or Gateway port 4001 (default 4001)"
-      +> flag "-duration" (optional_with_default (sec 30.) time_span)
-        ~doc:" duration of the option data stream (default 30s)"
-    )
-    (fun host port duration () ->
-      Monitor.try_with (fun () ->
-        print_option_data ~host ~port ~duration
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
-
-let () = Command.run print_option_data_cmd

File examples/common.ml

 open Async.Std
 open Ibx.Std
 
-let init_logger () =
-  let cwd = Core.Std.Unix.getcwd () in
-  let logfile = cwd ^/ "ibx.log" in
-  Log.Global.set_level `Debug;
-  Log.Global.set_output [Log.Output.file `Text ~filename:logfile]
+let with_tws_client f ~enable_logging ~host ~port =
+  if enable_logging then begin
+    let basedir = Core.Std.Unix.getcwd () in
+    let logfile = basedir ^/ "ibx.log" in
+    Log.Global.set_level `Debug;
+    Log.Global.set_output [Log.Output.file `Text ~filename:logfile]
+  end;
+  Monitor.try_with (fun () ->
+    Tws.with_client
+      ~enable_logging
+      ~host
+      ~port
+      ~on_handler_error:`Raise
+      (fun tws -> f tws)
+  )
+  >>| fun result ->
+  match result with
+  | Ok _ as x -> x
+  | Error exn -> Error (Error.of_exn (Monitor.extract_exn exn))
 
 let logging_flag () =
   Command.Spec.(

File examples/demultiplex.ml

     Console.Ansi.string_with_attr [`Bright; color] output
   else output)
 
-let print_market_data ~enable_logging ~host ~port ~duration =
-  Tws.with_client ~enable_logging ~host ~port ~on_handler_error:`Raise (fun tws ->
+let print_market_data ~duration =
+  Common.with_tws_client (fun tws ->
     let process_market_data symbol color =
       Tws.market_data tws ~contract:(Contract.stock ~currency:`USD symbol)
-      >>| function
+      >>= function
       | Error e ->
         prerr_endline (Error.to_string_hum e);
         let pipe_r, pipe_w = Pipe.create () in
         Pipe.close pipe_w;
-        pipe_r
+        return pipe_r
       | Ok (ticks, id) ->
         upon (Clock.after duration) (fun () -> Tws.cancel_market_data tws id);
-        Pipe.map ticks ~f:(unstage (make_tick_printer id symbol ~color))
+        return (Pipe.map ticks ~f:(unstage (make_tick_printer id symbol ~color)))
     in
     let symbols = ["AAPL"; "MSFT"; "GOOG"] in
     let colors  = [`Red; `Green; `Blue] in
     >>= fun pipes ->
     Pipe.iter_without_pushback (Pipe.interleave pipes) ~f:print_endline)
 
-let print_market_data_cmd  =
+let command =
   Command.async_basic ~summary:" print market data"
     Command.Spec.(
       empty
       +> Common.duration_arg ()
     )
     (fun enable_logging host port duration () ->
-      if enable_logging then Common.init_logger ();
-      Monitor.try_with (fun () ->
-        print_market_data ~enable_logging ~host ~port ~duration
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
+      print_market_data ~enable_logging ~host ~port ~duration
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run print_market_data_cmd
+let () = Command.run command

File examples/interactive_quotes.ml

     try Ok (Core_extended.Shell.run_full "clear" [])
     with exn -> Error exn)
 
-let display host port duration currency symbol =
-  Tws.with_client ~host ~port ~on_handler_error:`Raise (fun tws ->
+let display_quotes ~duration ~currency ~symbol =
+  Common.with_tws_client (fun tws ->
     let symbol = Symbol.of_string symbol in
     Tws.quotes_exn tws ~contract:(Contract.stock ~currency symbol)
     >>= fun (quotes, id) ->
       printf "%s%4.2f-%4.2f\n%!" clear_string
         (Price.to_float bid) (Price.to_float ask)))
 
-let display_cmd =
+let command =
   Command.async_basic ~summary:"displays quotes interactively"
     Command.Spec.(
       empty
+      +> Common.logging_flag ()
       +> Common.host_arg ()
       +> Common.port_arg ()
       +> Common.duration_arg ()
       +> Common.currency_arg ()
       +> anon ("STOCK-SYMBOL" %: string)
     )
-    (fun host port duration currency symbol () ->
-      Monitor.try_with (fun () -> display host port duration currency symbol)
-      >>| function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        shutdown 1
-      | Ok () -> ())
+    (fun enable_logging host port duration currency symbol () ->
+      display_quotes ~enable_logging ~host ~port ~duration ~currency ~symbol
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run display_cmd
+let () = Exn.handle_uncaught ~exit:true (fun () -> Command.run command)

File examples/last_price.ml

 open Async.Std
 open Ibx.Std
 
-let main ~enable_logging ~host ~port ~currency ~symbol =
-  Tws.with_client ~enable_logging ~host ~port
-    ~on_handler_error:(`Call (fun e ->
+let print_last_price ~currency ~symbol =
+  Common.with_tws_client (fun tws ->
+    let stock = Contract.stock ~currency (Symbol.of_string symbol) in
+    Tws.trade_snapshot tws ~contract:stock
+    >>= function
+    | Error e ->
       eprintf "[Error] Failed to retrieve last price for %s:\n%!" symbol;
       prerr_endline (Error.to_string_hum e);
-      shutdown 1))
-    (fun tws ->
-      let stock = Contract.stock ~currency (Symbol.of_string symbol) in
-      Tws.trade_snapshot_exn tws ~contract:stock
-      >>| fun snapshot ->
+      exit 1
+    | Ok snapshot ->
       let last_price = Trade_snapshot.last_price snapshot in
       printf "[Info] Last price for %s was %4.2f %s\n"
-        symbol (Price.to_float last_price) (Currency.to_string currency))
+        symbol (Price.to_float last_price) (Currency.to_string currency);
+      return ()
+  )
 
-let main_cmd =
+let command =
   Command.async_basic ~summary:"Retrieve last stock price"
     Command.Spec.(
       empty
       +> anon ("STOCK-SYMBOL" %: string)
     )
     (fun enable_logging host port currency symbol () ->
-      main ~enable_logging ~host ~port ~currency ~symbol
+      print_last_price ~enable_logging ~host ~port ~currency ~symbol
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
     )
 
-let () = Command.run main_cmd
+let () = Exn.handle_uncaught ~exit:true (fun () -> Command.run command)

File examples/plot_hist_bars.ml

 let sma20 xs = sma ~period:20 xs
 let sma50 xs = sma ~period:50 xs
 
-let plot_hist_bars ~host ~port ~currency ~symbol =
-  Tws.with_client ~host ~port ~on_handler_error:`Raise (fun tws ->
+let plot_hist_bars ~currency ~symbol =
+  Common.with_tws_client (fun tws ->
     Tws.historical_data_exn tws
       ~contract:(Contract.stock ~currency (Symbol.of_string symbol))
       ~bar_size:`Five_mins
     ];
     Gnuplot.close g)
 
-let plot_hist_bars_cmd =
+let command =
   Command.async_basic ~summary:"plot historical bars"
     Command.Spec.(
       empty
+      +> Common.logging_flag ()
       +> Common.host_arg ()
       +> Common.port_arg ()
       +> Common.currency_arg ()
       +> anon ("STOCK-SYMBOL" %: string)
     )
-    (fun host port currency symbol () ->
-      Monitor.try_with (fun () ->
-        plot_hist_bars ~host ~port ~currency ~symbol
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
+    (fun enable_logging host port currency symbol () ->
+      plot_hist_bars ~enable_logging ~host ~port ~currency ~symbol
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run plot_hist_bars_cmd
+let () = Exn.handle_uncaught ~exit:true (fun () -> Command.run command)

File examples/plot_taq_data.ml

 
 let verbose = ref true
 
-let plot_taq_data ~enable_logging ~host ~port ~duration ~currency ~symbol =
-  Tws.with_client ~enable_logging ~host ~port
-    ~on_handler_error:`Raise (fun tws ->
-      let stock = Contract.stock ~currency (Symbol.of_string symbol) in
-      Tws.taq_data_exn tws ~contract:stock
-      >>= fun (taq_data, id) ->
-      upon (Clock.after duration) (fun () -> Tws.cancel_quotes tws id);
-      Pipe.fold taq_data ~init:([], [], [], [], [])
-        ~f:(fun (ttms, tpxs, qtms, asks, bids) taq_record ->
-          if !verbose then Format.printf "@[%a@]@\n%!" TAQ.pp taq_record;
-          match taq_record with
-          | TAQ.Trade trade ->
-            Trade.time  trade :: ttms,
-            Trade.price trade :: tpxs,
-            qtms, asks, bids
-          | TAQ.Quote quote ->
-            ttms, tpxs,
-            Quote.time      quote :: qtms,
-            Quote.ask_price quote :: asks,
-            Quote.bid_price quote :: bids)
-      >>| fun (ttms, tpxs, qtms, asks, bids) ->
-      let ttms = Array.of_list_rev (ttms : Time.t  list :> float list) in
-      let tpxs = Array.of_list_rev (tpxs : Price.t list :> float list) in
-      let qtms = Array.of_list_rev (qtms : Time.t  list :> float list) in
-      let asks = Array.of_list_rev (asks : Price.t list :> float list) in
-      let bids = Array.of_list_rev (bids : Price.t list :> float list) in
-      let g = Gnuplot.create () in
-      Gnuplot.send g (sprintf "set title \"%s\"" symbol);
-      Gnuplot.send g "unset xtics";
-      Gnuplot.plot g [
-        [ttms; tpxs], "with points lc rgb 'blue'  title \"trades\"";
-        [qtms; asks], "with steps  lc rgb 'red'   title \"ask\"";
-        [qtms; bids], "with steps  lc rgb 'green' title \"bid\"";
-      ];
-      Gnuplot.close g)
+let plot_taq_data ~duration ~currency ~symbol =
+  Common.with_tws_client (fun tws ->
+    let stock = Contract.stock ~currency (Symbol.of_string symbol) in
+    Tws.taq_data_exn tws ~contract:stock
+    >>= fun (taq_data, id) ->
+    upon (Clock.after duration) (fun () -> Tws.cancel_quotes tws id);
+    Pipe.fold taq_data ~init:([], [], [], [], [])
+      ~f:(fun (ttms, tpxs, qtms, asks, bids) taq_record ->
+        if !verbose then Format.printf "@[%a@]@\n%!" TAQ.pp taq_record;
+        match taq_record with
+        | TAQ.Trade trade ->
+          Trade.time  trade :: ttms,
+          Trade.price trade :: tpxs,
+          qtms, asks, bids
+        | TAQ.Quote quote ->
+          ttms, tpxs,
+          Quote.time      quote :: qtms,
+          Quote.ask_price quote :: asks,
+          Quote.bid_price quote :: bids)
+    >>| fun (ttms, tpxs, qtms, asks, bids) ->
+    let ttms = Array.of_list_rev (ttms : Time.t  list :> float list) in
+    let tpxs = Array.of_list_rev (tpxs : Price.t list :> float list) in
+    let qtms = Array.of_list_rev (qtms : Time.t  list :> float list) in
+    let asks = Array.of_list_rev (asks : Price.t list :> float list) in
+    let bids = Array.of_list_rev (bids : Price.t list :> float list) in
+    let g = Gnuplot.create () in
+    Gnuplot.send g (sprintf "set title \"%s\"" symbol);
+    Gnuplot.send g "unset xtics";
+    Gnuplot.plot g [
+      [ttms; tpxs], "with points lc rgb 'blue'  title \"trades\"";
+      [qtms; asks], "with steps  lc rgb 'red'   title \"ask\"";
+      [qtms; bids], "with steps  lc rgb 'green' title \"bid\"";
+    ];
+    Gnuplot.close g)
 
-let plot_taq_data_cmd =
+let command =
   Command.async_basic ~summary:"plot TAQ data"
     Command.Spec.(
       empty
       +> anon ("STOCK-SYMBOL" %: string)
     )
     (fun enable_logging quiet host port duration currency symbol () ->
-      if enable_logging then Common.init_logger ();
       verbose := not quiet;
       if Time.Span.(duration > minute) then begin
         prerr_endline "Maximum duration is 1 minute";
         exit 1;
       end else
-        Monitor.try_with (fun () ->
-          plot_taq_data ~enable_logging ~host ~port ~duration ~currency ~symbol
-        ) >>= function
-        | Error exn ->
-          let err = Error.of_exn (Monitor.extract_exn exn) in
-          prerr_endline (Error.to_string_hum err);
-          exit 1
-        | Ok () -> return ())
+        plot_taq_data ~enable_logging ~host ~port ~duration ~currency ~symbol
+        >>= function
+        | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+        | Ok () -> return ()
+    )
 
-let () = Command.run plot_taq_data_cmd
+let () = Exn.handle_uncaught ~exit:true (fun () -> Command.run command)

File examples/print_market_depth.ml

 open Async.Std
 open Ibx.Std
 
-let print_market_depth ~host ~port ~duration ~currency ~symbol =
-  Tws.with_client ~host ~port ~on_handler_error:`Raise (fun tws ->
+let print_market_depth ~duration ~currency ~symbol =
+  Common.with_tws_client (fun tws ->
     let stock = Contract.stock ~currency (Symbol.of_string symbol) in
     Tws.market_depth_exn tws ~contract:stock
     >>= fun (book_updates, id) ->
       printf "%s\n%!" (Book_update.sexp_of_t book_update |! Sexp.to_string_hum))
   )
 
-let print_market_depth_cmd =
+let command =
   Command.async_basic ~summary:"print market depth"
     Command.Spec.(
       empty
+      +> Common.logging_flag ()
       +> Common.host_arg ()
       +> Common.port_arg ()
       +> Common.duration_arg ()
       +> Common.currency_arg ()
       +> anon ("STOCK-SYMBOL" %: string)
     )
-    (fun host port duration currency symbol () ->
-      Monitor.try_with (fun () ->
-        print_market_depth ~host ~port ~duration ~currency ~symbol
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
+    (fun enable_logging host port duration currency symbol () ->
+      print_market_depth ~enable_logging ~host ~port ~duration ~currency ~symbol
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run print_market_depth_cmd
+let () = Exn.handle_uncaught ~exit:true (fun () -> Command.run command)

File examples/print_option_data.ml

+open Core.Std
+open Async.Std
+open Ibx.Std
+
+(* This example demonstrates how to customize a client. *)
+
+module Tws_req : sig
+  val req_option_data : (Query.Market_data.t, Tick_option.t) Ib.Streaming_request.t
+end = struct
+  module S = Send_tag
+  module R = Recv_tag
+
+  let req_option_data = Ib.Streaming_request.create
+    ~send_header:(Ib.Header.create ~tag:S.Market_data        ~version:9)
+    ~canc_header:(Ib.Header.create ~tag:S.Cancel_market_data ~version:1)
+    ~recv_header:[
+      Ib.Header.create ~tag:R.Tick_option  ~version:6;
+    ]
+    ~skip_header:[
+      Ib.Header.create ~tag:R.Tick_price   ~version:6;
+      Ib.Header.create ~tag:R.Tick_size    ~version:6;
+      Ib.Header.create ~tag:R.Tick_string  ~version:6;
+      Ib.Header.create ~tag:R.Tick_generic ~version:6;
+    ]
+    ~tws_query:Query.Market_data.pickler
+    ~tws_response:[Response.Tick_option.unpickler]
+    ()
+end
+
+module Option_client : sig
+  type t
+  include Client_intf.S with type t := t
+
+  val option_data
+    :  t
+    -> option:[ `Option ] Contract.t
+    -> (Tick_option.t Pipe.Reader.t * Query_id.t) Or_error.t Deferred.t
+
+  val option_data_exn
+    :  t
+    -> option:[ `Option ] Contract.t
+    -> (Tick_option.t Pipe.Reader.t * Query_id.t) Deferred.t
+
+  val cancel_option_data : t -> Query_id.t -> unit
+end = struct
+  include Ib.Client
+
+  let option_data t ~option =
+    let q =
+      Query.Market_data.create
+        ~contract:option
+        ~tick_generics:[]
+        ~snapshot:false
+    in
+    dispatch_streaming_request t Tws_req.req_option_data q
+
+  let option_data_exn t ~option =
+    option_data t ~option >>| Or_error.ok_exn
+
+  let cancel_option_data t id =
+    cancel_streaming_request t Tws_req.req_option_data id
+end
+
+let print_option_data ~duration =
+  Option_client.with_client
+    ~on_handler_error:(`Call (fun e ->
+      prerr_endline (Error.to_string_hum e);
+      shutdown 1
+    ))
+    (fun clt ->
+      (* For current contracts check: http://finance.yahoo.com/q/op?s=GOOG *)
+      let goog_call =
+        Contract.option
+          ~id:(Contract_id.of_string "116034093")
+          ~exchange:`CBOE
+          ~currency:`USD
+          ~option_right:`Call
+          ~expiry:(Date.create_exn ~y:2013 ~m:Month.Jun ~d:21)
+          ~strike:(Price.of_float 850.)
+          (Symbol.of_string "GOOG")
+      in
+      Option_client.option_data_exn clt ~option:goog_call
+      >>= fun (option_ticks, id) ->
+      upon (after duration) (fun () -> Option_client.cancel_option_data clt id);
+      Pipe.iter_without_pushback option_ticks ~f:(fun option_tick ->
+        print_endline (Sexp.to_string_hum (Tick_option.sexp_of_t option_tick)))
+    )
+
+let command =
+  Command.async_basic ~summary:"print option data"
+    Command.Spec.(
+      empty
+      +> Common.host_arg ()
+      +> Common.port_arg ()
+      +> Common.duration_arg ()
+    )
+    (fun host port duration () ->
+      print_option_data ~host ~port ~duration
+    )
+
+let () = Command.run command

File examples/quote_table.ml

     create_col "Ask price" get_ask_price;
   ] quotes
 
-let main ~enable_logging ~host ~port =
-  Tws.with_client ~enable_logging ~host ~port
-    ~on_handler_error:`Raise (fun tws ->
-      Deferred.all (List.map symbols ~f:(fun symbol ->
-        let stock = Contract.stock
-          ~exchange:`SMART
-          ~currency:`USD
-          (Symbol.of_string symbol)
-        in
-        Tws.quote_snapshot_exn tws ~contract:stock))
-      >>| fun quotes -> print_quote_table quotes)
+let run () =
+  Common.with_tws_client (fun tws ->
+    Deferred.all (List.map symbols ~f:(fun symbol ->
+      let stock = Contract.stock
+        ~exchange:`SMART
+        ~currency:`USD
+        (Symbol.of_string symbol)
+      in
+      Tws.quote_snapshot_exn tws ~contract:stock))
+    >>| fun quotes -> print_quote_table quotes)
 
-let main_cmd =
+let command =
   Command.async_basic ~summary:" print market data"
     Command.Spec.(
       empty
       +> Common.port_arg ()
     )
     (fun enable_logging host port () ->
-      if enable_logging then Common.init_logger ();
-      Monitor.try_with (fun () ->
-        main ~enable_logging ~host ~port
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
+      run ~enable_logging ~host ~port ()
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run main_cmd
+let () = Command.run command

File examples/server_time.ml

       >>| fun time ->
       print_endline (Time.to_string_trimmed time))
 
-let server_time_cmd =
+let command =
   Command.async_basic ~summary:"print server time"
     Command.Spec.(
       empty
     )
     (fun host port () -> print_server_time ~host ~port)
 
-let () = Command.run server_time_cmd
+let () = Command.run command

File examples/show_contract_specs.ml

     (Symbol.of_string "USD");
 ]
 
-let main_cmd =
+let run () =
+  Common.with_tws_client (fun tws ->
+    Deferred.List.iter contracts ~f:(fun contract ->
+      Tws.contract_specs_exn tws ~contract
+      >>| fun con_specs ->
+      printf "===== [ %s ] =====\n%!"
+        (Contract.symbol contract |! Symbol.to_string);
+      printf "%s\n\n%!"
+        (Contract_specs.sexp_of_t con_specs |! Sexp.to_string_hum)))
+
+let command =
   Command.async_basic ~summary:"show contract specifications"
     Command.Spec.(
       empty
+      +> Common.logging_flag ()
       +> Common.host_arg ()
       +> Common.port_arg ()
     )
-    (fun host port () ->
-      Tws.with_client ~host ~port
-        ~on_handler_error:(`Call (fun e ->
-          prerr_endline (Error.to_string_hum e);
-          shutdown 1))
-        (fun tws ->
-          Deferred.List.iter contracts ~f:(fun contract ->
-            Tws.contract_specs_exn tws ~contract
-            >>| fun con_specs ->
-            printf "===== [ %s ] =====\n%!"
-              (Contract.symbol contract |! Symbol.to_string);
-            printf "%s\n\n%!"
-              (Contract_specs.sexp_of_t con_specs |! Sexp.to_string_hum)))
+    (fun enable_logging host port () ->
+      run ~enable_logging ~host ~port ()
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
     )
 
-let () = Command.run main_cmd
+let () = Command.run command

File examples/submit_orders.ml

     Tws.cancel_order_status tws oid
   | `Result () -> ()
 
-let main ~enable_logging ~host ~port ~timeout =
+let run ~timeout =
   let symbol = Symbol.of_string "IBM" in
   let ibm = Contract.stock ~exchange:`BATS ~currency:`USD symbol in
   let num_shares = 100 in
-  Tws.with_client ~enable_logging ~host ~port
-    ~on_handler_error:`Raise (fun tws ->
-      Tws.quote_snapshot_exn tws ~contract:ibm
-      >>= fun snapshot ->
-      let ask_price = Quote_snapshot.ask_price snapshot in
-      printf "Last ask price %4.2f\n%!" (Price.to_float ask_price);
-      let buy_mkt = Order.buy_market ~quantity:num_shares in
-      let buy_lmt = Order.buy_limit  ~quantity:num_shares ask_price in
-      Deferred.all_unit [
-        submit_and_wait_for_fill tws ~timeout ~contract:ibm ~order:buy_mkt;
-        submit_and_wait_for_fill tws ~timeout ~contract:ibm ~order:buy_lmt;
-      ] >>= fun () ->
-      Tws.filter_executions_exn tws ~contract:ibm ~order_action:`Buy
-      >>= fun exec_reports ->
-      Pipe.iter_without_pushback exec_reports ~f:(fun exec_report ->
-        printf "Execution: \
+  Common.with_tws_client (fun tws ->
+    Tws.quote_snapshot_exn tws ~contract:ibm
+    >>= fun snapshot ->
+    let ask_price = Quote_snapshot.ask_price snapshot in
+    printf "Last ask price %4.2f\n%!" (Price.to_float ask_price);
+    let buy_mkt = Order.buy_market ~quantity:num_shares in
+    let buy_lmt = Order.buy_limit  ~quantity:num_shares ask_price in
+    Deferred.all_unit [
+      submit_and_wait_for_fill tws ~timeout ~contract:ibm ~order:buy_mkt;
+      submit_and_wait_for_fill tws ~timeout ~contract:ibm ~order:buy_lmt;
+    ] >>= fun () ->
+    Tws.filter_executions_exn tws ~contract:ibm ~order_action:`Buy
+    >>= fun exec_reports ->
+    Pipe.iter_without_pushback exec_reports ~f:(fun exec_report ->
+      printf "Execution: \
           exec_id=%s time=%s exchange=%s side=%s shares=%d price=%4.2f\n%!"
-          (Execution_report.exec_id exec_report |! Execution_id.to_string)
-          (Execution_report.time exec_report |! Time.to_string_trimmed)
-          (Execution_report.exchange exec_report |! Exchange.to_string)
-          (match Execution_report.side exec_report with
-          | `Purchase -> "purchase" | `Sale -> "sale")
-          (Execution_report.quantity exec_report)
-          (Execution_report.price exec_report |! Price.to_float))
+        (Execution_report.exec_id exec_report |! Execution_id.to_string)
+        (Execution_report.time exec_report |! Time.to_string_trimmed)
+        (Execution_report.exchange exec_report |! Exchange.to_string)
+        (match Execution_report.side exec_report with
+        | `Purchase -> "purchase" | `Sale -> "sale")
+        (Execution_report.quantity exec_report)
+        (Execution_report.price exec_report |! Price.to_float))
     )
 
 let timeout_arg () =
       ~doc:" timeout on fill (default 5s)"
   )
 
-let main_cmd =
+let command =
   Command.async_basic ~summary:"submit market buy order"
     Command.Spec.(
       empty
       +> timeout_arg ()
     )
     (fun enable_logging host port timeout () ->
-      if enable_logging then Common.init_logger ();
-      Monitor.try_with (fun () ->
-        main ~enable_logging ~host ~port ~timeout
-      ) >>= function
-      | Error exn ->
-        let err = Error.of_exn (Monitor.extract_exn exn) in
-        prerr_endline (Error.to_string_hum err);
-        exit 1
-      | Ok () -> return ())
+      run ~enable_logging ~host ~port ~timeout
+      >>= function
+      | Error e -> prerr_endline (Error.to_string_hum e); exit 1
+      | Ok () -> return ()
+    )
 
-let () = Command.run main_cmd
+let () = Command.run command