Git Product home page Git Product logo

devalpha-node's Introduction

DevAlpha

Build Status Dependencies NPM Version Coverage Status

DevAlpha is a Javascript framework for creating and running your own algorithmic trading systems. It is built using TypeScript, weighs in at a less than 1500 lines of code, and is speedy as hell.

The internal architecture primarily consists of one big stream and a bunch of consumers. It is implemented using the excellent Highland streams library, and also makes use of some helper functions from Redux.

Features

  • Event sourced
  • Tiny footprint
  • Easily extensible
  • Simple API
  • Thoroughly tested
  • Typescript definitions

Interested in finance?

Talos is hiring senior engineers! Send an email to filip+hiring at talos.com.

Installation

Install using NPM:

npm install devalpha

Quickstart

(Check out devalpha-example for a starter repo.)

Getting started is easy as pie. Hook up any source of data you like and start trading in seconds.

import { createTrader } from 'devalpha'

const feeds = {
  myQuandlFeed: [1, 2, 3, 4],
  myStreamFeed: fs.createReadStream(...)
}

const strategy = (context, action) => {

  // Place an order
  if (action.type === 'myQuandlFeed') {
    context.order({
      identifier: action.payload.identifier,
      quantity: 100 * action.payload.signalStrength,
      price: 1000
    })
  }

  // Get current portfolio state
  const state = context.state()

  // Cancel an order
  if (state.capital.cash < 10000) {
    context.cancel({
      id: 123
    })
  }
}

// Create the trading stream
const stream = createTrader({ feeds }, strategy)

// Consumer the stream and make money!
stream.done(() => {
  console.log('Finished!')
})

Settings

const settings = {

  /* Toggle backtesting/realtime mode. In backtesting mode, events from the feed stream are pulled
  as needed rather than pushed as created. This allows you to do a number of events for each feed
  item, and then pull the next one only when you're finished with the current.
  
  NOTE: DevAlpha will only activate realtime mode when this parameter is explicitly set to `false`.
  This means that setting `backtesting: 0` will not do the job. */
  backtesting: true,

  /* Only used in realtime mode. The client manages order execution, and is provided to the 
  internal broker middleware. */
  client: null,

  /* Define the starting capital of your algorithm. Use only in backtesting mode. In realtime mode
  you're better of using the `initialStates` setting instead. */
  startCapital: 0,
  
  /* Provide initial states for your algorithm. One obvious use case would be when realtime
  trading, and you want to fetch positions, capital, or order information from your broker. */
  initialStates: {},

  /* An object mapping event names to stream-like objects. See https://highlandjs.org/#_(source)
  for a definition of "stream-like". Keys will be used as event type names. */
  feeds: {},

  /* Settings for your backtest. */
  backtest: {
    
    /* Denotes when your backtest is started (the first date of your backtesting data). */
    timestamp: 0,

    /* A number or a function used when calculating expected commission. */
    commission: 0

  },

  /* Settings for the guard middleware, which will prevent or alter orders (based on your
  configuration). */
  guard: {
    
    /* Allow/disallow shorting. */
    shorting: false,
    
    /* Allow/disallow trading on margin. */
    margin: false,

    /* An array of restricted instrument identifiers. Example: ['GOOG', 'SPOT']. */
    restricted: []

  },

  /* DevAlpha dashboard settings. */
  dashboard: {

    /* Toggle the DevAlpha dashboard. */
    active: false,

    /* Port used to pipe portfolio data. */
    port: 4449
  }

}

Usage

The createTrader-function returns an unconsumed stream, and so it is up to you to consume it (thereby running the strategy). Highland provides a number of ways of doing this (see here), but the easiest one is probably just to use .resume() like so:

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

createTrader(settings, strategy).resume()

However, you could also do crazy things like this:

import { createTrader, ORDER_FILLED, ORDER_FAILED } from 'devalpha'

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

const stream = createTrader(settings, strategy)

const slackStream = stream.fork()
const redisStream = stream.fork()

// Get Slack notifications on filled or failed orders
slackStream.each((event) => {
  if (event.action.type === ORDER_FILLED) {
    slackLogger.log('Hooray! An order was filled!')
  } else if (event.action.type === ORDER_FAILED) {
    slackLogger.log('Whoops! One of your orders was not executed!')
  }
})

// Place the current state in a Redis store
redisStream.each((event) => {
  redisClient.set('state', JSON.stringify(event.state))
})

Pretty neat, huh?

Resources

License

GNU GPL license. See the LICENSE.md file for details.

Responsibilities

The author of this software is not responsible for any indirect damages (foreseeable or unforeseeable), such as, if necessary, loss or alteration of or fraudulent access to data, accidental transmission of viruses or of any other harmful element, loss of profits or opportunities, the cost of replacement goods and services or the attitude and behavior of a third party.

devalpha-node's People

Contributors

fhqvst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

devalpha-node's Issues

README.md Quickstart problem

It has this code (I've removed your comments for brevity).

const stream = createTrader({ feeds }, strategy).done(() => {
  console.log('Finished!')
})
stream.resume();

and then re-uses stream. But .done(anything) returns undefined. I guess you intended:

const stream = createTrader(...);
stream.done(...);
stream.resume();

(though this seems to be attempting to consume the same stream twice???).

Realtime trading?

Hej,
jag har svårt att få ut nåt begripligt om Vesta. Kan jag realtidshandla mot börsen?

Provide a realtime example

Can you provide an example of how to add new data to a feed as it is running (how I imagine realtime must work). For example, add a new item to the stream every 2 seconds.

Allow charting of custom variables

I'd love to compare my strategy to buy and hold, or even overlay the price (I would manually have to do some scaling but that's fine). Is there any chance I could specify additional variables in my stream that I'd like graphed?

Quickstart problems

I'm creating issue here, as instructed at end of Quickstart section of the product docs at https://devalpha.io/.

In the https://devalpha.io/ Quickstart it says to create new file "index.js" and then you have 4 snippets that all start with "// index.js" as if you have 4 files all named "index.js". You said nothing about where the files belong or a directory structure, so I guess you are working in a single directory and all of the snippets get concatenated into a single file.

When I run "node index.js" as instructed, node dies complaining about the import statement. I run pretty leading-edge Arch Linux, but web searches tell me that current Node JS doesn't support the import statement. The example project works for me, so you are obviously doing something in the example project that is not happening when I clone and build the base project. What?

Postnote: I got the Quickstart to work.

  1. I looked at the example project and saw that you use require instead of import there, so I changed the Quickstart "index.js" to do the same.
  2. I fixed the line "const strategy = (context, action) {" to be "const strategy = function(context, action) {".

error TS2304: Cannot find name 'Element'.

while run npm run build
will show error like below
`../../node_modules/@types/sizzle/index.d.ts:19:53 - error TS2304: Cannot find name 'Element'.

19 matches(selector: string, elements: Element[]): Element[];
~~~~~~~

../../node_modules/@types/sizzle/index.d.ts:41:48 - error TS2304: Cannot find name 'Element'.

41 (match: RegExpMatchArray, context: Element | Document, isXML: boolean): Element[] | void;
~~~~~~~

../../node_modules/@types/sizzle/index.d.ts:41:58 - error TS2304: Cannot find name 'Document'.

41 (match: RegExpMatchArray, context: Element | Document, isXML: boolean): Element[] | void;
~~~~~~~~

../../node_modules/@types/sizzle/index.d.ts:41:85 - error TS2304: Cannot find name 'Element'.

41 (match: RegExpMatchArray, context: Element | Document, isXML: boolean): Element[] | void;
~~~~~~~

../../node_modules/@types/sizzle/index.d.ts:73:20 - error TS2304: Cannot find name 'Element'.

73 (elem: Element): boolean;
~~~~~~~

../../node_modules/@types/sizzle/index.d.ts:81:24 - error TS2304: Cannot find name 'Element'.

81 (elements: Element[], argument: number, not: boolean): Element[];
~~~~~~~

../../node_modules/@types/sizzle/index.d.ts:81:68 - error TS2304: Cannot find name 'Element'.

81 (elements: Element[], argument: number, not: boolean): Element[];
~~~~~~~`

favicon

Suggestion: Put a favicon in place for https://devalpha.io/. Unfortunate for the most handsome site in my tab list to have the ugliest tab. More pragmatically, when using many tabs (which I do constantly), this is how one can immediately find the tabs for a particular site. I'm always clicking into several no-favicon tabs to find which ones have my devalpha docs and dashboard.

Missing Custom Broker docs

According to https://www.reddit.com/r/algotrading/comments/8fqz9w/i_built_an_opensource_algorithmic_trading_platform/ , a month ago trams said regarding custom broker documentation,

Now I have finally pushed the docs update!

, yet at https://devalpha.io/documentation#custom-brokers today all it says regarding creation of custom brokers is:

Defining a createBroker function
The createBroker function should return an object containing three functions.

type brokerCreator = (onFill) => ({

})

Is there product documentation somewhere other than the Git README.md's and https://devalpha.io/documentation ?

Tick data

I see the example use Open high low and close. However i want to back test a hft algo on tick data with quote of bid and and also the book and order flow to ensure my orders get filled or not. Because if submit a limit buy order at the best bid and there is sell market order the buy never get executed ... howver the backtester might think i am long...

So question does devalpha support ticks data ??

API Documentation

It would be really helpful if there were API spec docs. I'm a Java developer and I'm used to working from API docs and having a reference stating the purpose of each method and input parameter and output value.

If you think it worth the effort and want a hand, I could fork and add annotations/symbols/whatever (tool-specific) for what I know (in hopes that somebody more knowledgeable about devalpha would fill in what I don't know), and add script for generating the docs, if you tell me what library you like. Several choices at https://www.npmjs.com/search?q=api%20documentation .

Another doc mistake on devalpha.io

You have

const csvStream = fs.createReadStream("myData.csv")

and then

feeds: {
    myData: csvStream.through(pipeline)

through is a Highland stream function, so I believe you would need: myData: _(csvStream).trough.

Cannot connect to backtester

Steps to reproduce:

git clone https://github.com/devalpha-io/devalpha-example.git
cd $_
npm install
npm start

Output:

> [email protected] start /home/starlord/projects/devalpha/devalpha-example
> node index.js

Waiting for DevAlpha...

My setup:

[starlord@localhost devalpha-example]$ npm --version
3.10.10
[starlord@localhost devalpha-example]$ node --version
v6.11.2
[starlord@localhost devalpha-example]$ uname -a
Linux localhost.localdomain 4.12.9-200.fc25.x86_64 #1 SMP Fri Aug 25 13:23:30 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[starlord@localhost devalpha-example]$ 

Roadmap

Looking at the documentation:

In the next major version of DevAlpha you will also be able to place percentage orders and market orders. The identifier property is required, and since DevAlpha currently only supports limit orders, so is the quantity and the price property.

Curious when the next version is planned on being released?

generality of dashboard

It may well be that this isn't an issue at all, and I just need help understanding purpose or usage of the dashboard. If I should post questions like to this to the reddit algotrading community or elsewhere, please say so.

I read somewhere in the docs that backtesting and the dashboard are very general and will work for any data, not just market trading. But I can't even get it to work generally with market trading.

Is the purpose of the chart to display only your holdings? Because it if I make no context.order then it displays nothing useful, does not chart the feed values. If I place a single buy then it seems to chart the value of my holding according to subsequent feed events. If I make a buy and later a sell then it seems to chart the value of my holding based only on buy and sell price with no influence by feed event prices. Specifically, I buy at 1.00 (with no correspondence to any feed value) and later sell at 3.00 (with no correspondence to any feed value) and this is charted as a line from 1.00 to 3.00. So in this case the feed data has only indirect influence (if I use it when calculating buy or sell prices in my strategy function).

Why does context.order return false even though it gets successfully requested, created, placed, and filled? Maybe false indicates that it's a backtesting order?

I thought I remembered reading somewhere that order rejections included a reason string. For my rejection events I get back only the same attributes as the order itself. Not useful for troubleshooting.

Now for the really flaky parts.

If I make buys at price 1.00, with my fake stocks, regardless of the feed prices, it goes through, and I can later sell them at this same price. Buys at other prices are rejected. Why a limit order would succeed when it is nowhere near the market prices, I don't know. Do you use some back-trading rules for accepting limit prices, and somehow allow "1.00"? In this strategy callback I can place multiple orders for different stocks at price 1.00 and they all succeed.

But context.order is only working for me in the first strategy callback in which I attempt it. As I said, multiple buys at 1.00 will succeed for multiple stocks. But if I try the same thing (to buy any stock) in a following strategy callback, the buy attempts are always rejected. It would be awesome if you would provide reason detail with rejection events.

I'm attaching my exercise script.

playTrader.js.txt

backtesting cash synchronization problem

I am not limited by startCapital. In any strategy event callback invocation where state.capital.cash > 0, I can buy as I wish to using multiple buys as long as each buy is for <= state.capital.cash. state.capital.cash goes negative.

It seems that within a single event cycle you either don't update state.capital.cash or don't check trades against the updated value.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.