Skip to content

Commit

Permalink
adding interaction fsm and player
Browse files Browse the repository at this point in the history
  • Loading branch information
sameerlal committed Apr 13, 2019
0 parents commit f5c348d
Show file tree
Hide file tree
Showing 17 changed files with 759 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# assignment
doc.public
doc.private
adv.zip

# ocaml
*.cmo
*.cma
*.cmi
*.out
*.cmx
*.native
*.byte
_build

# temporary files
*.swp
*~
\#*\#
.DS_Store

4 changes: 4 additions & 0 deletions .merlin
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
B _build
PKG oUnit
PKG yojson
PKG ANSITerminal
8 changes: 8 additions & 0 deletions .ocamlinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#require "oUnit";;
#require "yojson";;
#require "ANSITerminal";;
#directory "_build";;
#load "marketmaker.cmo";;
#load "parse.cmo";;
#load "trader.cmo";;
#load "state.cmo";;
46 changes: 46 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
MODULES=marketmaker trader command parse main
OBJECTS=$(MODULES:=.cmo)
MLS=$(MODULES:=.ml)
MLIS=$(MODULES:=.mli)
TEST=test.byte
MAIN=main.byte
OCAMLBUILD=ocamlbuild -use-ocamlfind

default: build
utop

build:
$(OCAMLBUILD) $(OBJECTS)

test:
$(OCAMLBUILD) -tag 'debug' $(TEST) && ./$(TEST)

play:
$(OCAMLBUILD) $(MAIN) && ./$(MAIN)

check:
bash checkenv.sh && bash checktypes.sh

finalcheck: check
bash checkzip.sh
bash finalcheck.sh

zip:
zip adv.zip *.ml* *.json _tags Makefile

docs: docs-public docs-private

docs-public: build
mkdir -p doc.public
ocamlfind ocamldoc -I _build -package yojson,ANSITerminal \
-html -stars -d doc.public $(MLIS)

docs-private: build
mkdir -p doc.private
ocamlfind ocamldoc -I _build -package yojson,ANSITerminal \
-html -stars -d doc.private \
-inv-merge-ml-mli -m A $(MLIS) $(MLS)

clean:
ocamlbuild -clean
rm -rf doc.public doc.private adv.zip
1 change: 1 addition & 0 deletions _tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true: package(oUnit),package(yojson),package(ANSITerminal)
43 changes: 43 additions & 0 deletions command.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
open Pervasives

type object_phrase = string list

type command =
| Profit
| Set of object_phrase
| Inventory
| Orderbook
| First_Trade
| Last_Trade
| Quit

exception Empty

exception Malformed

(**[parse string] is the command type which a player wants to be acted upon.
It takes in a string and converts it to a type of command.
Raises: Empty if no command given or just whitespace;
Malformed if not a recognized command;*)
let parse str =
let wordlst = String.split_on_char ' ' (String.trim str) in
let filtered = List.filter (fun s -> String.length s > 1) wordlst in
if List.length filtered > 0 then let cmd = List.hd filtered in
match cmd with
| "Set" -> if List.length filtered > 1 then
let obj = begin match filtered with
| [] -> []
| h::t -> t end
in (Set obj) else raise Malformed
| "Profit" -> if List.length filtered = 1 then Profit else raise Malformed
| "Inventory" -> if List.length filtered = 1 then Inventory else raise Malformed
| "Orderbook" -> if List.length filtered = 1 then Orderbook else raise Malformed
| "First Trade" -> if List.length filtered = 1 then First_Trade else raise Malformed
| "Last_Trade" -> if List.length filtered = 1 then Last_Trade else raise Malformed
| "Quit" -> if List.length filtered = 1 then Quit else raise Malformed
| "inventory" -> Inventory
| _ -> raise Malformed
else
raise Empty


13 changes: 13 additions & 0 deletions command.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type object_phrase = string list
type command =
| Profit
| Set of object_phrase
| Inventory
| Orderbook
| First_Trade
| Last_Trade
| Quit
exception Empty
exception Malformed

val parse: string -> command
23 changes: 23 additions & 0 deletions fermi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"id": "1",
"fermi": [
{
"question": "What is the volume of air that I breathe in one day?",
"answer": "2880"
},
{
"question": "How many people in the world are talking on their cell phones in any given minute?",
"answer": "125000000"
}
],
"situation": [
{
"event": "Flash Crash, all stocks are down",
"effect": "-10%"
},
{
"event": "Interest rates decrease",
"effect": "+2%"
}
]
}
99 changes: 99 additions & 0 deletions main.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
open Yojson.Basic.Util
open Marketmaker
open Trader
open Command
open Parse

exception UnknownFile

type trader_players = {
simple_ai : Trader.t;
}

type big_state = {
mmstate : Marketmaker.t;
traders : trader_players
}

let init_trader_players =
{ simple_ai = (Trader.init_trader ()) }

let rec parse_user_input state =
print_endline "\n \n Set market \n";
print_string "$ ";
match read_line() with
| exception End_of_file -> print_endline "Try again . . ."; parse_user_input state
| user_response -> begin
try Command.parse user_response with
| Command.Empty -> parse_user_input state
| Command.Malformed -> print_endline "Error in command."; parse_user_input state
end

let fsm fermi (state: big_state) =
print_endline ("reached fsm");
let user_command = parse_user_input state in
if (Marketmaker.get_timestamp state.mmstate) = 69 then
(* TODO CHANGE STATE WITH NEW EVENTS *)
state
else
match user_command with
| Command.Quit -> print_endline "QUIT"; exit 0
| Command.Set phr ->
let bid = int_of_string (List.nth phr 0) in
let ask = int_of_string (List.nth phr 1) in (* TODO UPDATE STATE BELOW TO REFLECT NEW STATES *)
let trade_transaction = Trader.make_transaction (Marketmaker.get_timestamp state.mmstate) bid ask "blank" in
let trader_response = Trader.make_trade state.traders.simple_ai trade_transaction in
begin
match trader_response with
| None -> print_endline "No Trade occured"; state
| Some (new_trader_state, response) ->
match response with
(* TODO UPDATE THE STATES BELOW IWTH THE NEW MMSTATE AND TRADER STATE *)
| "lift" -> print_endline "Trader has lifted your offer"; state
| "hit" -> print_endline "Trader has hit your bid"; state
| _ -> print_endline "error in trader's make trade"; exit 2
end
| _ -> print_endline "Done"; state


let rec cli fermi big_state =
print_string ("Timestamp ");
print_endline (" xxxx");
print_string (" Prev. bid/ask: ");
print_endline (" xxxx ");
print_string (" Outstanding Shares: " );
print_endline (" xxxx ");
match (Marketmaker.get_timestamp big_state.mmstate) with
| 10 -> print_endline ("GAME OVER ");
print_endline (" ADD STATISTICS AT END ");
exit 0
| _ -> cli fermi (fsm fermi big_state )



let init_big_state =
{
mmstate = Marketmaker.init_market "init";
traders = init_trader_players;
}


let play_game f =
Parse.introduction ();
let obtained_json = Yojson.Basic.from_file f in
let fermi = Parse.from_json obtained_json in
print_endline (Parse.get_question fermi);
print_endline ("Let us begin... make your market: ");
cli fermi init_big_state

let main () =
ANSITerminal.(print_string [blue]
"\n\nWelcome to the CamlCoin exchange! Here you will practice your maket
making skills \n");
print_endline "Please enter the name of the file: \n";
print_string "> ";
match read_line () with
| exception End_of_file -> ()
| file_name -> play_game file_name

let () = main ()
Empty file added main.mli
Empty file.
119 changes: 119 additions & 0 deletions marketmaker.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
open Pervasives

(* holds bid ask struct *)
type bidask = {
trade_type : string;
number_of_shares: int;
bid: int;
ask: int;
spread: int;
}

(* keeps track of market maker's holdings *)
type orderbook = {
outstanding_shares: int;
}

(* Holds market maker type *)
type t = {
currbidask: bidask;
timestamp: int;
curr_profit: int;
orderbook: orderbook
}


(* Trade variant. To be sent to engine *)

type send_market = {
timestamp : int;
transaction: bidask;
}

type receive_transaction = {
timestamp : int;
trader_id : string;
trade_type : string; (* hit the bid or lifted offer *)
transaction : bidask;
}


(**[init_market game] is the initial state of the market after a [game] is
started. *)
let init_market game : t =
{
currbidask = {
trade_type = "init";
number_of_shares = 0;
bid = 0;
ask = 0;
spread = 0;
};
timestamp = 0;
curr_profit = 0;
orderbook = {
outstanding_shares = 0
}
}

type result = Legal of t | Illegal



let calculate_new_profit (transaction:receive_transaction) market : t =
failwith "Unimplemented"

(**[readjust_spread transaction market] is a market with the updated spread for the
marketmaker after a bidask change. It has the new bid-offer pair after the
marketmaker has finished a trade for the security at a certain price. The
goal of readjustment is to prevent hacks and hopefully be above scratch. It
takes in a new [bid] and [ask] price set by the player and the current
[market] of type t.*)
let readjust_spread (transaction:receive_transaction) (market:t) : t =
failwith "Unimplemented"



(**[transaction market trade] is the new state of the marketmaker after a trade.
It takes in a type t [market] and a [trade] and sets a new inventory,
bidask, timestamp, orderbook and curr_profit for the marketmaker.*)
let transaction (transaction:receive_transaction) (market:t) =
{
currbidask = {
trade_type = transaction.trade_type;
number_of_shares = market.currbidask.number_of_shares + transaction.transaction.number_of_shares;
bid = transaction.transaction.bid;
ask = transaction.transaction.ask;
spread = transaction.transaction.spread;
};
timestamp = transaction.timestamp;
curr_profit = market.curr_profit; (* TODO *)
orderbook = {
outstanding_shares = market.orderbook.outstanding_shares
+ transaction.transaction.number_of_shares; (* TODO *)
}
}


(**[send_market market] is the new marketmaker after the player has set new
bid/ask prices. *)
let send_market market =
failwith "Unimplemented"

let get_profit market =
market.curr_profit

let get_outstandingshares market =
market.outstanding_shares

let get_orderbook (market : t) =
market.orderbook

let get_timestamp (market : t) =
market.timestamp






5 changes: 5 additions & 0 deletions marketmaker.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

(** The abstract type of values representing adventures. *)
type t
val init_market : string -> t
val get_timestamp : t -> int
Loading

0 comments on commit f5c348d

Please sign in to comment.