text:
from ccxt.async_support.base.exchange import Exchange
import math
from ccxt.base.errors import ExchangeError
from ccxt.base.errors import AuthenticationError
from ccxt.base.errors import ArgumentsRequired
from ccxt.base.errors import BadRequest
from ccxt.base.errors import BadSymbol
from ccxt.base.errors import BadResponse
from ccxt.base.errors import InsufficientFunds
from ccxt.base.errors import InvalidAddress
from ccxt.base.errors import InvalidOrder
from ccxt.base.errors import DDoSProtection
from ccxt.base.errors import RateLimitExceeded
from ccxt.base.errors import ExchangeNotAvailable
from ccxt.base.decimal_to_precision import TRUNCATE
from ccxt.base.decimal_to_precision import TICK_SIZE
from ccxt.base.precise import Precise

class probit(Exchange):

    def describe(self):
        return self.deep_extend(super(probit, self).describe(), {
            'id': 'probit',
            'name': 'ProBit',
            'countries': ['SC', 'KR'],  # Seychelles, South Korea
            'rateLimit': 50,  # ms
            'has': {
                'CORS': True,
                'spot': True,
                'margin': False,
                'swap': False,
                'future': False,
                'option': False,
                'addMargin': False,
                'cancelOrder': True,
                'createMarketOrder': True,
                'createOrder': True,
                'createReduceOnlyOrder': False,
                'createStopLimitOrder': False,
                'createStopMarketOrder': False,
                'createStopOrder': False,
                'fetchBalance': True,
                'fetchBorrowRate': False,
                'fetchBorrowRateHistories': False,
                'fetchBorrowRateHistory': False,
                'fetchBorrowRates': False,
                'fetchBorrowRatesPerSymbol': False,
                'fetchClosedOrders': True,
                'fetchCurrencies': True,
                'fetchDepositAddress': True,
                'fetchDepositAddresses': True,
                'fetchFundingHistory': False,
                'fetchFundingRate': False,
                'fetchFundingRateHistory': False,
                'fetchFundingRates': False,
                'fetchIndexOHLCV': False,
                'fetchLeverage': False,
                'fetchLeverageTiers': False,
                'fetchMarginMode': False,
                'fetchMarkets': True,
                'fetchMarkOHLCV': False,
                'fetchMyTrades': True,
                'fetchOHLCV': True,
                'fetchOpenInterestHistory': False,
                'fetchOpenOrders': True,
                'fetchOrder': True,
                'fetchOrderBook': True,
                'fetchPosition': False,
                'fetchPositionMode': False,
                'fetchPositions': False,
                'fetchPositionsRisk': False,
                'fetchPremiumIndexOHLCV': False,
                'fetchTicker': True,
                'fetchTickers': True,
                'fetchTime': True,
                'fetchTrades': True,
                'fetchTradingFee': False,
                'fetchTradingFees': False,
                'fetchTransfer': False,
                'fetchTransfers': False,
                'fetchWithdrawal': False,
                'fetchWithdrawals': False,
                'reduceMargin': False,
                'setLeverage': False,
                'setMarginMode': False,
                'setPositionMode': False,
                'signIn': True,
                'transfer': False,
                'withdraw': True,
            },
            'timeframes': {
                '1m': '1m',
                '3m': '3m',
                '5m': '5m',
                '10m': '10m',
                '15m': '15m',
                '30m': '30m',
                '1h': '1h',
                '4h': '4h',
                '6h': '6h',
                '12h': '12h',
                '1d': '1D',
                '1w': '1W',
                '1M': '1M',
            },
            'version': 'v1',
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/51840849/79268032-c4379480-7ea2-11ea-80b3-dd96bb29fd0d.jpg',
                'api': {
                    'accounts': 'https://accounts.probit.com',
                    'public': 'https://api.probit.com/api/exchange',
                    'private': 'https://api.probit.com/api/exchange',
                },
                'www': 'https://www.probit.com',
                'doc': [
                    'https://docs-en.probit.com',
                    'https://docs-ko.probit.com',
                ],
                'fees': 'https://support.probit.com/hc/en-us/articles/360020968611-Trading-Fees',
                'referral': 'https://www.probit.com/r/34608773',
            },
            'api': {
                'public': {
                    'get': {
                        'market': 1,
                        'currency': 1,
                        'currency_with_platform': 1,
                        'time': 1,
                        'ticker': 1,
                        'order_book': 1,
                        'trade': 1,
                        'candle': 1,
                    },
                },
                'private': {
                    'post': {
                        'new_order': 2,
                        'cancel_order': 1,
                        'withdrawal': 2,
                    },
                    'get': {
                        'balance': 1,
                        'order': 1,
                        'open_order': 1,
                        'order_history': 1,
                        'trade_history': 1,
                        'deposit_address': 1,
                    },
                },
                'accounts': {
                    'post': {
                        'token': 1,
                    },
                },
            },
            'fees': {
                'trading': {
                    'tierBased': False,
                    'percentage': True,
                    'maker': self.parse_number('0.002'),
                    'taker': self.parse_number('0.002'),
                },
            },
            'exceptions': {
                'exact': {
                    'UNAUTHORIZED': AuthenticationError,
                    'INVALID_ARGUMENT': BadRequest,  # Parameters are not a valid format, parameters are empty, or out of range, or a parameter was sent when not required.
                    'TRADING_UNAVAILABLE': ExchangeNotAvailable,
                    'NOT_ENOUGH_BALANCE': InsufficientFunds,
                    'NOT_ALLOWED_COMBINATION': BadRequest,
                    'INVALID_ORDER': InvalidOrder,  # Requested order does not exist, or it is not your order
                    'RATE_LIMIT_EXCEEDED': RateLimitExceeded,  # You are sending requests too frequently. Please try it later.
                    'MARKET_UNAVAILABLE': ExchangeNotAvailable,  # Market is closed today
                    'INVALID_MARKET': BadSymbol,  # Requested market is not exist
                    'MARKET_CLOSED': BadSymbol,  # {"errorCode":"MARKET_CLOSED"}
                    'MARKET_NOT_FOUND': BadSymbol,  # {"errorCode":"MARKET_NOT_FOUND","message":"8e2b8496-0a1e-5beb-b990-a205b902eabe","details":{}}
                    'INVALID_CURRENCY': BadRequest,  # Requested currency is not exist on ProBit system
                    'TOO_MANY_OPEN_ORDERS': DDoSProtection,  # Too many open orders
                    'DUPLICATE_ADDRESS': InvalidAddress,  # Address already exists in withdrawal address list
                    'invalid_grant': AuthenticationError,  # {"error":"invalid_grant"}
                },
            },
            'requiredCredentials': {
                'apiKey': True,
                'secret': True,
            },
            'precisionMode': TICK_SIZE,
            'options': {
                'createMarketBuyOrderRequiresPrice': True,
                'timeInForce': {
                    'limit': 'gtc',
                    'market': 'ioc',
                },
                'networks': {
                    'BEP20': 'BSC',
                    'ERC20': 'ETH',
                    'TRC20': 'TRON',
                    'TRX': 'TRON',
                },
            },
            'commonCurrencies': {
                'AUTO': 'Cube',
                'AZU': 'Azultec',
                'BCC': 'BCC',
                'BDP': 'BidiPass',
                'BIRD': 'Birdchain',
                'BTCBEAR': 'BEAR',
                'BTCBULL': 'BULL',
                'CBC': 'CryptoBharatCoin',
                'CHE': 'Chellit',
                'CLR': 'Color Platform',
                'CTK': 'Cryptyk',
                'CTT': 'Castweet',
                'DIP': 'Dipper',
                'DKT': 'DAKOTA',
                'EGC': 'EcoG9coin',
                'EPS': 'Epanus',  # conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909
                'FX': 'Fanzy',
                'GDT': 'Gorilla Diamond',
                'GM': 'GM Holding',
                'GOGOL': 'GOL',
                'GOL': 'Goldofir',
                'GRB': 'Global Reward Bank',
                'HBC': 'Hybrid Bank Cash',
                'HUSL': 'The Hustle App',
                'LAND': 'Landbox',
                'LBK': 'Legal Block',
                'ORC': 'Oracle System',
                'PXP': 'PIXSHOP COIN',
                'PYE': 'CreamPYE',
                'ROOK': 'Reckoon',
                'SOC': 'Soda Coin',
                'SST': 'SocialSwap',
                'TCT': 'Top Coin Token',
                'TOR': 'Torex',
                'TPAY': 'Tetra Pay',
                'UNI': 'UNICORN Token',
                'UNISWAP': 'UNI',
            },
        })

    async def fetch_markets(self, params={}):
        """
        retrieves data on all markets for probit
        :param dict params: extra parameters specific to the exchange api endpoint
        :returns [dict]: an array of objects representing market data
        """
        response = await self.publicGetMarket(params)
        #
        #     {
        #         "data":[
        #             {
        #                 "id":"MONA-USDT",
        #                 "base_currency_id":"MONA",
        #                 "quote_currency_id":"USDT",
        #                 "min_price":"0.001",
        #                 "max_price":"9999999999999999",
        #                 "price_increment":"0.001",
        #                 "min_quantity":"0.0001",
        #                 "max_quantity":"9999999999999999",
        #                 "quantity_precision":4,
        #                 "min_cost":"1",
        #                 "max_cost":"9999999999999999",
        #                 "cost_precision":8,
        #                 "taker_fee_rate":"0.2",
        #                 "maker_fee_rate":"0.2",
        #                 "show_in_ui":true,
        #                 "closed":false
        #             },
        #         ]
        #     }
        #
        markets = self.safe_value(response, 'data', [])
        result = []
        for i in range(0, len(markets)):
            market = markets[i]
            id = self.safe_string(market, 'id')
            baseId = self.safe_string(market, 'base_currency_id')
            quoteId = self.safe_string(market, 'quote_currency_id')
            base = self.safe_currency_code(baseId)
            quote = self.safe_currency_code(quoteId)
            closed = self.safe_value(market, 'closed', False)
            takerFeeRate = self.safe_string(market, 'taker_fee_rate')
            taker = Precise.string_div(takerFeeRate, '100')
            makerFeeRate = self.safe_string(market, 'maker_fee_rate')
            maker = Precise.string_div(makerFeeRate, '100')
            result.append({
                'id': id,
                'symbol': base + '/' + quote,
                'base': base,
                'quote': quote,
                'settle': None,
                'baseId': baseId,
                'quoteId': quoteId,
                'settleId': None,
                'type': 'spot',
                'spot': True,
                'margin': False,
                'swap': False,
                'future': False,
                'option': False,
                'active': not closed,
                'contract': False,
                'linear': None,
                'inverse': None,
                'taker': self.parse_number(taker),
                'maker': self.parse_number(maker),
                'contractSize': None,
                'expiry': None,
                'expiryDatetime': None,
                'strike': None,
                'optionType': None,
                'precision': {
                    'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'quantity_precision'))),
                    'price': self.safe_number(market, 'price_increment'),
                    'cost': self.parse_number(self.parse_precision(self.safe_string(market, 'cost_precision'))),
                },
                'limits': {
                    'leverage': {
                        'min': None,
                        'max': None,
                    },
                    'amount': {
                        'min': self.safe_number(market, 'min_quantity'),
                        'max': self.safe_number(market, 'max_quantity'),
                    },
                    'price': {
                        'min': self.safe_number(market, 'min_price'),
                        'max': self.safe_number(market, 'max_price'),
                    },
                    'cost': {
                        'min': self.safe_number(market, 'min_cost'),
                        'max': self.safe_number(market, 'max_cost'),
                    },
                },
                'info': market,
            })
        return result

    async def fetch_currencies(self, params={}):
        """
        fetches all available currencies on an exchange
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: an associative dictionary of currencies
        """
        response = await self.publicGetCurrencyWithPlatform(params)
        #
        #     {
        #         "data":[
        #             {
        #                 "id":"USDT",
        #                 "display_name":{"ko-kr":"테더","en-us":"Tether"},
        #                 "show_in_ui":true,
        #                 "platform":[
        #                     {
        #                         "id":"ETH",
        #                         "priority":1,
        #                         "deposit":true,
        #                         "withdrawal":true,
        #                         "currency_id":"USDT",
        #                         "precision":6,
        #                         "min_confirmation_count":15,
        #                         "require_destination_tag":false,
        #                         "display_name":{"name":{"ko-kr":"ERC-20","en-us":"ERC-20"}},
        #                         "min_deposit_amount":"0",
        #                         "min_withdrawal_amount":"1",
        #                         "withdrawal_fee":[
        #                             {"amount":"0.01","priority":2,"currency_id":"ETH"},
        #                             {"amount":"1.5","priority":1,"currency_id":"USDT"},
        #                         ],
        #                         "deposit_fee":{},
        #                         "suspended_reason":"",
        #                         "deposit_suspended":false,
        #                         "withdrawal_suspended":false
        #                     },
        #                     {
        #                         "id":"OMNI",
        #                         "priority":2,
        #                         "deposit":true,
        #                         "withdrawal":true,
        #                         "currency_id":"USDT",
        #                         "precision":6,
        #                         "min_confirmation_count":3,
        #                         "require_destination_tag":false,
        #                         "display_name":{"name":{"ko-kr":"OMNI","en-us":"OMNI"}},
        #                         "min_deposit_amount":"0",
        #                         "min_withdrawal_amount":"5",
        #                         "withdrawal_fee":[{"amount":"5","priority":1,"currency_id":"USDT"}],
        #                         "deposit_fee":{},
        #                         "suspended_reason":"wallet_maintenance",
        #                         "deposit_suspended":false,
        #                         "withdrawal_suspended":false
        #                     }
        #                 ],
        #                 "stakeable":false,
        #                 "unstakeable":false,
        #                 "auto_stake":false,
        #                 "auto_stake_amount":"0"
        #             }
        #         ]
        #     }
        #
        currencies = self.safe_value(response, 'data', [])
        result = {}
        for i in range(0, len(currencies)):
            currency = currencies[i]
            id = self.safe_string(currency, 'id')
            code = self.safe_currency_code(id)
            displayName = self.safe_value(currency, 'display_name')
            name = self.safe_string(displayName, 'en-us')
            platforms = self.safe_value(currency, 'platform', [])
            platformsByPriority = self.sort_by(platforms, 'priority')
            platform = self.safe_value(platformsByPriority, 0, {})
            depositSuspended = self.safe_value(platform, 'deposit_suspended')
            withdrawalSuspended = self.safe_value(platform, 'withdrawal_suspended')
            deposit = not depositSuspended
            withdraw = not withdrawalSuspended
            active = deposit and withdraw
            withdrawalFees = self.safe_value(platform, 'withdrawal_fee', {})
            fees = []
            # sometimes the withdrawal fee is an empty object
            # [{'amount': '0.015', 'priority': 1, 'currency_id': 'ETH'}, {}]
            for j in range(0, len(withdrawalFees)):
                withdrawalFee = withdrawalFees[j]
                amount = self.safe_number(withdrawalFee, 'amount')
                priority = self.safe_integer(withdrawalFee, 'priority')
                if (amount is not None) and (priority is not None):
                    fees.append(withdrawalFee)
            withdrawalFeesByPriority = self.sort_by(fees, 'priority')
            withdrawalFee = self.safe_value(withdrawalFeesByPriority, 0, {})
            fee = self.safe_number(withdrawalFee, 'amount')
            result[code] = {
                'id': id,
                'code': code,
                'info': currency,
                'name': name,
                'active': active,
                'deposit': deposit,
                'withdraw': withdraw,
                'fee': fee,
                'precision': self.parse_number(self.parse_precision(self.safe_string(platform, 'precision'))),
                'limits': {
                    'amount': {
                        'min': None,
                        'max': None,
                    },
                    'deposit': {
                        'min': self.safe_number(platform, 'min_deposit_amount'),
                        'max': None,
                    },
                    'withdraw': {
                        'min': self.safe_number(platform, 'min_withdrawal_amount'),
                        'max': None,
                    },
                },
            }
        return result

    def parse_balance(self, response):
        result = {
            'info': response,
            'timestamp': None,
            'datetime': None,
        }
        data = self.safe_value(response, 'data', [])
        for i in range(0, len(data)):
            balance = data[i]
            currencyId = self.safe_string(balance, 'currency_id')
            code = self.safe_currency_code(currencyId)
            account = self.account()
            account['total'] = self.safe_string(balance, 'total')
            account['free'] = self.safe_string(balance, 'available')
            result[code] = account
        return self.safe_balance(result)

    async def fetch_balance(self, params={}):
        """
        query for balance and get the amount of funds available for trading or funds locked in orders
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
        """
        await self.load_markets()
        response = await self.privateGetBalance(params)
        #
        #     {
        #         data: [
        #             {
        #                 "currency_id":"XRP",
        #                 "total":"100",
        #                 "available":"0",
        #             }
        #         ]
        #     }
        #
        return self.parse_balance(response)

    async def fetch_order_book(self, symbol, limit=None, params={}):
        """
        fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
        :param str symbol: unified symbol of the market to fetch the order book for
        :param int|None limit: the maximum amount of order book entries to return
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/en/latest/manual.html#order-book-structure>` indexed by market symbols
        """
        await self.load_markets()
        market = self.market(symbol)
        request = {
            'market_id': market['id'],
        }
        response = await self.publicGetOrderBook(self.extend(request, params))
        #
        #     {
        #         data: [
        #             {side: 'buy', price: '0.000031', quantity: '10'},
        #             {side: 'buy', price: '0.00356007', quantity: '4.92156877'},
        #             {side: 'sell', price: '0.1857', quantity: '0.17'},
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        dataBySide = self.group_by(data, 'side')
        return self.parse_order_book(dataBySide, market['symbol'], None, 'buy', 'sell', 'price', 'quantity')

    async def fetch_tickers(self, symbols=None, params={}):
        """
        fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
        :param [str]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: an array of `ticker structures <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
        """
        await self.load_markets()
        request = {}
        if symbols is not None:
            marketIds = self.market_ids(symbols)
            request['market_ids'] = ','.join(marketIds)
        response = await self.publicGetTicker(self.extend(request, params))
        #
        #     {
        #         "data":[
        #             {
        #                 "last":"0.022902",
        #                 "low":"0.021693",
        #                 "high":"0.024093",
        #                 "change":"-0.000047",
        #                 "base_volume":"15681.986",
        #                 "quote_volume":"360.514403624",
        #                 "market_id":"ETH-BTC",
        #                 "time":"2020-04-12T18:43:38.000Z"
        #             }
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        return self.parse_tickers(data, symbols)

    async def fetch_ticker(self, symbol, params={}):
        """
        fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
        :param str symbol: unified symbol of the market to fetch the ticker for
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
        """
        await self.load_markets()
        market = self.market(symbol)
        request = {
            'market_ids': market['id'],
        }
        response = await self.publicGetTicker(self.extend(request, params))
        #
        #     {
        #         "data":[
        #             {
        #                 "last":"0.022902",
        #                 "low":"0.021693",
        #                 "high":"0.024093",
        #                 "change":"-0.000047",
        #                 "base_volume":"15681.986",
        #                 "quote_volume":"360.514403624",
        #                 "market_id":"ETH-BTC",
        #                 "time":"2020-04-12T18:43:38.000Z"
        #             }
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        ticker = self.safe_value(data, 0)
        if ticker is None:
            raise BadResponse(self.id + ' fetchTicker() returned an empty response')
        return self.parse_ticker(ticker, market)

    def parse_ticker(self, ticker, market=None):
        #
        #     {
        #         "last":"0.022902",
        #         "low":"0.021693",
        #         "high":"0.024093",
        #         "change":"-0.000047",
        #         "base_volume":"15681.986",
        #         "quote_volume":"360.514403624",
        #         "market_id":"ETH-BTC",
        #         "time":"2020-04-12T18:43:38.000Z"
        #     }
        #
        timestamp = self.parse8601(self.safe_string(ticker, 'time'))
        marketId = self.safe_string(ticker, 'market_id')
        symbol = self.safe_symbol(marketId, market, '-')
        close = self.safe_string(ticker, 'last')
        change = self.safe_string(ticker, 'change')
        baseVolume = self.safe_string(ticker, 'base_volume')
        quoteVolume = self.safe_string(ticker, 'quote_volume')
        return self.safe_ticker({
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'high': self.safe_string(ticker, 'high'),
            'low': self.safe_string(ticker, 'low'),
            'bid': None,
            'bidVolume': None,
            'ask': None,
            'askVolume': None,
            'vwap': None,
            'open': None,
            'close': close,
            'last': close,
            'previousClose': None,  # previous day close
            'change': change,
            'percentage': None,
            'average': None,
            'baseVolume': baseVolume,
            'quoteVolume': quoteVolume,
            'info': ticker,
        }, market)

    async def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}):
        """
        fetch all trades made by the user
        :param str|None symbol: unified market symbol
        :param int|None since: the earliest time in ms to fetch trades for
        :param int|None limit: the maximum number of trades structures to retrieve
        :param dict params: extra parameters specific to the probit api endpoint
        :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html#trade-structure>`
        """
        await self.load_markets()
        market = None
        request = {
            'limit': 100,
            'start_time': self.iso8601(0),
            'end_time': self.iso8601(self.milliseconds()),
        }
        if symbol is not None:
            market = self.market(symbol)
            request['market_id'] = market['id']
        if since is not None:
            request['start_time'] = self.iso8601(since)
        if limit is not None:
            request['limit'] = limit
        response = await self.privateGetTradeHistory(self.extend(request, params))
        #
        #     {
        #         data: [
        #             {
        #                 "id":"BTC-USDT:183566",
        #                 "order_id":"17209376",
        #                 "side":"sell",
        #                 "fee_amount":"0.657396569175",
        #                 "fee_currency_id":"USDT",
        #                 "status":"settled",
        #                 "price":"6573.96569175",
        #                 "quantity":"0.1",
        #                 "cost":"657.396569175",
        #                 "time":"2018-08-10T06:06:46.000Z",
        #                 "market_id":"BTC-USDT"
        #             }
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        return self.parse_trades(data, market, since, limit)

    async def fetch_trades(self, symbol, since=None, limit=None, params={}):
        """
        get the list of most recent trades for a particular symbol
        :param str symbol: unified symbol of the market to fetch trades for
        :param int|None since: timestamp in ms of the earliest trade to fetch
        :param int|None limit: the maximum amount of trades to fetch
        :param dict params: extra parameters specific to the probit api endpoint
        :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
        """
        await self.load_markets()
        market = self.market(symbol)
        request = {
            'market_id': market['id'],
            'limit': 100,
            'start_time': '1970-01-01T00:00:00.000Z',
            'end_time': self.iso8601(self.milliseconds()),
        }
        if since is not None:
            request['start_time'] = self.iso8601(since)
        if limit is not None:
            request['limit'] = limit
        response = await self.publicGetTrade(self.extend(request, params))
        #
        #     {
        #         "data":[
        #             {
        #                 "id":"ETH-BTC:3331886",
        #                 "price":"0.022981",
        #                 "quantity":"12.337",
        #                 "time":"2020-04-12T20:55:42.371Z",
        #                 "side":"sell",
        #                 "tick_direction":"down"
        #             },
        #             {
        #                 "id":"ETH-BTC:3331885",
        #                 "price":"0.022982",
        #                 "quantity":"6.472",
        #                 "time":"2020-04-12T20:55:39.652Z",
        #                 "side":"sell",
        #                 "tick_direction":"down"
        #             }
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        return self.parse_trades(data, market, since, limit)

    def parse_trade(self, trade, market=None):
        #
        # fetchTrades(public)
        #
        #     {
        #         "id":"ETH-BTC:3331886",
        #         "price":"0.022981",
        #         "quantity":"12.337",
        #         "time":"2020-04-12T20:55:42.371Z",
        #         "side":"sell",
        #         "tick_direction":"down"
        #     }
        #
        # fetchMyTrades(private)
        #
        #     {
        #         "id":"BTC-USDT:183566",
        #         "order_id":"17209376",
        #         "side":"sell",
        #         "fee_amount":"0.657396569175",
        #         "fee_currency_id":"USDT",
        #         "status":"settled",
        #         "price":"6573.96569175",
        #         "quantity":"0.1",
        #         "cost":"657.396569175",
        #         "time":"2018-08-10T06:06:46.000Z",
        #         "market_id":"BTC-USDT"
        #     }
        #
        timestamp = self.parse8601(self.safe_string(trade, 'time'))
        id = self.safe_string(trade, 'id')
        marketId = None
        if id is not None:
            parts = id.split(':')
            marketId = self.safe_string(parts, 0)
        marketId = self.safe_string(trade, 'market_id', marketId)
        symbol = self.safe_symbol(marketId, market, '-')
        side = self.safe_string(trade, 'side')
        priceString = self.safe_string(trade, 'price')
        amountString = self.safe_string(trade, 'quantity')
        orderId = self.safe_string(trade, 'order_id')
        feeCostString = self.safe_string(trade, 'fee_amount')
        fee = None
        if feeCostString is not None:
            feeCurrencyId = self.safe_string(trade, 'fee_currency_id')
            feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
            fee = {
                'cost': feeCostString,
                'currency': feeCurrencyCode,
            }
        return self.safe_trade({
            'id': id,
            'info': trade,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'symbol': symbol,
            'order': orderId,
            'type': None,
            'side': side,
            'takerOrMaker': None,
            'price': priceString,
            'amount': amountString,
            'cost': None,
            'fee': fee,
        }, market)

    async def fetch_time(self, params={}):
        """
        fetches the current integer timestamp in milliseconds from the exchange server
        :param dict params: extra parameters specific to the probit api endpoint
        :returns int: the current integer timestamp in milliseconds from the exchange server
        """
        response = await self.publicGetTime(params)
        #
        #     {"data":"2020-04-12T18:54:25.390Z"}
        #
        timestamp = self.parse8601(self.safe_string(response, 'data'))
        return timestamp

    def normalize_ohlcv_timestamp(self, timestamp, timeframe, after=False):
        duration = self.parse_timeframe(timeframe)
        if timeframe == '1M':
            iso8601 = self.iso8601(timestamp)
            parts = iso8601.split('-')
            year = self.safe_string(parts, 0)
            month = self.safe_integer(parts, 1)
            if after:
                month = self.sum(month, 1)
            if month < 10:
                month = '0' + str(month)
            else:
                month = str(month)
            return year + '-' + month + '-01T00:00:00.000Z'
        elif timeframe == '1w':
            timestamp = int(timestamp / 1000)
            firstSunday = 259200  # 1970-01-04T00:00:00.000Z
            difference = timestamp - firstSunday
            numWeeks = int(math.floor(difference / duration))
            previousSunday = self.sum(firstSunday, numWeeks * duration)
            if after:
                previousSunday = self.sum(previousSunday, duration)
            return self.iso8601(previousSunday * 1000)
        else:
            timestamp = int(timestamp / 1000)
            timestamp = duration * int(timestamp / duration)
            if after:
                timestamp = self.sum(timestamp, duration)
            return self.iso8601(timestamp * 1000)

    async def fetch_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
        """
        fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
        :param str symbol: unified symbol of the market to fetch OHLCV data for
        :param str timeframe: the length of time each candle represents
        :param int|None since: timestamp in ms of the earliest candle to fetch
        :param int|None limit: the maximum amount of candles to fetch
        :param dict params: extra parameters specific to the probit api endpoint
        :returns [[int]]: A list of candles ordered as timestamp, open, high, low, close, volume
        """
        await self.load_markets()
        market = self.market(symbol)
        interval = self.timeframes[timeframe]
        limit = 100 if (limit is None) else limit
        requestLimit = self.sum(limit, 1)
        requestLimit = min(1000, requestLimit)  # max 1000
        request = {
            'market_ids': market['id'],
            'interval': interval,
            'sort': 'asc',  # 'asc' will always include the start_time, 'desc' will always include end_time
            'limit': requestLimit,  # max 1000
        }
        now = self.milliseconds()
        duration = self.parse_timeframe(timeframe)
        startTime = since
        endTime = now
        if since is None:
            if limit is None:
                limit = requestLimit
            startTime = now - limit * duration * 1000
        else:
            if limit is None:
                endTime = now
            else:
                endTime = self.sum(since, self.sum(limit, 1) * duration * 1000)
        startTimeNormalized = self.normalize_ohlcv_timestamp(startTime, timeframe)
        endTimeNormalized = self.normalize_ohlcv_timestamp(endTime, timeframe, True)
        request['start_time'] = startTimeNormalized
        request['end_time'] = endTimeNormalized
        response = await self.publicGetCandle(self.extend(request, params))
        #
        #     {
        #         "data":[
        #             {
        #                 "market_id":"ETH-BTC",
        #                 "open":"0.02811",
        #                 "close":"0.02811",
        #                 "low":"0.02811",
        #                 "high":"0.02811",
        #                 "base_volume":"0.0005",
        #                 "quote_volume":"0.000014055",
        #                 "start_time":"2018-11-30T18:19:00.000Z",
        #                 "end_time":"2018-11-30T18:20:00.000Z"
        #             },
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        return self.parse_ohlcvs(data, market, timeframe, since, limit)

    def parse_ohlcv(self, ohlcv, market=None):
        #
        #     {
        #         "market_id":"ETH-BTC",
        #         "open":"0.02811",
        #         "close":"0.02811",
        #         "low":"0.02811",
        #         "high":"0.02811",
        #         "base_volume":"0.0005",
        #         "quote_volume":"0.000014055",
        #         "start_time":"2018-11-30T18:19:00.000Z",
        #         "end_time":"2018-11-30T18:20:00.000Z"
        #     }
        #
        return [
            self.parse8601(self.safe_string(ohlcv, 'start_time')),
            self.safe_number(ohlcv, 'open'),
            self.safe_number(ohlcv, 'high'),
            self.safe_number(ohlcv, 'low'),
            self.safe_number(ohlcv, 'close'),
            self.safe_number(ohlcv, 'base_volume'),
        ]

    async def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
        """
        fetch all unfilled currently open orders
        :param str|None symbol: unified market symbol
        :param int|None since: the earliest time in ms to fetch open orders for
        :param int|None limit: the maximum number of  open orders structures to retrieve
        :param dict params: extra parameters specific to the probit api endpoint
        :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
        """
        await self.load_markets()
        since = self.parse8601(since)
        request = {}
        market = None
        if symbol is not None:
            market = self.market(symbol)
            request['market_id'] = market['id']
        response = await self.privateGetOpenOrder(self.extend(request, params))
        data = self.safe_value(response, 'data')
        return self.parse_orders(data, market, since, limit)

    async def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
        """
        fetches information on multiple closed orders made by the user
        :param str|None symbol: unified market symbol of the market orders were made in
        :param int|None since: the earliest time in ms to fetch orders for
        :param int|None limit: the maximum number of  orde structures to retrieve
        :param dict params: extra parameters specific to the probit api endpoint
        :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
        """
        await self.load_markets()
        request = {
            'start_time': self.iso8601(0),
            'end_time': self.iso8601(self.milliseconds()),
            'limit': 100,
        }
        market = None
        if symbol is not None:
            market = self.market(symbol)
            request['market_id'] = market['id']
        if since:
            request['start_time'] = self.iso8601(since)
        if limit:
            request['limit'] = limit
        response = await self.privateGetOrderHistory(self.extend(request, params))
        data = self.safe_value(response, 'data')
        return self.parse_orders(data, market, since, limit)

    async def fetch_order(self, id, symbol=None, params={}):
        """
        fetches information on an order made by the user
        :param str symbol: unified symbol of the market the order was made in
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: An `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
        """
        if symbol is None:
            raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol argument')
        await self.load_markets()
        market = self.market(symbol)
        request = {
            'market_id': market['id'],
        }
        clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_id')
        if clientOrderId is not None:
            request['client_order_id'] = clientOrderId
        else:
            request['order_id'] = id
        query = self.omit(params, ['clientOrderId', 'client_order_id'])
        response = await self.privateGetOrder(self.extend(request, query))
        data = self.safe_value(response, 'data', [])
        order = self.safe_value(data, 0)
        return self.parse_order(order, market)

    def parse_order_status(self, status):
        statuses = {
            'open': 'open',
            'cancelled': 'canceled',
            'filled': 'closed',
        }
        return self.safe_string(statuses, status, status)

    def parse_order(self, order, market=None):
        #
        #     {
        #         id: string,
        #         user_id: string,
        #         market_id: string,
        #         type: 'orderType',
        #         side: 'side',
        #         quantity: string,
        #         limit_price: string,
        #         time_in_force: 'timeInForce',
        #         filled_cost: string,
        #         filled_quantity: string,
        #         open_quantity: string,
        #         cancelled_quantity: string,
        #         status: 'orderStatus',
        #         time: 'date',
        #         client_order_id: string,
        #     }
        #
        status = self.parse_order_status(self.safe_string(order, 'status'))
        id = self.safe_string(order, 'id')
        type = self.safe_string(order, 'type')
        side = self.safe_string(order, 'side')
        marketId = self.safe_string(order, 'market_id')
        symbol = self.safe_symbol(marketId, market, '-')
        timestamp = self.parse8601(self.safe_string(order, 'time'))
        price = self.safe_string(order, 'limit_price')
        filled = self.safe_string(order, 'filled_quantity')
        remaining = self.safe_string(order, 'open_quantity')
        canceledAmount = self.safe_string(order, 'cancelled_quantity')
        if canceledAmount is not None:
            remaining = Precise.string_add(remaining, canceledAmount)
        amount = self.safe_string(order, 'quantity', Precise.string_add(filled, remaining))
        cost = self.safe_string_2(order, 'filled_cost', 'cost')
        if type == 'market':
            price = None
        clientOrderId = self.safe_string(order, 'client_order_id')
        timeInForce = self.safe_string_upper(order, 'time_in_force')
        return self.safe_order({
            'id': id,
            'info': order,
            'clientOrderId': clientOrderId,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'lastTradeTimestamp': None,
            'symbol': symbol,
            'type': type,
            'timeInForce': timeInForce,
            'side': side,
            'status': status,
            'price': price,
            'stopPrice': None,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'average': None,
            'cost': cost,
            'fee': None,
            'trades': None,
        }, market)

    def cost_to_precision(self, symbol, cost):
        return self.decimal_to_precision(cost, TRUNCATE, self.markets[symbol]['precision']['cost'], self.precisionMode)

    async def create_order(self, symbol, type, side, amount, price=None, params={}):
        """
        create a trade order
        :param str symbol: unified symbol of the market to create an order in
        :param str type: 'market' or 'limit'
        :param str side: 'buy' or 'sell'
        :param float amount: how much of currency you want to trade in units of base currency
        :param float|None price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
        """
        await self.load_markets()
        market = self.market(symbol)
        options = self.safe_value(self.options, 'timeInForce')
        defaultTimeInForce = self.safe_value(options, type)
        timeInForce = self.safe_string_2(params, 'timeInForce', 'time_in_force', defaultTimeInForce)
        request = {
            'market_id': market['id'],
            'type': type,
            'side': side,
            'time_in_force': timeInForce,
        }
        clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_id')
        if clientOrderId is not None:
            request['client_order_id'] = clientOrderId
        costToPrecision = None
        if type == 'limit':
            request['limit_price'] = self.price_to_precision(symbol, price)
            request['quantity'] = self.amount_to_precision(symbol, amount)
        elif type == 'market':
            # for market buy it requires the amount of quote currency to spend
            if side == 'buy':
                cost = self.safe_number(params, 'cost')
                createMarketBuyOrderRequiresPrice = self.safe_value(self.options, 'createMarketBuyOrderRequiresPrice', True)
                if createMarketBuyOrderRequiresPrice:
                    if price is not None:
                        if cost is None:
                            cost = amount * price
                    elif cost is None:
                        raise InvalidOrder(self.id + " createOrder() requires the price argument for market buy orders to calculate total order cost(amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = False and supply the total cost value in the 'amount' argument or in the 'cost' extra parameter(the exchange-specific behaviour)")
                else:
                    cost = amount if (cost is None) else cost
                costToPrecision = self.cost_to_precision(symbol, cost)
                request['cost'] = costToPrecision
            else:
                request['quantity'] = self.amount_to_precision(symbol, amount)
        query = self.omit(params, ['timeInForce', 'time_in_force', 'clientOrderId', 'client_order_id'])
        response = await self.privatePostNewOrder(self.extend(request, query))
        #
        #     {
        #         data: {
        #             id: string,
        #             user_id: string,
        #             market_id: string,
        #             type: 'orderType',
        #             side: 'side',
        #             quantity: string,
        #             limit_price: string,
        #             time_in_force: 'timeInForce',
        #             filled_cost: string,
        #             filled_quantity: string,
        #             open_quantity: string,
        #             cancelled_quantity: string,
        #             status: 'orderStatus',
        #             time: 'date',
        #             client_order_id: string,
        #         }
        #     }
        #
        data = self.safe_value(response, 'data')
        order = self.parse_order(data, market)
        # a workaround for incorrect huge amounts
        # returned by the exchange on market buys
        if (type == 'market') and (side == 'buy'):
            order['amount'] = None
            order['cost'] = self.parse_number(costToPrecision)
            order['remaining'] = None
        return order

    async def cancel_order(self, id, symbol=None, params={}):
        """
        cancels an open order
        :param str id: order id
        :param str symbol: unified symbol of the market the order was made in
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: An `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
        """
        if symbol is None:
            raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
        await self.load_markets()
        market = self.market(symbol)
        request = {
            'market_id': market['id'],
            'order_id': id,
        }
        response = await self.privatePostCancelOrder(self.extend(request, params))
        data = self.safe_value(response, 'data')
        return self.parse_order(data)

    def parse_deposit_address(self, depositAddress, currency=None):
        address = self.safe_string(depositAddress, 'address')
        tag = self.safe_string(depositAddress, 'destination_tag')
        currencyId = self.safe_string(depositAddress, 'currency_id')
        currency = self.safe_currency(currencyId, currency)
        code = currency['code']
        network = self.safe_string(depositAddress, 'platform_id')
        self.check_address(address)
        return {
            'currency': code,
            'address': address,
            'tag': tag,
            'network': network,
            'info': depositAddress,
        }

    async def fetch_deposit_address(self, code, params={}):
        """
        fetch the deposit address for a currency associated with self account
        :param str code: unified currency code
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: an `address structure <https://docs.ccxt.com/en/latest/manual.html#address-structure>`
        """
        await self.load_markets()
        currency = self.currency(code)
        request = {
            'currency_id': currency['id'],
            # 'platform_id': 'TRON',(undocumented)
        }
        networks = self.safe_value(self.options, 'networks', {})
        network = self.safe_string_upper(params, 'network')  # self line allows the user to specify either ERC20 or ETH
        network = self.safe_string(networks, network, network)  # handle ERC20>ETH alias
        if network is not None:
            request['platform_id'] = network
            params = self.omit(params, 'platform_id')
        response = await self.privateGetDepositAddress(self.extend(request, params))
        #
        # without 'platform_id'
        #     {
        #         "data":[
        #             {
        #                 "currency_id":"ETH",
        #                 "address":"0x12e2caf3c4051ba1146e612f532901a423a9898a",
        #                 "destination_tag":null
        #             }
        #         ]
        #     }
        #
        # with 'platform_id'
        #     {
        #         "data":[
        #             {
        #                 "platform_id":"TRON",
        #                 "address":"TDQLMxBTa6MzuoZ6deSGZkqET3Ek8v7uC6",
        #                 "destination_tag":null
        #             }
        #         ]
        #     }
        #
        data = self.safe_value(response, 'data', [])
        firstAddress = self.safe_value(data, 0)
        if firstAddress is None:
            raise InvalidAddress(self.id + ' fetchDepositAddress() returned an empty response')
        return self.parse_deposit_address(firstAddress, currency)

    async def fetch_deposit_addresses(self, codes=None, params={}):
        """
        fetch deposit addresses for multiple currencies and chain types
        :param [str]|None codes: list of unified currency codes, default is None
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: a list of `address structures <https://docs.ccxt.com/en/latest/manual.html#address-structure>`
        """
        await self.load_markets()
        request = {}
        if codes:
            currencyIds = []
            for i in range(0, len(codes)):
                currency = self.currency(codes[i])
                currencyIds.append(currency['id'])
            request['currency_id'] = ','.join(codes)
        response = await self.privateGetDepositAddress(self.extend(request, params))
        data = self.safe_value(response, 'data', [])
        return self.parse_deposit_addresses(data)

    async def withdraw(self, code, amount, address, tag=None, params={}):
        """
        make a withdrawal
        :param str code: unified currency code
        :param float amount: the amount to withdraw
        :param str address: the address to withdraw to
        :param str|None tag:
        :param dict params: extra parameters specific to the probit api endpoint
        :returns dict: a `transaction structure <https://docs.ccxt.com/en/latest/manual.html#transaction-structure>`
        """
        tag, params = self.handle_withdraw_tag_and_params(tag, params)
        # In order to use self method
        # you need to allow API withdrawal from the API Settings Page, and
        # and register the list of withdrawal addresses and destination tags on the API Settings page
        # you can only withdraw to the registered addresses using the API
        self.check_address(address)
        await self.load_markets()
        currency = self.currency(code)
        if tag is None:
            tag = ''
        request = {
            'currency_id': currency['id'],
            # 'platform_id': 'ETH',  # if omitted it will use the default platform for the currency
            'address': address,
            'destination_tag': tag,
            'amount': self.number_to_string(amount),
            # which currency to pay the withdrawal fees
            # only applicable for currencies that accepts multiple withdrawal fee options
            # 'fee_currency_id': 'ETH',  # if omitted it will use the default fee policy for each currency
            # whether the amount field includes fees
            # 'include_fee': False,  # makes sense only when fee_currency_id is equal to currency_id
        }
        networks = self.safe_value(self.options, 'networks', {})
        network = self.safe_string_upper(params, 'network')  # self line allows the user to specify either ERC20 or ETH
        network = self.safe_string(networks, network, network)  # handle ERC20>ETH alias
        if network is not None:
            request['platform_id'] = network
            params = self.omit(params, 'network')
        response = await self.privatePostWithdrawal(self.extend(request, params))
        data = self.safe_value(response, 'data')
        return self.parse_transaction(data, currency)

    def parse_transaction(self, transaction, currency=None):
        id = self.safe_string(transaction, 'id')
        amount = self.safe_number(transaction, 'amount')
        address = self.safe_string(transaction, 'address')
        tag = self.safe_string(transaction, 'destination_tag')
        txid = self.safe_string(transaction, 'hash')
        timestamp = self.parse8601(self.safe_string(transaction, 'time'))
        type = self.safe_string(transaction, 'type')
        currencyId = self.safe_string(transaction, 'currency_id')
        code = self.safe_currency_code(currencyId)
        status = self.parse_transaction_status(self.safe_string(transaction, 'status'))
        feeCost = self.safe_number(transaction, 'fee')
        fee = None
        if feeCost is not None and feeCost != 0:
            fee = {
                'currency': code,
                'cost': feeCost,
            }
        return {
            'id': id,
            'currency': code,
            'amount': amount,
            'network': None,
            'addressFrom': None,
            'address': address,
            'addressTo': address,
            'tagFrom': None,
            'tag': tag,
            'tagTo': tag,
            'status': status,
            'type': type,
            'txid': txid,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'updated': None,
            'fee': fee,
            'info': transaction,
        }

    def parse_transaction_status(self, status):
        statuses = {
            'requested': 'pending',
            'pending': 'pending',
            'confirming': 'pending',
            'confirmed': 'pending',
            'applying': 'pending',
            'done': 'ok',
            'cancelled': 'canceled',
            'cancelling': 'canceled',
        }
        return self.safe_string(statuses, status, status)

    def nonce(self):
        return self.milliseconds()

    def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
        url = self.urls['api'][api] + '/'
        query = self.omit(params, self.extract_params(path))
        if api == 'accounts':
            self.check_required_credentials()
            url += self.implode_params(path, params)
            auth = self.apiKey + ':' + self.secret
            auth64 = self.string_to_base64(auth)
            headers = {
                'Authorization': 'Basic ' + self.decode(auth64),
                'Content-Type': 'application/json',
            }
            if query:
                body = self.json(query)
        else:
            url += self.version + '/'
            if api == 'public':
                url += self.implode_params(path, params)
                if query:
                    url += '?' + self.urlencode(query)
            elif api == 'private':
                now = self.milliseconds()
                self.check_required_credentials()
                expires = self.safe_integer(self.options, 'expires')
                if (expires is None) or (expires < now):
                    raise AuthenticationError(self.id + ' access token expired, call signIn() method')
                accessToken = self.safe_string(self.options, 'accessToken')
                headers = {
                    'Authorization': 'Bearer ' + accessToken,
                }
                url += self.implode_params(path, params)
                if method == 'GET':
                    if query:
                        url += '?' + self.urlencode(query)
                elif query:
                    body = self.json(query)
                    headers['Content-Type'] = 'application/json'
        return {'url': url, 'method': method, 'body': body, 'headers': headers}

    async def sign_in(self, params={}):
        """
        sign in, must be called prior to using other authenticated methods
        :param dict params: extra parameters specific to the probit api endpoint
        :returns: response from exchange
        """
        self.check_required_credentials()
        request = {
            'grant_type': 'client_credentials',  # the only supported value
        }
        response = await self.accountsPostToken(self.extend(request, params))
        #
        #     {
        #         access_token: '0ttDv/2hTTn3bLi8GP1gKaneiEQ6+0hOBenPrxNQt2s=',
        #         token_type: 'bearer',
        #         expires_in: 900
        #     }
        #
        expiresIn = self.safe_integer(response, 'expires_in')
        accessToken = self.safe_string(response, 'access_token')
        self.options['accessToken'] = accessToken
        self.options['expires'] = self.sum(self.milliseconds(), expiresIn * 1000)
        return response

    def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
        if response is None:
            return  # fallback to default error handler
        if 'errorCode' in response:
            errorCode = self.safe_string(response, 'errorCode')
            message = self.safe_string(response, 'message')
            if errorCode is not None:
                feedback = self.id + ' ' + body
                self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
                self.throw_broadly_matched_exception(self.exceptions['exact'], errorCode, feedback)
                raise ExchangeError(feedback)


text:
Evening Edition is an Open Thread
From Yahoo News Top Stories
1 Eight killed as Syria quells massive protests
Syrian security forces killed at least eight civilians on Friday as more than 1.2 million protesters swarmed cities in the north and east to protest against President Bashar al-Assad's rule, activists said.
Activists had called for Friday's demonstrations on Facebook group The Syrian Revolution 2011, a driving force behind more than four months of anti-regime protests, to show support for the flashpoint city of Homs.
More than 50 people have been killed since Saturday in central Homs, activists have said, accusing the regime of sowing sectarian strife among the city's Christian and Muslim inhabitants.
Tags: Evening Edition, News
Congressional Game of Chicken: To The Right of the Right
The rumors and leaks are really coming fast and furious and it looks like Obama ready to sell out any Democratic principles that were left. From Jon Walker at FDL Action:
Reports circulate that President Obama may agree to a massive all cuts debt ceiling package, creating a lot of anger and a sense of betrayal because Obama will fold on his demand that any debt ceiling package contain at least a small amount of new revenue. I can't understand the amount of anger though because from the moment Obama made this his bizarre line in the sand, chances were he would break his word. Demanding what was basically a symbolic level of loophole closing is such a small and silly hill of sand to fight over, and there was no way Obama was actually going to die on it.
Even the idea that the only thing Obama would go to the mat on here is a symbolic tax increase is almost comical, given his history of not fighting to raise taxes. Obama promised to let the Bush tax cuts for the wealthy expire, but when it came down do it, he let it slide. In fact, the deal he made to extend them actually included more tax cuts. And now reports are Obama is searching for a way to avoid having this tax fight again in 2012.
It is bizarre to have Obama basically saying "I will "give in" on Social Security cuts but only to achieve my goal of changing how corporations deduct the purchase of a jet." It just defies credulity to think a small amount of new revenue was ever really his line in the sand.
I'm not surprised Obama broke his word to his supporters again. But I am surprised he would choose to stick his flag on such a small pile of sand knowing he'll give it up in the end. I'm also surprised anyone takes Obama's stances seriously anymore.
It gets worse:
That framework includes spending cuts, plus entitlement changes and increased tax revenues (as part of a tax overhaul) that would come later. But there are two big hurdles left: 1) on the substance, and 2) on soothing egos. On the substance, the most contentious matter is how you "trigger" the provisions to guarantee completing tax and entitlement reform. The Democrats have offered a trigger of letting the Bush tax cuts expire for those making $250,000 or more. Republicans, meanwhile, have countered that if those Bush tax cuts are hanging in the balance, they'd offer a trigger of their own to ensure Dem action: scaling back Obama's health-care law and eliminating the mandate. Bottom line: If entitlement and tax reform is completed on time, then the Bush tax cuts and the health-care law don't get touched. Also on the substance front, we're hearing that there's yet to be an agreement on the scope of the entitlement changes. And never mind the actual individual cuts on the discretionary side. Details, details. The K Street Army is gathering forces if this deal goes through because we haven't seen this much change in the way government spends and gathers money in a generation.
The rumors of this far right wing deal by Obama and Boehner was leaked just as the Senate Democratic leadership was sitting down with White House budget director Jacob J. Lew, setting off a very contentious meeting. After leaving the meeting Lew said that he "not aware of a deal". Senate Majority leader Harry Reid (D-NV) stated, "There has to be a balance. There has to be some revenue and cuts. My caucus agrees with that. I hope that the president sticks with that." Sen Diane Feinstein bluntly said "no" when asked if she and the White House were on the "same page".
Obama is even losing the Blue Dogs. This deal to make drastic cuts in our safety net in exchange for a promise of negotiating tax increases later just isn't working for either House or Senate Democrats and will sink Obama's reelection.
At a town hall meeting in College Park, MD, President Obama said he would sign on any deal to raise the debt ceiling. It's a wonder that he has any supporters left.
Tags: Barack Obama, Congressional Game of Chicken, Debt Ceiling, Federal Budget, TMC Politics. Politics
Paul Krugman: The Lesser Depression
These are interesting times – and I mean that in the worst way. Right now we're looking at not one but two looming crises, either of which could produce a global disaster. In the United States, right-wing fanatics in Congress may block a necessary rise in the debt ceiling, potentially wreaking havoc in world financial markets. Meanwhile, if the plan just agreed to by European heads of state fails to calm markets, we could see falling dominoes all across southern Europe – which would also wreak havoc in world financial markets.
We can only hope that the politicians huddled in Washington and Brussels succeed in averting these threats. But here's the thing: Even if we manage to avoid immediate catastrophe, the deals being struck on both sides of the Atlantic are almost guaranteed to make the broader economic slump worse.
Glenn Greenwald: Barack Obama is Gutting the Core Principles of the Democratic Party
The president's attacks on America's social safety net are destroying the soul of the Democratic party's platform
In 2005, American liberals achieved one of their most significant political victories of the last decade. It occurred with the resounding rejection of George W Bush's campaign to privatise social security. . . . . .
But in 2009, clear signs emerged that President Obama was eager to achieve what his right-predecessor could not: cut social security. Before he was even inaugurated, Obama echoed the right's manipulative rhetorical tactic: that (along with Medicare) the programme was in crisis and producing "red ink as far as the eye can see." President-elect Obama thus vowed that these crown jewels of his party since the New Deal would be, as Politico reported, a "central part" of his efforts to reduce the deficit.
The next month, his top economic adviser, the Wall Street-friendly Larry Summers, also vowed specific benefit cuts to Time magazine. He then stacked his "deficit commission" with long-time advocates of social security cuts.
Many progressives, ebullient over the election of a Democratic president, chose to ignore these preliminary signs, unwilling to believe that their own party's leader was as devoted as he claimed to attacking the social safety net. But some were more realistic. The popular liberal blogger and economist Duncan "Atrios" Black, who was one of the leaders of the campaign against Bush's privatisation scheme, vowed in response to these early reports:
The left … will create an epic 360-degree shitstorm if Obama and the Dems decide that cutting social security benefits is a good idea.
Fast forward to 2011: it is now beyond dispute that President Obama not only favours, but is the leading force in Washington pushing for, serious benefit cuts to both social security and Medicare.
Amanda Marcotte and Jesse Taylor: How States Could Ban Abortion With 'Roe' Still Standing
For decades, the debate over abortion rights has centered on a single court decision, Roe v. Wade, and the possibility of its overturn. Overturning Roe has become the holy grail of the antichoice movement, and many states have "trigger laws" on the books that would ban abortion immediately should the Supreme Court overturn Roe. Unfortunately for antichoicers, the justices resist overturning precedent; more importantly, Justice Anthony Kennedy, the likely swing vote on any abortion case before the court, upheld Roe on the basis of precedent in 1992. However, the recent surge in state legislation against abortion demonstrates that antichoice activists have figured out a new strategy: eliminating legal abortion without directly overturning Roe.
The Supreme Court granting states the power to ban abortion with Roe still standing seemed outlandish even just a few years ago, but the appointment of John Roberts as chief justice shifted the equation. Roberts specializes in decisions that reverse the spirit of precedent while leaving intact the letter of it, like when he squashed large chunks of Brown v. the Board of Education while claiming to uphold it. To make it legal to ban abortion in the states, all the Court needs is a law that eliminates legal abortion while dodging the logic of Roe v. Wade.
George Zornick: [Gang of Pain: Who Suffers Under the Bipartisan Deficit Reduction Scheme]
President Obama endorsed the Senate's Gang of Six deficit reduction plan Tuesday, saying that the proposal "is broadly consistent with the approach that I've urged" and "makes sure that nobody is disproportionately hurt from us making progress on the debt and deficits."
However, an examination of the plan's specifics reveals that corporations and wealthy Americans won't feel much pain at all-in many cases, just the opposite. The plan slashes taxes and could bring the top personal income rate down as low as 23 percent-meaning CEOs like Jamie Dimon and Lloyd Blankfein could see their after-tax income increase by as much as $3 million, according to Dean Baker, co-director of the Center for Economic and Policy Research. The corporate tax rate would be reduced from 35 percent to between 23 and 29 percent under the proposal. (Supposedly enough loopholes would be closed to keep total revenue from corporate taxes the same. Even in that scenario, corporations won't pay an extra penny). Military spending also remains virtually untouched.
Eugene Robinson: The Limits of Compromise
Before we make political partisanship a felony, punishable by endless lectures from weather-vane senators and allegedly "wise" commentators, let's remember that some choices are real, consequential and mutually exclusive.
I'm not talking about the kind of scorched-earth partisanship that Senate Minority Leader Mitch McConnell espouses-the notion that Republicans should favor anything that's politically harmful to Democrats, never mind what the impact on the country might be. "The single most important thing we want to achieve is for President Obama to be a one-term president," McConnell said last year, displaying a candor that is all too rare in Washington.
I'm talking about partisanship based on issues, policy options and incompatible philosophies about the nature and purpose of government. Powerful forces are pulling the nation in opposite directions. The danger of too much compromise is that we end up not moving at all.
David Sirota: The Terrorist Threat We're Ignoring
According to the U.S. government, the list of known bogeymen working to compromise American national security is long, and getting longer by the day. By my back-of-the-envelope count, we have shoe bombers, underwear bombers, dirty bombers and car bombers. Now, we are being told to fear "implant bombers" who will surgically attach explosives to their innards.
All of these threats are, indeed, scary. But the fear of individual attacks has diverted attention from a more systemic threat of terrorists or foreign governments exploiting our economy's penchant for job-offshoring. How? By using our corresponding reliance on imports to stitch security-compromising technology into our society's central IT nervous system.
Sounds farfetched, right? That's what I thought, until I read a recent article in Fast Company. Covering a little-noticed congressional hearing, the magazine reported that a top Department of Homeland Security official "admitted on the record that electronics sold in the U.S. are being preloaded with spyware, malware, and security-compromising components."
Bernie Sanders: Congrats to the Gang of Six, the Powerful, the Wealthy, and Multinational Corporations
If there was ever a time in the modern history of America that the American people should become engaged in what's going on here in Washington, now is that time. Decisions are being made that will impact not only our generation but the lives of our children and our grandchildren for decades to come, and I fear very much that the decisions being contemplated are not good decisions, are not fair decisions.
There is increased understanding that that defaulting for the first time in our history on our debts would be a disaster for the American economy and for the world's economy. We should not do that.
There also is increased discussion about long-term deficit reduction and how we address the crisis which we face today of a record-breaking deficit of $1.4 trillion and a $14 trillion-plus national debt.
One of the long-term deficit reduction plans came from the so-called Gang of Six. We do not know all of the details of that proposal. In fact, we never will know because a lot of the decisions are booted to committees to work out the details.
This Week In The Steamy Dream Antilles
by davidseth
This was quite a bizarre week. And this will be a short digest. Your Bloguero was obsessed all week long with the California Prison Hunger Strike. Five essays. One every day. Monday through Friday. And because your Bloguero was convinced that the Trad Media TM weren't giving the story any real coverage and that what there was, was simple stenography of the official half truths and maliciousness of prison officials, your Bloguero decided these essays should be cross-posted at various blogs. Good idea. Hard to carry out. Your Bloguero found himself involuntarily drowning in the fabled ocean of Java and html errors. Repeatedly. Let's face it. Your Bloguero can tickle the keyboard, and maybe he can write the essays, but alas and alack, when that dreaded red warning jumps up when he hits "publish," he freaks out. And curses. And gets impatient. And frustrated. And does not know how to fix the problem so the essay will actually publish. And so, it has been a week both of frenzied hammering away at the keyboard and the soaring agitation and frustration the red warnings elicit.
This could be crazy making anywhere. And it probably is. But because he is back from Mexico and is again in Upstate New York, the heat and humidity have fueled both the intensity and duration of your Bloguero's massive freak outs. Let's not mention his impatience. Or his irritation. Or his reactions to the comments your Bloguero took umbrage at. Or the epithets he muttered (but did not type).
Thank goodness that the hunger strike has now ended peacefully so your Bloguero can now attempt to re-establish his so often lost equanimity.
Here are the essays supporting the prison hunger strikers:
Friday, Thursday, Wednesday, Tuesday, and Monday.
Was there anything else in the Dream Antilles other than your Bloguero's obsession? In what seems like a million years ago, your Bloguero actually wrote a piece on Sunday about Hoaracio Castellanos Moya's book She-Devil in The Mirror. Moya is a wonderful writer, and this book is an unusual description of the pervasive corruption in post Revolution El Salvador, told by a very distinctive and unusual narrator. An interesting book that should be wider known.
This Week In The Dream Antilles is a weekly digest. Sometimes, like now, it is actually a digest of essays posted in the past week. Your Bloguero always solicits your support. No, not your money. Just leave a comment so that your Bloguero will know that you stopped by. Humor him. Or, even easier, just click the "Encouragement jar". Your Bloguero likes to know that you're visiting.
Tags: digest, Port Writers Alliance
California Prison Hunger Strike Ends Peacefully
(Note: This is my fifth and final essay in support of the California prisoners on hunger strike. The first is here. The second is here. OPOL's wonderful treatment of the situation is here. The third is here. Yesterday's is here.
SF Gate reports that after three full weeks the California Prisoners' Hunger Strike has come peacefully to an end. Prisoners across California are now eating:
Tags: California, hunger strike, prison
Le Tour- Stage 19
Modane Valfréjus to Alpe-d'Huez 69 miles
Le. Tour. De. France.
As it turns out BruceMcF was quite right to suspect that yesterday the Mad Manx, Mark Cavendish, 4 Stage winner and leader in the points competition by a comfortable 35 would come under tremendous pressure to finish inside the time limit (which yesterday was 33:07) or be dropped from the Tour.
Well he didn't do that, and was part of a group of 88 riders that finished 35:50 back.
But there is safety in numbers and as one can imagine the Tour organizers were kind of embarrassed at the prospect of losing about half the field, including some other high recognition sprinters like Gilbert and Hushovd, so instead they used a loophole in the rules designed for after a spectacular Peloton splitting crash and fined the all the riders in the group 20 points instead.
This did a bit of reshuffling of the sprinter standings from Wednesday to Thursday and instead of a commanding 35 point lead the Mad Manx has a margin of but a bare 15 and is headed to another day in the mountains.
At the front Andy Schleck put on quite a show with an early break away after the Casse Déserte that he maintained all the way up the Galibier and gained more than 4 Minutes over Alberto Contador who has defeated him for the past two years. While the shuffling in the GC was not quite as dramatic there were still a few changes-
Rank Name Team ET delta
1 Thomas Voeckler Europcar 79h 34′ 06″
2 Andy Schleck Leopard Trek 79h 34′ 21″ + 00′ 15″
3 Frank Schleck Leopard Trek 79h 35′ 14″ + 01′ 08″
4 Cadel Evans BMC 79h 35′ 18″ + 01′ 12″
5 Damiano Cunego Lampre 79h 37′ 52″ + 03′ 46″
6 Ivan Basso Cannondale 79h 37′ 52″ + 03′ 46″
7 Alberto Contador Saxo Bank 79h 38′ 50″ + 04′ 44″
8 Samuel Sanchez Euskaltel 79h 39′ 26″ + 05′ 20″
9 Tom Danielson Garmin 79h 41′ 14″ + 07′ 08″
10 Jean-Christophe Peraud AG2R 79h 43′ 33″ + 09′ 27″
The most important thing is the deltas, the time margin between competitors, because after today it will be very difficult to make up more than a minute, maybe 2, in the Individual Time Trials without a major mistake or a disasterous crash. The route tomorrow is relatively flat and short, only 27 miles.
Today's Stage is the last in the Alps and contains 1 category 1 and 2 Unclassified climbs finishing uphill on the Alpe d'Huez. It's fairly short so you can expect climbing attacks early.
At about 56 miles there is a descent that looks in the profile like you're dropping straight off a cliff. They exaggerate the scale so the elevation changes are more visible but it is still a high speed and twisty bit and people, especially if they are tired and anxious, might make mistakes.
If there are any sprinters left, their checkpoint will be after that.
Tomorrow is a very busy day for me as I'll also have Formula One Qualfying at Nurburgring at 8 am, the same time as Le Tour. Today's Vs. coverage starts at 8 am.
Jada Yuan Previews the Hell Out of the Tour de France in the New Yorker, 7/1/11 at 2:00 PM
Le Tour 2011 official site
Your The Stars Hollow Gazette Le Tour coverage tags-
Le Tour 2010
Tags: Le Tour, Le Tour 2011
On This Day In History July 22
July 22 is the 203rd day of the year (204th in leap years) in the Gregorian calendar. There are 162 days remaining until the end of the year.
On this day in 1933, Wiley Post becomes the first person to fly solo around the world traveling 15,596 miles in 7 days, 18 hours and 45 minutes.
Like many pilots at the time, Post disliked the fact that the speed record for flying around the world was not held by a fixed-wing aircraft, but by the Graf Zeppelin, piloted by Hugo Eckener in 1929 with a time of 21 days. On June 23, 1931, Post and his navigator, Harold Gatty, left Roosevelt Field on Long Island, New York in the Winnie Mae with a flight plan that would take them around the world, stopping at Harbour Grace, Flintshire, Hanover twice, Berlin, Moscow, Novosibirsk, Irkutsk, Blagoveshchensk, Khabarovsk, Nome where his airscrew had to be repaired, Fairbanks where the airscrew was replaced, Edmonton, and Cleveland before returning to Roosevelt Field. They arrived back on July 1, after traveling 15,474 miles in the record time of 8 days and 15 hours and 51 minutes. The reception they received rivaled Lindbergh's everywhere they went. They had lunch at the White House on July 6, rode in a ticker-tape parade the next day in New York City, and were honored at a banquet given by the Aeronautical Chamber of Commerce of America at the Hotel Astor. After the flight, Post acquired the Winnie Mae from F.C. Hall, and he and Gatty published an account of their journey titled, Around the World in Eight Days, with an introduction by Will Rogers.
His Lockheed Vega aircraft, the Winnie Mae is on display at the National Air and Space Museum's Steven F. Udvar-Hazy Center, and his pressure suit is being prepared for display at the same location. On August 15, 1935, Post and American humorist Will Rogers were killed when Post's aircraft crashed on takeoff from a lagoon near Point Barrow, in Alaska.
Schumer Pushes For A Corporate Tax Holiday
A corporate tax holiday? Does Sen. Chuck Schumer (D-NY) seriously think that by cutting the tax rate on overseas profits for US Multinationals from 35% to 5,25% it will encourage these companies to create jobs here? That is what Schumer, our elected Wall St. lobbyist, is pushing despite the fact that the last time this was done in 2005, most of the money went to shareholders and executives (pdf) in the form of dividends and stock buy backs. We all know how many jobs were created, zero. Indeed, the companies that profited the most actually laid off more workers and cut back production in the US. We all know how many jobs were created, zero. Indeed, the companies that profited the most actually laid off more workers and cut back production in the US. As to increased revenue, short term it might bring $50 billion into the Treasury but over a ten year period there would be an $80 billion loss.
In his Rolling Stone blog, Matt Taibbi explains how this is just another "con" by corporation lobbyists:
Here's how it works: the tax laws say that companies can avoid paying taxes as long as they keep their profits overseas. Whenever that money comes back to the U.S., the companies have to pay taxes on it.
Think of it as a gigantic global IRA. Companies that put their profits in the offshore IRA can leave them there indefinitely with no tax consequence. Then, when they cash out, they pay the tax.
Only there's a catch. In 2004, the corporate lobby got together and major employers like Cisco and Apple and GE begged congress to give them a "one-time" tax holiday, arguing that they would use the savings to create jobs. Congress, shamefully, relented, and a tax holiday was declared. Now companies paid about 5 percent in taxes, instead of 35-40 percent.
Money streamed back into America. But the companies did not use the savings to create jobs. Instead, they mostly just turned it into executive bonuses and ate the extra cash. Some of those companies promising waves of new hires have already committed to massive layoffs..
According to Forbes, Chuck Schumer has garnered the blessings of some "left" Democrats by pairing it with a job creating infrastructure program. Former SEIU president Andy Stern and Sen. Kay Hagen (D-NC), who voiced her support at a Third Way breakfast, have endorsed the idea and the multi-nationals have already sent out their dogs to push it:
While the repatriation holiday alone is a non-starter for most Democrats, pairing it with an infrastructure program could marshal labor support. It's an approach backed by former Service Employees International Union president Andy Stern, who's emerged as the most vocal proponent of the tax holiday on the left.
The team of corporate heavyweights behind the lobbying push for the holiday — including Apple (AAPL), Cisco (CSCO), Duke Energy (DUK), Google (GOOG), Kodak (EK), Microsoft (MSFT), Pfizer (PFE), and Oracle (ORCL) – has shown some success softening up Democratic opposition recently. Last week, the centrist Democratic think tank Third Way hosted a breakfast on the topic that featured Sen. Kay Hagan (D-N.C.). "A repatriation holiday can encourage economic activity at a fraction of the cost of recent fiscal policy," Hagan said in her prepared remarks.
Tags: Charles Schumer, Deficit, Economy, Jobs, Politics, taxes, TMC Politics
Countdown with Keith Olbermann
If you do not get Current TV you can watch Keith here:
Watch live video from CURRENT TV LIVE Countdown Olbermann on www.justin.tv
Tags: Countdown, Current TV, Keith Olbermann, Politics, TMC Politics
1 End of an era for US spaceflight as Atlantis lands
By Jean-Louis Santini, AFP
The shuttle Atlantis cruised home for a final time Thursday, ending its last mission to the International Space Station and closing a 30-year chapter in American space exploration.
Under cover of darkness, the shuttle glided seamlessly to a predawn landing at Kennedy Space Center at 5:57 am (0957 GMT), marking the formal retirement of the shuttle program and leaving Russia as the world's only taxi to the ISS.
"Mission complete, Houston," shuttle commander Chris Ferguson said as the black and white orbiter, emblazoned with an American flag, rolled to a stop.

redpajama_set_name: RedPajamaCommonCrawl


text:
This article was published on March 1, 2013
FTC: Chairman was unaware of Google's donation to ceremony celebrating his work during investigation
March 1, 2013 - 6:39 pm
Alex Wilhelm
Alex Wilhelm is a San Francisco-based writer. You can find Alex on Twitter, and on Facebook. You can reach Alex via email at [email protected] (show all) Alex Wilhelm is a San Francisco-based writer. You can find Alex on Twitter, and on Facebook. You can reach Alex via email at [email protected]
The FTC has responded to yesterday's controversy regarding Google and its director stating that he knew nothing at the time of the donation in question. This implicitly states that the funds therefore had no impact on the decision of the agency regarding Google.
Yesterday it became known that Google donated $25,000 to Common Sense Media to help it put on an awards event that including the honoring of Jon Leibowitz, chairman of the FTC, which at that time was investigating the search giant for possible antitrust violations involving how it ranked its own services among organic results.
Google, in the view of TNW, came out on top of the investigation, with little more than a wrist tap. Response to the FTC's decision drew the ire of Microsoft, for one.
Regarding the donation, TNW noted yesterday that it does not "indicate that Google intended the funds as a bribe or anything of the sort, however, the PR mess that this sort of coincidence evokes is not particularly savory." We stand by that analysis.
The FTC reached out with the following comment this morning, attributable to its spokesperson Peter Kaplan:
"Chairman Leibowitz had no idea that Google was one of the many corporate contributors to the event until he read the article. But he is grateful and honored to accept the award from Common Sense Media, which does so much for kids and families and privacy."
While the above situation isn't pleasant for either party, there doesn't appear to have been any sort of foul play either intended or affected. Google, which spends heavily on its lobbying efforts, would do well to be a bit more careful with where it deploys cash in the future.
Top Image Credit: Håkan Dahlström
Published March 1, 2013 - 6:39 pm UTC
Google kills Hangouts — but its dreams of Gmail dethroning Slack feel far away
5 life-changing Google Docs features you might have missed in 2022


text:
Overall Winners of 2021 Vodacom Journalist of the Year Awards announced
by Tech Talk | Nov 29, 2021 | Partnerships | 0 comments
South African journalism has once again excelled at capturing and telling the stories of our colourful, vibrant and deeply complex society – made even more so by the enormous impact of the COVID-19 pandemic. This was the verdict by the Vodacom Journalist of the Year Awards' (VJOY) judging panel as the winners were announced at a virtual ceremony on last week.
The overall 2021 Vodacom Journalist of the Year winner is Siphamandla Goge of eNCA for his story titled, "The sun sets on Zulu kingdom", who walked away with the coveted R100 000 prize and title. Goge covered the deaths of the Zulu king and the queen regent, a moment in our country's history which engulfed the nation in uncertainty, confusion and grief, as well as evoking a sense of pride and of learning. The coverage of this poignant event was described as "superb, incisive and instructive live TV reporting".
The virtual event was hosted by CNN anchor Eleni Giokos. Award-winning South African singer, Lira, wowed the audience with her exquisite vocal performance while renowned former Sky News, BBC and ITN correspondent Jeremy Thompson delivered a speech to the audience live from London detailing his decades-long global experience as a war correspondent, including in Apartheid South Africa.
The national category winners of the VJOY awards, now in its 20th year, were chosen after a rigorous selection process which began in August and saw over 1 300 entries received nationally across 12 categories. This year's VJOY judging panel consists of convener Ryland Fisher and judges Jermaine Craig, Arthur Goldstuck, Patricia McCracken, Mapi Mhlangu, Gilbert Motsaathebe, Collin Nxumalo, Jovial Rantao, Robin Sewlal, Phindile Xaba and Obed Zilwa.
The theme for the 2021 Awards – "Resilience" – spoke to the deep challenges which journalists across South Africa have had to face during the pandemic while continuing to produce high-quality work. Takalani Netshitenzhe, Vodacom South Africa Chief Officer for External Affairs, says: "The VJOY awards offer the perfect opportunity for us as a nation to recognise the sterling efforts of our country's media sector. Quality journalism takes enormous skill, dedication and courage to find and tell the stories which matter, and which impact the lives of people from every sphere of life. For that, we salute the national winners who exemplify the very best of the journalism profession."
"As Vodacom, we continue to support quality South African journalism, which is a pillar of our democracy. The VJOYs recognise, honour and celebrate the remarkable storytellers of our nation and I would like to extend my personal congratulations to all the national award winners on their achievements. Vodacom is also deeply appreciative of the exhaustive efforts of our hardworking panel of judges who make the VJOYs one of South Africa's most prestigious and longstanding journalism awards."
VJOY judging panel convener, Ryland Fisher, says: "Like 2020, 2021 has been dominated by the COVID-19 pandemic, which has forced entire countries and industries to review the way they work and imagine their futures. South Africa is no different, with intense focus on how we will overcome the economic crisis associated with the virus.
"But the virus has not been the only big story in South Africa. Corruption, unemployment, poverty and inequality continue unabated, some political leaders have struggled to display true leadership skills and 'ordinary' South Africans have expressed their displeasure at their material conditions and the efforts of national, provincial and local political leadership in many different ways."
Fisher adds: "It has been up to the media to try and make sense of this complex society called South Africa. The quality of entries in the Vodacom Journalist of the Year has shown once again that the industry is strong and up to the challenges presented by world events and, more importantly, by events in South Africa. We have seen the best of reporting from throughout the industry, whether it was for breaking news, investigations, opinion or features, and a host of other categories associated with these awards. The journalists have, through their determination and resilience, once again made us proud to be South African."
The VJOY Lifetime Achiever Award went to the late writer, author, journalist and editor Helen Nantando "Noni" Jabavu, who is described as a "true trailblazer. She was born in 1919 into an Eastern Cape family steeped in literary figures, and while she largely grew up in Britain, she returned to South Africa in 1976 and cemented an already formidable career as a writer and journalist. Jabavu died in 2008 but has been honoured with a number of awards and the VJOY Lifetime Achiever Award is added to this list in recognition of the "global ambassadorial role she played for South Africa in media and the literary world".
The national category winners, who each won R10 000, are:
Investigative – Daily Maverick, Pieter-Louis Myburgh
Opinion – Sunday Times Daily, Tanya Farber
Features – Joint national winners from PE Express, Candice Bezuidenhout; and from, Cutting Edge, SABC TV, Nontsikelelo Nohiya with contributors Sibusiso Tembe, Fatima Modise and Hlubikazi Kulu
Lifestyle – Saturday Star, Independent on Saturday and Weekend Argus, Nelandri Narainan
Sport – Sport24, Sibusiso Mjikeliso
Financial and Economics – AmaBhungane Centre for Investigative Journalism, Susan Comrie and Sam Sole
Politics – Saturday Star, Independent on Saturday and Weekend Argus, Nelandri Narainan
Sustainability – amaBhungane.org, Dewald van Rensburg with contributors Tebogo Tshwane, Susan Comrie, Micah Reddy, Irwin Manoim and Tabelo Timse
Live reporting/ breaking news – eNCA, Siphamandla Goge, with contributors Bongumusa Mkhize and Nkanyiso Mdlalose
Photography – Netwerk24/Beeld, Deaan Vivier
Innovation in journalism – News24, Jeff Wicks and contributor Kyle Cowan
The Young Journalist of the Year Award went to Jabulile Mbatha from eNCA Checkpoint. This award emphasises the VJOY's commitment to furthering the career of a dynamic young rising star journalist in South Africa. Mbatha has won an all-expenses paid overseas trip to work in an international newsroom. Should the pandemic continue to interrupt international travel, an alternative arrangement will be made.
sixteen − 7 =


Nagarjuna is the major highlight of the film and he convinces us all as Sai Baba. Keeravani's re-recording and background score are major assets for the film.Songs have been shot well and with great colours. Some scenes stand out, like Baba re-entering his body after three days and his practical explanation of spiritual concepts.
Shirdi Sai (Nagarjuna) appears in Shirdi at an early age and disappears. He goes to Himalayas and returns to Shirdi after a gap of 9 years. He chooses a dilapidated mosque as his abode. Amazed by his presence and miracles, the local people start calling his Sai and Baba. He keeps helping people around and spreading communal harmony by saying that there is only one God. Certain local people are suspicious of Sai Baba and they learn about his greatness over a period of time. The rest of the story is all about what Sai Baba did to make Shirdi the only pilgrimage for people of all religions and about he entering Samadhi.


Check out the 2019-2020 Member Funding Guidelines to see if your group is eligible for SGC funding.
The SGC Youth Funding Program Mach mit! – Get involved! is intended to support innovative youth projects within Saskatchewan's German and German-Canadian community. SGC member groups as well as other youth groups are eligible for funding. The Council is also accepting applications from individuals applying on behalf of a group of youth.
Applications for the Macht mit! – Get involved! program will be accepted on an ongoing basis. Therefore, there is no deadline. As with SGC's Member Funding Program, successful groups are required to fill in a follow-up form to receive funding.
The Saskatchewan German Council offers costume funding for performing member groups. The funding that each group receives depends on the number of members performing. Funding for the 2017/2018 fiscal year has already been paid out. The applications for 2018/2019 will be sent out in January 2019.
The Saskatchewan German Council offers travel funding for performing member groups. The funding that each group receives depends on the number of members performing. Funding for the 2017/2018 fiscal year has already been paid out. The applications for 2018/2019 will be sent out in January 2019.
The Saskatchewan German Council offers sponsorships for projects and events that contribute to German/Austrian/Swiss culture and traditions in the province and help strengthen communities by engaging people in cultural activities.
Only non-SGC members are eligible for funding. Applications for sponsorships are accepted throughout the year and funding depends on the number of applications received. Successful groups are required to fill in a follow-up form to receive funding.


text:
Q: using the values of rendered datatable in later analysis When an object is created using DT::renderDataTable ( I need use DT::, because I modify the original table by adding rows), say "myTable", can this object be used in later analysis? To be more clear, is there an input$myTable or a myTable() command which gives me the modified table?

A: In the DT package you can create a proxy object of a table using dataTableProxy(). But the manipulation of the proxy seems to be focused on (un)selection of rows. So you can access the index of rows selected and such, but not the information inside the table. At least not directly.
One way to go around this is to modify the original table inside a reactive(), and then call it in the renderDataTable(). So later on, you can call the table inside the reactive.

redpajama_set_name: RedPajamaStackExchange