def Reset(*_): print('---------------------\nReset\n---------------------') global mornitorFilePath global transacFilePath if not os.path.exists(mornitorFilePath): return None m_df = pd.read_csv(mornitorFilePath) t_df = pd.read_csv(transacFilePath) deleteList = [] m_user_list = m_df['User'].unique().tolist() t_user_list = t_df['User'].unique().tolist() for user in m_user_list: print('Checking User {} in Mornitor {}'.format(user, m_user_list)) if not user in list(configJson): deleteList.append(user) for user in t_user_list: print('Checking User {} in Transaction {}'.format(user, t_user_list)) if not user in list(configJson): deleteList.append(user) #Sending Restart for user in list(configJson): systemName = configJson[user]['system'] if bool(configJson[user]['reset']): gSheet.setValue('Config', findKey='idName', findValue=user, key='reset', value=0) gSheet.setValue('Config', findKey='idName', findValue=user, key='lastReport', value=time.time()) text = '[ Reset Portfoilo ]\n' +\ 'User ID : {} \n'.format(user) +\ 'Preset ID : {} \n'.format(configJson[user]['preset']) +\ 'System ID : {} \n'.format(systemName) +\ 'Size : {} \n'.format(systemJson[systemName]['size']) +\ 'Target Profit : {}%'.format(systemJson[systemName]['percentageProfitTarget']) lineNotify.sendNotifyMassage(configJson[user]['lineToken'], text) print(text) for user in deleteList: print('delete [ {} ]'.format(user)) m_df = m_df[m_df['User'] != user] t_df = t_df[t_df['User'] != user] m_df.to_csv(mornitorFilePath, index=False) t_df.to_csv(transacFilePath, index=False) print('User Reset')
def getBalance(idName): API_KEY = configJson[idName]['bk_apiKey'] API_SECRET = configJson[idName]['bk_apiSecret'] if API_KEY == '' or API_SECRET == '': print('this user have no API KEY or API SECRET to send order') return None bitkub = Bitkub() bitkub.set_api_key(API_KEY) bitkub.set_api_secret(API_SECRET) balance = bitkub.balances() data = {} if balance['error'] == 0: for sym in balance['result']: if balance['result'][sym]['available'] > 0: available = balance['result'][sym]['available'] available_h = max([ available, configJson[idName]['available'], configJson[idName]['availableHigh'] ]) p_drawdown = (abs(available_h - available) / available_h) * 100 p_drawdown = round(p_drawdown, 2) data[sym] = { 'available': available, 'reserved': balance['result'][sym]['reserved'] } #update balance data sheet if sym == 'THB': gSheet.setValue('Config', findKey='idName', findValue=idName, key='available', value=available) gSheet.setValue('Config', findKey='idName', findValue=idName, key='availableHigh', value=available_h) gSheet.setValue('Config', findKey='idName', findValue=idName, key='percentageDrawdown', value=p_drawdown) return data
def Realtime(idName, sendNotify=True): isActive = bool(configJson[idName]['active']) isActive = True isReset = bool(configJson[idName]['reset']) if isActive == False: return None print('---------------------\n[ {} ] Monitoring\n---------------------'. format(idName)) ticker = kbApi.getTicker() now = round(time.time()) reportHourDuration = round( float(((now - configJson[idName]['lastReport']) / 60) / 60), 2) preset = configJson[idName]['preset'] system = configJson[idName]['system'] token = configJson[idName]['lineToken'] portSize = int(configJson[idName]['portSize']) buySize = int(configJson[idName]['buySize']) profitTarget = float(configJson[idName]['percentageProfitTarget']) lossTarget = float(configJson[idName]['percentageLossTarget']) * (-1) triggerBuy = systemJson[system]['triggerBuy'] triggerSell = systemJson[system]['triggerSell'] triggerBuyPos = systemJson[system]['triggerBuyPosition'] triggerSellPos = systemJson[system]['triggerSellPosition'] adaptiveLoss = bool(configJson[idName]['adaptiveLoss']) print('Portfolio Size : {} | Buy Position Size : {}'.format( portSize, buySize)) print('Buy : {} | Sell : {}'.format(triggerBuy, triggerSell)) print('Trigger Buy : {} | Trigger Sell : {}'.format( triggerBuyPos, triggerSellPos)) #print(ticker) colSelect = [ 'User', 'Symbol', 'Signal', 'Buy', 'Market', 'Profit%', 'Max_Drawdown%', 'Change4HR%', 'Volume', 'BreakOut_H', 'BreakOut_MH', 'BreakOut_M', 'BreakOut_ML', 'BreakOut_L', 'Low', 'High', 'Rec_Date', 'Count' ] #Signal Dataframe signal_df = pd.read_csv(dataPath + '/signal.csv') signal_df = signal_df[ (signal_df['Rec_Date'] == signal_df['Rec_Date'].max()) & (signal_df['Preset'] == preset)] signal_df.sort_values(['Change4HR%', 'Volume', 'Risk%'], ascending=[True, False, True]) signal_df.reset_index(inplace=True) # New Column For Signal DF signal_df['User'] = idName signal_df['Buy'] = signal_df['Close'] signal_df['Market'] = signal_df['Close'] signal_df['Profit%'] = ( (signal_df['Market'] - signal_df['Buy']) / signal_df['Buy']) * 100 signal_df['Max_Drawdown%'] = 0.0 signal_df['Count'] = 1 for sym in ticker: signal_df.loc[(signal_df['Symbol'] == sym), 'Buy'] = ticker[sym]['last'] signal_df.loc[(signal_df['Symbol'] == sym), 'Market'] = ticker[sym]['last'] #print(signal_df[colSelect]) #Portfolio File Checking if not os.path.exists(mornitorFilePath): port_df = pd.DataFrame(columns=colSelect) port_df.to_csv(mornitorFilePath, index=False) #Read User Portfolio port_df = pd.read_csv(mornitorFilePath) port_df = port_df[(port_df['User'] == idName)] port_df.reset_index(inplace=True) print('Portfolio') print(port_df['Symbol'].tolist()) print('---------------------\nBuying\n---------------------') #Find New Buy buy_df = None if triggerBuyPos == 'Lower': buy_df = signal_df[(signal_df['Signal'] == triggerBuy) & ( signal_df['Market'] < signal_df['BreakOut_ML'])][colSelect] elif triggerBuyPos == 'Upper': buy_df = signal_df[(signal_df['Signal'] == triggerBuy) & ( signal_df['Market'] > signal_df['BreakOut_MH'])][colSelect] elif triggerBuyPos == 'Middle': buy_df = signal_df[(signal_df['Signal'] == triggerBuy) & ( signal_df['Market'] < signal_df['BreakOut_M'])][colSelect] buy_df = buy_df.head(portSize) #print('Buy Data Frame') #print(buy_df[['Symbol','Signal','Market','BreakOut_MH','BreakOut_ML']]) #Buy Condition for i in buy_df.index.tolist(): row = buy_df.loc[i] text = '[ Buy ] {}\n{} Bath'.format(row['Symbol'], row['Buy']) #print('Buying {} : {}'.format(row['Symbol'],row['Market'])) if row['Symbol'] in port_df['Symbol'].tolist( ): #Symbol is in portfolio already #print(' Checking buy count') symbol_index = port_df[port_df['Symbol'] == row['Symbol']].index.tolist()[0] if port_df.loc[symbol_index, 'Count'] < buySize: #Buy position size is not full if row['Rec_Date'] != port_df.loc[ symbol_index, 'Rec_Date']: #if Date Time not exist # Do Buy print('Buy {} more'.format(row['Symbol'])) portfolioList = port_df['Symbol'].tolist() countLeft = (buySize * portSize) - (port_df['Count'].sum()) CreateBuyOrder(idName, row['Symbol'], portfolioList, countLeft) Transaction( idName, 'Buy', row['Symbol'], (configJson[idName]['percentageComission'] / 100) * -1) if sendNotify: lineNotify.sendNotifyMassage(token, text) port_df.loc[symbol_index, 'Count'] += 1 port_df.loc[symbol_index, 'Rec_Date'] = row['Rec_Date'] port_df.loc[symbol_index, 'Buy'] = round( (port_df.loc[symbol_index, 'Buy'] + row['Buy']) * 0.5, 2) elif not row['Symbol'] in port_df['Symbol'].tolist( ): #Symbol isn't in portfolio #print(' Checking port is not full') if port_df['Symbol'].count() < portSize: #Portfolio isn't full # Do Buy print('Buy {} as new symbol'.format(row['Symbol'])) portfolioList = port_df['Symbol'].tolist() countLeft = (buySize * portSize) - (port_df['Count'].sum()) CreateBuyOrder(idName, row['Symbol'], portfolioList, countLeft) Transaction(idName, 'Buy', row['Symbol'], (configJson[idName]['percentageComission'] / 100) * -1) if sendNotify: quote = row['Symbol'].split('_')[-1] imgFilePath = imgPath + os.sep + '{}_{}.png'.format( preset, quote) lineNotify.sendNotifyImageMsg(token, imgFilePath, text) port_df = port_df.append(row, ignore_index=False) print('---------------------\nProfit Calulating\n---------------------') #Market Update and Calculate Profit for i in signal_df.index.tolist(): row = signal_df.loc[i] if row['Symbol'] in port_df['Symbol'].tolist(): print('Profit Update {}'.format(row['Symbol'])) symbol_index = port_df[port_df['Symbol'] == row['Symbol']].index.tolist()[0] port_df.loc[symbol_index, 'Market'] = row['Market'] port_df.loc[symbol_index, 'Profit%'] = ((port_df.loc[symbol_index, 'Market'] - port_df.loc[symbol_index, 'Buy']) / port_df.loc[symbol_index, 'Buy']) * 100 port_df.loc[symbol_index, 'Profit%'] = round( port_df.loc[symbol_index, 'Profit%'], 2) if (port_df.loc[symbol_index, 'Profit%'] < 0) and (abs(port_df.loc[symbol_index, 'Profit%']) > port_df.loc[symbol_index, 'Max_Drawdown%']): port_df.loc[symbol_index, 'Max_Drawdown%'] = abs(port_df.loc[symbol_index, 'Profit%']) port_df.loc[symbol_index, 'Change4HR%'] = row['Change4HR%'] port_df.loc[symbol_index, 'Volume'] = row['Volume'] port_df.loc[symbol_index, 'BreakOut_H'] = row['BreakOut_H'] port_df.loc[symbol_index, 'BreakOut_MH'] = row['BreakOut_MH'] port_df.loc[symbol_index, 'BreakOut_M'] = row['BreakOut_M'] port_df.loc[symbol_index, 'BreakOut_ML'] = row['BreakOut_ML'] port_df.loc[symbol_index, 'BreakOut_L'] = row['BreakOut_L'] port_df.loc[symbol_index, 'Low'] = row['Low'] port_df.loc[symbol_index, 'High'] = row['High'] port_df.loc[symbol_index, 'Signal'] = row['Signal'] # Portfolio report if port_df['Symbol'].count( ) != 0 and reportHourDuration >= configJson[idName]['reportEveryHour']: gSheet.setValue('Config', findKey='idName', findValue=idName, key='lastReport', value=time.time()) text = '[ Report ]\n' + \ '{}\n'.format(' , '.join(port_df['Symbol'].tolist())) + \ 'Avg Profit {}%'.format(port_df['Profit%'].mean().round(2)) print(text) if sendNotify: lineNotify.sendNotifyMassage(token, text) print('---------------------\nSelling\n---------------------') #Sell Condition for i in port_df.index.tolist(): row = port_df.loc[i] sell_signal = False sell_profit = row['Profit%'] > profitTarget sell_loss = row['Profit%'] < lossTarget #Adaptive Loss if adaptiveLoss and sell_loss: gSheet.setValue('Config', findKey='idName', findValue=idName, key='percentageLossTarget', value=abs(row['Profit%'])) if triggerSellPos == 'Lower': sell_signal = ((row['Signal'] == triggerSell) and (row['Market'] < row['BreakOut_ML']) and (row['Profit%'] > 1)) elif triggerSellPos == 'Upper': sell_signal = ((row['Signal'] == triggerSell) and (row['Market'] > row['BreakOut_MH']) and (row['Profit%'] > 1)) elif triggerSellPos == 'Middle': sell_signal = ((row['Signal'] == triggerSell) and (row['Market'] > row['BreakOut_M']) and (row['Profit%'] > 1)) if sell_signal or sell_profit or sell_loss or isReset: #Sell if isReset: port_df.loc[i, 'Count'] = 0 # Sell All else: port_df.loc[i, 'Count'] -= 1 text = '[ Sell ] {}\n{} Bath ({}%)'.format(row['Symbol'], row['Market'], row['Profit%']) print(text) # Do Sell count = port_df.loc[i, 'Count'] + 1 CreateSellOrder(idName, row['Symbol'], count=count) time.sleep(1) profit = ((row['Profit%'] / buySize) * row['Count']) / portSize #real percentage of total cost Transaction( idName, 'Sell', row['Symbol'], ((configJson[idName]['percentageComission'] / 100) * -1) + profit) if sendNotify: lineNotify.sendNotifyMassage(token, text) if port_df.loc[i, 'Count'] <= 0: #Delete symbol if no count port_df = port_df[port_df['Symbol'] != row['Symbol']] #Finish if 'index' in port_df.columns.tolist(): port_df.drop(columns=['index'], inplace=True) alluser_df = pd.read_csv(mornitorFilePath) alluser_df = alluser_df[alluser_df['User'] != idName] alluser_df = alluser_df.append(port_df) alluser_df.to_csv(mornitorFilePath, index=False) print('---------------------\nFinish\n---------------------\n')
def Reset(*_): print('---------------------\nReset\n---------------------') global mornitorFilePath global transacFilePath if not os.path.exists(mornitorFilePath): return None m_df = pd.read_csv(mornitorFilePath) t_df = pd.read_csv(transacFilePath) deleteList = [] m_user_list = m_df['User'].unique().tolist() t_user_list = t_df['User'].unique().tolist() for user in m_user_list: print('Checking User {} in Mornitor'.format(user)) if not user in list(configJson): deleteList.append(user) for user in t_user_list: print('Checking User {} in Transaction'.format(user)) if not user in list(configJson): deleteList.append(user) #Sending Restart for user in list(configJson): if bool(configJson[user]['reset']): text = '[ Reset Portfoilo ]\n' +\ 'User ID : {} \n'.format(user) +\ 'Preset ID : {} \n'.format(configJson[user]['preset']) +\ 'System ID : {} \n'.format(configJson[user]['system']) +\ 'Portfolio Size : {} \n'.format(configJson[user]['portSize']) +\ 'Position Size : {} \n'.format(configJson[user]['buySize']) +\ 'Target Profit : {}%'.format(configJson[user]['percentageProfitTarget']) lineNotify.sendNotifyMassage(configJson[user]['lineToken'], text) gSheet.setValue('Config', findKey='idName', findValue=user, key='reset', value=0) gSheet.setValue('Config', findKey='idName', findValue=user, key='lastReport', value=time.time()) print(text) #Clear all real portfolio API_KEY = configJson[user]['bk_apiKey'] API_SECRET = configJson[user]['bk_apiSecret'] bitkub = Bitkub() bitkub.set_api_key(API_KEY) bitkub.set_api_secret(API_SECRET) balance = getBalance(user) #print(balance) for sym in balance: if sym == 'THB': continue symbol = 'THB_{}'.format(sym) print(symbol) print('Sell {} {}'.format(balance[sym]['available'], sym)) CreateSellOrder(user, symbol, count=1) for user in deleteList: print('delete [ {} ]'.format(user)) m_df = m_df[m_df['User'] != user] t_df = t_df[t_df['User'] != user] m_df.to_csv(mornitorFilePath, index=False) t_df.to_csv(transacFilePath, index=False) print('User Reset')
def MornitoringUser(idName, sendNotify=True): isActive = bool(configJson[idName]['active']) isReset = bool(configJson[idName]['reset']) if isActive == False: return None print('---------------------\n[ {} ] Monitoring\n---------------------'. format(idName)) ticker = kbApi.getTicker() now = round(time.time()) reportHourDuration = round( float(((now - configJson[idName]['lastReport']) / 60) / 60), 2) preset = configJson[idName]['preset'] system = configJson[idName]['system'] token = configJson[idName]['lineToken'] size = int(systemJson[system]['size']) profitTarget = float(systemJson[system]['percentageProfitTarget']) duplicateBuyCount = 2 secondaryBuy = bool(systemJson[system]['secondaryBuy']) print('Last Report {} Hour Ago / Report Every {} H'.format( reportHourDuration, configJson[idName]['reportEveryHour'])) signal_df = pd.read_csv(dataPath + '/signal.csv') signal_df = signal_df[ (signal_df['Rec_Date'] == signal_df['Rec_Date'].max()) & (signal_df['Preset'] == preset)] signal_df.reset_index(inplace=True) # New Column For Signal DF signal_df['User'] = idName signal_df['Buy'] = signal_df['Close'] signal_df['Market'] = signal_df['Close'] signal_df['Profit%'] = ( (signal_df['Market'] - signal_df['Buy']) / signal_df['Buy']) * 100 signal_df['Max_Drawdown%'] = 0.0 signal_df['Buy_Count'] = 0 for sym in ticker: signal_df.loc[(signal_df['Symbol'] == sym), 'Buy'] = ticker[sym]['last'] # Select Entry entry_df = signal_df #entry_df['Change4HR%_Abs'] = entry_df['Change4HR%'].abs() entry_df = entry_df[ (entry_df['Rec_Date'] == entry_df['Rec_Date'].max()) & (entry_df['Signal'] == 'Entry') & (entry_df['Preset'] == preset) #( entry_df['Change4HR%'] >= 0 ) & #( entry_df['Close'] <= entry_df['BreakOut_M'] ) ] #entry_df = entry_df.sort_values(['Change4HR%_Abs','Value_M'], ascending=[True,False]) entry_df = entry_df.sort_values(['Change4HR%', 'Value_M'], ascending=[True, False]) #entry_df = entry_df.head(size) # Select Count entry_df.reset_index(inplace=True) #print(entry_df) # Signal Checking """ # New Column For Entry DF entry_df['User'] = idName entry_df['Buy'] = entry_df['Close'] entry_df['Market'] = entry_df['Close'] entry_df['Profit%'] = ( ( entry_df['Market'] - entry_df['Buy'] ) / entry_df['Buy'] ) * 100 entry_df['Max_Drawdown%'] = 0.0 """ colSelect = [ 'User', 'Symbol', 'Signal', 'Buy', 'Market', 'Profit%', 'Max_Drawdown%', 'Change4HR%', 'Value_M', 'BreakOut_H', 'BreakOut_MH', 'BreakOut_M', 'BreakOut_ML', 'BreakOut_L', 'Low', 'High', 'Rec_Date', 'Buy_Count' ] entry_df = entry_df[colSelect] #print(entry_df[['Symbol','Signal','Change4HR%']]) print('Select Entry {}'.format(entry_df['Symbol'].to_list())) # Mornitor data frame global mornitorFilePath if not os.path.exists(mornitorFilePath): morn_df = pd.DataFrame(columns=colSelect) morn_df.to_csv(mornitorFilePath, index=False) morn_df = pd.read_csv(mornitorFilePath) # Checking Column for c in colSelect: if not c in morn_df.columns.tolist(): morn_df[c] = None #Portfolio portfolioList = morn_df[morn_df['User'] == idName]['Symbol'].tolist() portfolioCount = morn_df[morn_df['User'] == idName]['Buy_Count'].sum() print('{} Portfolio have {}'.format(idName, portfolioList)) # Buy Notify (by Singnal) # ============================== for i in range(entry_df['Symbol'].count()): if isReset: break row = entry_df.iloc[i] buy_condition = ((not row['Symbol'] in portfolioList) and (portfolioCount < size) and # Port is not full (row['BreakOut_ML'] != row['BreakOut_L']) and (row['BreakOut_MH'] != row['BreakOut_H']) and (row['Low'] != row['BreakOut_ML']) and (row['Low'] < row['BreakOut_M'])) if buy_condition and not row['Symbol'] in portfolioList: # Buy Primary row['Buy_Count'] = 1 text = '[ Buy ] {}\n{} Bath'.format(row['Symbol'], row['Buy']) quote = row['Symbol'].split('_')[-1] #entry_df['Buy_Count'].iloc[i] = row['Buy_Count']+1 imgFilePath = imgPath + os.sep + '{}_{}.png'.format(preset, quote) print(text) print(imgFilePath) if sendNotify: lineNotify.sendNotifyImageMsg(token, imgFilePath, text) morn_df = morn_df.append(row, ignore_index=True) morn_df['Buy'] = morn_df.groupby(['User', 'Symbol' ]).transform('first')['Buy'] portfolioList.append(row['Symbol']) portfolioCount += 1 CreateBuyOrder(idName, row['Symbol'], portfolioList) Transaction(idName, 'Buy', row['Symbol'], (systemJson[system]['percentageComission'] / 100) * -1) elif portfolioCount >= size or row[ 'Symbol'] in portfolioList: # Port is Full or Duplicate Buy is Limited print('Can\'t Buy More Because Size is Full...') break # ============================== # Update Checking for i in range(signal_df['Symbol'].count()): if isReset: break row = signal_df.iloc[i] port_df = morn_df[(morn_df['User'] == idName) & (morn_df['Symbol'] == row['Symbol'])] if port_df['Symbol'].count() != 0: #Have Symbol in Port buy_low_condition = ( secondaryBuy and (row['Symbol'] in portfolioList) and #is already in port (portfolioCount < size) and # size is not full (row['BreakOut_ML'] != row['BreakOut_L']) and (row['BreakOut_ML'] < row['BreakOut_M']) and (row['Market'] < row['BreakOut_ML']) and (port_df['Buy_Count'].tolist()[0] >= 1) and (port_df['Buy_Count'].tolist()[0] < 2)) if buy_low_condition: # Secondary Buying row['Buy_Count'] = 1 text = '[ Secondary Buy ] {}\n{} Bath\nStop Loss {} Bath'.format( row['Symbol'], row['Market'], row['BreakOut_L']) if sendNotify: lineNotify.sendNotifyMassage(token, text) morn_df = morn_df.append(row, ignore_index=True) morn_df['Buy'] = morn_df.groupby(['User', 'Symbol' ]).transform('mean')['Buy'] CreateBuyOrder(idName, row['Symbol'], portfolioList) Transaction(idName, 'Buy', row['Symbol'], (systemJson[system]['percentageComission'] / 100) * -1) # Update Trailing trailing_condition = ( (row['Symbol'] in portfolioList) and (ticker[row['Symbol']]['last'] > row['BreakOut_M'])) if trailing_condition: morn_df = morn_df.append(row, ignore_index=True) print('Updated Trailing ( {} )'.format(row['Symbol'])) # ============================== morn_df = morn_df[colSelect] # Ticker ( Update Last Price as 'Market' ) for sym in ticker: if not sym in morn_df['Symbol'].unique().tolist(): continue morn_df.loc[morn_df['Symbol'] == sym, 'Market'] = ticker[sym]['last'] print('Update Market Price') # Calculate in Column print('Profit Calculating...') if not morn_df.empty: morn_df['Buy_Count'] = morn_df.groupby( ['User', 'Symbol']).transform('sum')['Buy_Count'] morn_df['Buy'] = morn_df.groupby(['User', 'Symbol']).transform('first')['Buy'] morn_df['Profit%'] = ( (morn_df['Market'] - morn_df['Buy']) / morn_df['Buy']) * 100 morn_df['Profit%'] = morn_df['Profit%'].round(2) morn_df.loc[(morn_df['Profit%'] < 0.0) & (morn_df['Max_Drawdown%'] == 0.0), 'Max_Drawdown%'] = morn_df['Profit%'].abs() morn_df.loc[(morn_df['Profit%'] > 0.0) & (morn_df['Max_Drawdown%'] == 0.0), 'Max_Drawdown%'] = 0.0 morn_df.loc[(morn_df['Profit%'] < 0.0) & (morn_df['Profit%'] < morn_df['Max_Drawdown%'].abs() * -1), 'Max_Drawdown%'] = morn_df['Profit%'].abs() morn_df['Max_Drawdown%'] = morn_df.groupby( ['User', 'Symbol'])['Max_Drawdown%'].transform('max') morn_df.drop_duplicates(['User', 'Symbol'], keep='last', inplace=True) morn_df.to_csv(mornitorFilePath, index=False) # Reload mornitor again morn_df = pd.read_csv(mornitorFilePath) morn_df = morn_df.sort_values(['User', 'Profit%'], ascending=[True, False]) holdList = morn_df[(morn_df['User'] == idName) & ( morn_df['Profit%'] > 0.0)].head(size)['Symbol'].tolist() # Sell Notify # ============================== """ sell_df = signal_df[ (signal_df['Signal'] == 'Exit') & (signal_df['Preset'] == preset) ] """ sellList = [] for i in range(morn_df['Symbol'].count()): row = morn_df.iloc[i] text = '[ Sell ] {}\n{} Bath ({}%)'.format(row['Symbol'], row['Market'], row['Profit%']) sell_condition = ( # Sell Default (row['Market'] < row['BreakOut_L']) and (row['User'] == idName)) or ((row['User'] == idName) and (row['Profit%'] > profitTarget)) if (row['Profit%'] <= 0.0): # Fast Cut Loss if no profit sell_condition = ( # Sell Default (row['Market'] < row['BreakOut_ML']) and (row['User'] == idName)) if sell_condition: print(text) if sendNotify: lineNotify.sendNotifyMassage(token, text) sellList.append({'User': row['User'], 'Symbol': row['Symbol']}) # ============================== #Report report_df = morn_df[morn_df['User'] == idName] report_df = report_df.sort_values(['Profit%'], ascending=[False]) #Portfolio report if report_df['Symbol'].count( ) != 0 and reportHourDuration >= configJson[idName]['reportEveryHour']: gSheet.setValue('Config', findKey='idName', findValue=idName, key='lastReport', value=time.time()) text = '[ Report ]\n' +\ '{}\n'.format( ' , '.join(report_df['Symbol'].tolist()) ) +\ 'Profit Sum {}%\n'.format(report_df['Profit%'].sum().round(2)) + \ 'Profit Average {}%'.format(report_df['Profit%'].mean().round(2)) print(text) if sendNotify: lineNotify.sendNotifyMassage(token, text) #Take profit all (Clear Portfolio) profit_condition = ((report_df['Profit%'].mean() >= profitTarget) and (report_df['Profit%'].count() >= size)) if (profit_condition or isReset) and report_df['Profit%'].count() != 0: gSheet.setValue('Config', findKey='idName', findValue=idName, key='reset', value=1) text = '[ Take Profit ]\n' + \ 'Target Profit {}%\n'.format(profitTarget) + \ 'Profit Average {}%'.format(report_df['Profit%'].mean().round(2)) print(text) if sendNotify: lineNotify.sendNotifyMassage(token, text) # Prepare Sell When Take Profit or Reset for sym in report_df['Symbol'].tolist(): if sym in sellList: continue sellList.append({'User': idName, 'Symbol': sym}) # Sell And Delete Symbol for i in sellList: profit = morn_df[(morn_df['User'] == i['User']) & ( morn_df['Symbol'] == i['Symbol'])]['Profit%'].tolist()[0] profit = profit / size morn_df = morn_df.drop( morn_df[(morn_df['User'] == i['User']) & (morn_df['Symbol'] == i['Symbol'])].index) CreateSellOrder(i['User'], i['Symbol']) Transaction(i['User'], 'Sell', i['Symbol'], ((systemJson[system]['percentageComission'] / 100) * -1) + profit) #Finish morn_df.to_csv(mornitorFilePath, index=False) print('{} Update Finished\n'.format(idName))