Skip to content
This repository was archived by the owner on Oct 19, 2022. It is now read-only.

Feature: Allow external async calls into strategy #15

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The internal architecture primarily consists of one big stream and a bunch of co
- [x] Simple API
- [x] Thoroughly tested
- [x] Typescript definitions
- [x] Allow async calls into strategy

## Installation

Expand All @@ -38,7 +39,7 @@ const feeds = {
myStreamFeed: fs.createReadStream(...)
}

const strategy = (context, action) => {
const strategy = (context, action, next) => {

// Place an order
if (action.type === 'myQuandlFeed') {
Expand All @@ -58,6 +59,9 @@ const strategy = (context, action) => {
id: 123
})
}

// Will call strategy with next data
next(action);
}

// Create the trading stream
Expand Down Expand Up @@ -143,7 +147,7 @@ The `createTrader`-function returns an unconsumed stream, and so it is up to you

```javascript
const settings = {...}
const strategy = (context, action) => {...}
const strategy = (context, action ,next) => {...}

createTrader(settings, strategy).resume()
```
Expand All @@ -154,7 +158,7 @@ However, you could also do crazy things like this:
import { createTrader, ORDER_FILLED, ORDER_FAILED } from 'devalpha'

const settings = {...}
const strategy = (context, action) => {...}
const strategy = (context, action, next) => {...}

const stream = createTrader(settings, strategy)

Expand Down
7 changes: 0 additions & 7 deletions __tests__/createStrategy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ beforeEach(() => {
t.context.middleware = createMiddleware(() => {})(store)(next)
})

test("pass the intercepted action to the next", () => {
const { middleware, next } = t.context
const action = { type: "FOO", payload: {} }
middleware(action)
expect(next.mock.calls[0][0]).toBe(action)
})

test("order() should synchronously dispatch order requested", done => {
const { store, next } = t.context
const action = { type: "FOO", payload: { timestamp: 0 } }
Expand Down
32 changes: 20 additions & 12 deletions __tests__/devalpha.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const t = { context: {} }

test("backtest event order", done => {
const executions = []
const strategy = ({ order }, action) => {
const strategy = ({ order }, action, next) => {
switch (action.type) {
case "example":
executions.push("a")
Expand All @@ -45,6 +45,7 @@ test("backtest event order", done => {
default:
break
}
next(action);
}

createTrader(
Expand Down Expand Up @@ -80,7 +81,7 @@ test("backtest event order", done => {

test("live trading event order", done => {
const executions = []
const strategy = ({ order }, action) => {
const strategy = ({ order }, action, next) => {
switch (action.type) {
case "example":
executions.push("a")
Expand All @@ -106,6 +107,7 @@ test("live trading event order", done => {
default:
break
}
next(action)
}

createTrader(
Expand Down Expand Up @@ -140,7 +142,7 @@ test("live trading event order", done => {
})

test("state() returns an object", done => {
const strategy = ({ state }, action) => {
const strategy = ({ state }, action, next) => {
expect(typeof state()).toBe("object")
done()
}
Expand All @@ -154,7 +156,7 @@ test("state() returns an object", done => {
})

test("failing orders are dispatched", done => {
const strategy = ({ order }, action) => {
const strategy = ({ order }, action, next) => {
switch (action.type) {
case "example":
order({
Expand All @@ -169,6 +171,7 @@ test("failing orders are dispatched", done => {
default:
break
}
next(action)
}

createTrader(
Expand All @@ -193,7 +196,7 @@ test("failing orders are dispatched", done => {
})

test("orders are cancellable", done => {
const strategy = ({ order, cancel, state }, action) => {
const strategy = ({ order, cancel, state }, action, next) => {
switch (action.type) {
case "example":
order({
Expand All @@ -214,6 +217,7 @@ test("orders are cancellable", done => {
default:
break
}
next(action)
}

createTrader(
Expand All @@ -238,7 +242,7 @@ test("orders are cancellable", done => {
})

test("should not be able to cancel unknown orders", done => {
const strategy = ({ cancel }, action) => {
const strategy = ({ cancel }, action, next) => {
switch (action.type) {
case "example":
cancel("1")
Expand All @@ -249,6 +253,7 @@ test("should not be able to cancel unknown orders", done => {
default:
break
}
next()
}

createTrader(
Expand Down Expand Up @@ -286,7 +291,7 @@ test("stream returns items containing action and state during live trading", don
feeds: {},
backtesting: false
},
() => {}
(context, action, next) => {next(action)}
)

strat
Expand All @@ -309,7 +314,7 @@ test("stream returns items containing action and state during backtests", done =
{
feeds: {}
},
() => {}
(context, action, next) => { next(action) }
)

strat
Expand Down Expand Up @@ -390,8 +395,9 @@ test("stream consumers recieve all events in the right order", done => {
events: [{ timestamp: 0 }, { timestamp: 1 }]
}
},
(context, action) => {
(context, action, next) => {
events.push("a")
next(action)
}
)

Expand All @@ -413,8 +419,9 @@ test("stream consumers can apply backpressure", done => {
events: [{ timestamp: 0 }, { timestamp: 1 }]
}
},
() => {
(context, action, next) => {
events.push("a")
next(action)
}
)

Expand Down Expand Up @@ -456,8 +463,9 @@ test("dashboard works as expected", done => {
active: true
}
},
() => {
(context, action, next) => {
serverEvents.push("a")
next(action)
}
).resume()

Expand Down Expand Up @@ -485,7 +493,7 @@ test("dashboard works as expected", done => {

test("calling devalpha logs to console", done => {
const actions = []
const strategy = ({ order }, action) => {}
const strategy = ({ order }, action, next) => {next(action)}
console.error = jest.fn()
devalpha(
{
Expand Down
7 changes: 4 additions & 3 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ export function createTrader(settings: any, strategy: Strategy) {
}

if (config.dashboard.active && config.project === null) {
throw new Error('the dashboard will not recognize your algorithm unless you set config.project to the ID of your DevAlpha project');
// tslint:disable:max-line-length
throw new Error('the dashboard will not recognize your algorithm unless you set config.project to the ID of your DevAlpha project')
}

// Store
Expand Down Expand Up @@ -200,10 +201,10 @@ export function createTrader(settings: any, strategy: Strategy) {
const socketStream = output.fork()
output = output.fork()

let id = 0;
let id = 0
const createMessage = (message: any) => {
let response = ''
response += `id: ${id++}\n`
response += `id: ${id+=1}\n`
response += `event: ${message.type}\n`
response += `data: ${JSON.stringify(message.payload)}\n`
response += `\n`
Expand Down
4 changes: 2 additions & 2 deletions lib/middleware/createStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ export function createStrategy(strategy: Strategy): Middleware {
}
})
},
action
action,
next
)
return next(action)
}

}
2 changes: 1 addition & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,4 @@ export interface ExecutedOrder extends CreatedOrder {
id: string
}

export type Strategy = (context: Context, action: StreamAction) => void
export type Strategy = (context: Context, action: StreamAction, next: Function) => void