Skip to content

Instantly share code, notes, and snippets.

@fatherofluqmaan
Last active August 12, 2021 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fatherofluqmaan/41f8b42b390159bfd4bcf1782a478ba8 to your computer and use it in GitHub Desktop.
Save fatherofluqmaan/41f8b42b390159bfd4bcf1782a478ba8 to your computer and use it in GitHub Desktop.
Another strategy.py and config.json that brings back lower profits on the sims, but may be a safer option for smaller but consistent gains on some of the pairs
{
"coinbasepro" : {
"api_url" : "https://api.pro.coinbase.com",
"api_key_file" : "coinbase.key",
"config" : {
"base_currency" : "ETH",
"quote_currency" : "EUR",
"live" : 1,
"sellatloss" : 0,
"sellatresistance" : 1,
"sellupperpcnt" : 5,
"trailingstoploss" : -1.5,
"disableFailsafeLowerPcnt" : 1,
"disablebullonly" : 1,
"disablebuynearhigh" : 1,
"disablebuymacd" : 1,
"disablebuyobv" : 0,
"disablebuyelderray" : 0,
"disablefailsafefibonaccilow" : 1,
"disableprofitbankreversal" : 1,
"disabletracker" : 1,
"autorestart" : 1,
"graphs" : 1,
"verbose" : 1,
"stats" : 0
}
)
}
Simulation Summary: July-Aug sim, 3600 granularity
Buy Count : 2
Sell Count : 2
First Buy : 1000
Last Sell : 1071.723642988876
Margin : 7.1723%
** non-live simulation, assuming highest fees
from datetime import datetime
from pandas import DataFrame
from models.PyCryptoBot import PyCryptoBot
from models.AppState import AppState
from models.helper.LogHelper import Logger
class Strategy():
def __init__(self, app: PyCryptoBot=None, state: AppState=AppState, df: DataFrame=DataFrame, iterations: int=0) -> None:
if not isinstance(df, DataFrame):
raise TypeError("'df' not a Pandas dataframe")
if len(df) == 0:
raise ValueError("'df' is empty")
self._action = 'WAIT'
self.app = app
self.state = state
self._df = df
self._df_last = app.getInterval(df, iterations)
def isBuySignal(self, now: datetime = datetime.today().strftime('%Y-%m-%d %H:%M:%S'), price: float=0.0) -> bool:
# required technical indicators or candle sticks for buy signal strategy
required_indicators = [ 'ema12gtema26co', 'macdgtsignal', 'goldencross', 'obv_pc', 'eri_buy' ]
for indicator in required_indicators:
if indicator not in self._df_last:
raise AttributeError(f"'{indicator}' not in Pandas dataframe")
# buy signal exclusion (if disabled, do not buy within 3% of the dataframe close high)
if self.state.last_action == 'SELL' and self.app.disableBuyNearHigh() is True and (price > (self._df['close'].max() * 0.97)):
log_text = str(now) + ' | ' + self.app.getMarket() + ' | ' + self.app.printGranularity() + ' | Ignoring Buy Signal (price ' + str(price) + ' within 3% of high ' + str(self._df['close'].max()) + ')'
Logger.warning(log_text)
return False
# if EMA, MACD are disabled, do not buy
if self.app.disableBuyEMA() and self.app.disableBuyMACD() :
log_text = str(now) + ' | ' + self.app.getMarket() + ' | ' + self.app.printGranularity() + ' | EMA, MACD indicators are disabled '
Logger.warning(log_text)
return False
# criteria for a buy signal 1
if (bool(self._df_last['ema12gtema26co'].values[0]) is True or self.app.disableBuyEMA())\
and (bool(self._df_last['macdgtsignal'].values[0]) is True or self.app.disableBuyMACD()) \
and (bool(self._df_last['goldencross'].values[0]) is True or self.app.disableBullOnly()) \
and (float(self._df_last['obv_pc'].values[0]) > -5 or self.app.disableBuyOBV()) \
and (bool(self._df_last['eri_buy'].values[0]) is True or self.app.disableBuyElderRay()) \
and self.state.last_action != 'BUY': # required for all strategies
Logger.debug('*** Buy Signal ***')
for indicator in required_indicators:
Logger.debug(f'{indicator}: {self._df_last[indicator].values[0]}')
Logger.debug(f'last_action: {self.state.last_action}')
return True
# criteria for buy signal 2 (optionally add additional buy singals)
elif (bool(self._df_last['ema12gtema26co'].values[0]) is True or self.app.disableBuyEMA())\
and bool(self._df_last['macdgtsignalco'].values[0]) is True \
and (bool(self._df_last['goldencross'].values[0]) is True or self.app.disableBullOnly()) \
and (float(self._df_last['obv_pc'].values[0]) > -5 or self.app.disableBuyOBV()) \
and (bool(self._df_last['eri_buy'].values[0]) is True or self.app.disableBuyElderRay()) \
and self.state.last_action != 'BUY': # required for all strategies
Logger.debug('*** Buy Signal ***')
for indicator in required_indicators:
Logger.debug(f'{indicator}: {self._df_last[indicator].values[0]}')
Logger.debug(f'last_action: {self.state.last_action}')
return True
return False
def isSellSignal(self) -> bool:
# required technical indicators or candle sticks for buy signal strategy
required_indicators = [ 'ema12ltema26co', 'macdltsignal' ]
for indicator in required_indicators:
if indicator not in self._df_last:
raise AttributeError(f"'{indicator}' not in Pandas dataframe")
# criteria for a sell signal 1
if bool(self._df_last['ema12ltema26co'].values[0]) is True \
and (bool(self._df_last['macdltsignal'].values[0]) is True or self.app.disableBuyMACD()) \
and self.state.last_action not in ['', 'SELL']:
Logger.debug('*** Sell Signal ***')
for indicator in required_indicators:
Logger.debug(f'{indicator}: {self._df_last[indicator].values[0]}')
Logger.debug(f'last_action: {self.state.last_action}')
return True
return False
def isSellTrigger(self, price: float=0.0, price_exit: float=0.0, margin: float=0.0, change_pcnt_high: float=0.0, obv_pc: float=0.0, macdltsignal: bool=False) -> bool:
# loss failsafe sell at fibonacci band
if self.app.disableFailsafeFibonacciLow() is False and self.app.allowSellAtLoss() and self.app.sellLowerPcnt() is None and self.state.fib_low > 0 and self.state.fib_low >= float(price):
log_text = '! Loss Failsafe Triggered (Fibonacci Band: ' + str(self.state.fib_low) + ')'
Logger.warning(log_text)
self.app.notifyTelegram(self.app.getMarket() + ' (' + self.app.printGranularity() + ') ' + log_text)
return True
# loss failsafe sell at trailing_stop_loss ## CHANGED BACK TO THIS 09/08 ##
if self.app.trailingStopLoss() != None and change_pcnt_high < self.app.trailingStopLoss() and (self.app.allowSellAtLoss() or (margin > 0 and margin < 3)):
log_text = '! Trailing Stop Loss Triggered (< ' + str(self.app.trailingStopLoss()) + '%)'
Logger.warning(log_text)
self.app.notifyTelegram(self.app.getMarket() + ' (' + self.app.printGranularity() + ') ' + log_text)
return True
# loss failsafe sell at sell_lower_pcnt
elif self.app.disableFailsafeLowerPcnt() is False and self.app.allowSellAtLoss() and self.app.sellLowerPcnt() != None and margin < self.app.sellLowerPcnt():
log_text = '! Loss Failsafe Triggered (< ' + str(self.app.sellLowerPcnt()) + '%)'
Logger.warning(log_text)
self.app.notifyTelegram(self.app.getMarket() + ' (' + self.app.printGranularity() + ') ' + log_text)
return True
# profit bank at sell_upper_pcnt
if self.app.disableProfitbankUpperPcnt() is False and self.app.sellUpperPcnt() != None and margin > self.app.sellUpperPcnt():
log_text = '! Profit Bank Triggered (> ' + str(self.app.sellUpperPcnt()) + '%)'
Logger.warning(log_text)
self.app.notifyTelegram(self.app.getMarket() + ' (' + self.app.printGranularity() + ') ' + log_text)
return True
# profit bank when strong reversal detected
if self.app.disableProfitbankReversal() is False and margin > 3 and obv_pc < 0 and macdltsignal is True:
log_text = '! Profit Bank Triggered (Strong Reversal Detected)'
Logger.warning(log_text)
self.app.notifyTelegram(self.app.getMarket() + ' (' + self.app.printGranularity() + ') ' + log_text)
return True
# profit bank when strong reversal detected
if self.app.sellAtResistance() is True and margin >= 2 and price > 0 and price != price_exit:
log_text = '! Profit Bank Triggered (Selling At Resistance)'
Logger.warning(log_text)
if not (not self.app.allowSellAtLoss() and margin <= 0):
self.app.notifyTelegram(self.app.getMarket() + ' (' + self.app.printGranularity() + ') ' + log_text)
return True
return False
def isWaitTrigger(self, margin: float=0.0):
# configuration specifies to not sell at a loss ## CHANGED BACK TO THIS 09/08 ##
if self.state.action == 'SELL' and not self.app.allowSellAtLoss() and margin <= 0 and margin > -6:
log_text = '! Ignore Sell Signal (No Sell At Loss)'
Logger.warning(log_text)
return True
return False
def getAction(self):
if self.isBuySignal():
return 'BUY'
elif self.isSellSignal():
return 'SELL'
else:
return 'WAIT'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment