Serpens66 (OP)
Legendary
Offline
Activity: 2954
Merit: 1131
|
|
May 16, 2015, 04:48:12 PM Last edit: July 15, 2015, 03:41:03 PM by Serpens66 |
|
GelöstHi Ich möchte eine API Anbindung an Yacuna.com in Python3. Hier deren API Seite mit Beschreibung was wie gefordert wird: http://docs.yacuna.com/api/Ich habe mich schon selbst so gut es geht daran versucht und auch ein wenig Hilfe vom Support bekommen. Leider kann dieser aber kein Python, weshalb sie wohl auch mit ihrer Weisheit am Ende sind.. Zusätzlich gibt es das Problem, dass man bei einem Fehler von Yacuna nur sinngemäß "fehler" zurückbekommt, ohne irgendeinen Hinweis darauf, was denn nun nicht stimmt. So sieht mein Skript bisher aus (key, secret und wallet Ids im init müssen natürlich durch korrekte werte ersetzt werden): import json import requests import sys import hmac import hashlib import time from requests import Request, Session
class YacunaAPI:
def load_key(self, path): # falls key nicht in skript speichern, hiermit laden f = open(path, "r") self.key = f.readline().strip() self.secret = f.readline().strip() def __init__(self, key = '', secret = ''): self.key = "abc" self.secret = "123" self.uri = 'https://yacuna.com' self.apiversion = '1' self.walletId = "AAA" # die ganzen Walletdaten bekommt man über die GetWallet Funktion und können dann hardgecodet werden (glaub ich) self.walletAccountIdEUR = "BBB" self.walletAccountIdXBT = "CCC"
def CalculateURLPath(self, method, params): urlpath = '/api/' + self.apiversion + '/' + method + '/' s = Session() req = Request('POST', self.uri + urlpath, data=params) # für den body ists egal ob post oder get prepped = s.prepare_request(req) aufgeteilt = prepped.body.split("&") # bei & getrennt aufgeteilt2 = sorted(aufgeteilt) # und alpabetisch sortiert neu = "?" # startet mit einem ? for element in aufgeteilt2: neu = neu + element + "&" # elemente werden mit einem & dazwischen wieder zusammengesetzt neu = neu[0:len(neu)-1] # das letzte & Zeichen abschneiden return(urlpath + neu) def query_call(self, method, public=0, get=0, params={}): print("") DetailedUrlPath = self.CalculateURLPath(method, params) print(DetailedUrlPath) # zur überprüfung mal printen.. print("") if get: if public: urlpath = '/api/' + self.apiversion + '/' + method + '/' return (requests.get(self.uri + urlpath, params=params,timeout=30).json() ) else: urlpath = '/api/' + self.apiversion + '/' + method + '/' nonce = str(int(1000*time.time())) string = nonce + "@" + self.secret + "@GET@" + DetailedUrlPath encoded = string.encode() signature = hashlib.sha512(encoded).hexdigest() signature = nonce + "T" + signature print(signature) print("") headers = { "Api-Token-Id": self.key, "Api-Token": signature, "Api-Token-OTP": "" } return (requests.get(self.uri + urlpath, params=params,headers=headers,timeout=30).json() ) else: if public: urlpath = '/api/' + self.apiversion + '/' + method + '/' return (requests.post(self.uri + urlpath, params=params,timeout=30).json() ) else: urlpath = '/api/' + self.apiversion + '/' + method + '/' nonce = str(int(1000*time.time())) string = nonce + "@" + self.secret + "@GET@" + DetailedUrlPath encoded = string.encode() signature = hashlib.sha512(encoded).hexdigest() signature = nonce + "T" + signature print(signature) print("") headers = { "Api-Token-Id": self.key, "Api-Token": signature, "Api-Token-OTP": "" } return (requests.post(self.uri + urlpath, params=params,headers=headers,timeout=30).json() )
def GetWallet(self,currency=0): # gibt alle möglichen Wallet infos, inklusive aller Balances aus method = 'wallet/get' if currency: Wallet = self.query_call(method,0,1,{"currency":currency}) else: Wallet = self.query_call(method,0,1) return(Wallet) def OrderBook(self, currency1, currency2):# getting the full orderbook method = "orderbook/get" # zb https://yacuna.com/api/1/orderbook/get/EUR/XBT Orders = self.query_call(method,0,1,{"currency1":currency1,"currency2":currency2}) return Orders # Fehlerprüfung in eigenen Funktionen def CancelOrder(self, ID): method = "order/cancel" Cancel = self.query_call(method,0,0,{"orderId":ID}) return Cancel # Fehlerprüfung in eigenen Funktionen
def CreateOrder(self, currency1, currency2, type, amount, price): method = "order/create" # es werden immer btc gekauft/verkauft, also walletid XBT if type=="buy": tradeOrderType="BuyLimit" buyAmount = amount buyCurrency = "XBT" priceLimitCurrency = "EUR" priceLimitAmount = price Create = self.query_call(method,0,0,{"currency1":currency1,"currency2":currency2,"walletAccountId":self.walletAccountIdXBT,"tradeOrderType":tradeOrderType,"buyAmount":amount,"buyCurrency":buyCurrency,"priceLimitCurrency":priceLimitCurrency,"priceLimitAmount":priceLimitAmount}) elif type=="sell": tradeOrderType="SellLimit" sellAmount = amount sellCurrency = "XBT" priceLimitCurrency = "EUR" priceLimitAmount = price Create = self.query_call(method,0,0,{"currency1":currency1,"currency2":currency2,"walletAccountId":self.walletAccountIdXBT,"tradeOrderType":tradeOrderType,"sellAmount":amount,"sellCurrency":sellCurrency,"priceLimitCurrency":priceLimitCurrency,"priceLimitAmount":priceLimitAmount}) else: raise AssertionError("Ungültiger kauf/verkauftype in YacunaAPI createorder.") return Create # Fehlerprüfung in eigenen Funktionen def OrderList(self, tradeOrderStatus, count=30): # tradeOrderStatus == "Confirmed" .. gibt noch mehr sortierungsmöglichkeiten, siehe api doku method = "order/list" List = self.query_call(method,0,1,{"walletAccountId":self.walletAccountIdEUR,"tradeOrderStatus":tradeOrderStatus,"count":count,"startWith":0}) return List # Fehlerprüfung in eigenen Funktionen
Ich glaube jeder Pythonprogrammierer würde mir nun erstmal einen Vortrag halten, wie unschön dieses Skript ist und so weiter. Das ist der Grund weshalb ich die Frage nicht im Pythonforum stelle.. habe da keine guten erfahrungen gemacht. Es ist mir egal wie es aussieht, hauptsache es tut was es soll Jedenfalls möchte ich, wie man sieht, das Modul "requests" verwenden, welches hier beschrieben wird: http://docs.python-requests.org/en/latest/Ich glaube der GetWallet Aufruf funktioniert sogar schon. Probleme gibt es mit anderen Aufrufen, wie CreateOrder bzw CancelOrder (also den Post-Anfragen). Zum austesten ob eure Korrektur funktioniert würde ich empfehlen einfach schnell einen Yacuna Account aufzumachen und dort API Key + Secret zu generieren. Ich glaube dazu muss man sich nicht verifizieren, sollte also kein Problem sein.
|
Mit Cointracking (10% Rabatt) behältst du die Übersicht über all deine Trades und Gewinne. Sogar ein Tool für die Steuer ist dabei Great Freeware Game: Clonk Rage binance.com hat nun auch SEPA und EUR Paare! Mit dem RefLink bekommst du 5% Rabatt auf die Tradinggebühren!
|
|
|
Sukrim
Legendary
Offline
Activity: 2618
Merit: 1007
|
|
May 17, 2015, 10:54:28 AM |
|
Lass einfach mal pylint drüber laufen, das spuckt dir dann schon aus, was du erstmal ausbessern solltest - von unbenutzten Variablen + Imports, fehlenden Docstrings und auch schlimmeren Problemen, wie z.B. dem Umdefinieren von eingebauten Keywords wie "type" in der CreateOrder Funktion. In einer halben Stunde maximal hast du die "Formfehler" beseitigt und danna uch ein weitaus übersichtlicheres Programm, das du auch leichter debuggen lassen kannst, weil es auch andere verstehen können.
Ist ja ganz nett, dass du nicht auf Konventionen zurückgreifen willst, allerdings ist das Ding da ziemlich konfus geschrieben und recht uneinheitlich, also muss man sich viel tiefer einarbeiten als die paar Euro rechtfertigen würden imho.
|
|
|
|
Serpens66 (OP)
Legendary
Offline
Activity: 2954
Merit: 1131
|
|
May 17, 2015, 11:31:46 AM |
|
Lass einfach mal pylint drüber laufen, das spuckt dir dann schon aus, was du erstmal ausbessern solltest - von unbenutzten Variablen + Imports, fehlenden Docstrings und auch schlimmeren Problemen, wie z.B. dem Umdefinieren von eingebauten Keywords wie "type" in der CreateOrder Funktion. In einer halben Stunde maximal hast du die "Formfehler" beseitigt und danna uch ein weitaus übersichtlicheres Programm, das du auch leichter debuggen lassen kannst, weil es auch andere verstehen können.
Ist ja ganz nett, dass du nicht auf Konventionen zurückgreifen willst, allerdings ist das Ding da ziemlich konfus geschrieben und recht uneinheitlich, also muss man sich viel tiefer einarbeiten als die paar Euro rechtfertigen würden imho.
also kannst du python3? Ich bin mir relativ sicher, dass alles richtig ist, bis auf den post request. Also könntest du vllt zumindest schauen, ob dies so funktionieren sollte? Das ist zumindest der Teil den ich noch nicht verstehe: encoded = string.encode() signature = hashlib.sha512(encoded).hexdigest() headers = { "Api-Token-Id": self.key, "Api-Token": signature, "Api-Token-OTP": "" } return (requests.post(self.uri + urlpath, params=params,headers=headers,timeout=30).json() )
|
Mit Cointracking (10% Rabatt) behältst du die Übersicht über all deine Trades und Gewinne. Sogar ein Tool für die Steuer ist dabei Great Freeware Game: Clonk Rage binance.com hat nun auch SEPA und EUR Paare! Mit dem RefLink bekommst du 5% Rabatt auf die Tradinggebühren!
|
|
|
Sukrim
Legendary
Offline
Activity: 2618
Merit: 1007
|
|
May 17, 2015, 02:35:00 PM |
|
Ich bin mir relativ sicher, dass da einiges an ... Zweifelhaftigkeiten in dem Code steckt. z.B.: def CreateOrder(self, currency1, currency2, type, amount, price): "type" ist ein reservierter Name in Python. Der teil den du da nicht verstehst encodiert einen String, generiert einen sha512 Hash darüber und sendet dann einige Daten via der requests Bibliothek, die die Antwort dann als JSON zurückgeben/interpretieren dürfte. Bis auf einige Probleme mit Variablennamen und Codingstil sehe ich in dem kleinen Beispiel da nichts Ungewöhnliches.
|
|
|
|
Serpens66 (OP)
Legendary
Offline
Activity: 2954
Merit: 1131
|
|
May 17, 2015, 05:23:58 PM |
|
Ich bin mir relativ sicher, dass da einiges an ... Zweifelhaftigkeiten in dem Code steckt. z.B.: def CreateOrder(self, currency1, currency2, type, amount, price): "type" ist ein reservierter Name in Python. Der teil den du da nicht verstehst encodiert einen String, generiert einen sha512 Hash darüber und sendet dann einige Daten via der requests Bibliothek, die die Antwort dann als JSON zurückgeben/interpretieren dürfte. Bis auf einige Probleme mit Variablennamen und Codingstil sehe ich in dem kleinen Beispiel da nichts Ungewöhnliches. Dass type reserviert ist wusste ich nicht, danke, kann ich abändern. Also um deine Aussage auf meine Hauptfrage zu beziehen: Du meinst, dass meine request.post anfrage den Anforderungen von Yacuna entspricht ? (wir gehen mal davon aus, dass mein self.uri, mein urlpath, mein params und mein header korrekt sind) ich bin zb. unsicher, ob ich .hexdigest() anwenden muss oder nur .digest() .... und ob ich iwo noch hmac oderso anwenden muss Ich hatte im Bezug aufs Codieren das Skript von Kraken zur Hilfe genommen: https://github.com/veox/python3-krakenex/blob/master/krakenex/api.pyDort wird halt digest() und hmac verwendet... Ich gehe davon aus, dass diese ganzen Codierungsbefehle sehr viel Verständnis im Codieren voraussetzen und dass es lange dauern würde, das alles zu verstehen. Da ich das Codieren nur für die Anbindung brauche und sonst nie bei meinen Programmierungen, halte ich es für am effektivsten mich nicht mit dem Codieren zu beschäftigen, sondern es über try and error zu probieren... Bisher hatte das ganz gut geklappt Nur jetzt komme ich halt nicht weiter, weil ich keine Angabe über Fehler von Yacuna erhalte.
|
Mit Cointracking (10% Rabatt) behältst du die Übersicht über all deine Trades und Gewinne. Sogar ein Tool für die Steuer ist dabei Great Freeware Game: Clonk Rage binance.com hat nun auch SEPA und EUR Paare! Mit dem RefLink bekommst du 5% Rabatt auf die Tradinggebühren!
|
|
|
Sukrim
Legendary
Offline
Activity: 2618
Merit: 1007
|
|
May 17, 2015, 05:57:07 PM |
|
Dass type reserviert ist wusste ich nicht, danke, kann ich abändern. Hättest du, wie zuvor von mir empfohlen, pylint drüber laufen lassen, hättest du das schon gewusst. Du meinst, dass meine request.post anfrage den Anforderungen von Yacuna entspricht ? Was Yacuna da für seine API verlangt, weiß ich nicht. Deren Webseite lässt sich ohne Javascript nicht mal laden... und wegen 0.07 BTC fang ich da jetzt auch nicht an, mich durch Dokumentation zu hangeln. Vermutlich wird da was gröber falsch laufen, wenn du nur versuchst, die API von Kraken zu kopieren. https://github.com/yacuna/api hat anscheinend Implementationen in perl und in PHP, es sollte durchaus zu machen sein, ~100 Zeilen perl ( https://github.com/yacuna/api/blob/master/perl/Finance-Bitcoin-Yacuna-0.2/lib/Finance/Bitcoin/Yacuna.pm) in Python nachzubauen...
|
|
|
|
Serpens66 (OP)
Legendary
Offline
Activity: 2954
Merit: 1131
|
|
May 17, 2015, 08:13:24 PM |
|
Dass type reserviert ist wusste ich nicht, danke, kann ich abändern. Hättest du, wie zuvor von mir empfohlen, pylint drüber laufen lassen, hättest du das schon gewusst. So war das nicht gemeint ^^ Ich meinte vor deinen Posts allgemein wusste ich das nicht Und ansonsten werde ich mir Pylint mal genauer anschauen... ich tue mich wirklich extreeemst schwer damit, mich den Python Konventionen anzupassen. Habe diesbezüglich auch shcon etliche hitzige Diskussionen im Pythonforum führen müssen. In erster Linie liegt es daran, dass ich lange brauche vorgefertigte Skripte, wie zb das von Kraken nachzuvollziehen. Skripte wie meines kann ich aber sehr schnell nachvollziehen (also vom aufbau her). Deswegen erscheint es für mich unlogisch eine Konvention zu nutzen, die es für mich nur komplizierter macht und deswegen nutze ich sie nicht. Früher war mein Code natürlich noch schlimmer. Je mehr ich lerne und verstehe, desto übersichtlicher wird mein Code. Und ich finde, dass das genau der richtige Weg ist. Irgendwann wird mein Code sowohl für mich als auch für andere verständlich sein. Auf diesen Weg wird mir Pylint vllt helfen, also danke für diesen Tipp Ich schau mir die tage mal die Perl version an, vllt kann ich daraus ja ein bisschen was ableiten...
|
Mit Cointracking (10% Rabatt) behältst du die Übersicht über all deine Trades und Gewinne. Sogar ein Tool für die Steuer ist dabei Great Freeware Game: Clonk Rage binance.com hat nun auch SEPA und EUR Paare! Mit dem RefLink bekommst du 5% Rabatt auf die Tradinggebühren!
|
|
|
tyz
Legendary
Offline
Activity: 3360
Merit: 1533
|
|
June 20, 2015, 10:46:46 AM |
|
Das Thema ist schon ein paar Tage alt, aber besteht das Problem noch? Bin nebenberuflich Python Entwickler und könnte dir da weiterhelfen.
|
|
|
|
Serpens66 (OP)
Legendary
Offline
Activity: 2954
Merit: 1131
|
|
June 20, 2015, 01:46:32 PM |
|
Das Thema ist schon ein paar Tage alt, aber besteht das Problem noch? Bin nebenberuflich Python Entwickler und könnte dir da weiterhelfen.
Hey, danke dass du dich meldest Ja das Problem besteht noch. Aus den bisherigen Posts kannst du ja auch glaube ich lesen, worin das Hauptproblem besteht. Ich komme noch nicht so ganz mit dem ganzen Codieren und Internetkram klar. Also ich weiß nicht, wann ich was wie codieren muss und welche Befehle ich dafür verwenden muss, z.b .hexdigest() vs digest(). Ich tippe stark darauf, dass genau das in meinem Skript der Hauptfehler ist. Nebenbei gibt es sicherlich einige Dinge, die ein echter Programmierer anders lösen würde, aber in erster Linie kommt es für mich darauf an, dass es funktioniert, egal wie umständlich geschrieben.
|
Mit Cointracking (10% Rabatt) behältst du die Übersicht über all deine Trades und Gewinne. Sogar ein Tool für die Steuer ist dabei Great Freeware Game: Clonk Rage binance.com hat nun auch SEPA und EUR Paare! Mit dem RefLink bekommst du 5% Rabatt auf die Tradinggebühren!
|
|
|
Serpens66 (OP)
Legendary
Offline
Activity: 2954
Merit: 1131
|
|
July 15, 2015, 03:40:06 PM |
|
Ich hab eben nochmal ein wenig rumprobiert und festgestellt, dass alles funktioniert, solange ich keine Zahlen als Parameter übergebe. Das heißt folgender link, welcher dann in die signature verwandelt wird, funktioniert (ausgedachte walletid): /api/1/order/list/?tradeOrderStatus=Confirmed&walletAccountId=DFSDFWFS12321231AFDSF während er nicht mehr funktiniert, wenn ich einen Paramtert zufüge, der eine Zahl beinhaltet, zb.: /api/1/order/list/?startWith=0&tradeOrderStatus=Confirmed&walletAccountId=DFSDFWFS12321231AFDSF Habe die Frage nun an den Yacuna Support weitergeleitet, warum Zahlen nicht funzen und denke dass das damit dann alles gelöst wird Vielen dank an diejenigen die sich hier und per PN gemeldet hatten, auch wenn keiner das Problem lösen konnte
|
Mit Cointracking (10% Rabatt) behältst du die Übersicht über all deine Trades und Gewinne. Sogar ein Tool für die Steuer ist dabei Great Freeware Game: Clonk Rage binance.com hat nun auch SEPA und EUR Paare! Mit dem RefLink bekommst du 5% Rabatt auf die Tradinggebühren!
|
|
|
|