Last active
August 12, 2021 23:22
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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 | |
} | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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