<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <b>This is a free api which gives bitcoin pricing</b>
This function will download and cache datasets from Quandl.
Step1:  <p>I'm using pickle to searialize and save the downloaded data as a file which wont redownload everytime ths script is run.(This is the cache that is being referred to).</p>
<p> The data returned is a Pandas dataframe.</p>
We will now pull the bitcoin data from the kraken bitcoin exchange
Step2:  generating a sample chart to see how the data looks visually.
Step3:  <p>What can be immediately inferred is that there is a missing element which is evident from the sharp drops in late 2014 and early 2016.</p>
<p>The nature of bitcoin is very supply and demand oriented,Hence it entirely depends if and how much the particular bitcoin exchange platform was in use at that time*(A little bit unlclear but this is my basic understanding of cryptocurrency trading,sorry if this is altogether inaccurate!)</p>
<p>To fill in our gaps the most effective solution will be to get datasets from a wide array of exhanges which will fill up most gaps in our plots</p>
<ASSISTANT_TASK:>
Python Code:
def get_quandl_data(quandl_id):
    '''Download and cache Quandl dataseries'''
    cache_path = '{}.pkl'.format(quandl_id).replace('/','-')
    try:
        f = open(cache_path,'rb')
        df= pickle.load(f)
        print('Loaded {} from cache'.format(quandl_id))
    except(OSError,IOError) as e:
        print('Downloading {} from Quandl'.format(quandl_id))
        df=quandl.get(quandl_id,returns="pandas")
        df.to_pickle(cache_path)
        print('cached {} at {}'.format(quandl_id,cache_path))
    return df
Explanation: <b>This is a free api which gives bitcoin pricing</b>
This function will download and cache datasets from Quandl.
End of explanation
btc_usd_price_kraken = get_quandl_data('BCHARTS/KRAKENUSD')
btc_usd_price_kraken.head()
Explanation: <p>I'm using pickle to searialize and save the downloaded data as a file which wont redownload everytime ths script is run.(This is the cache that is being referred to).</p>
<p> The data returned is a Pandas dataframe.</p>
We will now pull the bitcoin data from the kraken bitcoin exchange
End of explanation
btc_trace=go.Scatter(x=btc_usd_price_kraken.index,y=btc_usd_price_kraken['Weighted Price'])
py.iplot([btc_trace])
Explanation: generating a sample chart to see how the data looks visually.
End of explanation
#pull data for 3 more exchanges
exchanges = ['COINBASE','BITSTAMP','ITBIT']
exchange_data={}
exchange_data['Kraken']= btc_usd_price_kraken
for exchange in exchanges:
    exchange_code = 'BCHARTS/{}USD'.format(exchange)
    btc_exchange_df= get_quandl_data(exchange_code)
    exchange_data[exchange]=btc_exchange_df
def merge_dfs_on_column(dataframes,labels,col):
    '''merge a single column of each dataframe into a new combined dataframe'''
    series_dict = {}
    for index in range(len(dataframes)):
        series_dict[labels[index]]=dataframes[index][col]
    return pd.DataFrame(series_dict)
#merge the BTC prices into one dataframe
btc_usd_datasets = merge_dfs_on_column(list(exchange_data.values()),list(exchange_data.keys()),'Weighted Price')
btc_usd_datasets.tail()
def df_scatter(df, title, seperate_y_axis=False, y_axis_label='', scale='linear', initial_hide=False):
    '''Generate a scatter plot of the entire dataframe'''
    label_arr = list(df)
    series_arr = list(map(lambda col: df[col], label_arr))
    
    layout = go.Layout(
        title=title,
        legend=dict(orientation="h"),
        xaxis=dict(type='date'),
        yaxis=dict(
            title=y_axis_label,
            showticklabels= not seperate_y_axis,
            type=scale
        )
    )
    
    y_axis_config = dict(
        overlaying='y',
        showticklabels=False,
        type=scale )
    
    visibility = 'visible'
    if initial_hide:
        visibility = 'legendonly'
        
    # Form Trace For Each Series
    trace_arr = []
    for index, series in enumerate(series_arr):
        trace = go.Scatter(
            x=series.index, 
            y=series, 
            name=label_arr[index],
            visible=visibility
        )
        
        # Add seperate axis for the series
        if seperate_y_axis:
            trace['yaxis'] = 'y{}'.format(index + 1)
            layout['yaxis{}'.format(index + 1)] = y_axis_config    
        trace_arr.append(trace)
    fig = go.Figure(data=trace_arr, layout=layout)
    py.iplot(fig)
    # Plot all of the BTC exchange prices
df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')
Explanation: <p>What can be immediately inferred is that there is a missing element which is evident from the sharp drops in late 2014 and early 2016.</p>
<p>The nature of bitcoin is very supply and demand oriented,Hence it entirely depends if and how much the particular bitcoin exchange platform was in use at that time*(A little bit unlclear but this is my basic understanding of cryptocurrency trading,sorry if this is altogether inaccurate!)</p>
<p>To fill in our gaps the most effective solution will be to get datasets from a wide array of exhanges which will fill up most gaps in our plots</p>
End of explanation
<END_TASK>