<link>http://people.skolelinux.org/pere/blog/</link>
<atom:link href="http://people.skolelinux.org/pere/blog/index.rss" rel="self" type="application/rss+xml" />
+ <item>
+ <title>Valutakrambod - A python and bitcoin love story</title>
+ <link>http://people.skolelinux.org/pere/blog/Valutakrambod___A_python_and_bitcoin_love_story.html</link>
+ <guid isPermaLink="true">http://people.skolelinux.org/pere/blog/Valutakrambod___A_python_and_bitcoin_love_story.html</guid>
+ <pubDate>Sat, 29 Sep 2018 22:20:00 +0200</pubDate>
+ <description><p>It would come as no surprise to anyone that I am interested in
+bitcoins and virtual currencies. I've been keeping an eye on virtual
+currencies for many years, and it is part of the reason a few months
+ago, I started writing a python library for collecting currency
+exchange rates and trade on virtual currency exchanges. I decided to
+name the end result valutakrambod, which perhaps can be translated to
+small currency shop.</p>
+
+<p>The library uses the tornado python library to handle HTTP and
+websocket connections, and provide a asynchronous system for
+connecting to and tracking several services. The code is available
+from
+<a href="http://github.com/petterreinholdtsen/valutakrambod">github</a>.</p>
+
+</p>There are two example clients of the library. One is very simple and
+list every updated buy/sell price received from the various services.
+This code is started by running bin/btc-rates and call the client code
+in valutakrambod/client.py. The simple client look like this:</p>
+
+<p><blockquote><pre>
+import functools
+import tornado.ioloop
+import valutakrambod
+class SimpleClient(object):
+ def __init__(self):
+ self.services = []
+ self.streams = []
+ pass
+ def newdata(self, service, pair, changed):
+ print("%-15s %s-%s: %8.3f %8.3f" % (
+ service.servicename(),
+ pair[0],
+ pair[1],
+ service.rates[pair]['ask'],
+ service.rates[pair]['bid'])
+ )
+ async def refresh(self, service):
+ await service.fetchRates(service.wantedpairs)
+ def run(self):
+ self.ioloop = tornado.ioloop.IOLoop.current()
+ self.services = valutakrambod.service.knownServices()
+ for e in self.services:
+ service = e()
+ service.subscribe(self.newdata)
+ stream = service.websocket()
+ if stream:
+ self.streams.append(stream)
+ else:
+ # Fetch information from non-streaming services immediately
+ self.ioloop.call_later(len(self.services),
+ functools.partial(self.refresh, service))
+ # as well as regularly
+ service.periodicUpdate(60)
+ for stream in self.streams:
+ stream.connect()
+ try:
+ self.ioloop.start()
+ except KeyboardInterrupt:
+ print("Interrupted by keyboard, closing all connections.")
+ pass
+ for stream in self.streams:
+ stream.close()
+</pre></blockquote></p>
+
+<p>The library client loop over all known "public" services,
+initialises it, subscribe to any updates from the service, check and
+activate websocket streaming if the service provide it, and if no
+streaming is supported, fetch information from the service and set up
+a periodic update every 60 seconds. The output from this client can
+look like this:</p>
+
+<p><blockquote><pre>
+Bl3p BTC-EUR: 5687.110 5653.690
+Bl3p BTC-EUR: 5687.110 5653.690
+Bl3p BTC-EUR: 5687.110 5653.690
+Hitbtc BTC-USD: 6594.560 6593.690
+Hitbtc BTC-USD: 6594.560 6593.690
+Bl3p BTC-EUR: 5687.110 5653.690
+Hitbtc BTC-USD: 6594.570 6593.690
+Bitstamp EUR-USD: 1.159 1.154
+Hitbtc BTC-USD: 6594.570 6593.690
+Hitbtc BTC-USD: 6594.580 6593.690
+Hitbtc BTC-USD: 6594.580 6593.690
+Hitbtc BTC-USD: 6594.580 6593.690
+Bl3p BTC-EUR: 5687.110 5653.690
+Paymium BTC-EUR: 5680.000 5620.240
+</pre></blockquote></p>
+
+<p>The exchange order book is tracked in addition to the best buy/sell
+price, for those that need to know the details.</p>
+
+<p>The other example client is focusing on providing a curses view
+with updated buy/sell prices as soon as they are received from the
+services. This code is located in bin/btc-rates-curses and activated
+by using the '-c' argument. Without the argument the "curses" output
+is printed without using curses, which is useful for debugging. The
+curses view look like this:</p>
+
+<p><blockquote><pre>
+ Name Pair Bid Ask Spr Ftcd Age
+ BitcoinsNorway BTCEUR 5591.8400 5711.0800 2.1% 16 nan 60
+ Bitfinex BTCEUR 5671.0000 5671.2000 0.0% 16 22 59
+ Bitmynt BTCEUR 5580.8000 5807.5200 3.9% 16 41 60
+ Bitpay BTCEUR 5663.2700 nan nan% 15 nan 60
+ Bitstamp BTCEUR 5664.8400 5676.5300 0.2% 0 1 1
+ Bl3p BTCEUR 5653.6900 5684.9400 0.5% 0 nan 19
+ Coinbase BTCEUR 5600.8200 5714.9000 2.0% 15 nan nan
+ Kraken BTCEUR 5670.1000 5670.2000 0.0% 14 17 60
+ Paymium BTCEUR 5620.0600 5680.0000 1.1% 1 7515 nan
+ BitcoinsNorway BTCNOK 52898.9700 54034.6100 2.1% 16 nan 60
+ Bitmynt BTCNOK 52960.3200 54031.1900 2.0% 16 41 60
+ Bitpay BTCNOK 53477.7833 nan nan% 16 nan 60
+ Coinbase BTCNOK 52990.3500 54063.0600 2.0% 15 nan nan
+ MiraiEx BTCNOK 52856.5300 54100.6000 2.3% 16 nan nan
+ BitcoinsNorway BTCUSD 6495.5300 6631.5400 2.1% 16 nan 60
+ Bitfinex BTCUSD 6590.6000 6590.7000 0.0% 16 23 57
+ Bitpay BTCUSD 6564.1300 nan nan% 15 nan 60
+ Bitstamp BTCUSD 6561.1400 6565.6200 0.1% 0 2 1
+ Coinbase BTCUSD 6504.0600 6635.9700 2.0% 14 nan 117
+ Gemini BTCUSD 6567.1300 6573.0700 0.1% 16 89 nan
+ Hitbtc+BTCUSD 6592.6200 6594.2100 0.0% 0 0 0
+ Kraken BTCUSD 6565.2000 6570.9000 0.1% 15 17 58
+ Exchangerates EURNOK 9.4665 9.4665 0.0% 16 107789 nan
+ Norgesbank EURNOK 9.4665 9.4665 0.0% 16 107789 nan
+ Bitstamp EURUSD 1.1537 1.1593 0.5% 4 5 1
+ Exchangerates EURUSD 1.1576 1.1576 0.0% 16 107789 nan
+ BitcoinsNorway LTCEUR 1.0000 49.0000 98.0% 16 nan nan
+ BitcoinsNorway LTCNOK 492.4800 503.7500 2.2% 16 nan 60
+ BitcoinsNorway LTCUSD 1.0221 49.0000 97.9% 15 nan nan
+ Norgesbank USDNOK 8.1777 8.1777 0.0% 16 107789 nan
+</pre></blockquote></p>
+
+<p>The code for this client is too complex for a simple blog post, so
+you will have to check out the git repository to figure out how it
+work. What I can tell is how the three last numbers on each line
+should be interpreted. The first is how many seconds ago information
+was received from the service. The second is how long ago, according
+to the service, the provided information was updated. The last is an
+estimate on how often the buy/sell values change.</p>
+
+<p>If you find this library useful, or would like to improve it, I
+would love to hear from you. Note that for some of the services I've
+implemented a trading API. It might be the topic of a future blog
+post.</p>
+
+<p>As usual, if you use Bitcoin and want to show your support of my
+activities, please send Bitcoin donations to my address
+<b><a href="bitcoin:15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b">15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b</a></b>.</p>
+</description>
+ </item>
+
<item>
<title>VLC in Debian now can do bittorrent streaming</title>
<link>http://people.skolelinux.org/pere/blog/VLC_in_Debian_now_can_do_bittorrent_streaming.html</link>
<p>PS: A new version of Cura was uploaded to Debian yesterday.</p>
-<p>As usual, if you use Bitcoin and want to show your support of my
-activities, please send Bitcoin donations to my address
-<b><a href="bitcoin:15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b">15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b</a></b>.</p>
-</description>
- </item>
-
- <item>
- <title>Debian APT upgrade without enough free space on the disk...</title>
- <link>http://people.skolelinux.org/pere/blog/Debian_APT_upgrade_without_enough_free_space_on_the_disk___.html</link>
- <guid isPermaLink="true">http://people.skolelinux.org/pere/blog/Debian_APT_upgrade_without_enough_free_space_on_the_disk___.html</guid>
- <pubDate>Sun, 8 Jul 2018 12:10:00 +0200</pubDate>
- <description><p>Quite regularly, I let my Debian Sid/Unstable chroot stay untouch
-for a while, and when I need to update it there is not enough free
-space on the disk for apt to do a normal 'apt upgrade'. I normally
-would resolve the issue by doing 'apt install &lt;somepackages&gt;' to
-upgrade only some of the packages in one batch, until the amount of
-packages to download fall below the amount of free space available.
-Today, I had about 500 packages to upgrade, and after a while I got
-tired of trying to install chunks of packages manually. I concluded
-that I did not have the spare hours required to complete the task, and
-decided to see if I could automate it. I came up with this small
-script which I call 'apt-in-chunks':</p>
-
-<p><blockquote><pre>
-#!/bin/sh
-#
-# Upgrade packages when the disk is too full to upgrade every
-# upgradable package in one lump. Fetching packages to upgrade using
-# apt, and then installing using dpkg, to avoid changing the package
-# flag for manual/automatic.
-
-set -e
-
-ignore() {
- if [ "$1" ]; then
- grep -v "$1"
- else
- cat
- fi
-}
-
-for p in $(apt list --upgradable | ignore "$@" |cut -d/ -f1 | grep -v '^Listing...'); do
- echo "Upgrading $p"
- apt clean
- apt install --download-only -y $p
- for f in /var/cache/apt/archives/*.deb; do
- if [ -e "$f" ]; then
- dpkg -i /var/cache/apt/archives/*.deb
- break
- fi
- done
-done
-</pre></blockquote></p>
-
-<p>The script will extract the list of packages to upgrade, try to
-download the packages needed to upgrade one package, install the
-downloaded packages using dpkg. The idea is to upgrade packages
-without changing the APT mark for the package (ie the one recording of
-the package was manually requested or pulled in as a dependency). To
-use it, simply run it as root from the command line. If it fail, try
-'apt install -f' to clean up the mess and run the script again. This
-might happen if the new packages conflict with one of the old
-packages. dpkg is unable to remove, while apt can do this.</p>
-
-<p>It take one option, a package to ignore in the list of packages to
-upgrade. The option to ignore a package is there to be able to skip
-the packages that are simply too large to unpack. Today this was
-'ghc', but I have run into other large packages causing similar
-problems earlier (like TeX).</p>
-
-<p>Update 2018-07-08: Thanks to Paul Wise, I am aware of two
-alternative ways to handle this. The "unattended-upgrades
---minimal-upgrade-steps" option will try to calculate upgrade sets for
-each package to upgrade, and then upgrade them in order, smallest set
-first. It might be a better option than my above mentioned script.
-Also, "aptutude upgrade" can upgrade single packages, thus avoiding
-the need for using "dpkg -i" in the script above.</p>
-
<p>As usual, if you use Bitcoin and want to show your support of my
activities, please send Bitcoin donations to my address
<b><a href="bitcoin:15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b">15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b</a></b>.</p>