diff --git a/docs/algorithms/Average.md b/docs/algorithms/Average.md
new file mode 100644
index 0000000000000000000000000000000000000000..9a1b0fb098fcecb38b997c1f1d26bb4d2ff701ef
--- /dev/null
+++ b/docs/algorithms/Average.md
@@ -0,0 +1,38 @@
+Average Algorithm
+-----------------
+
+Algorithm Theoretical Basis for "Average Algorithm"
+
+## Summary
+Averages multiple observatory data for the same channel.
+Used mainly to average disturbance data in order to find
+the general disturbance in the magnetic field. The algorithm
+takes data from multiple observatories with the same channel
+and returns a stream of the averaged data.
+
+## Background and Motivation
+The averaging function is used to smooth out the plots and
+find a combined disturbance of the magnetic field that
+encompasses the Earth. This can be used to determine the 
+overall effect of magnetic storms over a large area. The 
+algorithm is also used to average the Solar Quiet response 
+to find the daily change in the magnetic field. The algorithm
+can be used to find the average of any channel over multiple
+observation stations.
+
+## Math and Theory
+Multiple data streams are averaged using a numpy function
+(numpy.mean) that takes multiple ndarrays as an argument
+and averages them into one array. A latitude correction
+can be applied based on the different observation locations.
+The correction is really just a weighting value based on a
+0-1 scale in order to put more validity in some stations.
+
+## Practical Considerations
+The averaging function can be called from geomag.py and stating 
+the '--algorithm average' option or by calling the average.py 
+script which automatically chooses the averaging option to the 
+algorithm. Only one channel at a time can be run through the 
+algorithm. Any input that geomag.py can handle can be used
+such as the edge server or a file url input this is also true
+for any output.
diff --git a/geomagio/__init__.py b/geomagio/__init__.py
index e896583b7b50762cf9858d9032c35d3c050a25b4..d871a122884b9940dd200d5ac436c9b2414b5d50 100644
--- a/geomagio/__init__.py
+++ b/geomagio/__init__.py
@@ -25,6 +25,5 @@ __all__ = [
     'TimeseriesFactoryException',
     'TimeseriesUtility',
     'Util',
-    'Url',
-    'XYZAlgorithm'
+    'Url'
 ]
diff --git a/geomagio/algorithm/AverageAlgorithm.py b/geomagio/algorithm/AverageAlgorithm.py
new file mode 100644
index 0000000000000000000000000000000000000000..f030fd0e357008f1158bde2cb00fe792f132b058
--- /dev/null
+++ b/geomagio/algorithm/AverageAlgorithm.py
@@ -0,0 +1,210 @@
+"""Algorithm that creates an averaged Dst.
+
+"""
+from __future__ import absolute_import
+
+from .Algorithm import Algorithm
+from .AlgorithmException import AlgorithmException
+from ..ObservatoryMetadata import ObservatoryMetadata
+import numpy
+import obspy.core
+
+
+# Possible correction factors.
+# Defaults to 1.0 if station not found in list.
+CORR = {
+    'HON': 1.0,
+    'SJG': 1.0,
+    'HER': 1.0,
+    'KAK': 1.0,
+    'GUA': 1.0
+}
+
+
+class AverageAlgorithm(Algorithm):
+    """Algorithm that creates an averaged Dst.
+
+    Parameters
+    ----------
+
+    """
+
+    def __init__(self):
+        Algorithm.__init__(self)
+        self._npts = -1
+        self._stt = -1
+        self._stats = None
+        self.observatoryMetadata = ObservatoryMetadata()
+
+    def check_stream(self, timeseries):
+        """checks a stream to make certain the required data
+            exists.
+
+        Parameters
+        ----------
+        timeseries: obspy.core.Stream
+            stream to be checked.
+        """
+
+        # A stream produced by EdgeFactory should always pass these checks.
+
+        # must have only one channel for each observatory
+        if len(timeseries) != len(self.observatories):
+            raise AlgorithmException(
+                'Expected data for %d stations, received %d \n'
+                    'Only 1 channel may be averaged at one time'
+                    % (len(self.observatories), len(timeseries)))
+
+        # timeseries starttime and number of samples must match
+        for ts in timeseries:
+            # grab 1st set of stats to use in output.
+            # Its values will be good if checks pass.
+            if self._stats is None:
+                self._stats = ts.stats
+
+            if self._npts == -1:
+                self._npts = ts.stats.npts
+            if ts.stats.npts != self._npts:
+                raise AlgorithmException(
+                    'Received timeseries have different lengths')
+
+            if self._stt == -1:
+                self._stt = ts.stats.starttime
+            if ts.stats.starttime != self._stt:
+                raise AlgorithmException(
+                    'Received timeseries have different starttimes')
+
+    def process(self, timeseries):
+        """averages a channel across multiple stations
+
+        Parameters
+        ----------
+
+        Returns
+        -------
+        out_stream:
+            new stream object containing the averaged values.
+        """
+
+        self.check_stream(timeseries)
+
+        # initialize array for data to be appended
+        combined = []
+        # loop over stations
+        for obsy in self.observatories:
+
+            # lookup latitude correction factor, default = 1.0
+            latcorr = 1.0
+            if obsy in CORR:
+                latcorr = CORR[obsy]
+
+            # create array of data for each station
+            # and take into account correction factor
+            ts = timeseries.select(station=obsy)[0]
+            combined.append(ts.data * latcorr)
+
+        # after looping over stations, compute average
+        dst_tot = numpy.mean(combined, axis=0)
+
+        # Create a stream from the trace function
+        stream = obspy.core.Stream((
+                get_trace(self.outchannel, self._stats, dst_tot), ))
+
+        # set the full metadata for the USGS station used for averaged
+        # data sets
+        self.set_metadata(
+            stream=stream,
+            observatory='USGS',
+            channel=self.outchannel,
+            type=stream[0].stats.data_type,
+            interval=timeseries[0].stats.data_interval)
+
+        # return averaged values as a stream
+        return stream
+
+    def set_metadata(self, stream, observatory, channel, type, interval):
+        """set metadata for a given stream/channel
+        Parameters
+        ----------
+        observatory : str
+            observatory code
+        channel : str
+            edge channel code {MVH, MVE, MVD, ...}
+        type : str
+            data type {definitive, quasi-definitive, variation}
+        interval : str
+            interval length {minute, second}
+        """
+
+        for trace in stream:
+            self.observatoryMetadata.set_metadata(trace.stats, observatory,
+                    channel, type, interval)
+
+    @classmethod
+    def add_arguments(cls, parser):
+        """Add command line arguments to argparse parser.
+
+        Parameters
+        ----------
+        parser: ArgumentParser
+            command line argument parser
+        """
+        parser.add_argument('--average-observatory-scale',
+               default=(None,),
+               help='Scale factor for observatories specified with ' +
+                    '--observatory argument',
+               nargs='*',
+               type=float)
+
+    def configure(self, arguments):
+        """Configure algorithm using comand line arguments.
+
+        Parameters
+        ----------
+        arguments: Namespace
+            parsed command line arguments
+        """
+
+        self.observatories = arguments.observatory
+        if len(arguments.outchannels) > 1:
+            raise AlgorithmException(
+                'Only 1 channel can be specified')
+        if arguments.outchannels:
+            self.outchannel = arguments.outchannels[0]
+        else:
+            self.outchannel = 'MSD'
+        self.scales = arguments.average_observatory_scale
+        if self.scales[0] is not None:
+            if len(self.observatories) != len(self.scales):
+                raise AlgorithmException(
+                    'Mismatch between observatories and scale factors')
+            else:
+                for (i, obs) in enumerate(self.observatories):
+                    CORR[obs] = self.scales[i]
+
+
+def get_trace(channel, stats, data):
+    """Utility to create a new trace object.
+
+    Parameters
+    ----------
+    channel : str
+        channel name.
+    stats : obspy.core.Stats
+        channel metadata to clone.
+    data : numpy.array
+        channel data.
+
+    Returns
+    -------
+    obspy.core.Trace
+        trace containing data and metadata.
+    """
+    stats = obspy.core.Stats(stats)
+
+    stats.channel = channel
+    stats.station = 'USGS'
+    stats.network = 'NT'
+    stats.location = 'R0'
+
+    return obspy.core.Trace(data, stats)
diff --git a/geomagio/algorithm/__init__.py b/geomagio/algorithm/__init__.py
index 2a6ac517a2a7ac0758f017f848407342b5b5376f..9b41729b35b2f010e7079fee586717af3cc71c06 100644
--- a/geomagio/algorithm/__init__.py
+++ b/geomagio/algorithm/__init__.py
@@ -8,6 +8,7 @@ from .Algorithm import Algorithm
 from .AlgorithmException import AlgorithmException
 # algorithms
 from .AdjustedAlgorithm import AdjustedAlgorithm
+from .AverageAlgorithm import AverageAlgorithm
 from .DeltaFAlgorithm import DeltaFAlgorithm
 from .SqDistAlgorithm import SqDistAlgorithm
 from .XYZAlgorithm import XYZAlgorithm
@@ -17,6 +18,7 @@ from .XYZAlgorithm import XYZAlgorithm
 algorithms = {
     'identity': Algorithm,
     'adjusted': AdjustedAlgorithm,
+    'average': AverageAlgorithm,
     'deltaf': DeltaFAlgorithm,
     'sqdist': SqDistAlgorithm,
     'xyz': XYZAlgorithm
@@ -29,6 +31,7 @@ __all__ = [
     'AlgorithmException',
     # algorithms
     'AdjustedAlgorithm',
+    'AverageAlgorithm',
     'DeltaFAlgorithm',
     'SqDistAlgorithm',
     'XYZAlgorithm'
diff --git a/setup.py b/setup.py
index edb67644460431478a7ec44ed1be080979f79b99..d74bc0f5f276d4e3d0e4fc45049efde86ef8d630 100644
--- a/setup.py
+++ b/setup.py
@@ -26,6 +26,6 @@ setup(
     ],
     scripts=[
         'bin/geomag.py',
-        'bin/make_cal.py'
+        'bin/make_cal.py',
     ]
 )