Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use UTC datetimes everywhere #69

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Use UTC datetimes everywhere #69

wants to merge 3 commits into from

Conversation

rubik
Copy link
Contributor

@rubik rubik commented Apr 9, 2016

What changed

  • All datetime math is now done in UTC. DateTimeFields are guaranteed to be already UTC since when USE_TZ = True Django will set PostgreSQL's timezone config option to UTC, as explained here:
    https://docs.djangoproject.com/en/1.9/ref/databases/#optimizing-postgresql-s-configuration;
  • created_on and modified_on do not rely anymore on get_time, everything is done automatically with auto_now=True and auto_now_add=True. Those two options use internally timezone.now();
  • a new migration has been generated to alter the aforementioned fields;
  • created_on_str is now saved in UTC. In this way the DB is not tied to a specific timezone. However, it's still not perfect, since the old data is still in MST and a migration could be necessary. created_on_str remained in MST.
    Thanks to django-chartit2, created_on_str and date_str have been removed.

Migration

Since PostgreSQL stores all the datetimes as UTC, no DB migration is required. However, some Django fields have been altered, so a python manage.py migrate is necessary to get things working.

Notes

created_on and modified_on are no longer shown in the admin. This is due to the fact that those two attributes are now managed automatically by Django.

For reference, see #9.

@owocki
Copy link
Owner

owocki commented Apr 10, 2016

👏 thanks!

i want to

  1. verify theres no custom datetime mutation logic that this PR missed
  2. test locally

before merging.

@rubik
Copy link
Contributor Author

rubik commented Apr 10, 2016

Sure, let me know if anything goes wrong.

@rubik
Copy link
Contributor Author

rubik commented Apr 11, 2016

Maybe I can open a PR with the linting, get it merged and then rebase my branch on master so that only the relevant changes are left in this PR? That would make it easier to review.

@rubik rubik mentioned this pull request Apr 11, 2016
@owocki
Copy link
Owner

owocki commented Apr 11, 2016

I still see a little bit of timezone mutation on this branch

Searching 71 files for "hours=7"

/Users/kevinowocki/pytrader/history/views.py:
  555      data = {}
  556      for t in Trade.objects.filter(symbol=symbol,status='fill').order_by('-created_on').all():
  557:         date = datetime.datetime.strftime(t.created_on-datetime.timedelta(hours=7),'%Y-%m-%d')
  558          if not date in data.keys():
  559              data[date] = { 'buyvol' : [], 'sellvol' : [], 'buy' : [], 'sell': [], 'bal' : 0.00 }

/Users/kevinowocki/pytrader/history/management/commands/compare_perf.py:
   56                               directionally_same=directionally_same,
   57                               directionally_same_int=1 if directionally_same else 0,
   58:                              created_on_str=(tr_timerange_end - datetime.timedelta(hours=7)).strftime('%Y-%m-%d %H:%M'))
   59          pc.save()
   60  

2 matches across 2 files

@owocki
Copy link
Owner

owocki commented Apr 11, 2016

While I agree that storage in UTC is the right way to go, I'd really like to be able to display data in my local timezone. This prevents me from having to do timezone math in my head everytime I look at some data. Any thoughts on the best way to do that?

@owocki
Copy link
Owner

owocki commented Apr 11, 2016

@rubik merged your previous PR.

@owocki
Copy link
Owner

owocki commented Apr 11, 2016

However, it's still not perfect, since the old data is still in MST and a migration could be necessary.

Is it worth writing a data migration for this? I know there's 5-10 others from slack that are running the repo, so I know it's not just me that has old data in the DB.

@rubik
Copy link
Contributor Author

rubik commented Apr 11, 2016

Is it worth writing a data migration for this? I know there's 5-10 others from slack that are running the repo, so I know it's not just me that has old data in the DB.

Fair enough, I don't think there's a good solution to this. I'll just revert the created_on_str changes.
I also think that this is temporary. Either #35 comes up with a good solution (which maybe does not use django-chartit), or we'll look into some alternatives (perhaps for performance reasons).
The problem is that django-chartit is not really maintained anymore, so the issue relevant to us (chartit/django-chartit#2) is never going to be fixed.

for b in Balance.objects.filter(date_str='0'):
# django timezone stuff , FML
b.date_str = datetime.datetime.strftime(b.created_on - datetime.timedelta(hours=int(7)),'%Y-%m-%d %H:%M')
for b in Balance.objects.filter(date_str=''):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is date_str='' correct or was it correct before?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rubik
Copy link
Contributor Author

rubik commented Apr 14, 2016

I suggest you test locally, since now I'm not able to. If everything works, I think it's simpler to merge this one after #72.

@owocki
Copy link
Owner

owocki commented Apr 14, 2016

this will need a rebase before merging.

@@ -564,7 +567,8 @@ def profit_view(request):
# get data
data = {}
for t in Trade.objects.filter(symbol=symbol, status='fill').order_by('-created_on').all():
date = datetime.datetime.strftime(t.created_on-datetime.timedelta(hours=7), '%Y-%m-%d')
mst_dt = timezone.localtime(t.created_on, pytz.timezone('MST'))
date = datetime.datetime.strftime(mst_dt, '%Y-%m-%d')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had forgotten this one. It should be MST since it's in a view.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MST was just what i used because thats where i live. might be worth making this a settings.DISPLAY_TIMEONE for others to configure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then DBs would be inconsistent between each other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's best to leave it MST and look for a django-chartit alternative.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then DBs would be inconsistent between each other.

could be solved with a migration

Maybe it's best to leave it MST and look for a django-chartit alternative.

i dont feel strongly about this enoguh to hold up the PR. just a suggestion

Copy link
Contributor Author

@rubik rubik Apr 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be solved with a migration

Well in that case we would have to store the data in UTC, but at that point it would be useless. We could remove created_on_str and add an attribute on the fly. Or use a Python property. Is it possible? Currently I don't have data to create a chart and check myself. I only have the seed from #2.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, django-chartit requires the data to be available within the queryset, so a python property will likely not work.

data is posted @ #2 (comment) not asking that you make the change, just telling you about this because now that you've made a PR you should at least have access to the data so you can trade :)

Copy link
Collaborator

@igorpejic igorpejic Apr 18, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this line be:

dt = timezone.localtime(t.created_on, pytz.timezone(settings.DISPLAY_TZ))

?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think it should be

@rubik
Copy link
Contributor Author

rubik commented Apr 14, 2016

There you go. It should be good now.

symbol=symbol, created_on__gte=start_time).filter(status__in=['fill', 'open', 'error']).order_by('id')
else:
trades = Trade.objects.exclude(created_on_str="").filter(
Copy link
Contributor Author

@rubik rubik Apr 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below about created_on_str=''.

@rubik
Copy link
Contributor Author

rubik commented Apr 15, 2016

From my experiments, 'categories': 'created_on' works fine. The real bottleneck was 'terms': 'created_on' which didn't work in django-chartit. With django-chartit2 it's possible to specify a function to handle the data. I wasn't able to test the code with the real data because I only have the prices (I never traded).

This PR needs #74.

@owocki
Copy link
Owner

owocki commented Apr 18, 2016

I'm good with merge here. @igorpejic @Snipa22 @t0mk ?

@@ -35,6 +35,4 @@ def handle(self, *args, **options):
d.status = status
d.created_on = created_on
d.modified_on = created_on
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line has no effect since, auto_now_add is used for modified_on?

Copy link
Contributor Author

@rubik rubik Apr 18, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! We are in the situation described here:
#75 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @owocki intention was to capture the time of creation on the poloniex server with this.
A proposal could be we add deposit_created_on to Deposit model and use created_on for the creation of the model in our database.
In short:
deposit_created_on - time of creation at poloniex server
created_on - time of saving in our database

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable. The only downside of this approach is that we will have to remember to use deposit_created_on instead of created_on.

@owocki
Copy link
Owner

owocki commented Apr 23, 2016

would like to get another to sign off on merge here... @Snipa22 @igorpejic @t0mk ?

@owocki
Copy link
Owner

owocki commented Apr 23, 2016

@rubik could you describe how you tested this? does your personal instance of pytrader have data flowing through the admin?

@rubik
Copy link
Contributor Author

rubik commented Apr 24, 2016

@owocki I had price data in the admin and the chart was displaying correctly. Then I generated fake data in another Django project to test PivotChart and it was working correctly.
If you could test it with trade data it would be even better. Locally I an only run predict_many_sk.py and it appears that c_chart works as intended.

What do you think about adding deposit_created_on? (See above.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants