Cette fois précédente, j'ai créé un "trading automatique de bitcoin de type Bot" Nous avons utilisé Lambda d'AWS pour créer une ** configuration sans serveur ** populaire! C'est dans le cloud, donc il continue de fonctionner de manière semi-permanente même si mon PC s'arrête. C'est juste un Bot!
À propos de la configuration du cloud J'ai choisi le sans serveur parce que j'ai entendu dire que les frais d'utilisation sont ** très bon marché ** + ** faciles à gérer **. [Référence]
En regardant le service que j'ai réellement utilisé cette fois, ... Avec la configuration suivante ** 1 $ par mois !! **
Service cible | Prix estimé |
---|---|
Lambda | $0 |
DynamoDB | $0 |
cloudwatch | $1.00? |
Lambda · Lambda offre gratuitement 1 000 000 requêtes et 400 000 Go-secondes de temps de calcul par mois. [Référence]
▶ Une fois par minute, si vous l'exécutez pendant un mois, 1 x 60m x 24h x 31 jours = 44640 fois, donc ** marge **
DynamoDB · L'offre gratuite d'AWS comprend 25 Go de stockage Amazon DynamoDB et traite jusqu'à 200 millions de demandes. [Référence]
** 200 millions ... (゜ Д ゜) ** Peut-il être dépassé par les individus? (Il semble que cela dépende de la capacité d'écriture et de lecture par heure, Je m'en fiche car je ne l'utiliserai pas si dur cette fois. )
cloudwatch : 1,00 $ [[Reference]] pour 1 million d'événements personnalisés créés (https://aws.amazon.com/jp/cloudwatch/pricing/)
▶ Si vous l'exécutez une fois par minute pendant un mois, 1 x 60 mx 24h x 31 jours = 44 640 fois, donc 1,00 $?
▶ Après l'avoir déplacé pendant environ une semaine, il n'y a aucun signe qu'il augmentera du tout ... Si vous restez debout pendant un mois et qu'il est de 0 yen, il sera fixé à 0 yen.
Le mouvement est comme d'habitude ** Achetez quand ça devient moins cher et vendez quand ça coûte cher! Cela reste un bot stupide comme **. Je veux résoudre ce problème rapidement, mais je ne peux pas trouver un bon algorithme. .. .. ..
① Obtenez le montant de la transaction précédente du DB (ce montant est la base du jugement) ② Annuler si la transaction précédente demeure ② Si vous avez Bitcoin et que le prix augmente, vendez-le! (Et enregistrez le montant de la transaction dans DB) ③ Si vous avez du yen japonais et que le prix baisse, achetez-le! (Et enregistrez le montant de la transaction dans DB)
Implémentez les trois dans AWS du diagramme d'architecture ci-dessus. (Cela fonctionne simplement en définissant ces trois!)
- DynamoDB --Créer un tableau
- Lambda --Codage --Déployer dans l'environnement d'exécution de code
- CloudWach --Définissez le Lambda défini ci-dessus dans le planificateur
1.DynamoDB
Lambda, l'environnement d'exécution de code utilisé cette fois, ne peut pas enregistrer les valeurs par exécution séquentielle, donc Utilisez la base de données.
Créez les deux tableaux suivants.
① last_transaction_price --Enregistrez le prix de la transaction ② séquence-Enregistrez le nombre de transactions réussies
①-1. Créez le tableau suivant à partir de [Create Table]
・ Nom de la table: last_transaction_pric ・ Clé primaire: trade_number (type numérique)
①-2. Enregistrer l'enregistrement à partir de [Créer un élément](enregistrer manuellement uniquement le premier)
①-1. Créez le tableau suivant à partir de [Create Table]
・ Nom de la table: séquence ・ Clé primaire: nom (chaîne de caractères)
①-2. Enregistrer l'enregistrement à partir de [Créer un élément](enregistrer manuellement uniquement le premier)
2.Lambda
① Codage ② Création de rôles ③ Créer Lambda ④ Déployer ⑤ Test
Constitution Cette fois, il augmente de diverses manières. []···dossier
[zaif] |- main.py | - [Config] - * zaif_keys.json * -Stocke les clés et les secrets zaif | - [Aws] - * dynamodb_utils.py * -Une classe qui facilite l'utilisation de l'API DynamoDB d'aws. | - [Define] - * common_define.py * - (Principalement utilisé dans DynamoDB) Une classe qui définit et résume les chaînes de caractères | - [Exception] - * error.py * -Classes qui résument les erreurs uniques | -...
- [Partie 1](http://qiita.com/speedkingg/items/2d874beee26106ce9f9a#2api installation)
■main.py
main.py
# -*- coding: utf-8 -*-
import json
from zaifapi import ZaifPublicApi #Classe qui exécute une API qui ne nécessite pas d'informations d'authentification publiées par Zaif
from zaifapi import ZaifPrivateApi #Une classe qui exécute une API qui nécessite des informations d'identification publiées par Zaif
from pprint import pprint #Pour l'affichage(Il affiche json proprement)
from aws.dynamodb_utils import DynamoDBUtils #Classes qui utilisent Dynamodb
from define.common_define import CommonDefine #Une classe qui définit des constantes telles que les noms de table
from exception.error import * #Une classe qui définit une erreur propriétaire
dynamodb = DynamoDBUtils()
zaif_keys_json = open('config/zaif_keys.json', 'r')
zaif_keys = json.load(zaif_keys_json)
KEY = zaif_keys["key"]
SECRET = zaif_keys["secret"]
zaif_public = ZaifPublicApi()
zaif_private = ZaifPrivateApi(KEY, SECRET)
#Ici est exécuté lorsqu'il est appelé de Lamda
def lambda_handler(event, context):
try:
#Obtenez des informations actuelles
info = _get_info()
last_price = info["last_price"]
funds_btc = info["funds_btc"]
funds_jpy = info["funds_jpy"]
open_orders = info["open_orders"]
#Acquisition du montant de la transaction précédente
trade_count = _get_trade_count()
last_transaction_data = _get_last_transaction_data(trade_count)
last_transaction_price = last_transaction_data[CommonDefine.LAST_TRANSACTION_PRICE]
order_id = last_transaction_data[CommonDefine.ORDER_ID]
print('▼[info] last_transaction_price: ' + str(last_transaction_price) + ', order_id: ' + str(order_id))
#Annuler si la transaction est en attente
if order_id > 0 and open_orders > 0:
try:
print('■ Annulé.')
pprint(zaif_private.cancel_order(order_id=order_id))
except Exception as e:
print(e)
else:
#Supprimer le montant de la transaction précédente
_delete_last_transaction_price(trade_count)
elif open_orders == 0:
dynamodb.update_by_partition_key(CommonDefine.LAST_TRANSACTION_TABLE,
CommonDefine.TRADE_NUMBER, trade_count,
CommonDefine.ORDER_ID, 0)
#Quand tu as du btc et que le prix monte
if funds_btc != 0 and last_price > last_transaction_price:
_sell_btc(last_price, funds_btc)
#Quand vous avez jpy et que le prix baisse
#(Unité minimum (0).0001btc minutes) lorsque vous avez plus que le yen japonais)
elif funds_jpy > last_transaction_price / 10000 and last_price < last_transaction_price:
_buy_btc(last_price, funds_jpy)
except ResourceNotFoundError:
raise
except IllegalArgumentError:
raise
except Exception:
raise
#Acquisition du montant de la transaction précédente
def _get_last_transaction_data(trade_count):
try:
last_transaction_data = dynamodb.get_item_by_partition_key(CommonDefine.LAST_TRANSACTION_TABLE,
CommonDefine.TRADE_NUMBER, trade_count)
if "Item" not in last_transaction_data:
raise ResourceNotFoundError("last_transaction_data is not found.")
if CommonDefine.LAST_TRANSACTION_PRICE not in last_transaction_data["Item"]:
raise ResourceNotFoundError(CommonDefine.LAST_TRANSACTION_PRICE + " is not found.")
if CommonDefine.ORDER_ID not in last_transaction_data["Item"]:
raise ResourceNotFoundError(CommonDefine.ORDER_ID + " is not found.")
except ResourceNotFoundError:
raise
except IllegalArgumentError:
raise
except Exception:
raise
return last_transaction_data["Item"]
def _get_trade_count():
trade_count_data = dynamodb.get_item_by_partition_key(CommonDefine.SEQUENCE,
CommonDefine.SEQUENCE_NAME, CommonDefine.TRADE_COUNT)
if "Item" not in trade_count_data:
raise ResourceNotFoundError("trade_count_data is not found.")
if CommonDefine.COUNT_NUMBER not in trade_count_data["Item"]:
raise ResourceNotFoundError(CommonDefine.COUNT_NUMBER + " is not found.")
return trade_count_data["Item"].get(CommonDefine.COUNT_NUMBER)
def _get_info():
info = {}
info["last_price"] = int(zaif_public.last_price('btc_jpy')["last_price"])
trade_info = zaif_private.get_info2()
info["funds_btc"] = trade_info["funds"]["btc"]
info["funds_jpy"] = trade_info["funds"]["jpy"]
info["open_orders"] = trade_info["open_orders"]
print('■ Ce sont les informations actuelles.')
print('last_price: ' + str(info["last_price"]))
print('funds_btc: ' + str(info["funds_btc"]))
print('funds_jpy: ' + str(info["funds_jpy"]))
print('open_orders: ' + str(info["open_orders"]))
return info
def _sell_btc(last_price, funds_btc):
try:
trade_result = zaif_private.trade(currency_pair="btc_jpy", action="ask",
price=last_price, amount=funds_btc)
print('■ J'ai demandé la vente de Bitcoin.')
pprint(trade_result)
if trade_result["order_id"] == 0:
_put_last_transaction_price(last_price, 0)
print('■ La transaction est terminée.')
elif trade_result["order_id"] != 0:
_put_last_transaction_price(last_price, trade_result["order_id"])
print('■ La transaction est en attente.')
except ResourceNotFoundError:
raise
except IllegalArgumentError:
raise
except Exception:
raise
def _buy_btc(last_price, funds_jpy):
try:
#Étant donné que l'API prend en charge jusqu'à 4 chiffres après la virgule décimale, arrondissez()
amount = round(float(funds_jpy) / last_price, 4)
print('▼[trace]_buy_btc')
print('amount: ' + str(amount))
#Acheter Bitcoin
trade_result = zaif_private.trade(currency_pair="btc_jpy", action="bid",
price=last_price, amount=amount)
print('■ J'ai demandé l'achat de Bitcoin')
pprint(trade_result)
if trade_result["order_id"] == 0:
_put_last_transaction_price(last_price, 0)
print('■ La transaction est terminée.')
elif trade_result["order_id"] != 0:
_put_last_transaction_price(last_price, trade_result["order_id"])
print('■ La transaction est en attente.')
except ResourceNotFoundError:
raise
except IllegalArgumentError:
raise
except Exception:
raise
#Écrire les informations de transaction dans la base de données
def _put_last_transaction_price(last_transaction_price, order_id):
try:
trade_count = _get_trade_count()
trade_count += 1
put_record_value = {
CommonDefine.TRADE_NUMBER: trade_count,
CommonDefine.LAST_TRANSACTION_PRICE: last_transaction_price,
CommonDefine.ORDER_ID: order_id
}
dynamodb.put_item(CommonDefine.LAST_TRANSACTION_TABLE, put_record_value)
dynamodb.update_by_partition_key(CommonDefine.SEQUENCE,
CommonDefine.SEQUENCE_NAME, CommonDefine.TRADE_COUNT,
CommonDefine.COUNT_NUMBER, trade_count)
except ResourceNotFoundError:
raise
except IllegalArgumentError:
raise
except Exception:
raise
#Supprimer les informations de transaction précédentes
def _delete_last_transaction_price(trade_count):
try:
trade_count -= 1
dynamodb.delete_by_partition_key(CommonDefine.LAST_TRANSACTION_TABLE,
CommonDefine.TRADE_NUMBER, CommonDefine.SEQUENCE_NAME)
dynamodb.update_by_partition_key(CommonDefine.SEQUENCE,
CommonDefine.SEQUENCE_NAME, CommonDefine.TRADE_COUNT,
CommonDefine.COUNT_NUMBER, trade_count)
except ResourceNotFoundError:
raise
except IllegalArgumentError:
raise
except Exception:
raise
■[config] - zaif_keys.json ・ Les débutants créeront un bot de trading automatique Bitcoin visant beaucoup d'argent! Partie 3
■[aws] - dynamodb_utils.py -Les méthodes de base pour faire fonctionner DynamoDB sont résumées. ・ Il est utilisé en citant * main.py *.
dynamodb_utils.py
# coding:utf-8
import boto3
from exception.error import * #Une classe qui définit une erreur propriétaire
class DynamoDBUtils:
def __init__(self):
self.dynamodb = boto3.resource('dynamodb')
#Obtenez tous les enregistrements dans la table spécifiée (jusqu'à 1 Mo)
def scan(self, table_name):
if isinstance(table_name, str) is False or isinstance(table_name, unicode):
raise IllegalArgumentError('item is not str/unicode')
table = self.dynamodb.Table(table_name)
response = table.scan()
print('▼[trace][DynamoDB access]scan')
print('table_name: ' + table_name)
print('response:')
print(str(response))
return response
#Json reçu en spécifiant la table(item)En tant qu'enregistrement ou écrasement
def put_item(self, table_name, item):
if isinstance(table_name, str) is False or isinstance(table_name, unicode):
raise IllegalArgumentError('item is not str/unicode')
if isinstance(item, dict) is False:
raise IllegalArgumentError('item is not dict')
table = self.dynamodb.Table(table_name)
response = table.put_item(
Item=item
)
print('▼[trace][DynamoDB access]put_item')
print('table_name: ' + table_name)
print('put_item: ' + str(item))
print('response:')
print(str(response))
return response
#Obtenir l'enregistrement en spécifiant la table et la clé primaire
def get_item_by_partition_key(self, table_name, partition_key, partition_key_value):
if isinstance(table_name, str) is False or isinstance(table_name, unicode):
raise IllegalArgumentError('item is not str/unicode')
table = self.dynamodb.Table(table_name)
response = table.get_item(
Key={partition_key: partition_key_value}
)
print('▼[trace][DynamoDB access]get_item_by_partition_key')
print('table_name: ' + table_name)
print('partition_key: ' + str(partition_key) + ', partition_key_value: ' + str(partition_key_value))
print('response:')
print(str(response))
return response
#Obtenir un enregistrement en spécifiant la table et la clé primaire / clé de tri
def get_item_by_partition_key_and_sort_key(self, table_name, partition_key, partition_key_value,
sort_key, sort_key_value):
if isinstance(table_name, str) is False or isinstance(table_name, unicode):
raise IllegalArgumentError('item is not str/unicode')
table = self.dynamodb.Table(table_name)
response = table.get_item(
Key={partition_key: partition_key_value,
sort_key: sort_key_value}
)
print('▼[trace][DynamoDB access]get_item_by_partition_key_and_sort_key')
print('table_name: ' + table_name)
print('partition_key: ' + str(partition_key) + ', partition_key_value: ' + str(partition_key_value))
print('sort_key: ' + str(sort_key) + ', sort_key_value: ' + str(sort_key_value))
print('response:')
print(str(response))
return response
#Mettre à jour l'enregistrement en spécifiant la table, la clé primaire et l'élément de mise à jour
def update_by_partition_key(self, table_name, partition_key, partition_key_value, update_key, update_value):
if isinstance(table_name, str) is False or isinstance(table_name, unicode):
raise IllegalArgumentError('item is not str/unicode')
table = self.dynamodb.Table(table_name)
response = table.update_item(
Key={
partition_key: partition_key_value
},
UpdateExpression='SET ' + update_key + ' = :uk',
ExpressionAttributeValues={
':uk': update_value
}
)
print('▼[trace][DynamoDB access]update_by_partition_key')
print('table_name: ' + table_name)
print('partition_key: ' + str(partition_key) + ', partition_key_value: ' + str(partition_key_value))
print('update_key: ' + str(update_key) + ', update_value: ' + str(update_value))
print('response:')
print(str(response))
return response
#Supprimer l'enregistrement en spécifiant la table et la clé primaire
def delete_by_partition_key(self, table_name, partition_key, partition_key_value):
if isinstance(table_name, str) is False or isinstance(table_name, unicode):
raise IllegalArgumentError('item is not str/unicode')
table = self.dynamodb.Table(table_name)
response = table.delete_item(
Key={partition_key: partition_key_value}
)
print('▼[trace][DynamoDB access]delete_by_partition_key')
print('table_name: ' + table_name)
print('partition_key: ' + str(partition_key) + ', partition_key_value: ' + str(partition_key_value))
print('response:')
print(str(response))
return response
■[define] - common_define.py -C'est une classe qui définit et résume les chaînes de caractères utilisées principalement dans DynamoDB. -Gérer tous ensemble afin que vous puissiez en profiter lorsque vous souhaitez changer le nom de la colonne, etc. plus tard.
common_define.py
# -*- coding: utf-8 -*-
class CommonDefine:
def __init__(self):
pass
# dynamoDB table name
LAST_TRANSACTION_TABLE = "last_transaction_price"
SEQUENCE = "sequence"
# dynamoDB key name
TRADE_NUMBER = "trade_number"
LAST_TRANSACTION_PRICE = "last_transaction_price"
SEQUENCE_NAME = "name"
COUNT_NUMBER = "count_number"
ORDER_ID = "order_id"
# other
TRADE_COUNT = "trade_count"
■[exception] - error.py -Un groupe de classes qui résume les erreurs uniques. -Utiliser lorsque le nom d'erreur que vous souhaitez émettre n'est pas préparé en standard.
error.py
# -*- coding: utf-8 -*-
class ResourceNotFoundError(Exception):
#Exception lorsque les données à acquérir n'existent pas
def __init__(self, message):
self.message = message
def __str__(self):
return "Requested resource " + self.message + " not found."
class IllegalArgumentError(Exception):
#Exception si l'argument saisi n'est pas valide
def __init__(self, message):
self.message = message
def __str__(self):
return "Illegal argument (" + self.message + ")"
-Créez un rôle avec les privilèges nécessaires pour exécuter Lambda.
- IAM ▶ Rôle ▶ Sélectionnez «Créer un nouveau rôle»
- Sélection du type de rôle: AWS Lambda
- Attacher la politique: AmazonDynamoDBFullAccess, AWSLambdaFullAccess
- Entrez le nom du rôle et cliquez sur "Créer un rôle"
-Créer un Lambda qui exécute réellement le code.
- Lambda ▶ Fonction ▶ Sélectionnez «Créer une fonction Lambda»
- Cliquez sur l'onglet "Paramètres des fonctions" sur la gauche
- Entrez un nom (tout va bien) Runtime : sélectionnez python2.7 Rôle existant : sélectionnez le rôle créé dans " ② Créer un rôle **" Paramètres détaillés ▶ Délai d'expiration: augmentez la valeur à 10 secondes
- "Suivant" ▶ "Créer"
・ ** ③ Mettez le code sur le Lambda créé dans ** Create Lambda **.
- Ouvrez l'onglet "Paramètres" et modifiez le gestionnaire en ** main.lambda_handler ** (Ce qui signifie appeler et exécuter main.py)
- ** ① Codage ** pour compresser le groupe de codes créé *** Attention à ne pas devenir [zaif] - [zaif] -main.py! (Correct: [zaif] -main.py) **
- Sélectionnez l'onglet Code et téléchargez le fichier
Appuyez sur le bouton "Enregistrer et tester", et si ** Résultat de l'exécution: Succès **, c'est OK!
3.CloudWach -Définissez le Lambda créé ci-dessus pour qu'il soit exécuté périodiquement.
- CloudWatch ▶ Règles ▶ Création de règles
- "Planifier" ▶ Changer la valeur à 1 "Ajouter une cible" ▶ Fonction *: ** Fonction Lambda créée ci-dessus **
- «Paramètres détaillés» ▶ Saisir le nom * ▶ «Paramètres de règle»
Cette fois, la procédure était longue. .. .. Je vous remercie pour votre travail acharné! Avec ce paramètre, vous avez un Bot ** qui échange BitCoin de manière semi-permanente! Maintenant, pensez à la logique rentable! !! (๑ • ̀ ㅂ • ́) و✧ Je vais faire des essais et des erreurs ٩ (• ౪ • ٩)
・ Générateur de logo d'amis Kemono
▶ Il y a des gens dans le monde qui font des choses merveilleuses. Merci de l'utiliser. Merci beaucoup.
・ 2017/4/27: J'ai oublié d'écrire le plus important ** main.py **. .. .. Je suis désolé. ・ 2017/4/27: Correction d'erreur de notation MarkDown (alt Merci de nous avoir signalé.)
Recommended Posts