Skip to content

Commit

Permalink
A rather difficult bug in Mimic, affecting only position flipping, ha…
Browse files Browse the repository at this point in the history
…s *finally* been crushed. The bug

caused reporting errors in the quote currency.

Added charting program for Mimic by alCa.

Version Update.

Changes to be committed:
	modified:   Base/JackrabbitLocker
	modified:   Base/JackrabbitOliverTwist
	modified:   Base/JackrabbitRelay
	modified:   Base/Library/JRRmimic.py
	modified:   Base/Library/JackrabbitProxy.py
	modified:   Base/Library/JackrabbitRelay.py
	modified:   Base/MIMIC-PlaceOrder
	new file:   Extras/Mimic/alCaCharts
	modified:   requirements.txt
  • Loading branch information
rapmd73 committed Jun 2, 2024
1 parent 32766e3 commit 2d0fe52
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Base/JackrabbitLocker
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import json

import JRRsupport

Version="0.0.0.1.855"
Version="0.0.0.1.870"
BaseDirectory='/home/JackrabbitRelay2/Base'
ConfigDirectory='/home/JackrabbitRelay2/Config'
LogDirectory="/home/JackrabbitRelay2/Logs"
Expand Down
2 changes: 1 addition & 1 deletion Base/JackrabbitOliverTwist
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import subprocess
import JRRsupport
import JackrabbitRelay as JRR

Version="0.0.0.1.855"
Version="0.0.0.1.870"
BaseDirectory='/home/JackrabbitRelay2/Base'
DataDirectory='/home/JackrabbitRelay2/Data'
ConfigDirectory='/home/JackrabbitRelay2/Config'
Expand Down
2 changes: 1 addition & 1 deletion Base/JackrabbitRelay
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import json

import JRRsupport

Version="0.0.0.1.855"
Version="0.0.0.1.870"
BaseDirectory='/home/JackrabbitRelay2/Base'
ConfigDirectory='/home/JackrabbitRelay2/Config'
LogDirectory="/home/JackrabbitRelay2/Logs"
Expand Down
59 changes: 48 additions & 11 deletions Base/Library/JRRmimic.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class mimic:
# placed in init and released at exit.

def __init__(self,Exchange,Config,Active,DataDirectory=None):
self.Version="0.0.0.1.855"
self.Version="0.0.0.1.870"

self.StableCoinUSD=['USDT','USDC','BUSD','UST','DAI','FRAX','TUSD', \
'USDP','LUSD','USDN','HUSD','FEI','TRIBE','RSR','OUSD','XSGD', \
Expand Down Expand Up @@ -339,14 +339,55 @@ def UpdateWallet(self,action,asset,amount,price,fee_rate=0):
if abs(actualAmount)<minimum or (abs(actualAmount)*actualPrice)<mincost:
return f'Below minimum requirements: {actualAmount:.8f} < {minimum:.8f} or {(abs(actualAmount)*actualPrice):.8f} < {mincost:.8f}'

if base in self.Wallet['Wallet'] and action=='buy':
if ((actualAmount>0 and self.Wallet['Wallet'][base]<0) \
or (actualAmount<0 and self.Wallet['Wallet'][base]>0)):
action='sell'
# Calculate the total cost for buying the asset including fees
total_cost=round(abs(actualAmount) * actualPrice * (1 + fee_rate),8)
# Calculate the total proceeds from selling the asset after deducting fees
total_proceeds=round(abs(actualAmount) * actualPrice * (1 - fee_rate),8)
# Current fees for this position
fee=round(abs(actualAmount) * actualPrice * fee_rate,8)

if action=='buy':
# Calculate the total cost for buying the asset including fees
total_cost=round(abs(actualAmount) * actualPrice * (1 + fee_rate),8)
# Handle position flipping
current_position = self.Wallet['Wallet'].get(base, 0)

if (current_position > 0 and actualAmount < 0) or (current_position < 0 and actualAmount > 0):
# Flipping logic
flip_proceeds = abs(current_position) * actualPrice
self.Wallet['Wallet'][quote] += flip_proceeds # Cover the existing position
self.Wallet['Wallet'][base] = 0 # Clear the existing position

# Open the new position with the amount provided
new_position_cost = abs(actualAmount) * actualPrice * (1 + fee_rate)
if self.Wallet['Wallet'][quote] < new_position_cost:
self.Wallet['Enabled'] = 'N'
return 'Account Liquidated!'

new_base_amount = (abs(actualAmount) - abs(current_position))
if actualAmount<0:
new_base_amount*=-1
self.Wallet['Wallet'][quote] -= new_position_cost
self.Wallet['Wallet'][base] = new_base_amount # Set the new position with the provided amount

# Update fees
fee = abs(actualAmount) * actualPrice * fee_rate
self.Wallet['Fees'] = self.Wallet.get('Fees', 0) + fee

# Update successful
order={}
order['DateTime']=(datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
order['ID']=f"{time.time()*10000000:.0f}"
order['Action']=action
order['Asset']=asset
order[base]=self.Wallet['Wallet'][base]
order[quote]=self.Wallet['Wallet'][quote]
order['Amount']=round(actualAmount,8)
order['Price']=round(actualPrice,8)
order['Fee']=round(fee,8)

JRRsupport.AppendFile(self.history, json.dumps(order) + '\n')
return order

# Handle regular buying.
# Check if the wallet has enough balance for the purchase including fees
if quote in self.Wallet['Wallet'] and self.Wallet['Wallet'][quote]>=total_cost:
# Deduct the total cost including fees from the quote currency balance
Expand All @@ -358,7 +399,6 @@ def UpdateWallet(self,action,asset,amount,price,fee_rate=0):
else:
self.Wallet['Wallet'][base]=actualAmount # Initialize the base currency wallet if not present
# Update fee balance
fee=round(abs(actualAmount) * actualPrice * fee_rate,8)
if 'Fees' in self.Wallet['Wallet']:
self.Wallet['Fees']+=fee
else:
Expand Down Expand Up @@ -391,9 +431,6 @@ def UpdateWallet(self,action,asset,amount,price,fee_rate=0):

# Check if the base currency is present in the base currency wallet and the amount to sell is available
if quote in self.Wallet['Wallet'] and self.Wallet['Wallet'][quote]>=0:
# Calculate the total proceeds from selling the asset after deducting fees
total_proceeds=round(abs(actualAmount) * actualPrice * (1 - fee_rate),8)

# Add the total proceeds minus fees to the quote currency balance
# quote MUST be >=0.
self.Wallet['Wallet'][quote]+=total_proceeds
Expand Down
2 changes: 1 addition & 1 deletion Base/Library/JackrabbitProxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
class JackrabbitProxy:
def __init__(self,framework=None,payload=None,exchange=None,account=None,asset=None,Usage=None):
# All the default locations
self.Version="0.0.0.1.855"
self.Version="0.0.0.1.870"
self.BaseDirectory='/home/JackrabbitRelay2/Base'
self.ConfigDirectory='/home/JackrabbitRelay2/Config'
self.DataDirectory="/home/JackrabbitRelay2/Data"
Expand Down
2 changes: 1 addition & 1 deletion Base/Library/JackrabbitRelay.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def Success(self,f,s):
class JackrabbitRelay:
def __init__(self,framework=None,payload=None,exchange=None,account=None,asset=None,secondary=None,NoIdentityVerification=False,Usage=None):
# All the default locations
self.Version="0.0.0.1.855"
self.Version="0.0.0.1.870"
self.NOhtml='<html><title>NO!</title><body style="background-color:#ffff00;display:flex;weight:100vw;height:100vh;align-items:center;justify-content:center"><h1 style="color:#ff0000;font-weight:1000;font-size:10rem">NO!</h1></body></html>'
self.Directories={}
self.Directories['Base']='/home/JackrabbitRelay2/Base'
Expand Down
4 changes: 0 additions & 4 deletions Base/MIMIC-PlaceOrder
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,6 @@ def main():
# If the amount is less then the minimum and action is to close. Sell opens
# a short position.

if ReduceOnly==True:
if (pBalance>0 and amount<0) or (pBalance<0 and amount>0):
relay.JRLog.Error(relay.Exchange, "ReduceOnly mode active, close position first")

if (abs(pBalance)<minimum or abs(pBalance*price)<mincost) \
and relay.Order['Action'].lower()=='close':
relay.JRLog.Error(relay.Exchange, "not enough to close position")
Expand Down
130 changes: 130 additions & 0 deletions Extras/Mimic/alCaCharts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Jackrabbit Relay
# 2021 Copyright © Robert APM Darin
# All rights reserved unconditionally.

import sys
sys.path.append('/home/JackrabbitRelay2/Base/Library')
import os
import time
import json
import pandas as pd
import matplotlib.pyplot as plt

import JRRsupport

chartDir='/home/JackrabbitRelay2/Data/Charts/'
MimicData='/home/JackrabbitRelay2/Data/Mimic/'

def plot_trading_data(trading_data,account,base,quot):
# Convert JSON strings to a list of dictionaries
# data = [json.loads(line) for line in trading_data.split('\n') if line]
data=trading_data

# Convert to DataFrame
df = pd.DataFrame(data)

# Convert 'DateTime' to datetime object
df['DateTime'] = pd.to_datetime(df['DateTime'])

# Plot PEPE balance over time
plt.figure(figsize=(15, 8))

plt.subplot(3, 2, 1)
plt.plot(df['DateTime'], df[base], marker='o')
plt.title(f'{base} Balance Over Time')
plt.xlabel('DateTime')
plt.ylabel(base)

# Plot USDT balance over time
plt.subplot(3, 2, 2)
plt.plot(df['DateTime'], df[quote], marker='o', color='orange')
plt.title(f'{quote} Balance Over Time')
plt.xlabel('DateTime')
plt.ylabel(quote)

# Plot transaction amounts over time
plt.subplot(3, 2, 3)
plt.plot(df['DateTime'], df['Amount'], marker='o', color='green')
plt.title('Transaction Amount Over Time')
plt.xlabel('DateTime')
plt.ylabel('Amount')

# Plot transaction prices over time
plt.subplot(3, 2, 4)
plt.plot(df['DateTime'], df['Price'], marker='o', color='red')
plt.title('Transaction Price Over Time')
plt.xlabel('DateTime')
plt.ylabel('Price')

# Plot fees over time
plt.subplot(3, 2, 5)
plt.plot(df['DateTime'], df['Fee'], marker='o', color='purple')
plt.title('Transaction Fee Over Time')
plt.xlabel('DateTime')
plt.ylabel('Fee')

# Plot action distribution
plt.subplot(3, 2, 6)
df['Action'].value_counts().plot(kind='bar', color=['blue', 'red'])
plt.title('Action Distribution')
plt.xlabel('Action')
plt.ylabel('Count')

plt.tight_layout()
# plt.show()
plt.savefig(f'{chartDir}alCaChart.mimic.{account}.{base}{quote}.png')
plt.close()

# Sample data input
#trading_data = """
#{"DateTime": "2024-05-26 19:42:27.144159", "ID": "17167453471441732", "Action": "buy", "Asset": "PEPE/USDT", "PEPE": 2451113.05611632, "USDT": 94817.5613180798, "Amount": 2450818.31777792, "Price": 1.593e-05, "Fee": 0.09760384}
#{"DateTime": "2024-05-26 19:42:29.191986", "ID": "17167453491920022", "Action": "sell", "Asset": "PEPE/USDT", "PEPE": 2591.021503230091, "USDT": 94856.4687616998, "Amount": 2448522.03461309, "Price": 1.593e-05, "Fee": 0.09751239}
#"""
#plot_trading_data(trading_data)

###
### Main code base.
###

if len(sys.argv)<2:
print("A Mimic account is required.")
sys.exit(1)

account=sys.argv[1]
acn=f'{MimicData}{account}.history'
if not os.path.exists(acn):
print('Please verify wallet name and case')
sys.exit(1)

TradeData=JRRsupport.ReadFile(acn)
lines=TradeData.strip().split('\n')

Wallet={}

for line in lines:
if line=='':
continue

try:
data=json.loads(line)
except:
print("Line damaged:")
print(f" {line}")
sys.exit(1)

if data['Asset'] not in Wallet:
Wallet[data['Asset']]=[]

Wallet[data['Asset']].append(data)

for asset in sorted(Wallet.keys()):
base,quote=asset.split('/')
if ':' in asset:
quote=asset.split(':')[1]
if '-' in quote:
quote=quote.split('-')[0]
plot_trading_data(Wallet[asset],account,base,quote)

2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ numpy
ccxt
oandapyV20
plotly
matplotlib

36 changes: 36 additions & 0 deletions x1
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
current_position = self.Wallet['Wallet'].get(base, 0)

if (current_position > 0 and actualAmount < 0) or (current_position < 0 and actualAmount > 0):
# Flipping logic
flip_proceeds = abs(current_position) * actualPrice
self.Wallet['Wallet'][quote] += flip_proceeds # Cover the existing position
self.Wallet['Wallet'][base] = 0 # Clear the existing position

# Open the new position with the amount provided
new_position_cost = abs(actualAmount) * actualPrice * (1 + fee_rate)
if self.Wallet['Wallet'][quote] < new_position_cost:
self.Wallet['Enabled'] = 'N'
return 'Account Liquidated!'

self.Wallet['Wallet'][quote] -= new_position_cost
self.Wallet['Wallet'][base] = actualAmount # Set the new position with the provided amount

# Update fees
fee = abs(actualAmount) * actualPrice * fee_rate
self.Wallet['Fees'] = self.Wallet.get('Fees', 0) + fee

# Record the order
order = {
'DateTime': datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'),
'ID': f"{time.time() * 10000000:.0f}",
'Action': action,
'Asset': asset,
base: self.Wallet['Wallet'][base],
quote: self.Wallet['Wallet'][quote],
'Amount': round(actualAmount, 8),
'Price': round(actualPrice, 8),
'Fee': round(fee, 8)
}
JRRsupport.AppendFile(self.history, json.dumps(order) + '\n')
return order

0 comments on commit 2d0fe52

Please sign in to comment.