Giter Club home page Giter Club logo

ktrade's People

Contributors

pareeohnos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ktrade's Issues

Create executable for `pip` package

The app will be installed through pip and should expose a ktrade command to launch the app. Setup should be as simple as

pip install ktrade
ktrade

Incompatible with Python 3.10

daven reported a failure trying to start up on python 3.9

:\ktrade-main>flask db upgrade
Traceback (most recent call last):
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\Scripts\flask.exe\__main__.py", line 7, in <module>
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\cli.py", line 990, in main
    cli.main(args=sys.argv[1:])
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\cli.py", line 596, in main
    return super().main(*args, **kwargs)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\click\core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\click\decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\cli.py", line 439, in decorator
    with __ctx.ensure_object(ScriptInfo).load_app().app_context():
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\cli.py", line 406, in load_app
    app = locate_app(self, import_name, None, raise_if_not_found=False)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\cli.py", line 256, in locate_app
    __import__(module_name)
  File "C:\ktrade-main\wsgi.py", line 4, in <module>
    from application import create_app, db, socketio
  File "C:\ktrade-main\application.py", line 9, in <module>
    from flask_socketio import SocketIO
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\flask_socketio\__init__.py", line 9, in <module>
    from socketio import socketio_manage  # noqa: F401
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\socketio\__init__.py", line 9, in <module>
    from .zmq_manager import ZmqManager
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\socketio\zmq_manager.py", line 5, in <module>
    import eventlet.green.zmq as zmq
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\__init__.py", line 17, in <module>
    from eventlet import convenience
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\convenience.py", line 7, in <module>
    from eventlet.green import socket
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\green\socket.py", line 4, in <module>
    __import__('eventlet.green._socket_nodns')
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\green\_socket_nodns.py", line 11, in <module>
    from eventlet import greenio
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\greenio\__init__.py", line 3, in <module>
    from eventlet.greenio.base import *  # noqa
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\greenio\base.py", line 32, in <module>
    socket_timeout = eventlet.timeout.wrap_is_timeout(socket.timeout)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\eventlet\timeout.py", line 166, in wrap_is_timeout
    base.is_timeout = property(lambda _: True)
TypeError: cannot set 'is_timeout' attribute of immutable type 'TimeoutError'

C:\ktrade-main>
C:\ktrade-main>python -V
Python 3.10.0

Handle connection failures

If the connection to TWS fails, the app should handle this in a nice way. Ideally it should present something to users on the UI so they are aware that things aren't working correctly.

This includes on launch of the app. If it can't connect when it first starts it already keeps trying until it can, however this is not reflected in the UI

Allow custom capital value to be specified

Right now the app fetches the account size on load, however some people trade using large accounts but only want to trade with a set amount of that. The app should allow you to configure your trading capital, and use that for calculations instead of getting the account size from TWS

Allow trimming an order

I should be able to trim an existing position by 1/2 or 1/3 with a button click. This should handle the selling of that amount, and if needed adjusting the stop loss to the break even point

Pull in account details

In order to correctly calculate position sizes when buying, we need to know details about the users account - specifically how large it is. The max size and risk of a trade is a percentage of your entire account, so without knowing what that is it cannot calculate the position size. Some code to pull this in thanks to Dolivent

class IB(EWrapper, EClient):
    def __init__(self):
        EWrapper.__init__(self)
        EClient.__init__(self, wrapper=self)
        self.connected = threading.Event()
        self.connect("127.0.0.1", 7496, 1)  # TODO pull address and port from config
        self.liquidityEstablished = threading.Event()
        self.liquidity = None


    def __del__(self):
        self.disconnect()


    # called when connection is actually established with TWS
    def nextValidId(self, orderId:int):
        self.connected.set()

    def getLiquidity(self):
        self.connected.wait()
        self.reqAccountSummary(9002, "All", "$LEDGER:USD")
        self.liquidityEstablished.wait()
        return self.liquidity

    def accountSummary(self, reqId:int, account:str, tag:str, value:str,
                       currency:str):
        if tag == "NetLiquidationByCurrency":
            self.liquidity = float(value)
            self.liquidityEstablished.set()

Improved notifications

Notifications in the app are a little messy at the moment. If for instance you place a huge order that is filled in multiple parts, you will get one notification for each part in quick succession.

Instead, the app should attempt to replace existing notifications an be clever. For example, if you place a huge order you should get one to say something like "Order filling", then it would update to say "Order filling: 1000/3000", then eventually update to success saying it's filled.

Add configuration for handling low buying power

When the app tries to buy a stock, it will calculate the position size based on your risk factors. In the event that the resulting position size calculated exceeds your buying power, the app needs to know what to do. The options are either:

  • Do nothing and error
  • Buy the max amount it can

Need to be careful with the latter option, as it won't be able to simply buy the full amount in the account, otherwise the order will be rejected due to no money to pay for the fees

LOD incorrect

image

LOD also moves around when price hovers around the LOD price. Returns something along hte lines of "stop price and buy price are the same"

Closing position deletes the record at the same time

What is the issue

When I close a position, the trade disappears and then the app crashes

What should happen

The trade should be closed, but shouldn't be deleted. The app should not crash

Other info

Relevant log section

INFO:werkzeug:127.0.0.1 - - [28/Sep/2021 00:06:44] "POST /trades/1/close HTTP/1.1" 200 -
INFO:ibapi.client:SENDING placeOrder b'\x00\x00\x01:3\x00555\x000\x00AAPL\x00STK\x00\x000.0\x00\x00\x00SMART\x00\x00USD\x00\x00\x00\x00\x00SELL\x0075.0\x00MKT\x00\x00\x00\x00\x00\x00\x000\x00\x001\x000\x000\x000\x000\x000\x000\x000\x00\x000\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00-1\x000\x00\x00\x000\x00\x00\x001\x001\x00\x000\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x000\x000\x00\x00\x000\x00\x000\x000\x000\x000\x00\x001.7976931348623157e+308\x001.7976931348623157e+308\x001.7976931348623157e+308\x001.7976931348623157e+308\x001.7976931348623157e+308\x000\x00\x00\x00\x001.7976931348623157e+308\x00\x00\x00\x00\x000\x000\x000\x00\x00'
INFO:ibapi.client:REQUEST cancelOrder {'orderId': 554}
INFO:ibapi.client:SENDING cancelOrder b'\x00\x00\x00\x084\x001\x00554\x00'
INFO:ibapi.wrapper:ANSWER error {'reqId': 555, 'errorCode': 2168, 'errorString': "Warning: The 'EtradeOnly' order attribute is not supported."}
ERROR:ibapi.wrapper:ERROR 555 2168 Warning: The 'EtradeOnly' order attribute is not supported.
INFO:ibapi.wrapper:ANSWER error {'reqId': 555, 'errorCode': 2169, 'errorString': "Warning: The 'FirmQuoteOnly' order attribute is not supported."}
ERROR:ibapi.wrapper:ERROR 555 2169 Warning: The 'FirmQuoteOnly' order attribute is not supported.
INFO:werkzeug:127.0.0.1 - - [28/Sep/2021 00:06:44] "OPTIONS /trades/1 HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [28/Sep/2021 00:06:44] "DELETE /trades/1 HTTP/1.1" 200 -
INFO:ibapi.wrapper:ANSWER tickString {'reqId': 552, 'tickType': 48, 'value': '144.47;25.0000000000000000;1632751604613;177457.0000000000000000;144.5486743;false'}
INFO:ibapi.wrapper:ANSWER tickString {'reqId': 552, 'tickType': 84, 'value': 'D'}
INFO:ibapi.wrapper:ANSWER tickPrice {'reqId': 552, 'tickType': 4, 'price': 144.48, 'attrib': 2912071928656: CanAutoExecute: 0, PastLimit: 0, PreOpen: 0}
INFO:werkzeug:127.0.0.1 - - [28/Sep/2021 00:06:44] "GET /socket.io/?EIO=4&transport=polling&t=Nmdb5A8&sid=JeWpuWKA8soLl8dyAAAA HTTP/1.1" 200 -
INFO:ibapi.wrapper:ANSWER tickSize {'reqId': 552, 'tickType': 5, 'size': 20}
INFO:ibapi.wrapper:ANSWER tickSize {'reqId': 552, 'tickType': 5, 'size': 20}
INFO:ibapi.wrapper:ANSWER tickSize {'reqId': 552, 'tickType': 8, 'size': 176955}
INFO:ibapi.wrapper:ANSWER orderStatus {'orderId': 554, 'status': 'Cancelled', 'filled': 0.0, 'remaining': 75.0, 'avgFillPrice': 0.0, 'permId': 718392687, 'parentId': 553, 'lastFillPrice': 0.0, 'clientId': 1, 'whyHeld': '', 'mktCapPrice': 0.0}
INFO:ibapi.wrapper:ANSWER error {'reqId': 554, 'errorCode': 202, 'errorString': 'Order Canceled - reason:'}
ERROR:ibapi.wrapper:ERROR 554 202 Order Canceled - reason:
INFO:ibapi.client:disconnecting
INFO:ibapi.wrapper:ANSWER connectionClosed {}
Exception in thread Thread-12:
Traceback (most recent call last):
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\threading.py", line 973, in _bootstrap_inner
    self.run()
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\pc_mo\PycharmProjects\ktrade\ktrade\providers\ib_provider.py", line 205, in ib_loop
    self.api.run()
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\site-packages\ibapi\client.py", line 263, in run
    self.decoder.interpret(fields)
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\site-packages\ibapi\decoder.py", line 1294, in interpret
    self.interpretWithSignature(fields, handleInfo)
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\site-packages\ibapi\decoder.py", line 1275, in interpretWithSignature
    method(*args)
  File "C:\Users\pc_mo\PycharmProjects\ktrade\ktrade\providers\ib\api.py", line 277, in error
    trade_failed(trade, errorString)
  File "C:\Users\pc_mo\PycharmProjects\ktrade\ktrade\provider_actions.py", line 40, in trade_failed
    trade = Trade.find(session, trade.id)
  File "C:\Users\pc_mo\PycharmProjects\ktrade\ktrade\models.py", line 13, in find
    return session.query(cls).filter_by(id=id).one()
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\orm\query.py", line 2730, in one
    return self._iter().one()
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\engine\result.py", line 1373, in one
    return self._only_one_row(True, True, False)
  File "C:\Users\pc_mo\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\engine\result.py", line 562, in _only_one_row
    raise exc.NoResultFound(
sqlalchemy.exc.NoResultFound: No row was found when one was required

Create a separate model for stop orders

Currently, the main Trade model has a stop_order_id column for tracking the stop loss order, however TWS reports statuses on the stop loss order separately. We should keep a track of this order separately so we can more accurately report the status of things.

We should either create a separate model for it, or (probably better) has child records (i.e add a parent_id column)

Automated EP trading

As requested by Corringham

I'd like the ability to load up some select EP Tickers chosen in the premarket, which then executes automatically during the open using straight KK defined opening range breakout criteria (with dynamic position sizing, SL placement, and ADR vs Range validation). I note your excellent tool looks to do the live pricing and position sizing with equity risk, but pushing the button on execution I think is manual? Would be great to set the Tickers, and it will trade them off a 1min ORH, and if stopped out will automatically reset (live checking ADR vs Range) and trade on a 5min ORH breakout, and then reset and go in on a 1 hour break. I'm basically doing this mechanically during the day using a spreadsheet, but being at the screen and executing isn't really adding any value to the process. To me the value is in choosing the right stocks to trade as EPs. I'd also like to spend more time Australia, so I'm happy choosing the stocks, putting execution on auto pilot would mean getting some sleep! Thanks in advance for any wisdom or pointers you might have!

Trimming a position leaves the order with the incorrect status

When we trim, the status of the trade switches to 'canceled' when it shouldn't. Ideally we should introduce one or more new statuses to cover these situations. Need to decide whether a trimmed order should still be shown as "complete" or do we mark it as "trimmed", or even "trimmed "

@Dolivent thoughts?

Allow trades to be removed

It should be possible to delete trades within KTrade. This might be because you don't want to manage it through KTrade, or you just want to clean up some clutter

Subscribe to real-time data when watching a ticker

When a new ticker is added to the watch list, it should register for real-time events from TWS. This is required so KTrade can calculate things like ADR, LOD etc and keep monitoring that ticker for updates

LOD bug still present

There is still a bug with the LOD calculations that is messing up entries, and it is extremely obvious when trying to enter an EP setup. It seems the app is loading yesterdays LOD values. One possibility is that TWS is not reporting the latest values when fetching historical data, so we need to change the time unit from days to something smaller. As small as possible would be best

Hook up the `buy` button

The BUY button currently does nothing. This should be hooked up so that it buys that stock with the appropriate values

LOD is wrong

When the app first starts up, it pulls in the last 20 days of bars and grabs the last one to get the LOD. TWS is reporting up to the time it was requested however, so this means the LOD is incorrect.

The app needs a better way of determining the LOD when it starts up, and also a way of refreshing this if the app is started before market opens.

Update existing orders on load

If I place an order using KTrade, shut the app, then open it again some other time such as mid-way through a trading day, it's possible that orders I placed have been stopped out or something else has changed.

When the app loads, it should fetch the latest status of each trade it has made, and update them accordingly

Validate ticker when adding to watchlist

When adding a ticker to your list of watched tickers, it is currently added immediately. Instead, it should be validated to ensure it is a real ticker, and on an exchange that KTrade (IB) supports.

Trim buttons let you go into a short position (if youre long and visa versa)

Trim buttons should be able to sell no more than the shares you own. Even if you submit a trim order, it hasn't been filled, and you click the button again (for whatever reason). A scenario where this is critical is if someone accidentally double clicks and submits sell orders in total in excess of what they have available to sell

Refresh trades when something changes

When trimming/closing a position, the table does not get updated after the order goes through. It should automatically refresh the moment there is an update from the server

Ticker autocomplete

When typing a ticker into the "Add ticker" input, it should present a list of possible results

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.