highfestiva / finplot

Performant and effortless finance plotting for Python
MIT License
889 stars 179 forks source link

Ability to use `timer_callback()` based on certain datetime instead of second(s) offset? #18

Closed ddm-j closed 4 years ago

ddm-j commented 4 years ago

So, I've developed a live updating chart based on the examples provided - but I was wondering if there would be a way to update timer_callback so that it would wait for a specific datetime before calling the update method.

I have zero experience with PyQt, so I'm not sure if I could just integrate the update method with something like what I have now:

target_time = datetime.utcnow()+timedelta(days=1) 
target_time = target_time.replace(hour=0,minute=1,second=0,microsecond=0)
print('Currently waiting until UTC time: {0}'.format(target_time))
while datetime.utcnow() < target_time:
    time.sleep(10)

get data and update plots

This code waits for 1 minute after midnight each day and then calls an API to get market prices. My API has limits so I need to have fine control over the number of calls that it makes. I understand that I could just implement something similar to the example, only waiting for the first midnight + 1minute and then setting the timer to every 24 hours... Would that be accurate over time? Or would there be a way to integrate the update method, similar to what you have in your examples, with a while loop like I have here?

Just found your library - it is fantastic compared to what is available elsewhere. Thank you for all of the hard work that you've put into it!

highfestiva commented 4 years ago

Hi, thanks for the positive feedback!

This is how I would callback every UTC midnight:

import finplot as fplt
import time

def time_until_midnight():
    now = time.time()
    day_in_seconds = 24*60*60
    utc_midnight_plus_one = now+day_in_seconds - now%day_in_seconds + 60
    return utc_midnight_plus_one - now

def midnight_callback():
    print('UTC midnight plus one!')
    fplt.timer_callback(midnight_callback, time_until_midnight(), single_shot=True)

fplt.create_plot()
fplt.timer_callback(midnight_callback, time_until_midnight(), single_shot=True)
fplt.show()

Clean and easy to grasp.

highfestiva commented 4 years ago

Just out of curiosity, how do you use this? You update once per day, and then just go in and look at the charts manually every day? Or export as an image? For day trading, or what purpose? Thanks!

ddm-j commented 4 years ago

@highfestiva Thank you! I wrote a workaround that uses the Threading module but this is much cleaner and I will be integrating it soon.

To answer your question, I run a cryptocurrency mining operation and I have developed a piece of code that will calculate some metrics for me to systematically cashout on the coins that I have mined. I really only care about the long term trends, so I use the daily chart which updates at UTC-midnight.

On the chart, I have displayed my average entry price (price calculated as the weighted average of the coins I've received at which price), current market price (updated every thirty minutes), and the candles which are updated at midnight.

Your library really is one of a kind, I was going to take some serious wrestling with matplotlib or plotly to get something like this to work. I have come across a few things that would be awesome additions, however:

Perhaps some of these things are possible and I just haven't spent enough time with the library or been clever enough to find a way quite yet! Thank you again for your reply.

highfestiva commented 4 years ago

Interesting, what currencies are you mining? I'm developing a trading robot, and I see huge annual amounts to be had if you offload at the right time. Did you ever consider trading/growing your coins instead of just selling them?

I like all of your suggestions, but as you say none of them are currently in the api. I'll implement them in a few weeks (when I'm done with my bot). Good luck with mining!

ddm-j commented 4 years ago

I'm mining Ethereum primarily right now! We've considered applying a trading bot to the strategy at some point. I've written a few for equities but haven't developed any for crypto yet - so we are focused on making a good earning against equipment depreciation before we start playing with that!

And cool I'll keep my eyes open for updates!

highfestiva commented 4 years ago

If you want to change the color of the whole plot you could do something like this (in the latest commit):

#!/usr/bin/env python3

import finplot as fplt
import numpy as np

times = np.arange(1594504800000, 1594504800100, 1)
rng = np.arange(len(times)) / 20
plot = fplt.plot(times, np.sin(rng))

def update(rng):
    rng += 0.1
    plot.update_data(np.sin(rng))
    plot.setPen(fplt.pg.mkPen(abs(np.sin(rng[0]/2))*255, 0, 255, width=3))

fplt.timer_callback(lambda:update(rng), 0.03)
fplt.show()

It's touching the internals, but I'm hesitant to add an API for it. Regarding setting colors per point, it does not reflect the internal data structure of the library, so it would have to be a helper. I'm afraid you'll have to make your own "split on slope and use two distinctly colored plots" function.

The other two features I've implemented (see S&P500 example).

A trading tip for you is to use Binance Futures if you depend on high wicks to sell (say on the 1m resolution). From experience in BTC I know that you even get limit orders eaten at the worst of times. If you are not dependent on high wicks for selling however, you should definitely use BitMEX as they give you 0.025% every time you get a limit order taken.