stockfighter 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +34 -6
- data/lib/stockfighter/api.rb +0 -23
- data/lib/stockfighter/gm.rb +3 -3
- data/lib/stockfighter/version.rb +1 -1
- data/lib/stockfighter/websockets.rb +102 -0
- data/lib/stockfighter.rb +1 -0
- data/stockfighter.gemspec +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 885259cfcbbb561e9bfcc16d21394302b6615f82
|
4
|
+
data.tar.gz: c1e9ebf5573a7056adcd8a154562b0fa0d76d015
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0093757ab0fd12e8ae655809826e5424f943be049bd9bb146bd35373b6a94cf64e60d8e8ea0059c09a250acefa77f60e1501f05a23c756019ef31613dc705178
|
7
|
+
data.tar.gz: a79a9cb440da8136034f8f6d19787329def1c2fbbbe9aaf002e22efcdf9d320a90bfa3f771399d8ad3bd6fa6830faa2ec8060c9ea8d989cb454e2e42147474bd
|
data/README.md
CHANGED
@@ -18,17 +18,35 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
$ gem install stockfighter
|
20
20
|
|
21
|
+
## Features
|
22
|
+
|
23
|
+
This gem can be used as a simple API client for the trading API, but also
|
24
|
+
includes more advanced features for interacting with the (officially undocumented)
|
25
|
+
GM API. This includes the ability to start / stop / restart / resume levels,
|
26
|
+
automatically fetch level info such as ticker, venue, and account, and also poll
|
27
|
+
the GM server regularly and return level and game information.
|
28
|
+
|
29
|
+
Support for the websockets API is also available
|
30
|
+
|
21
31
|
## Usage
|
22
32
|
|
33
|
+
Coming soon: comprehensive overview and API overview! For now, take a look at
|
34
|
+
some of the sample code below.
|
35
|
+
|
23
36
|
### Example
|
24
37
|
```ruby
|
25
38
|
require 'stockfighter'
|
26
39
|
|
27
|
-
# Use the GM to fetch
|
40
|
+
# Use the GM to fetch level info for the trading API automatically
|
41
|
+
|
42
|
+
gm = Stockfighter::GM.new(key: "supersecretapikey1234567", level: "first_steps")
|
43
|
+
|
44
|
+
api = Stockfighter::Api.new(gm.config)
|
45
|
+
|
46
|
+
# Use the GM to register message callbacks for messages received from the GM. The GM needs to be initialized with polling: true to set up polling of the GM and enable callbacks.
|
28
47
|
|
29
|
-
gm = Stockfighter::GM.new(key: "supersecretapikey1234567", level: "first_steps", polling:true)
|
48
|
+
gm = Stockfighter::GM.new(key: "supersecretapikey1234567", level: "first_steps", polling: true)
|
30
49
|
|
31
|
-
# Register message callbacks - GM needs to be constructed with polling:true for these callbacks to work
|
32
50
|
gm.add_message_callback('success') { |message|
|
33
51
|
puts "\e[#32m#{message}\e[0m"
|
34
52
|
}
|
@@ -41,8 +59,6 @@ gm.add_state_change_callback { |previous_state, new_state|
|
|
41
59
|
end
|
42
60
|
}
|
43
61
|
|
44
|
-
api = Stockfighter::Api.new(gm.config)
|
45
|
-
|
46
62
|
# Restart the level
|
47
63
|
|
48
64
|
gm.restart
|
@@ -99,12 +115,24 @@ api = Stockfighter::Api.new(key: key, account: account, symbol: symbol, venue: v
|
|
99
115
|
|
100
116
|
```
|
101
117
|
|
118
|
+
# Websockets api example
|
119
|
+
|
120
|
+
websockets = Stockfighter::Websockets.new(gm.config)
|
121
|
+
websockets.add_quote_callback { |quote|
|
122
|
+
puts quote
|
123
|
+
}
|
124
|
+
websockets.add_execution_callback { |execution|
|
125
|
+
puts execution
|
126
|
+
}
|
127
|
+
websockets.start()
|
128
|
+
|
129
|
+
|
102
130
|
## Todo
|
103
131
|
|
104
132
|
* ~~TODO: Usage instructions!~~
|
105
133
|
* ~~TODO: Game master integration~~
|
106
134
|
* TODO: Tests
|
107
|
-
* TODO: Error Handling
|
135
|
+
* TODO: Error Handling (partially complete)
|
108
136
|
|
109
137
|
## Contributing
|
110
138
|
|
data/lib/stockfighter/api.rb
CHANGED
@@ -15,18 +15,6 @@ module Stockfighter
|
|
15
15
|
HTTParty.get("#{BASE_URL}/venues/#{@venue}/stocks/#{@symbol}/quote", {"X-Starfighter-Authorization" => @api_key}).parsed_response
|
16
16
|
end
|
17
17
|
|
18
|
-
def block_until_first_trade()
|
19
|
-
puts "Waiting until first trade of #{@symbol}.#{@venue}"
|
20
|
-
|
21
|
-
quote = nil
|
22
|
-
loop do
|
23
|
-
quote = get_quote
|
24
|
-
puts quote
|
25
|
-
break if quote['last'] != nil
|
26
|
-
end
|
27
|
-
quote
|
28
|
-
end
|
29
|
-
|
30
18
|
def place_order(price:, quantity:, direction:, order_type:)
|
31
19
|
order = {
|
32
20
|
"account" => @account,
|
@@ -42,17 +30,6 @@ module Stockfighter
|
|
42
30
|
headers: {"X-Starfighter-Authorization" => @api_key}).parsed_response
|
43
31
|
end
|
44
32
|
|
45
|
-
def block_until_order_filled(order_id)
|
46
|
-
puts "Blocking until order #{order_id} is filled"
|
47
|
-
|
48
|
-
loop do
|
49
|
-
quote = get_quote
|
50
|
-
order_status = order_status(order_id)
|
51
|
-
puts "Order Status: #{order_status['direction']} #{order_status['originalQty']} #{order_status['symbol']}.#{order_status['venue']} @ #{order_status['price']} FilledQuantity:#{order_status['totalFilled']} Last Price: #{quote['last']}"
|
52
|
-
break if not order_status["open"]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
33
|
def cancel_order(order_id)
|
57
34
|
HTTParty.delete("#{BASE_URL}/venues/#{@venue}/stocks/#{@symbol}/orders/#{order_id}", headers: {"X-Starfighter-Authorization" => @api_key})
|
58
35
|
end
|
data/lib/stockfighter/gm.rb
CHANGED
@@ -13,7 +13,7 @@ module Stockfighter
|
|
13
13
|
|
14
14
|
@callback_types = ['success', 'info']
|
15
15
|
@message_callbacks = Hash.new { |h,k| h[k] = [] }
|
16
|
-
@
|
16
|
+
@state_change_callbacks = []
|
17
17
|
|
18
18
|
new_level_response = perform_request("post", "#{GM_URL}/levels/#{level}")
|
19
19
|
previous_state = new_level_response['state']
|
@@ -26,7 +26,7 @@ module Stockfighter
|
|
26
26
|
|
27
27
|
current_state = response['state']
|
28
28
|
if previous_state != current_state
|
29
|
-
@
|
29
|
+
@state_change_callbacks.each { |callback|
|
30
30
|
callback.call(previous_state, current_state)
|
31
31
|
}
|
32
32
|
previous_state = current_state
|
@@ -41,7 +41,7 @@ module Stockfighter
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def add_state_change_callback(&block)
|
44
|
-
@
|
44
|
+
@state_change_callbacks << block
|
45
45
|
end
|
46
46
|
|
47
47
|
def config
|
data/lib/stockfighter/version.rb
CHANGED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'websocket-eventmachine-client'
|
3
|
+
|
4
|
+
module Stockfighter
|
5
|
+
class Websockets
|
6
|
+
|
7
|
+
WS_URL = "https://www.stockfighter.io/ob/api/ws"
|
8
|
+
|
9
|
+
def initialize(key:, account:, symbol:, venue:)
|
10
|
+
@account = account
|
11
|
+
@venue = venue
|
12
|
+
@quote_callbacks = []
|
13
|
+
@execution_callbacks = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def start()
|
17
|
+
|
18
|
+
EM.epoll
|
19
|
+
EM.run do
|
20
|
+
|
21
|
+
EM.error_handler{ |e|
|
22
|
+
abort("Error raised during event loop: #{e}")
|
23
|
+
}
|
24
|
+
|
25
|
+
tickertape = WebSocket::EventMachine::Client.connect(:uri => "#{WS_URL}/#{@account}/venues/#{@venue}/tickertape", :ssl => true)
|
26
|
+
tickertape.onopen do
|
27
|
+
puts "tickertape websocket: connected"
|
28
|
+
end
|
29
|
+
|
30
|
+
tickertape.onmessage do |msg|
|
31
|
+
incoming = JSON.parse(msg)
|
32
|
+
if not incoming["ok"]
|
33
|
+
raise "tickertape websocket: Error response received: #{msg}"
|
34
|
+
end
|
35
|
+
if incoming.key?('quote')
|
36
|
+
quote = incoming['quote']
|
37
|
+
@quote_callbacks.each { |callback|
|
38
|
+
callback.call(quote)
|
39
|
+
}
|
40
|
+
else
|
41
|
+
raise "tickertape websocket: TODO: Unhandled message type: #{msg}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
tickertape.onerror do |e|
|
46
|
+
puts "tickertape websocket: Error #{e}"
|
47
|
+
end
|
48
|
+
|
49
|
+
tickertape.onping do |msg|
|
50
|
+
puts "tickertape websocket: Received ping: #{msg}"
|
51
|
+
end
|
52
|
+
|
53
|
+
tickertape.onpong do |msg|
|
54
|
+
puts "tickertape websocket: Received pong: #{msg}"
|
55
|
+
end
|
56
|
+
|
57
|
+
tickertape.onclose do
|
58
|
+
raise "tickertape websocket: Disconnected"
|
59
|
+
end
|
60
|
+
|
61
|
+
executions = WebSocket::EventMachine::Client.connect(:uri => "#{WS_URL}/#{@account}/venues/#{@venue}/executions", :ssl => true)
|
62
|
+
executions.onopen do
|
63
|
+
puts "executions websocket: Connected"
|
64
|
+
end
|
65
|
+
|
66
|
+
executions.onmessage do |msg|
|
67
|
+
execution = JSON.parse(msg)
|
68
|
+
if not execution["ok"]
|
69
|
+
raise "execution websocket: Error response received: #{msg}"
|
70
|
+
end
|
71
|
+
@execution_callbacks.each { |callback|
|
72
|
+
callback.call(execution)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
executions.onerror do |e|
|
77
|
+
puts "executions websocket: Error: #{e}"
|
78
|
+
end
|
79
|
+
|
80
|
+
executions.onping do |msg|
|
81
|
+
puts "executions websocket: Received ping: #{msg}"
|
82
|
+
end
|
83
|
+
|
84
|
+
executions.onpong do |msg|
|
85
|
+
puts "executions websocket: Received pong: #{msg}"
|
86
|
+
end
|
87
|
+
|
88
|
+
executions.onclose do
|
89
|
+
raise "executions websocket: Disconnected"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_quote_callback(&block)
|
95
|
+
@quote_callbacks << block
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_execution_callback(&block)
|
99
|
+
@execution_callbacks << block
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/stockfighter.rb
CHANGED
data/stockfighter.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "httparty", "~> 0.13.7"
|
22
22
|
spec.add_runtime_dependency "rufus-scheduler", "~> 3.1.10"
|
23
|
+
spec.add_runtime_dependency "websocket-eventmachine-client", "~> 1.1.0"
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
24
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stockfighter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert J Samson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 3.1.10
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: websocket-eventmachine-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.1.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,6 +96,7 @@ files:
|
|
82
96
|
- lib/stockfighter/api.rb
|
83
97
|
- lib/stockfighter/gm.rb
|
84
98
|
- lib/stockfighter/version.rb
|
99
|
+
- lib/stockfighter/websockets.rb
|
85
100
|
- stockfighter.gemspec
|
86
101
|
homepage: https://github.com/rjsamson/stockfighter
|
87
102
|
licenses:
|